added base files (NOT DONE)

This commit is contained in:
hyperdefined
2022-01-28 13:22:05 -05:00
commit 5133972c44
10 changed files with 720 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
package lol.hyper.toolstats;
import lol.hyper.githubreleaseapi.GitHubRelease;
import lol.hyper.githubreleaseapi.GitHubReleaseAPI;
import lol.hyper.toolstats.events.BlocksMined;
import lol.hyper.toolstats.events.CraftItem;
import lol.hyper.toolstats.events.EntityDeath;
import lol.hyper.toolstats.events.MobKill;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.IOException;
import java.util.logging.Logger;
public final class ToolStats extends JavaPlugin {
// stores who crafted an item
public final NamespacedKey craftedOwner = new NamespacedKey(this, "owner");
// stores when an item was crafted
public final NamespacedKey craftedTime = new NamespacedKey(this, "time-created");
// stores how many player kills by sword
public final NamespacedKey swordPlayerKills = new NamespacedKey(this, "player-kills");
// stores how many mob kills by sword
public final NamespacedKey swordMobKills = new NamespacedKey(this, "mob-kills");
// stores how blocks mined (used for all tools)
public final NamespacedKey genericMined = new NamespacedKey(this, "generic-mined");
// stores how many fish were caught
public final NamespacedKey fishingRodCaught = new NamespacedKey(this, "fish-caught");
// stores how many times sheep were sheared
public final NamespacedKey shearsSheared = new NamespacedKey(this, "sheared");
public BlocksMined blocksMined;
public CraftItem craftItem;
public EntityDeath entityDeath;
public MobKill mobKill;
public Logger logger = this.getLogger();
@Override
public void onEnable() {
blocksMined = new BlocksMined(this);
craftItem = new CraftItem(this);
entityDeath = new EntityDeath(this);
mobKill = new MobKill(this);
Bukkit.getServer().getPluginManager().registerEvents(blocksMined, this);
Bukkit.getServer().getPluginManager().registerEvents(craftItem, this);
Bukkit.getServer().getPluginManager().registerEvents(entityDeath, this);
Bukkit.getServer().getPluginManager().registerEvents(mobKill, this);
new Metrics(this, 14110);
Bukkit.getScheduler().runTaskAsynchronously(this, this::checkForUpdates);
}
public void checkForUpdates() {
GitHubReleaseAPI api;
try {
api = new GitHubReleaseAPI("ToolStats", "hyperdefined");
} catch (IOException e) {
logger.warning("Unable to check updates!");
e.printStackTrace();
return;
}
GitHubRelease current = api.getReleaseByTag(this.getDescription().getVersion());
GitHubRelease latest = api.getLatestVersion();
if (current == null) {
logger.warning("You are running a version that does not exist on GitHub. If you are in a dev environment, you can ignore this. Otherwise, this is a bug!");
return;
}
int buildsBehind = api.getBuildsBehind(current);
if (buildsBehind == 0) {
logger.info("You are running the latest version.");
} else {
logger.warning("A new version is available (" + latest.getTagVersion() + ")! You are running version " + current.getTagVersion() + ". You are " + buildsBehind + " version(s) behind.");
}
}
}

View File

@@ -0,0 +1,37 @@
package lol.hyper.toolstats;
import org.bukkit.persistence.PersistentDataAdapterContext;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import java.nio.ByteBuffer;
import java.util.UUID;
public class UUIDDataType implements PersistentDataType<byte[], UUID> {
@Override
public @NotNull Class<byte[]> getPrimitiveType() {
return byte[].class;
}
@Override
public @NotNull Class<UUID> getComplexType() {
return UUID.class;
}
@Override
public byte @NotNull [] toPrimitive(UUID complex, @NotNull PersistentDataAdapterContext context) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(complex.getMostSignificantBits());
bb.putLong(complex.getLeastSignificantBits());
return bb.array();
}
@Override
public @NotNull UUID fromPrimitive(byte @NotNull [] primitive, @NotNull PersistentDataAdapterContext context) {
ByteBuffer bb = ByteBuffer.wrap(primitive);
long firstLong = bb.getLong();
long secondLong = bb.getLong();
return new UUID(firstLong, secondLong);
}
}

View File

