From 60592fd01111e75335245835e2518f900e8d35d1 Mon Sep 17 00:00:00 2001 From: gennyble Date: Wed, 8 Nov 2023 21:36:31 -0600 Subject: fix --- src/main/java/dev/nyble/sunfright/Damager.java | 172 +++++++++++++++++++++ src/main/java/dev/nyble/sunfright/Sunfright.java | 60 +++++++ .../dev/nyble/sunfright/events/HelmetHandler.java | 61 ++++++++ 3 files changed, 293 insertions(+) create mode 100644 src/main/java/dev/nyble/sunfright/Damager.java create mode 100644 src/main/java/dev/nyble/sunfright/Sunfright.java create mode 100644 src/main/java/dev/nyble/sunfright/events/HelmetHandler.java (limited to 'src/main/java/dev/nyble') diff --git a/src/main/java/dev/nyble/sunfright/Damager.java b/src/main/java/dev/nyble/sunfright/Damager.java new file mode 100644 index 0000000..890bb98 --- /dev/null +++ b/src/main/java/dev/nyble/sunfright/Damager.java @@ -0,0 +1,172 @@ +package dev.nyble.sunfright; + +import java.util.Collection; +import java.util.Random; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.scheduler.BukkitRunnable; + +public class Damager extends BukkitRunnable { + private final Sunfright sf; + private final Random rand; + + public Damager(Sunfright sf) { + this.sf = sf; + this.rand = new Random(); + } + + public void run() { + if (!timeShouldDamage()) { + return; + } + + World sunnedWorld = sf.sunnedWorld; + Collection players = sunnedWorld.getPlayers(); + + players.forEach((player) -> { + Location loc = player.getLocation(); + int x = loc.getBlockX(); + int y = loc.getBlockY(); + int z = loc.getBlockZ(); + // Returns one lower than it should? + int highestY = sunnedWorld.getHighestBlockAt(loc).getLocation().getBlockY() + 1; + + for (int i = y; i < highestY; ++i) { + Block current = sunnedWorld.getBlockAt(x, i, z); + + if (!blockShouldDamage(current.getType())) { + /* + * player rulled to be safe. Remove their helmet if it's the one we gave, but + * only do so if the skylight is less than three. This will keep us from + * removing the starter helmet if they're just chopping down a tree + */ + if (player.getInventory().getHelmet() != null && + player.getLocation().getBlock().getLightFromSky() > 3 && + player.getInventory().getHelmet().getEnchantmentLevel(Enchantment.VANISHING_CURSE) == 2) { + player.getInventory().setHelmet(new ItemStack(Material.AIR)); + } + + return; + } + } + + new DoDamage(player, sf.damagaPerSecond).runTask(sf); + }); + } + + private boolean timeShouldDamage() { + World sunnedWorld = sf.sunnedWorld; + + long time = sunnedWorld.getTime(); + boolean storming = sunnedWorld.hasStorm(); + boolean thundering = sunnedWorld.isThundering(); + + // Times are pulled from Minecraft Gamepedia page on Light, specifically the + // internal light + // level section. https://minecraft.gamepedia.com/Light + // Times correspond to when the light level is over 8. + if (storming && !thundering) { + if (time >= 12734 && time <= 23266) { + return false; + } + } else if (storming && thundering) { + if (time >= 12300 && time <= 23700) { + return false; + } + } else if (time >= 13027 && time <= 22973) { + return false; + } + return true; + } + + /* + * Material.isTransparent() is buggy and awful and only gives true for some + * things. This function + * checks if a material lets light pass and should damage the player. + * I've never seen it give a false positive, only a false negative, so it is one + * of the first + * things we check. + */ + @SuppressWarnings("deprecation") + private boolean blockShouldDamage(Material mat) { + String key = mat.getKey().getKey().toLowerCase(); + + if (mat == Material.BLACK_STAINED_GLASS) { + return false; + } + + return mat.isTransparent() || key.indexOf("glass") != -1 || key.indexOf("leaves") != -1 + || key.indexOf("sign") != -1 || key.indexOf("trapdoor") != -1 || key.indexOf("fence") != -1 + || key.indexOf("bed") != -1 || mat == Material.ICE || mat == Material.HOPPER || mat == Material.COBWEB; + } + + private class DoDamage extends BukkitRunnable { + private final Player player; + private final int damage; + + public DoDamage(Player player, int damage) { + this.player = player; + this.damage = damage; + } + + public void run() { + ItemStack helmet = player.getInventory().getHelmet(); + + if (helmet != null) { + ItemMeta helmetMeta = helmet.getItemMeta(); + + if (helmetMeta instanceof Damageable) { + Damageable helmetDamageable = (Damageable) helmetMeta; + int helmetDamage = helmetDamageable.getDamage(); + int fireProtLevel = helmet.getEnchantmentLevel(Enchantment.PROTECTION_FIRE); + + if (fireProtLevel < 1) { + damagePlayer(); + return; + } + + if (helmetDamage + damage >= helmet.getType().getMaxDurability()) { + if (helmet.getEnchantmentLevel(Enchantment.VANISHING_CURSE) == 2) { + int bindLevel = helmet.getEnchantmentLevel(Enchantment.BINDING_CURSE); + + if (bindLevel < 5) { + helmetDamageable.setDamage(0); + helmet.setItemMeta((ItemMeta) helmetDamageable); + helmet.addUnsafeEnchantment(Enchantment.BINDING_CURSE, bindLevel + 1); + + return; + } + } + + player.getInventory().setHelmet(new ItemStack(Material.AIR)); + } else { + // Formula from https://minecraft.gamepedia.com/Unbreaking + // Origintal is 60 + (40 / (level+1)) but we subtract one from fireProtLevel + // so the +1 cancels + int chanceToDamage = 60 + (40 / (fireProtLevel)); + + if (rand.nextInt(99) + 1 <= chanceToDamage) { + int calculatedDamage = (int) Math.ceil(damage / 2); + helmetDamageable.setDamage(helmetDamage + calculatedDamage); + helmet.setItemMeta((ItemMeta) helmetDamageable); + } + } + } + } else { + damagePlayer(); + } + } + + private void damagePlayer() { + player.damage(damage); + } + } +} diff --git a/src/main/java/dev/nyble/sunfright/Sunfright.java b/src/main/java/dev/nyble/sunfright/Sunfright.java new file mode 100644 index 0000000..6661ab6 --- /dev/null +++ b/src/main/java/dev/nyble/sunfright/Sunfright.java @@ -0,0 +1,60 @@ +package dev.nyble.sunfright; + +import java.util.logging.Level; + +import org.bukkit.World; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import dev.nyble.sunfright.events.HelmetHandler; + +public class Sunfright extends JavaPlugin { + public World sunnedWorld; + public int damagaPerSecond; + public boolean respawnHelmetEnabled; + private BukkitTask damager; + + @Override + public void onEnable() { + if (!loadConfig()) { + getLogger().log(Level.SEVERE, "Could not load config file, aborting load. Plugin not active!"); + getPluginLoader().disablePlugin(this); + return; + } + + int time = 20; + damager = new Damager(this).runTaskTimerAsynchronously(this, time, time); + + this.getServer().getPluginManager().registerEvents(new HelmetHandler(this), this); + } + + @Override + public void onDisable() { + damager.cancel(); + } + + private boolean loadConfig() { + this.saveDefaultConfig(); + + String world = getConfig().getString("world"); + damagaPerSecond = getConfig().getInt("damagePerSecond"); + + sunnedWorld = getServer().getWorld(world); + if (sunnedWorld == null) { + getLogger().log(Level.SEVERE, "World '" + world + "' is not valid! Aborting loading config!"); + return false; + } + + if (damagaPerSecond == 0) { + getLogger().log(Level.WARNING, "damagePerSecond is 0. Was this intended?"); + } + + if (getConfig().isSet("enableRespawnHelmet")) { + respawnHelmetEnabled = getConfig().getBoolean("enableRespawnHelmet"); + } else { + getLogger().log(Level.WARNING, "enableRespawnHelmet was not set! Defaulting to true!"); + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/dev/nyble/sunfright/events/HelmetHandler.java b/src/main/java/dev/nyble/sunfright/events/HelmetHandler.java new file mode 100644 index 0000000..e744a33 --- /dev/null +++ b/src/main/java/dev/nyble/sunfright/events/HelmetHandler.java @@ -0,0 +1,61 @@ +package dev.nyble.sunfright.events; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; + +import dev.nyble.sunfright.Sunfright; + +public class HelmetHandler implements Listener { + private final Sunfright sf; + + public HelmetHandler(Sunfright sf) { + this.sf = sf; + } + + @EventHandler + public void onPlayerRespawn(PlayerRespawnEvent event) { + setRespawnHelmet(event.getPlayer()); + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + if (!player.hasPlayedBefore()) { + setRespawnHelmet(player); + } + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (event.getClickedInventory() instanceof PlayerInventory + && event.getCurrentItem().getEnchantmentLevel(Enchantment.VANISHING_CURSE) == 2) { + + event.setCancelled(true); + event.getView().setItem(event.getRawSlot(), new ItemStack(Material.AIR)); + } + } + + private void setRespawnHelmet(Player player) { + if (!sf.respawnHelmetEnabled || !player.getWorld().equals(sf.sunnedWorld)) { + return; + } + + PlayerInventory inv = player.getInventory(); + + ItemStack stack = new ItemStack(Material.LEATHER_HELMET); + stack.addUnsafeEnchantment(Enchantment.BINDING_CURSE, 1); + stack.addUnsafeEnchantment(Enchantment.VANISHING_CURSE, 2); + stack.addEnchantment(Enchantment.PROTECTION_FIRE, 1); + + inv.setHelmet(stack); + } +} -- cgit 1.4.1-3-g733a5