diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 9f28f09..f9b53ba 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,12 @@ - + + + + + + + - \ No newline at end of file diff --git a/src/me/Percyqaz/Lodestone/CompassListener.java b/src/me/Percyqaz/Lodestone/CompassListener.java index aec86d1..ee67939 100644 --- a/src/me/Percyqaz/Lodestone/CompassListener.java +++ b/src/me/Percyqaz/Lodestone/CompassListener.java @@ -1,6 +1,7 @@ package me.Percyqaz.Lodestone; import org.bukkit.*; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -11,22 +12,125 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.CompassMeta; -public class CompassListener implements Listener { +import java.util.HashMap; +import java.util.Map; - @EventHandler(priority = EventPriority.LOWEST) - public void Compass(PlayerInteractEvent e) { - Player p = e.getPlayer(); - ItemStack item = p.getInventory().getItemInMainHand(); - if (e.getHand() == EquipmentSlot.HAND && item.getType() == Material.COMPASS && e.getAction() == Action.RIGHT_CLICK_AIR) { - CompassMeta itemMeta = (CompassMeta)item.getItemMeta(); +public class CompassListener implements Listener +{ + Lodestone plugin; + FileConfiguration config; + long cooldownTimeMillis; + long warmupTimeTicks; + Map cooldowns = new HashMap<>(); + + public CompassListener(Lodestone plugin, FileConfiguration config) + { + this.config = config; + this.plugin = plugin; + + cooldownTimeMillis = (long)(config.getInt("cooldownSeconds")) * 1000L; + warmupTimeTicks = (long)(config.getInt("warmupSeconds")) * 20L; + + // Cooldown must always be at least as long as warmup + cooldownTimeMillis = Math.max(cooldownTimeMillis, warmupTimeTicks * 50L); + } + + void resetPlayerCooldown(String name) + { + long now = System.currentTimeMillis(); + cooldowns.put(name, now - cooldownTimeMillis); + } + + /// Returns 0 if no cooldown, else a positive number of seconds cooldown + int checkPlayerCooldown(String name) + { + long now = System.currentTimeMillis(); + if (cooldowns.containsKey(name)) + { + if (cooldowns.get(name) + cooldownTimeMillis < now) + { + cooldowns.put(name, now); + return 0; + } + return (int)((cooldowns.get(name) + cooldownTimeMillis - now) / 1000L) + 1; + } + cooldowns.put(name, now); + return 0; + } + + void PerformTeleport(Player player, Location oldLoc) + { + // Need to check player hasn't moved, is still holding a teleport compass + if (player.getLocation().distanceSquared(oldLoc) > 0 && !player.isDead()) + { + player.sendMessage(config.getString("teleportFailedMovedBeforeTeleport")); + resetPlayerCooldown(player.getName()); + return; + } + + ItemStack item = player.getInventory().getItemInMainHand(); + + if (item.getType() == Material.COMPASS) { + CompassMeta itemMeta = (CompassMeta) item.getItemMeta(); if (itemMeta.hasLodestone() && itemMeta.isLodestoneTracked()) { - String teleportMessage = itemMeta.hasDisplayName() ? " Teleported to " + ChatColor.GREEN + itemMeta.getDisplayName() : ""; - p.sendMessage(ChatColor.BLUE + "Whoosh!" + teleportMessage); + + String teleportMessage = + itemMeta.hasDisplayName() + ? config.getString("teleportSucceededNamedLocation").replace("%location%", itemMeta.getDisplayName()) + : config.getString("teleportSucceeded"); + player.sendMessage(teleportMessage); + player.spawnParticle(Particle.CLOUD, oldLoc.add(0.0f, 1.0f, 0.0f), 50); + Location pos = itemMeta.getLodestone(); - p.teleport(pos.add(0.5, 1.5, 0.5)); + player.teleport(pos.add(0.5, 1.5, 0.5)); item.setAmount(item.getAmount() - 1); - e.setCancelled(true); + + player.spawnParticle(Particle.CLOUD, player.getLocation().add(0.0f, 1.0f, 0.0f), 50); + return; + } + } + + player.sendMessage(config.getString("teleportFailedCompassNotInHand")); + resetPlayerCooldown(player.getName()); + } + + /// Returns true if a teleport went through and false otherwise + Boolean handlePlayerClickCompass(Player player, ItemStack item) + { + // Assert: Player's main hand is a compass, they have just right clicked air with it + // Assert: Item passed in is the main-hand compass + + CompassMeta itemMeta = (CompassMeta)item.getItemMeta(); + if (itemMeta.hasLodestone() && itemMeta.isLodestoneTracked()) + { + int cooldown = checkPlayerCooldown(player.getName()); + if (cooldown > 0) + { + player.sendMessage(config.getString("teleportFailedWaitForCooldown").replace("%cooldown%", String.valueOf(cooldown))); + return false; } + + // Success: Player has right clicked with a valid lodestone compass + Location oldLoc = player.getLocation(); + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask( + plugin, + () -> PerformTeleport(player, oldLoc), + warmupTimeTicks + ); + player.spawnParticle(Particle.ENCHANTMENT_TABLE, oldLoc.add(0.0f, 1.0f, 0.0f), 50); + return true; + } + return false; + } + + @EventHandler(priority = EventPriority.LOWEST) + public void Compass(PlayerInteractEvent e) + { + Player p = e.getPlayer(); + ItemStack item = p.getInventory().getItemInMainHand(); + if (e.getHand() == EquipmentSlot.HAND && item.getType() == Material.COMPASS && e.getAction() == Action.RIGHT_CLICK_AIR) + { + if (handlePlayerClickCompass(p, item)) e.setCancelled(true); } } } diff --git a/src/me/Percyqaz/Lodestone/Lodestone.java b/src/me/Percyqaz/Lodestone/Lodestone.java index ba9b971..eb5a9e2 100644 --- a/src/me/Percyqaz/Lodestone/Lodestone.java +++ b/src/me/Percyqaz/Lodestone/Lodestone.java @@ -1,11 +1,26 @@ package me.Percyqaz.Lodestone; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.java.JavaPlugin; public class Lodestone extends JavaPlugin { + + FileConfiguration config = getConfig(); + @Override public void onEnable() { + config.addDefault("cooldownSeconds", 60); + config.addDefault("warmupSeconds", 2); + config.addDefault("teleportFailedWaitForCooldown", "§4You cannot teleport for another %cooldown% seconds!"); + config.addDefault("teleportFailedMovedBeforeTeleport", "§4Teleport cancelled because you moved!"); + config.addDefault("teleportFailedCompassNotInHand", "§4Teleport cancelled because the compass is no longer in your hand!"); + config.addDefault("teleportSucceeded", "§9Whoosh!"); + config.addDefault("teleportSucceededNamedLocation", "§9Whoosh! Teleported to §a%location%"); + + config.options().copyDefaults(true); + saveConfig(); + this.getLogger().info("Listening to right clicks"); - getServer().getPluginManager().registerEvents(new CompassListener(), this); + getServer().getPluginManager().registerEvents(new CompassListener(this, config), this); } } diff --git a/src/plugin.yml b/src/plugin.yml index 07ab986..e146041 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,5 +1,5 @@ name: Lodestone -version: 1.0 +version: 2.0 author: Percyqaz main: me.Percyqaz.Lodestone.Lodestone -api-version: 1.16 \ No newline at end of file +api-version: 1.18 \ No newline at end of file