diff --git a/config.yml b/config.yml index 1965f34..78a4fd6 100644 --- a/config.yml +++ b/config.yml @@ -4,11 +4,11 @@ # {maxhealth} shows the max health of the mob or player. # {usestyle} will use the defined chars. -Health Message: '&6&l{name}: &a&l{health} / {maxhealth}' +Health Message: '&7&l{name}: {usestyle}' # Strip Name. -Strip Name: false +Strip Name: true # If enabled players with the permission 'ActionHealth.Health' will only see the action health message. @@ -48,4 +48,7 @@ Disabled regions: Region PvP: true # When set to true and style health is enabled this will limit the health symbols to 10. -Limit Health: true \ No newline at end of file +Limit Health: true + +# Saves players /actionhealth toggle state. +Remember Toggle: true \ No newline at end of file diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/FileHandler.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/FileHandler.class new file mode 100644 index 0000000..bb807a9 Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/FileHandler.class differ diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthCommand.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthCommand.class new file mode 100644 index 0000000..dc5bd6c Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthCommand.class differ diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthListeners.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthListeners.class new file mode 100644 index 0000000..d73ab0a Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthListeners.class differ diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthUtil$1.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthUtil$1.class new file mode 100644 index 0000000..023caf5 Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthUtil$1.class differ diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthUtil.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthUtil.class new file mode 100644 index 0000000..047182e Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/HealthUtil.class differ diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/Main.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/Main.class new file mode 100644 index 0000000..5f91e20 Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/Main.class differ diff --git a/out/production/ActionHealth/com/zeshanaslam/actionhealth/SettingsManager.class b/out/production/ActionHealth/com/zeshanaslam/actionhealth/SettingsManager.class new file mode 100644 index 0000000..17bf4d2 Binary files /dev/null and b/out/production/ActionHealth/com/zeshanaslam/actionhealth/SettingsManager.class differ diff --git a/plugin.yml b/plugin.yml index ff4ed3b..1b7167d 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,4 +3,4 @@ main: com.zeshanaslam.actionhealth.Main version: 5.0 commands: Actionhealth: - description: Reloads the plugin \ No newline at end of file + description: Actionhealth main command. \ No newline at end of file diff --git a/src/com/zeshanaslam/actionhealth/FileHandler.java b/src/com/zeshanaslam/actionhealth/FileHandler.java new file mode 100644 index 0000000..50e12f5 --- /dev/null +++ b/src/com/zeshanaslam/actionhealth/FileHandler.java @@ -0,0 +1,330 @@ +package com.zeshanaslam.actionhealth; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.configuration.file.YamlConfigurationOptions; +import org.bukkit.inventory.ItemStack; + +import java.io.File; +import java.io.IOException; +import java.util.Set; + +public class FileHandler { + + private File file = null; + + private YamlConfiguration yaml = new YamlConfiguration(); + + public FileHandler(File file) { + this.file = file; + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + this.load(); + } + + + public FileHandler(String path) { + this.file = new File(path); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + this.load(); + } + + public String getName() { + return file.getName(); + } + + public String getPath() { + return file.getPath(); + } + + public static boolean fileExists(String path) { + File file = new File(path); + + return file.exists(); + } + + private void load() { + try { + this.yaml.load(this.file); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void save() { + try { + yaml.save(file); + } catch (IOException e) { + System.out.println("CR: Error saving: " + file.getName()); + } + } + + public void delete() { + try { + this.file.delete(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public final File getfile(String PlayerName) { + return this.file; + } + + /** + * Get an Integer from the given path. + * + * @param s Path to the Integer. + * @return Integer at given path. + */ + public int getInteger(String s) { + if (!(this.yaml.contains(s))) { + return 0; + } + return this.yaml.getInt(s); + } + + /** + * Save, then load the Yaml file. **Warning** Very Unstable. + */ + public void reload() { + this.save(); + this.load(); + } + + /** + * Get a String from the path defined. + * + * @param s Path to the String. + * @return String at given path. + */ + public String getString(String s) { + return this.yaml.getString(s); + } + + /** + * Gets an Object at the given path. + * + * @param s Path to given Object. + * @return An Object at the given Path. + */ + public Object get(String s) { + return this.yaml.get(s); + } + + /** + * Gets all keys in file. + * + * @return An Set + */ + public Set getKeys() { + return this.yaml.getKeys(false); + } + + /** + * Gets a boolean at the given path. + * + * @param s Path to the boolean. + * @return Boolean at the given path. + */ + public boolean getBoolean(String s) { + return this.yaml.getBoolean(s); + } + + /** + * If the given path has no variable, it will be given a variable. + * + * @param s Path to look for. + * @param o Variable to be assigned if not existing. + */ + public void add(String s, Object o) { + if (!this.contains(s)) { + this.set(s, o); + } + + } + + /** + * Adds a String to a List of Strings. + * + * @param s Path to given String List. + * @param o String to add to the String List. + */ + public void addToStringList(String s, String o) { + this.yaml.getStringList(s).add(o); + } + + /** + * Removes a String to a List of Strings. + * + * @param s Path to given String List. + * @param o String to remove from the String List. + */ + public void removeFromStringList(String s, String o) { + this.yaml.getStringList(s).remove(o); + } + + /** + * Looks for a String List at given Path. + * + * @param s Path to String List. + * @return String List at given Path. + */ + public java.util.List getStringList(String s) { + return this.yaml.getStringList(s); + } + + /** + * Adds an Integer to a List of Integers. + * + * @param s Path to given Integer List. + * @param o Integer to add to the Integer List. + */ + public void addToIntegerList(String s, int o) { + this.yaml.getIntegerList(s).add(o); + } + + /** + * Removes an Integer to a List of Integers. + * + * @param s Path to given Integer List. + * @param o Integer to remove to the Integer List. + */ + public void removeFromIntegerList(String s, int o) { + this.yaml.getIntegerList(s).remove(o); + } + + /** + * Looks for a Integer List at given Path. + * + * @param s Path to Integer List. + * @return Integer List at given Path. + */ + public java.util.List getIntegerList(String s) { + return this.yaml.getIntegerList(s); + } + + /** + * Creates a new String List at given Path. + * + * @param s Path to create String List at. + * @param list List to add. + */ + public void createNewStringList(String s, java.util.List list) { + this.yaml.set(s, list); + } + + /** + * Creates a new Integer List at given Path. + * + * @param s Path to create Integer List at. + * @param list List to add. + */ + public void createNewIntegerList(String s, java.util.List list) { + this.yaml.set(s, list); + } + + /** + * **Untested/Unstable** Attempts to remove a variable at the given Path. + * + * @param s Path to given variable needing removal. + */ + public void remove(String s) { + this.set(s, null); + } + + /** + * Returns true if the given Path has a value. + * + * @param s Path to value. + * @return True if the given Path has a value. + */ + public boolean contains(String s) { + return this.yaml.contains(s); + } + + /** + * Gets a double at the given Path. + * + * @param s Path to double. + * @return Double at given Path. + */ + public double getDouble(String s) { + return this.yaml.getDouble(s); + } + + /** + * Sets a Object to the given Path. + * + * @param s Path to variable being assigned. + * @param o Variable being assigned. + */ + public void set(String s, Object o) { + this.yaml.set(s, o); + } + + /** + * Increases an Integer by 1. + * + * @param s Path to Integer being incremented. + */ + public void increment(String s) { + this.yaml.set(s, this.getInteger(s) + 1); + } + + /** + * Decreases an Integer by 1. + * + * @param s Path to Integer being decremented. + */ + public void decrement(String s) { + this.yaml.set(s, this.getInteger(s) - 1); + } + + /** + * Increases an Integer by i. + * + * @param s Path to Integer being incremented. + */ + public void increment(String s, int i) { + this.yaml.set(s, this.getInteger(s) + i); + } + + /** + * Decreases an Integer by 1. + * + * @param s Path to Integer being decremented. + */ + public void decrement(String s, int i) { + this.yaml.set(s, this.getInteger(s) - i); + } + + + /** + * Gets Itemstack. + * + * @param s Path to Itemstack. + */ + public ItemStack getItemStack(String s) { + return this.yaml.getItemStack(s); + } + + /** + * Returns the YamlConfiguration's Options. + * + * @return YamlConfiguration's Options. + */ + public YamlConfigurationOptions options() { + return this.yaml.options(); + } +} \ No newline at end of file diff --git a/src/com/zeshanaslam/actionhealth/HealthCommand.java b/src/com/zeshanaslam/actionhealth/HealthCommand.java new file mode 100644 index 0000000..6ec7d09 --- /dev/null +++ b/src/com/zeshanaslam/actionhealth/HealthCommand.java @@ -0,0 +1,70 @@ +package com.zeshanaslam.actionhealth; + +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; + +public class HealthCommand implements CommandExecutor { + + private final Main plugin; + + public HealthCommand(Main plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length <= 0) { + sender.sendMessage(ChatColor.RED + "ActionHealth Commands:"); + sender.sendMessage(ChatColor.GRAY + "/ActionHealth reload"); + sender.sendMessage(ChatColor.GRAY + "/ActionHealth toggle"); + } else { + if (args[0].equalsIgnoreCase("reload")) { + if (!sender.hasPermission("ActionHealth.Reload")) { + return false; + } + + plugin.reloadConfig(); + plugin.settingsManager = new SettingsManager(plugin); + sender.sendMessage(ChatColor.RED + "ActionHealth " + ChatColor.GRAY + "has been reloaded!"); + return true; + } + + if (args[0].equalsIgnoreCase("toggle")) { + if (sender instanceof Player) { + Player player = (Player) sender; + + if (plugin.toggle.contains(player.getUniqueId())) { + plugin.toggle.remove(player.getUniqueId()); + + player.sendMessage(ChatColor.GRAY + "ActionHealth has been " + ChatColor.RED + "enabled" + ChatColor.GRAY + "."); + } else { + plugin.toggle.add(player.getUniqueId()); + + player.sendMessage(ChatColor.GRAY + "ActionHealth has been " + ChatColor.RED + "disabled" + ChatColor.GRAY + "."); + } + + if (plugin.settingsManager.rememberToggle) { + FileHandler fileHandler = new FileHandler("plugins/ActionHealth/players/" + player.getUniqueId() + ".yml"); + fileHandler.set("toggle", plugin.toggle.contains(player.getUniqueId())); + + fileHandler.save(); + } + } else { + sender.sendMessage("ActionHealth toggle can only run in-game."); + } + return true; + } + + sender.sendMessage(ChatColor.RED + "ActionHealth Commands:"); + sender.sendMessage(ChatColor.GRAY + "/ActionHealth reload"); + sender.sendMessage(ChatColor.GRAY + "/ActionHealth toggle"); + } + + return true; + } +} diff --git a/src/com/zeshanaslam/actionhealth/HealthListeners.java b/src/com/zeshanaslam/actionhealth/HealthListeners.java new file mode 100644 index 0000000..208c6dc --- /dev/null +++ b/src/com/zeshanaslam/actionhealth/HealthListeners.java @@ -0,0 +1,120 @@ +package com.zeshanaslam.actionhealth; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +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.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class HealthListeners implements Listener { + + private Main plugin; + + public HealthListeners(Main plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onDamage(EntityDamageByEntityEvent event) { + if (plugin.settingsManager.checkPvP && event.isCancelled()) { + return; + } + + if (plugin.healthUtil.isDisabled(event.getDamager().getLocation())) { + return; + } + + if (plugin.settingsManager.worlds.contains(event.getDamager().getWorld().getName())) { + return; + } + + if (plugin.settingsManager.usePerms && !event.getDamager().hasPermission("ActionHealth.Health")) { + return; + } + + + Entity damaged = event.getEntity(); + + if (event.getDamager() instanceof Projectile) { + Projectile projectile = (Projectile) event.getDamager(); + + if (projectile.getShooter() instanceof Player) { + Player player = (Player) projectile.getShooter(); + + // Check if the setting 'Show Player' is enabled + if (event.getEntity() instanceof Player) { + if (!plugin.settingsManager.showPlayers) { + return; + } + } + + if (!plugin.settingsManager.showMobs) { + return; + } + + if (plugin.toggle.contains(player.getUniqueId())) { + return; + } + + // Send health + LivingEntity livingEntity = (LivingEntity) damaged; + plugin.healthUtil.sendHealth(player, (LivingEntity) damaged, livingEntity.getHealth() - event.getFinalDamage()); + + } + } + + if (event.getDamager() instanceof Player) { + Player player = (Player) event.getDamager(); + + // Check if the setting 'Show Player' is enabled + if (event.getEntity() instanceof Player) { + if (!plugin.settingsManager.showPlayers) { + return; + } + + if (player.hasMetadata("NPC")) { + return; + } + } + + if (!plugin.settingsManager.showMobs) { + return; + } + + if (plugin.toggle.contains(player.getUniqueId())) { + return; + } + + // Send health + LivingEntity livingEntity = (LivingEntity) damaged; + plugin.healthUtil.sendHealth(player, (LivingEntity) damaged, livingEntity.getHealth() - event.getFinalDamage()); + } + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + if (plugin.settingsManager.rememberToggle) { + FileHandler fileHandler = new FileHandler("plugins/ActionHealth/players/" + player.getUniqueId() + ".yml"); + + if (fileHandler.getBoolean("toggle")) { + plugin.toggle.add(player.getUniqueId()); + } + } + } + + @EventHandler + public void onLeave(PlayerQuitEvent event) { + Player player = event.getPlayer(); + + if (plugin.toggle.contains(player.getUniqueId())) { + plugin.toggle.remove(player.getUniqueId()); + } + } +} diff --git a/src/com/zeshanaslam/actionhealth/HealthUtil.java b/src/com/zeshanaslam/actionhealth/HealthUtil.java index 123a4f5..23720ba 100644 --- a/src/com/zeshanaslam/actionhealth/HealthUtil.java +++ b/src/com/zeshanaslam/actionhealth/HealthUtil.java @@ -1,7 +1,12 @@ package com.zeshanaslam.actionhealth; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -14,11 +19,68 @@ public class HealthUtil { this.plugin = plugin; } - private void sendActionBar(Player player, String message) { - if (player.hasMetadata("NPC")) { - return; + public void sendHealth(Player player, LivingEntity entity, double health) { + String name; + double maxHealth = entity.getMaxHealth(); + + if (entity.getCustomName() == null) { + name = entity.getName(); + } else { + name = entity.getCustomName(); } + if (plugin.settingsManager.stripName) name = ChatColor.stripColor(name); + if (plugin.settingsManager.translate.containsKey(entity.getName())) + name = plugin.settingsManager.translate.get(entity.getName()); + + String output = plugin.settingsManager.healthMessage; + output = output.replace("{name}", name); + output = output.replace("{health}", String.valueOf(health)); + output = output.replace("{maxhealth}", String.valueOf(maxHealth)); + + if (output.contains("{usestyle}")) { + String style = ""; + int left = 10; + double heart = maxHealth / 10; + double tempHealth = health; + + if (maxHealth != health && health >= 0 && !entity.isDead()) { + for (int i = 0; i < 10; i++) { + if (tempHealth - heart > 0) { + tempHealth = tempHealth - heart; + + style = style + plugin.settingsManager.filledHeartIcon; + left--; + } + } + + if (tempHealth >= 0) { + style = style + plugin.settingsManager.halfHeartIcon; + left--; + } + } + + for (int i = 0; i < left; i++) { + style = style + plugin.settingsManager.emptyHeartIcon; + } + + output = output.replace("{usestyle}", style); + } + + if (plugin.settingsManager.delay) { + String finalOutput = output; + + new BukkitRunnable() { + public void run() { + sendActionBar(player, finalOutput); + } + }.runTaskLater(plugin, 1L); + } else { + sendActionBar(player, output); + } + } + + private void sendActionBar(Player player, String message) { message = ChatColor.translateAlternateColorCodes('&', message); try { @@ -51,4 +113,19 @@ public class HealthUtil { ex.printStackTrace(); } } + + public boolean isDisabled(Location location) { + if (plugin.worldGuardPlugin == null) { + return false; + } + + ApplicableRegionSet applicableRegions = plugin.worldGuardPlugin.getRegionManager(location.getWorld()).getApplicableRegions(location); + for (ProtectedRegion region : applicableRegions) { + if (plugin.settingsManager.regions.contains(region.getId())) { + return true; + } + } + + return false; + } } diff --git a/src/com/zeshanaslam/actionhealth/Main.java b/src/com/zeshanaslam/actionhealth/Main.java index 32700c8..9c9e978 100644 --- a/src/com/zeshanaslam/actionhealth/Main.java +++ b/src/com/zeshanaslam/actionhealth/Main.java @@ -1,20 +1,46 @@ package com.zeshanaslam.actionhealth; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + public class Main extends JavaPlugin { public SettingsManager settingsManager; + public WorldGuardPlugin worldGuardPlugin; + public HealthUtil healthUtil; + + public List toggle = new ArrayList<>(); @Override - public void onEnable() - { + public void onEnable() { saveDefaultConfig(); + // Register health util + this.healthUtil = new HealthUtil(this); + // Load config settings settingsManager = new SettingsManager(this); + // Create player folder + File file = new File("plugins/ActionHealth/players/"); + file.mkdirs(); + // Register listeners + getServer().getPluginManager().registerEvents(new HealthListeners(this), this); + + + // Register command + getCommand("Actionhealth").setExecutor(new HealthCommand(this)); + + if (Bukkit.getServer().getPluginManager().isPluginEnabled("WorldGuard")) { + this.worldGuardPlugin = ((WorldGuardPlugin) getServer().getPluginManager().getPlugin("WorldGuard")); + } } @Override diff --git a/src/com/zeshanaslam/actionhealth/SettingsManager.java b/src/com/zeshanaslam/actionhealth/SettingsManager.java index af4f36b..0261fe5 100644 --- a/src/com/zeshanaslam/actionhealth/SettingsManager.java +++ b/src/com/zeshanaslam/actionhealth/SettingsManager.java @@ -5,6 +5,7 @@ import org.bukkit.Bukkit; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.UUID; public class SettingsManager { @@ -16,11 +17,13 @@ public class SettingsManager { public boolean checkPvP; public boolean limitHealth; public boolean stripName; + public boolean rememberToggle; public String filledHeartIcon; public String halfHeartIcon; public String emptyHeartIcon; public List worlds = new ArrayList<>(); public HashMap translate = new HashMap<>(); + public List regions = new ArrayList<>(); public String mcVersion; public boolean useOldMethods; @@ -38,13 +41,15 @@ public class SettingsManager { halfHeartIcon = plugin.getConfig().getString("Half Health Icon"); emptyHeartIcon = plugin.getConfig().getString("Empty Health Icon"); if (plugin.getConfig().getBoolean("Name Change")) { - for (String s : plugin.getConfig().getStringList("Name")) - { + for (String s : plugin.getConfig().getStringList("Name")) { String[] split = s.split(" = "); translate.put(split[0], split[1]); } } + // Load disabled regions + regions = plugin.getConfig().getStringList("Disabled regions"); + worlds = plugin.getConfig().getStringList("Disabled worlds"); // Check if using protocol build @@ -52,5 +57,11 @@ public class SettingsManager { mcVersion = mcVersion.substring(mcVersion.lastIndexOf(".") + 1); useOldMethods = mcVersion.equalsIgnoreCase("v1_8_R1") || mcVersion.equalsIgnoreCase("v1_7_"); + + if (plugin.getConfig().contains("Remember Toggle")) { + rememberToggle = plugin.getConfig().getBoolean("Remember Toggle"); + } else { + rememberToggle = false; + } } }