From fb0d179d370b082c5cf3b263acf63c8d16237feb Mon Sep 17 00:00:00 2001 From: hyperdefined Date: Thu, 29 Aug 2024 00:10:01 -0400 Subject: [PATCH] add flight time (#62) --- .../java/lol/hyper/toolstats/ToolStats.java | 7 ++ .../toolstats/commands/CommandToolStats.java | 36 ++++--- .../hyper/toolstats/events/PlayerMove.java | 100 ++++++++++++++++++ .../hyper/toolstats/tools/ItemChecker.java | 1 + .../toolstats/tools/config/ConfigTools.java | 3 + src/main/resources/config.yml | 2 + 6 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 src/main/java/lol/hyper/toolstats/events/PlayerMove.java diff --git a/src/main/java/lol/hyper/toolstats/ToolStats.java b/src/main/java/lol/hyper/toolstats/ToolStats.java index f37e1ac..e0817cc 100644 --- a/src/main/java/lol/hyper/toolstats/ToolStats.java +++ b/src/main/java/lol/hyper/toolstats/ToolStats.java @@ -97,6 +97,10 @@ public final class ToolStats extends JavaPlugin { * Key for arrows shot. */ public final NamespacedKey arrowsShot = new NamespacedKey(this, "arrows-shot"); + /** + * Key for tracking flight time. + */ + public final NamespacedKey flightTime = new NamespacedKey(this, "flightTime"); /** * Stores how an item was created. * 0 = crafted. @@ -134,6 +138,7 @@ public final class ToolStats extends JavaPlugin { public MorePaperLib morePaperLib; public HashMaker hashMaker; public CreativeEvent creativeEvent; + public PlayerMove playerMove; public ItemChecker itemChecker; public ShootBow shootBow; public ConfigTools configTools; @@ -164,6 +169,7 @@ public final class ToolStats extends JavaPlugin { inventoryOpen = new InventoryOpen(this); playerJoin = new PlayerJoin(this); creativeEvent = new CreativeEvent(this); + playerMove = new PlayerMove(this); itemChecker = new ItemChecker(); shootBow = new ShootBow(this); configTools = new ConfigTools(this); @@ -183,6 +189,7 @@ public final class ToolStats extends JavaPlugin { Bukkit.getServer().getPluginManager().registerEvents(playerJoin, this); Bukkit.getServer().getPluginManager().registerEvents(creativeEvent, this); Bukkit.getServer().getPluginManager().registerEvents(shootBow, this); + Bukkit.getServer().getPluginManager().registerEvents(playerMove, this); this.getCommand("toolstats").setExecutor(commandToolStats); diff --git a/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java b/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java index fa4f2d4..e0eb957 100644 --- a/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java +++ b/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java @@ -144,20 +144,30 @@ public class CommandToolStats implements TabExecutor { // hard code elytras if (finalItem.getType() == Material.ELYTRA) { - if (toolStats.config.getBoolean("enabled.elytra-tag")) { - lore.add(toolStats.configTools.getLoreFromConfig("looted.found-by", true).replace("{player}", player.getName())); - if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) { - Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG); - if (time != null) { - lore.add(toolStats.configTools.getLoreFromConfig("looted.found-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time)))); - } - } - finalMeta.setLore(lore); - finalItem.setItemMeta(finalMeta); - int slot = player.getInventory().getHeldItemSlot(); - player.getInventory().setItem(slot, finalItem); - return; + Long flightTime = null; + Long timeCreated = null; + if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) { + timeCreated = container.get(toolStats.timeCreated, PersistentDataType.LONG); } + if (container.has(toolStats.flightTime, PersistentDataType.LONG)) { + flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG); + } + + if (flightTime != null) { + if (toolStats.config.getBoolean("enabled.flight-time")) { + lore.add(toolStats.configTools.getLoreFromConfig("flight-time", true).replace("{time}", toolStats.numberFormat.formatDouble((double) flightTime / 1000))); + } + } + + if (timeCreated != null) { + lore.add(toolStats.configTools.getLoreFromConfig("looted.found-by", true).replace("{player}", player.getName())); + lore.add(toolStats.configTools.getLoreFromConfig("looted.found-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(timeCreated)))); + } + + finalMeta.setLore(lore); + finalItem.setItemMeta(finalMeta); + int slot = player.getInventory().getHeldItemSlot(); + player.getInventory().setItem(slot, finalItem); } if (toolStats.configTools.checkConfig(original.getType(), "created-by")) { diff --git a/src/main/java/lol/hyper/toolstats/events/PlayerMove.java b/src/main/java/lol/hyper/toolstats/events/PlayerMove.java new file mode 100644 index 0000000..ddd1503 --- /dev/null +++ b/src/main/java/lol/hyper/toolstats/events/PlayerMove.java @@ -0,0 +1,100 @@ +/* + * This file is part of ToolStats. + * + * ToolStats is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ToolStats is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ToolStats. If not, see . + */ + +package lol.hyper.toolstats.events; + +import lol.hyper.toolstats.ToolStats; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PlayerMove implements Listener { + + private final ToolStats toolStats; + private final Map playerStartFlight = new HashMap<>(); + + public PlayerMove(ToolStats toolStats) { + this.toolStats = toolStats; + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onCraft(PlayerMoveEvent event) { + Player player = event.getPlayer(); + // player starts to fly + if (player.isGliding()) { + // if they are flying, and we don't have them tracked, add them + if (!playerStartFlight.containsKey(player)) { + playerStartFlight.put(player, System.currentTimeMillis()); + } + } else { + // player is not flying + if (playerStartFlight.containsKey(player)) { + trackFlight(player, playerStartFlight.get(player)); + playerStartFlight.remove(player); + } + } + } + + private void trackFlight(Player player, long startTime) { + ItemStack chest = player.getInventory().getChestplate(); + // make sure their chest piece is an elytra + if (chest == null || chest.getType() != Material.ELYTRA) { + return; + } + ItemMeta meta = chest.getItemMeta(); + if (meta == null) { + toolStats.logger.warning(chest + " does NOT have any meta! Unable to update stats."); + return; + } + + // read the current stats from the item + // if they don't exist, then start from 0 + Long flightTime = 0L; + PersistentDataContainer container = meta.getPersistentDataContainer(); + if (container.has(toolStats.flightTime, PersistentDataType.LONG)) { + flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG); + } + + if (flightTime == null) { + flightTime = 0L; + toolStats.logger.warning(flightTime + " does not have valid flight-time set! Resting to zero. This should NEVER happen."); + } + + // get the duration of the flight + flightTime = (System.currentTimeMillis() - startTime) + flightTime; + container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime); + + // do we add the lore based on the config? + if (toolStats.config.getBoolean("enabled.flight-time")) { + String flightTimeFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000); + List newLore = toolStats.itemLore.addItemLore(meta, "{time}", flightTimeFormatted, "flight-time"); + meta.setLore(newLore); + } + chest.setItemMeta(meta); + } +} diff --git a/src/main/java/lol/hyper/toolstats/tools/ItemChecker.java b/src/main/java/lol/hyper/toolstats/tools/ItemChecker.java index 2238b4f..28c6dab 100644 --- a/src/main/java/lol/hyper/toolstats/tools/ItemChecker.java +++ b/src/main/java/lol/hyper/toolstats/tools/ItemChecker.java @@ -55,6 +55,7 @@ public class ItemChecker { validItems.add(Material.BOW); validItems.add(Material.FISHING_ROD); validItems.add(Material.CROSSBOW); + validItems.add(Material.ELYTRA); // combine the lists validItems.addAll(armorItems); diff --git a/src/main/java/lol/hyper/toolstats/tools/config/ConfigTools.java b/src/main/java/lol/hyper/toolstats/tools/config/ConfigTools.java index fb696a3..6a43447 100644 --- a/src/main/java/lol/hyper/toolstats/tools/config/ConfigTools.java +++ b/src/main/java/lol/hyper/toolstats/tools/config/ConfigTools.java @@ -171,6 +171,9 @@ public class ConfigTools { if (lore.contains("{arrows}")) { lore = lore.replace("{arrows}", ""); } + if (lore.contains("{time}")) { + lore = lore.replace("{time}", ""); + } } return lore; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index dccabbf..af5abb7 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -81,6 +81,7 @@ enabled: dropped-by: true elytra-tag: true arrows-shot: true + flight-time: true messages: created: @@ -110,6 +111,7 @@ messages: dropped-by: "&7Dropped by: &8{name}" # name will be player/mob name damage-taken: "&7Damage taken: &8{damage}" arrows-shot: "&7Arrows shot: &8{arrows}" + flight-time: "&7Flight time: &8{time}" # Display this message if the player shift click trades/crafts items. It's not really easy to get every single item # that is crafted. The tag will only be added to the first item. If you don't want this message, simply replace them both with "" shift-click-warning: