From 627b79325736ca450f4371c447538d75929c96bf Mon Sep 17 00:00:00 2001 From: Default Date: Tue, 29 Dec 2020 15:51:37 +0100 Subject: [PATCH] First Commit on 1.16.4 --- .gitignore | 113 +++++++++++ deploy.bat | 1 + deploy.sh | 1 + plugin.yml | 13 ++ .../com/benjocraeft/sharehealth/Commands.java | 133 +++++++++++++ .../benjocraeft/sharehealth/FileManager.java | 137 +++++++++++++ .../sharehealth/HealthManager.java | 74 +++++++ .../sharehealth/HealthRegenTask.java | 40 ++++ .../benjocraeft/sharehealth/Messenger.java | 110 +++++++++++ .../com/benjocraeft/sharehealth/Pair.java | 18 ++ .../sharehealth/PlayerListeners.java | 104 ++++++++++ .../benjocraeft/sharehealth/Sharehealth.java | 184 ++++++++++++++++++ .../benjocraeft/sharehealth/Statistics.java | 46 +++++ 13 files changed, 974 insertions(+) create mode 100644 .gitignore create mode 100644 deploy.bat create mode 100644 deploy.sh create mode 100644 plugin.yml create mode 100644 src/main/java/com/benjocraeft/sharehealth/Commands.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/FileManager.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/HealthManager.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/HealthRegenTask.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/Messenger.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/Pair.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/PlayerListeners.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/Sharehealth.java create mode 100644 src/main/java/com/benjocraeft/sharehealth/Statistics.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4788b4b --- /dev/null +++ b/.gitignore @@ -0,0 +1,113 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +target/ + +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next + +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +.flattened-pom.xml + +# Common working directory +run/ diff --git a/deploy.bat b/deploy.bat new file mode 100644 index 0000000..60eeadd --- /dev/null +++ b/deploy.bat @@ -0,0 +1 @@ +xcopy IntelliJ_IDEA\Sharehealth\target\Sharehealth.jar Minecraft_Servers\Server_1.16.4\plugins\ /Y \ No newline at end of file diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..a5b65b5 --- /dev/null +++ b/deploy.sh @@ -0,0 +1 @@ +cp IntelliJ_IDEA/Sharehealth_1.16.4/target/sharehealth-1.0-SNAPSHOT.jar Minecraft_Servers/Server_1.16.4/plugins/ diff --git a/plugin.yml b/plugin.yml new file mode 100644 index 0000000..16d6899 --- /dev/null +++ b/plugin.yml @@ -0,0 +1,13 @@ +name: Sharehealth +version: 1.0 +main: com.benjocraeft.sharehealth.Sharehealth +api-version: 1.16 +authors: [ BenjoCraeft ] +description: This plugin makes all players on the server share their health, if one dies, everybody dies. +website: https://mc.benjocraeft.com + +commands: + sharehealth: + usage: / + aliases: [sh] + description: Defined by ShareHealth plugin \ No newline at end of file diff --git a/src/main/java/com/benjocraeft/sharehealth/Commands.java b/src/main/java/com/benjocraeft/sharehealth/Commands.java new file mode 100644 index 0000000..ca48f2a --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/Commands.java @@ -0,0 +1,133 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.command.CommandExecutor; +import org.apache.commons.lang.math.NumberUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class Commands implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){ + + if (args.length != 0){ + if (args[0].equalsIgnoreCase("reset")){ + commandSetHealth(20, true); + } + else if (args[0].equalsIgnoreCase("set")){ + if (args.length > 1){ + if (NumberUtils.isNumber(args[1])){ + double num = NumberUtils.createDouble(args[1]); + commandSetHealth(num); + } else if (args[1].equalsIgnoreCase("max")){ + if (args.length > 2){ + if (NumberUtils.isNumber(args[2])){ + double num = NumberUtils.createDouble(args[2]); + commandSetMaxHealth(num); + } + } + } + } + } + else if (args[0].equalsIgnoreCase("get")){ + if (args.length > 1){ + if (args[1].equalsIgnoreCase("max")){ + if (args.length > 2){ + if (args[2].equalsIgnoreCase("raw")){ + commandGetMaxHealth(sender, true); + } + } else { + commandGetMaxHealth(sender, false); + } + } + } else { + commandGetHealth(sender); + } + + } + else if (args[0].equalsIgnoreCase("log")){ + if (args.length > 1){ + if (args[1].equalsIgnoreCase("off")){ + commandSetLogging(false); + } + if (args[1].equalsIgnoreCase("on")){ + commandSetLogging(true); + } + } + } + else if(args[0].equalsIgnoreCase("stats")){ + commandSendStats(); + } + else if (args[0].equalsIgnoreCase("help")){ + commandGetHelp(sender); + } else { + unknownCommand(sender); + } + } else { + commandGetHelp(sender); + } + + return true; + } + + private void commandSetMaxHealth(double health){ + + } + + private void commandSetHealth(double health, boolean reset){ + Sharehealth.Instance.getHealthManager().setHealth(health); + if (reset){ + Sharehealth.Instance.reset(); + } + } + + private void commandSetHealth(double health){ + commandSetHealth(health, false); + } + + private void commandGetHealth(CommandSender sender){ + sender.sendMessage("Current health: " + Sharehealth.Instance.getHealthManager().getHealthString()); + } + + private void commandGetMaxHealth(CommandSender sender, boolean raw){ + + } + + private void commandSetLogging(boolean log){ + Sharehealth.Instance.getMessenger().setLogging(log); + } + + private void commandSendStats(){ + StringBuilder stats = new StringBuilder("Statistics:\n"); + Sharehealth.Instance.getStatistics().getStatistics().forEach(((uuid, values) -> { + Player player = Bukkit.getPlayer(uuid); + if (player != null){ + String playerName = player.getDisplayName(); + String stat = ChatColor.AQUA + playerName + ChatColor.WHITE + + ": Damage caused: " + ChatColor.RED + String.format("%.2f", values.first) + ChatColor.WHITE + + " Healing done: " + ChatColor.GREEN + String.format("%.2f", values.second) + "\n"; + stats.append(stat); + } + })); + Bukkit.getOnlinePlayers().forEach((Player p) -> p.sendMessage(stats.toString())); + } + + private void commandGetHelp(CommandSender sender){ + String help = "Usage:\n" + + "get -> returns current globally shared health\n" + + "set [number] -> sets new globally shared health\n" + + "reset -> heals every player and resets 'isFailed' to false\n" + + "log [on/off] -> activates/deactivates player log messages about damage and healings" + + "stats -> sends everyone statistics for every player"; + sender.sendMessage(help); + } + + private void unknownCommand(CommandSender sender){ + String msg = "Unknown command, use help."; + sender.sendMessage(msg); + } + +} diff --git a/src/main/java/com/benjocraeft/sharehealth/FileManager.java b/src/main/java/com/benjocraeft/sharehealth/FileManager.java new file mode 100644 index 0000000..77d62f0 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/FileManager.java @@ -0,0 +1,137 @@ +package com.benjocraeft.sharehealth; + +import java.io.*; +import java.util.*; + +public class FileManager { + + final private File settingsFile; + final private File statisticsFile; + final private File statusFile; + + + public FileManager(){ + File pluginFolder = new File(System.getProperty("user.dir"), "plugins/sharehealth"); + String pluginPath = pluginFolder.getPath(); + + //Prepare storage folder + if (pluginFolder.mkdirs()){ + //TODO Log + } + + settingsFile = new File(pluginPath + "/settings.txt"); + statisticsFile = new File(pluginPath + "/statistics.txt"); + statusFile = new File(pluginPath + "/status.txt"); + try { + if (settingsFile.createNewFile()){ + //TODO Log + } + if (statisticsFile.createNewFile()){ + //TODO Log + } + if (statusFile.createNewFile()){ + //TODO Log + } + } catch(IOException e){ + e.printStackTrace(); + } + } + + public Map loadSettings(){ + return loadFromFile(settingsFile); + } + public Map> loadStatistics(){ + Map map = loadFromFile(statisticsFile); + + Map> statisticsMap = new HashMap<>(); + map.forEach((String s1, String s2) -> { + UUID uuid = UUID.fromString(s1); + + String[] split = s2.split(","); + Double damage = Double.parseDouble(split[0]); + Double healing = Double.parseDouble(split[1]); + Pair statistics = Pair.pair(damage, healing); + + statisticsMap.put(uuid, statistics); + }); + + return statisticsMap; + } + public Map loadStatus(){ + Map map = loadFromFile(statusFile); + Map statusMap = new HashMap<>(); + + map.putIfAbsent("health", "20"); + map.putIfAbsent("isFailed", "false"); + + statusMap.put("health", Double.parseDouble(map.get("health"))); + statusMap.put("isFailed", Boolean.parseBoolean(map.get("isFailed"))); + + return statusMap; + } + + public void saveStatistics(Map> statistics){ + Map map = new HashMap<>(); + + statistics.forEach((UUID uuid, Pair pair) -> { + String uuidString = uuid.toString(); + map.put(uuidString, Statistics.Rounded(pair.first) + "," + Statistics.Rounded(pair.second)); + }); + + saveToFile(statisticsFile, map); + } + + public void saveStatus(Map statusMap){ + saveToFile(statusFile, statusMap); + } + + private Map loadFromFile(File file) { + Map map = new HashMap<>(); + + try{ + DataInputStream input = new DataInputStream(new FileInputStream(file)); + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + + try{ + String line; + while((line = reader.readLine()) != null){ + String[] split = line.split("="); + map.put(split[0], split[1]); + } + } catch (NullPointerException ignore){} + + reader.close(); + input.close(); + } catch(IOException e){ + e.printStackTrace(); + } + + return map; + } + + private void saveToFile(File file, Map content){ + try{ + FileWriter stream = new FileWriter(file); + BufferedWriter out = new BufferedWriter(stream); + + content.forEach((String key, Object obj) -> { + try { + String value = obj.toString(); + if (obj instanceof Double){ + value = new Formatter(Locale.US).format("%.2f", obj).toString(); + } + out.write(key + "=" + value); + out.write("\n"); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + out.close(); + stream.close(); + } catch (IOException e){ + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/benjocraeft/sharehealth/HealthManager.java b/src/main/java/com/benjocraeft/sharehealth/HealthManager.java new file mode 100644 index 0000000..774b4a8 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/HealthManager.java @@ -0,0 +1,74 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; + +import java.util.Formatter; +import java.util.Locale; + +public class HealthManager { + + private double health = 20; + + double getHealth(){ + return health; + } + + void setHealth(double health){ + if (health > 20) + health = 20; + if (health < 0) + health = 0; + this.health = health; + } + + String getHealthString(){ + return new Formatter(Locale.US).format("%.2f", health).toString(); + } + + + public HealthManager() { + + } + public void updatePlayer(Player player){ + if (player.getGameMode().equals(GameMode.SURVIVAL)) + player.setHealth(health); + if (player.getGameMode().equals(GameMode.SPECTATOR)) + player.setHealth(20); + } + + private void subtractHealth(double sub){ + setHealth(health - sub); + } + + void addHealth(double add){ + setHealth(health + add); + } + + void reset(){ + health = 20; + Bukkit.getOnlinePlayers().forEach(p -> p.setHealth(health)); + } + + boolean onPlayerGotDamage(Player player, double damage){ + subtractHealth(damage); + setHealthByPlayer(player); + + return health > 0; + } + + void onPlayerRegainedHealth(Player player, double regainedHealth){ + addHealth(regainedHealth); + setHealthByPlayer(player); + } + + void setHealthByPlayer(Player player){ + for (Player p : Sharehealth.GetAlivePlayers()){ + if (p.equals(player)) + continue; + p.setHealth(health); + } + } + +} diff --git a/src/main/java/com/benjocraeft/sharehealth/HealthRegenTask.java b/src/main/java/com/benjocraeft/sharehealth/HealthRegenTask.java new file mode 100644 index 0000000..4da6b12 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/HealthRegenTask.java @@ -0,0 +1,40 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Objects; + +public class HealthRegenTask extends BukkitRunnable { + + final private HealthManager healthManager; + + + HealthRegenTask(HealthManager healthManager){ + this.healthManager = healthManager; + runTaskTimer(Sharehealth.Instance, 80, 80); + } + + @Override + public void run(){ + int allPlayersCount = Sharehealth.GetAlivePlayers().size(); + if (allPlayersCount == 0) + return; + + int allFoodPoints = 0; + for (Player p : Sharehealth.GetAlivePlayers()){ + allFoodPoints += p.getFoodLevel(); + } + + //According to MinecraftWiki, players automatically regen if their food level + // is greater than or equal to 18 of 20 (90%) + //Here, we look for the average food level + if (allFoodPoints / allPlayersCount >= 18 && this.healthManager.getHealth() != 0){ + this.healthManager.addHealth(1); + this.healthManager.setHealthByPlayer(null); + } + + } + +} diff --git a/src/main/java/com/benjocraeft/sharehealth/Messenger.java b/src/main/java/com/benjocraeft/sharehealth/Messenger.java new file mode 100644 index 0000000..c03f5a7 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/Messenger.java @@ -0,0 +1,110 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; + +import java.util.Objects; +import java.util.logging.Logger; + +public class Messenger { + + private boolean logging = true; + void setLogging(boolean logging){ + this.logging = logging; + } + + private Logger logger; + + Messenger(Logger logger){ + this.logger = logger; + } + + void onPlayerRegainedHealth(Player player, double amount, RegainReason reason){ + if (!logging || amount <= 0) + return; + String message = healMessage(player, amount, reason); + Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(message)); + } + + void sendFailedMessage(Player cause){ + Bukkit.getOnlinePlayers().forEach(p -> { + String message = "Mission failed, go next! CAUSE: " + ChatColor.RED + cause.getDisplayName(); + p.sendMessage(message); + }); + } + + void onPlayerGotDamageMessage(Player player, double damage, DamageCause cause){ + if (!logging) + return; + String message = damageMessage(player, damage, cause); + Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(message)); + } + + void onPlayerGotDamageMessage(Player player, double damage, Entity damager){ + if (!logging) + return; + String message = damageMessage(player, damage, damager); + Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(message)); + } + + void onPlayerGotDamageMessage(Player player, double damage, Block damager){ + if (!logging) + return; + String message = damageMessage(player, damage, damager); + Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(message)); + } + + private String damageMessage(Player player, double damage){ + String playerS = player.getDisplayName(); + String damageS = String.format("%.2f", damage / 2); + return ChatColor.AQUA + playerS + + ChatColor.WHITE + " shared " + + ChatColor.RED + damageS + + ChatColor.WHITE + " hearts damage!"; + } + + private String damageMessage(Player player, double damage, DamageCause cause){ + return damageMessage(player, damage) + ChatColor.YELLOW + " Cause: " + cause; + } + + private String damageMessage(Player player, double damage, Entity damager){ + String name = damager.getName(); + if (damager instanceof Projectile){ + name = Objects.requireNonNull(((Projectile) damager).getShooter()).toString(); + } + return damageMessage(player, damage) + ChatColor.YELLOW + " Attacker: " + name; + } + + private String damageMessage(Player player, double damage, Block damager){ + String name; + try{ + name = damager.getType().name(); + } catch(NullPointerException e){ + name = "Unknown"; + e.printStackTrace(); + logger.info("Unknown error. Proceeding"); + } + return damageMessage(player, damage) + ChatColor.YELLOW + " Block: " + name; + } + + private String healMessage(Player player, double regainedHealth, RegainReason reason){ + String playerS = player.getDisplayName(); + String healingS = Double.toString(regainedHealth / 2); + String causeS = reason.toString(); + return ChatColor.AQUA + playerS + + ChatColor.WHITE + " shared " + + ChatColor.GREEN + healingS + + ChatColor.WHITE + " hearts healing!" + + ChatColor.YELLOW + " Cause: " + causeS; + } + +} diff --git a/src/main/java/com/benjocraeft/sharehealth/Pair.java b/src/main/java/com/benjocraeft/sharehealth/Pair.java new file mode 100644 index 0000000..0f3a9a0 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/Pair.java @@ -0,0 +1,18 @@ +package com.benjocraeft.sharehealth; + + +public class Pair { + + + public F first; + public S second; + + public Pair(F first, S second){ + this.first = first; + this.second = second; + } + + public static Pair pair(F first, S second){ + return new Pair<>(first, second); + } +} diff --git a/src/main/java/com/benjocraeft/sharehealth/PlayerListeners.java b/src/main/java/com/benjocraeft/sharehealth/PlayerListeners.java new file mode 100644 index 0000000..1e98069 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/PlayerListeners.java @@ -0,0 +1,104 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.*; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + + +public class PlayerListeners implements Listener{ + + @EventHandler + public void onJoin(PlayerJoinEvent e){ + Sharehealth.Instance.onPlayerJoin(e.getPlayer()); + } + + @EventHandler + public void onPlayerRespawn(final PlayerRespawnEvent event){ + Sharehealth.Instance.onPlayerRespawn(event.getPlayer()); + } + + @EventHandler + public void onEntityGotDamage(final EntityDamageEvent event){ + Entity entity = event.getEntity(); + double damage = event.getFinalDamage(); + DamageCause cause = event.getCause(); + + DamageCause[] notAllowed = new DamageCause[]{ + DamageCause.ENTITY_ATTACK, + DamageCause.ENTITY_EXPLOSION, + DamageCause.PROJECTILE, + DamageCause.CONTACT + }; + + if (entity instanceof Player){ + boolean allowed = true; + for (DamageCause damageCause : notAllowed) { + if (cause.equals(damageCause)){ + allowed = false; + break; + } + } + Sharehealth.Instance.onPlayerGotDamage((Player) entity, damage, cause, allowed); + } + } + + @EventHandler + public void onEntityGotDamageByEntity(final EntityDamageByEntityEvent event){ + Entity entity = event.getEntity(); + double damage = event.getFinalDamage(); + Entity cause = event.getDamager(); + + if (entity instanceof Player) { + Sharehealth.Instance.onPlayerGotDamageByEntity((Player)entity, damage, cause); + } + } + + @EventHandler + public void onEntityGotDamageByBlock(final EntityDamageByBlockEvent event){ + Entity entity = event.getEntity(); + double damage = event.getFinalDamage(); + Block cause = event.getDamager(); + + if (entity instanceof Player) { + Sharehealth.Instance.onPlayerGotDamageByBlock((Player)entity, damage, cause); + } + } + + @EventHandler + public void onEntityRegainedHealth(final EntityRegainHealthEvent event){ + Entity entity = event.getEntity(); + double amount = event.getAmount(); + RegainReason reason = event.getRegainReason(); + + if (entity instanceof Player){ + Player player = (Player) entity; + if (!Sharehealth.Instance.onPlayerRegainedHealth(player, amount, reason)){ + event.setCancelled(true); + } + } + } + + @EventHandler + public void onEntityPotionEffectModified(final EntityPotionEffectEvent event){ + Entity entity = event.getEntity(); + if (entity instanceof Player){ + PotionEffect newEffect = event.getNewEffect(); + if (newEffect != null){ + if (newEffect.getType().equals(PotionEffectType.ABSORPTION)){ + event.setCancelled(true); + int level = newEffect.getAmplifier(); + Sharehealth.Instance.onAbsorptionPrevented(level); + } + } + } + } +} diff --git a/src/main/java/com/benjocraeft/sharehealth/Sharehealth.java b/src/main/java/com/benjocraeft/sharehealth/Sharehealth.java new file mode 100644 index 0000000..a22ae22 --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/Sharehealth.java @@ -0,0 +1,184 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.entity.*; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.*; + +public class Sharehealth extends JavaPlugin { + + static Sharehealth Instance; + + private FileManager fileManager; + public FileManager getFileManager(){ + return fileManager; + } + + private HealthManager healthManager; + public HealthManager getHealthManager(){ + return healthManager; + } + + private Messenger messenger; + public Messenger getMessenger(){ + return messenger; + } + + private Statistics statistics; + public Statistics getStatistics(){ + return statistics; + } + + boolean isFailed = false; + + @Override + public void onEnable(){ + + //Singleton setup + Instance = this; + + //Create File Manager for saving stats and settings + fileManager = new FileManager(); + + //Starting Health Manager for controlling actual health + healthManager = new HealthManager(); + + //Messenger + messenger = new Messenger(getLogger()); + + //Create statistics from file + statistics = new Statistics(fileManager.loadStatistics()); + + loadStatus(); + + //Starts custom health regeneration + new HealthRegenTask(healthManager); + + //Register Events and Commands + Bukkit.getPluginManager().registerEvents(new PlayerListeners(), this); + Objects.requireNonNull(getCommand("sharehealth")).setExecutor(new Commands()); + + //Ready to go + getLogger().info("ShareHealth has been enabled!"); + } + + @Override + public void onDisable() { + getLogger().info("ShareHealth has been disabled!"); + } + + void onPlayerJoin(Player player){ + updateGameMode(player); + + healthManager.updatePlayer(player); + statistics.onPlayerJoined(player); + fileManager.saveStatistics(statistics.getStatistics()); + } + + void onPlayerRespawn(Player player){ + updateGameMode(player); + + healthManager.updatePlayer(player); + } + + void onPlayerGotDamage(Player player, double damage, DamageCause cause, boolean allowed){ + if (isFailed) + return; + + if (allowed) + messenger.onPlayerGotDamageMessage(player, damage, cause); + + statistics.onPlayerGotDamage(player, damage); + if (!healthManager.onPlayerGotDamage(player, damage)){ + failed(player); + } + + saveStatus(); + } + void onPlayerGotDamageByEntity(Player player, double damage, Entity cause){ + if (isFailed) + return; + + messenger.onPlayerGotDamageMessage(player, damage, cause); + } + void onPlayerGotDamageByBlock(Player player, double damage, Block cause){ + if (isFailed) + return; + + messenger.onPlayerGotDamageMessage(player, damage, cause); + } + + boolean onPlayerRegainedHealth(Player player, double amount, RegainReason reason){ + if (isFailed) + return true; + + if (reason.equals(RegainReason.REGEN) || reason.equals(RegainReason.SATIATED)){ + return false; + } + + messenger.onPlayerRegainedHealth(player, amount, reason); + statistics.onPlayerRegainedHealth(player, amount); + healthManager.onPlayerRegainedHealth(player, amount); + + saveStatus(); + + return true; + } + + void onAbsorptionPrevented(int level){ + getLogger().info("Add " + level * 2 + "hearts!"); + } + + private void failed(Player cause){ + if (isFailed) + return; + isFailed = true; + messenger.sendFailedMessage(cause); + Bukkit.getOnlinePlayers().forEach(p -> p.setGameMode(GameMode.SPECTATOR)); + + saveStatus(); + } + + void reset(){ + isFailed = false; + healthManager.reset(); + Bukkit.getOnlinePlayers().forEach(p -> p.setGameMode(GameMode.SURVIVAL)); + + saveStatus(); + } + + private void updateGameMode(Player player){ + if (!isFailed){ + player.setGameMode(GameMode.SURVIVAL); + } else { + player.setGameMode(GameMode.SPECTATOR); + } + } + + static List GetAlivePlayers(){ + List list = new ArrayList<>(Bukkit.getOnlinePlayers()); + list.removeIf(Entity::isDead); + return list; + } + + void saveStatus(){ + Map map = new HashMap<>(); + + map.put("health", healthManager.getHealth()); + map.put("isFailed", isFailed); + + fileManager.saveStatus(map); + } + + private void loadStatus(){ + Map map = fileManager.loadStatus(); + + healthManager.setHealth((Double)map.get("health")); + isFailed = (boolean) map.get("isFailed"); + } + +} diff --git a/src/main/java/com/benjocraeft/sharehealth/Statistics.java b/src/main/java/com/benjocraeft/sharehealth/Statistics.java new file mode 100644 index 0000000..b875cbd --- /dev/null +++ b/src/main/java/com/benjocraeft/sharehealth/Statistics.java @@ -0,0 +1,46 @@ +package com.benjocraeft.sharehealth; + +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class Statistics { + + final private Map> statistics = new HashMap<>(); + public Map> getStatistics(){ + return statistics; + } + + public static Double Rounded(Double value, int afterComma){ + return Math.round(value * Math.pow(10, afterComma)) / Math.pow(10, afterComma); + } + public static Double Rounded(Double value){ + return Rounded(value, 2); + } + + public Statistics(Map> statistics){ + getStatistics().putAll(statistics); + } + + public void onPlayerJoined(Player player){ + UUID uuid = player.getUniqueId(); + Pair empty = Pair.pair(0., 0.); + statistics.putIfAbsent(uuid, empty); + } + + void onPlayerRegainedHealth(Player player, double amount){ + UUID uuid = player.getUniqueId(); + Pair oldPair = statistics.get(uuid); + statistics.put(uuid, Pair.pair(oldPair.first, oldPair.second + amount)); + } + + void onPlayerGotDamage(Player player, double amount){ + UUID uuid = player.getUniqueId(); + Pair oldPair = statistics.get(uuid); + statistics.put(uuid, Pair.pair(oldPair.first + amount, oldPair.second)); + } + +}