@@ -0,0 +1,90 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlocksMined implements Listener {
private final ToolStats toolStats;
private final String[] validTools = {"pickaxe", "axe", "hoe", "shovel"};
private final String blocksMinedLore = ChatColor.GRAY + "Blocks mined: " + ChatColor.DARK_GRAY + "X";
public BlocksMined(ToolStats toolStats) {
this.toolStats = toolStats;
}
@EventHandler
public void onBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
if (player.getGameMode() != GameMode.SURVIVAL) {
return;
}
ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot());
if (heldItem == null || heldItem.getType() == Material.AIR) {
return;
}
String itemName = heldItem.getType().toString().toLowerCase();
if (Arrays.stream(validTools).noneMatch(itemName::contains)) {
return;
}
updateBlocksMined(heldItem);
}
private void updateBlocksMined(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return;
}
Integer blocksMined = 0;
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) {
blocksMined = container.get(toolStats.genericMined, PersistentDataType.INTEGER);
}
if (blocksMined == null) {
return;
} else {
blocksMined++;
}
container.set(toolStats.genericMined, PersistentDataType.INTEGER, blocksMined);
List<String> lore;
if (meta.hasLore()) {
lore = meta.getLore();
assert lore != null;
boolean hasLore = false;
// we do a for loop like this, we can keep track of index
// this doesn't mess the lore up of existing items
for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Blocks mined")) {
hasLore = true;
lore.set(x, blocksMinedLore.replace("X", Integer.toString(blocksMined)));
break;
}
}
// if the item has lore but doesn't have the tag, add it
if (!hasLore) {
lore.add(blocksMinedLore.replace("X", Integer.toString(blocksMined)));
}
} else {
// if the item has no lore, create a new list and add the string
lore = new ArrayList<>();
lore.add(blocksMinedLore.replace("X", Integer.toString(blocksMined)));
}
meta.setLore(lore);
itemStack.setItemMeta(meta);
}
}

View File

@@ -0,0 +1,72 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.UUIDDataType;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.text.SimpleDateFormat;
import java.util.*;
public class CraftItem implements Listener {
private final ToolStats toolStats;
public final String[] validItems = {
"pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing"
};
private final String timeCreatedLore = ChatColor.GRAY + "Crafted on: " + ChatColor.DARK_GRAY + "X";
private final String ownerLore = ChatColor.GRAY + "Crafted by: " + ChatColor.DARK_GRAY + "X";
private final SimpleDateFormat format = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH);
public CraftItem(ToolStats toolStats) {
this.toolStats = toolStats;
}
@EventHandler
public void onCraft(CraftItemEvent event) {
Player player = (Player) event.getWhoClicked();
ItemStack itemStack = event.getCurrentItem();
if (itemStack == null || itemStack.getType() == Material.AIR) {
return;
}
String name = itemStack.getType().toString().toLowerCase(Locale.ROOT);
for (String x : validItems) {
if (name.contains(x)) {
event.setCurrentItem(addLore(itemStack, player));
}
}
}
private ItemStack addLore(ItemStack itemStack, Player owner) {
ItemStack newItem = itemStack.clone();
ItemMeta meta = newItem.getItemMeta();
if (meta == null) {
return null;
}
long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated);
PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(toolStats.craftedTime, PersistentDataType.LONG, timeCreated);
container.set(toolStats.craftedOwner, new UUIDDataType(), owner.getUniqueId());
List<String> lore;
if (meta.hasLore()) {
lore = meta.getLore();
assert lore != null;
} else {
lore = new ArrayList<>();
}
lore.add(timeCreatedLore.replace("X", format.format(finalDate)));
lore.add(ownerLore.replace("X", owner.getName()));
meta.setLore(lore);
newItem.setItemMeta(meta);
return newItem;
}
}

View File

@@ -0,0 +1,57 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.*;
public class EntityDeath implements Listener {
private final ToolStats toolStats;
private final String droppedLore = ChatColor.GRAY + "Dropped by: " + ChatColor.DARK_GRAY + "X";
public EntityDeath(ToolStats toolStats) {
this.toolStats = toolStats;
}
@EventHandler
public void onDeath(EntityDeathEvent event) {
LivingEntity livingEntity = event.getEntity();
UUID livingEntityUUID = event.getEntity().getUniqueId();
if (toolStats.mobKill.trackedMobs.contains(livingEntityUUID)) {
for (ItemStack current : event.getDrops()) {
String name = current.getType().toString().toLowerCase(Locale.ROOT);
for (String item : toolStats.craftItem.validItems) {
if (name.contains(item)) {
addLore(current, livingEntity.getName());
}
}
}
toolStats.mobKill.trackedMobs.remove(livingEntityUUID);
}
}
private void addLore(ItemStack itemStack, String mob) {
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return;
}
List<String> lore;
if (meta.hasLore()) {
lore = meta.getLore();
assert lore != null;
} else {
// if the item has no lore, create a new list and add the string
lore = new ArrayList<>();
}
lore.add(droppedLore.replace("X", mob));
meta.setLore(lore);
itemStack.setItemMeta(meta);
}
}

View File

@@ -0,0 +1,149 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.*;
public class MobKill implements Listener {
private final ToolStats toolStats;
private final String[] validTools = {"sword", "trident", "axe"};
private final String playerKillsLore = ChatColor.GRAY + "Player kills: " + ChatColor.DARK_GRAY + "X";
private final String mobKillsLore = ChatColor.GRAY + "Mob kills: " + ChatColor.DARK_GRAY + "X";
public Set<UUID> trackedMobs = new HashSet<>();
public MobKill(ToolStats toolStats) {
this.toolStats = toolStats;
}
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
LivingEntity livingEntity = (LivingEntity) event.getEntity();
// mob is going to die
if (livingEntity.getHealth() - event.getFinalDamage() <= 0) {
// a player is killing something
if (event.getDamager() instanceof Player) {
Player player = (Player) event.getDamager();
if (player.getGameMode() != GameMode.SURVIVAL) {
return;
}
ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot());
if (heldItem == null || heldItem.getType() == Material.AIR) {
return;
}
String itemName = heldItem.getType().toString().toLowerCase();
if (Arrays.stream(validTools).noneMatch(itemName::contains)) {
return;
}
// a player is killing another player
if (livingEntity instanceof Player) {
updatePlayerKills(heldItem);
return;
}
// player is killing regular mob
updateMobKills(heldItem);
trackedMobs.add(livingEntity.getUniqueId());
}
}
}
private void updatePlayerKills(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return;
}
Integer playerKills = 0;
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.swordPlayerKills, PersistentDataType.INTEGER)) {
playerKills = container.get(toolStats.swordPlayerKills, PersistentDataType.INTEGER);
}
if (playerKills == null) {
return;
} else {
playerKills++;
}
container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills);
List<String> lore;
if (meta.hasLore()) {
lore = meta.getLore();
assert lore != null;
boolean hasLore = false;
// we do a for loop like this, we can keep track of index
// this doesn't mess the lore up of existing items
for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Mob kills")) {
hasLore = true;
lore.set(x, playerKillsLore.replace("X", Integer.toString(playerKills)));
break;
}
}
// if the item has lore but doesn't have the tag, add it
if (!hasLore) {
lore.add(playerKillsLore.replace("X", Integer.toString(playerKills)));
}
} else {
// if the item has no lore, create a new list and add the string
lore = new ArrayList<>();
lore.add(playerKillsLore.replace("X", Integer.toString(playerKills)));
}
meta.setLore(lore);
itemStack.setItemMeta(meta);
}
private void updateMobKills(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return;
}
Integer mobKills = 0;
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.swordMobKills, PersistentDataType.INTEGER)) {
mobKills = container.get(toolStats.swordMobKills, PersistentDataType.INTEGER);
}
if (mobKills == null) {
return;
} else {
mobKills++;
}
container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills);
List<String> lore;
if (meta.hasLore()) {
lore = meta.getLore();
assert lore != null;
boolean hasLore = false;
// we do a for loop like this, we can keep track of index
// this doesn't mess the lore up of existing items
for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Mob kills")) {
hasLore = true;
lore.set(x, mobKillsLore.replace("X", Integer.toString(mobKills)));
break;
}
}
// if the item has lore but doesn't have the tag, add it
if (!hasLore) {
lore.add(mobKillsLore.replace("X", Integer.toString(mobKills)));
}
} else {
// if the item has no lore, create a new list and add the string
lore = new ArrayList<>();
lore.add(mobKillsLore.replace("X", Integer.toString(mobKills)));
}
meta.setLore(lore);
itemStack.setItemMeta(meta);
}
}