callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- int value = callable.call();
- if (value == 0) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("value", value).build();
- }
- }
-
- /**
- * An extremely simple JSON builder.
- *
- * While this class is neither feature-rich nor the most performant one, it's sufficient enough
- * for its use-case.
- */
- public static class JsonObjectBuilder {
-
- private StringBuilder builder = new StringBuilder();
-
- private boolean hasAtLeastOneField = false;
-
- public JsonObjectBuilder() {
- builder.append("{");
- }
-
- /**
- * Appends a null field to the JSON.
- *
- * @param key The key of the field.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendNull(String key) {
- appendFieldUnescaped(key, "null");
- return this;
- }
-
- /**
- * Appends a string field to the JSON.
- *
- * @param key The key of the field.
- * @param value The value of the field.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, String value) {
- if (value == null) {
- throw new IllegalArgumentException("JSON value must not be null");
- }
- appendFieldUnescaped(key, "\"" + escape(value) + "\"");
- return this;
- }
-
- /**
- * Appends an integer field to the JSON.
- *
- * @param key The key of the field.
- * @param value The value of the field.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, int value) {
- appendFieldUnescaped(key, String.valueOf(value));
- return this;
- }
-
- /**
- * Appends an object to the JSON.
- *
- * @param key The key of the field.
- * @param object The object.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, JsonObject object) {
- if (object == null) {
- throw new IllegalArgumentException("JSON object must not be null");
- }
- appendFieldUnescaped(key, object.toString());
- return this;
- }
-
- /**
- * Appends a string array to the JSON.
- *
- * @param key The key of the field.
- * @param values The string array.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, String[] values) {
- if (values == null) {
- throw new IllegalArgumentException("JSON values must not be null");
- }
- String escapedValues =
- Arrays.stream(values)
- .map(value -> "\"" + escape(value) + "\"")
- .collect(Collectors.joining(","));
- appendFieldUnescaped(key, "[" + escapedValues + "]");
- return this;
- }
-
- /**
- * Appends an integer array to the JSON.
- *
- * @param key The key of the field.
- * @param values The integer array.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, int[] values) {
- if (values == null) {
- throw new IllegalArgumentException("JSON values must not be null");
- }
- String escapedValues =
- Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
- appendFieldUnescaped(key, "[" + escapedValues + "]");
- return this;
- }
-
- /**
- * Appends an object array to the JSON.
- *
- * @param key The key of the field.
- * @param values The integer array.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, JsonObject[] values) {
- if (values == null) {
- throw new IllegalArgumentException("JSON values must not be null");
- }
- String escapedValues =
- Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
- appendFieldUnescaped(key, "[" + escapedValues + "]");
- return this;
- }
-
- /**
- * Appends a field to the object.
- *
- * @param key The key of the field.
- * @param escapedValue The escaped value of the field.
- */
- private void appendFieldUnescaped(String key, String escapedValue) {
- if (builder == null) {
- throw new IllegalStateException("JSON has already been built");
- }
- if (key == null) {
- throw new IllegalArgumentException("JSON key must not be null");
- }
- if (hasAtLeastOneField) {
- builder.append(",");
- }
- builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
- hasAtLeastOneField = true;
- }
-
- /**
- * Builds the JSON string and invalidates this builder.
- *
- * @return The built JSON string.
- */
- public JsonObject build() {
- if (builder == null) {
- throw new IllegalStateException("JSON has already been built");
- }
- JsonObject object = new JsonObject(builder.append("}").toString());
- builder = null;
- return object;
- }
-
- /**
- * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
- *
- *
This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
- * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
- *
- * @param value The value to escape.
- * @return The escaped value.
- */
- private static String escape(String value) {
- final StringBuilder builder = new StringBuilder();
- for (int i = 0; i < value.length(); i++) {
- char c = value.charAt(i);
- if (c == '"') {
- builder.append("\\\"");
- } else if (c == '\\') {
- builder.append("\\\\");
- } else if (c <= '\u000F') {
- builder.append("\\u000").append(Integer.toHexString(c));
- } else if (c <= '\u001F') {
- builder.append("\\u00").append(Integer.toHexString(c));
- } else {
- builder.append(c);
- }
- }
- return builder.toString();
- }
-
- /**
- * A super simple representation of a JSON object.
- *
- *
This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
- * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
- * JsonObject)}.
- */
- public static class JsonObject {
-
- private final String value;
-
- private JsonObject(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
- }
- }
}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/api/HeadAPI.java b/src/main/java/tsp/headdb/api/HeadAPI.java
deleted file mode 100644
index a728f00..0000000
--- a/src/main/java/tsp/headdb/api/HeadAPI.java
+++ /dev/null
@@ -1,259 +0,0 @@
-package tsp.headdb.api;
-
-import org.apache.commons.lang.Validate;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-import tsp.headdb.HeadDB;
-import tsp.headdb.implementation.Category;
-import tsp.headdb.implementation.Head;
-import tsp.headdb.implementation.HeadDatabase;
-import tsp.headdb.implementation.LocalHead;
-import tsp.headdb.inventory.InventoryUtils;
-import tsp.headdb.storage.PlayerDataFile;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * This class provides simple methods
- * for interacting with the HeadDB plugin
- *
- * @author TheSilentPro
- */
-// TODO: Optional instead of null.
-// TODO: Remove stream, use loop.
-public final class HeadAPI {
-
- private HeadAPI() {}
-
- private static final String VALIDATION_PLAYER_NULL = "Player can not be null!";
- private static final String VALIDATION_CATEGORY_NULL = "Category can not be null!";
- private static final String VALIDATION_UUID_NULL = "UUID can not be null!";
- private static final String VALIDATION_VALUE_NULL = "Value can not be null!";
-
- /**
- * Main {@link HeadDatabase} that he HeadDB plugin uses.
- */
- private static final HeadDatabase database = new HeadDatabase(HeadDB.getInstance());
-
- /**
- * Retrieves the main {@link HeadDatabase}
- *
- * @return Head Database
- */
- public static HeadDatabase getDatabase() {
- return database;
- }
-
- /**
- * Opens the database for a player
- *
- * @param player Target player
- */
- public static void openDatabase(@Nonnull Player player) {
- Validate.notNull(player, VALIDATION_PLAYER_NULL);
-
- InventoryUtils.openDatabase(player);
- }
-
- /**
- * Opens a specific category of the database for a player
- *
- * @param player Target player
- * @param category Category to open
- */
- public static void openCategoryDatabase(@Nonnull Player player, @Nonnull Category category) {
- Validate.notNull(player, VALIDATION_PLAYER_NULL);
- Validate.notNull(category, VALIDATION_CATEGORY_NULL);
-
- InventoryUtils.openCategoryDatabase(player, category);
- }
-
- /**
- * Opens the database with results of a specific search term
- *
- * @param player Target player
- * @param search Search term
- */
- public static void openSearchDatabase(@Nonnull Player player, @Nonnull String search) {
- Validate.notNull(player, VALIDATION_PLAYER_NULL);
- Validate.notNull(search, "Search can not be null!");
-
- InventoryUtils.openSearchDatabase(player, search);
- }
-
- /**
- * Opens the database with results of a specific tag search term
- *
- * @param player Target player
- * @param tag Tag search term
- */
- public static void openTagSearchDatabase(@Nonnull Player player, @Nonnull String tag) {
- Validate.notNull(player, VALIDATION_PLAYER_NULL);
- Validate.notNull(tag, "Tag can not be null!");
-
- InventoryUtils.openTagSearchDatabase(player, tag);
- }
-
- /**
- * Retrieve a {@link Head} by it's ID
- *
- * @param id The ID of the head
- * @return The head
- */
- @Nullable
- public static Head getHeadByID(int id) {
- return database.getHeadByID(id);
- }
-
- /**
- * Retrieve a {@link Head} by it's UUID
- *
- * @param uuid The UUID of the head
- * @return The head
- */
- @Nullable
- public static Head getHeadByUniqueId(@Nonnull UUID uuid) {
- Validate.notNull(uuid, VALIDATION_UUID_NULL);
-
- return database.getHeadByUniqueId(uuid);
- }
-
- /**
- * Retrieve a {@link List} of {@link Head}'s by their tag
- *
- * @param tag The tag
- * @return List of heads
- */
- @Nonnull
- public static List
getHeadsByTag(@Nonnull String tag) {
- Validate.notNull(tag, "Tag can not be null!");
-
- return database.getHeadsByTag(tag);
- }
-
- /**
- * Retrieves a {@link List} of {@link Head}'s matching a name
- *
- * @param name The name to match for
- * @return List of heads
- */
- @Nonnull
- public static List getHeadsByName(@Nonnull String name) {
- Validate.notNull(name, "Name can not be null!");
-
- return database.getHeadsByName(name);
- }
-
- /**
- * Retrieves a {@link List} of {@link Head}'s in a {@link Category} matching a name
- *
- * @param category The category to search in
- * @param name The name to match for
- * @return List of heads
- */
- @Nonnull
- public static List getHeadsByName(@Nonnull Category category, @Nonnull String name) {
- Validate.notNull(category, VALIDATION_CATEGORY_NULL);
- Validate.notNull(name, "Name can not be null!");
-
- return database.getHeadsByName(category, name);
- }
-
- /**
- * Retrieve a {@link Head} by it's value
- *
- * @param value The texture value
- * @return The head
- */
- @Nullable
- public static Head getHeadByValue(@Nonnull String value) {
- Validate.notNull(value, VALIDATION_VALUE_NULL);
-
- return database.getHeadByValue(value);
- }
-
- /**
- * Retrieve a {@link List} of {@link Head}'s in a specific {@link Category}
- *
- * @param category The category to search in
- * @return List of heads
- */
- @Nonnull
- public static List getHeads(@Nonnull Category category) {
- Validate.notNull(category, VALIDATION_CATEGORY_NULL);
-
- return database.getHeads(category);
- }
-
- /**
- * Retrieve a {@link List} of all {@link Head}'s
- *
- * @return List of all heads
- */
- @Nonnull
- public static List getHeads() {
- return database.getHeads();
- }
-
- /**
- * Add a favorite {@link Head} to the player
- *
- * @param uuid The player's unique id
- * @param textureValue The head's texture value
- */
- public static void addFavoriteHead(@Nonnull UUID uuid, @Nonnull String textureValue) {
- Validate.notNull(uuid, VALIDATION_UUID_NULL);
- Validate.notNull(textureValue, VALIDATION_VALUE_NULL);
-
- HeadDB.getInstance().getPlayerData().modifyFavorite(uuid, textureValue, PlayerDataFile.ModificationType.SET);
- }
-
- /**
- * Remove a favorite {@link Head} from the player
- *
- * @param uuid The player's unique id
- * @param textureValue The head's texture value
- */
- public static void removeFavoriteHead(@Nonnull UUID uuid, @Nonnull String textureValue) {
- Validate.notNull(uuid, VALIDATION_UUID_NULL);
- Validate.notNull(textureValue, VALIDATION_VALUE_NULL);
-
- HeadDB.getInstance().getPlayerData().modifyFavorite(uuid, textureValue, PlayerDataFile.ModificationType.REMOVE);
- }
-
- /**
- * Retrieve a {@link List} of favorite {@link Head}'s for the player
- *
- * @param uuid The player's unique id
- * @return List of favorite {@link Head}'s for the player
- */
- @Nonnull
- public static List getFavoriteHeads(@Nonnull UUID uuid) {
- Validate.notNull(uuid, VALIDATION_UUID_NULL);
-
- return HeadDB.getInstance().getPlayerData().getFavoriteHeadsByTexture(uuid).stream()
- .map(HeadAPI::getHeadByValue)
- .filter(Objects::nonNull)
- .toList();
- }
-
- /**
- * Retrieve a list of {@link LocalHead}'s.
- * These are heads from players that have joined the server at least once.
- * Requires config option localHeads = true
- *
- * @return List of {@link LocalHead}'s
- */
- @Nonnull
- public static List getLocalHeads() {
- return HeadDB.getInstance().getPlayerData().getEntries().stream()
- .map(entry -> Bukkit.getOfflinePlayer(UUID.fromString(entry)))
- .map(player -> new LocalHead(player.getUniqueId()).name(player.getName()))
- .toList();
- }
-
-}
diff --git a/src/main/java/tsp/headdb/api/event/DatabaseUpdateEvent.java b/src/main/java/tsp/headdb/api/event/DatabaseUpdateEvent.java
deleted file mode 100644
index f46f54f..0000000
--- a/src/main/java/tsp/headdb/api/event/DatabaseUpdateEvent.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package tsp.headdb.api.event;
-
-import org.bukkit.event.Event;
-import org.bukkit.event.HandlerList;
-import tsp.headdb.implementation.Head;
-import tsp.headdb.implementation.Category;
-import tsp.headdb.implementation.HeadDatabase;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * This event is called AFTER a {@link HeadDatabase} updates.
- * The event is called asynchronously and can not be cancelled.
- *
- * @author TheSilentPro
- */
-public class DatabaseUpdateEvent extends Event {
-
- private final HandlerList handlerList = new HandlerList();
- private final HeadDatabase database;
- private final Map> heads;
-
- public DatabaseUpdateEvent(HeadDatabase database, Map> heads) {
- super(true);
-
- this.database = database;
- this.heads = heads;
- }
-
- /**
- * Retrieve the {@link HeadDatabase} associated with this event
- *
- * @return The database
- */
- public HeadDatabase getDatabase() {
- return database;
- }
-
- /**
- * Retrieve the result of the update
- *
- * @return The heads fetched from the update
- */
- public Map> getHeads() {
- return heads;
- }
-
- @Override
- public HandlerList getHandlers() {
- return handlerList;
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/api/event/PlayerHeadPurchaseEvent.java b/src/main/java/tsp/headdb/api/event/PlayerHeadPurchaseEvent.java
deleted file mode 100644
index a9faf87..0000000
--- a/src/main/java/tsp/headdb/api/event/PlayerHeadPurchaseEvent.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package tsp.headdb.api.event;
-
-import org.bukkit.entity.Player;
-import org.bukkit.event.Cancellable;
-import org.bukkit.event.Event;
-import org.bukkit.event.HandlerList;
-import tsp.headdb.implementation.Head;
-
-/**
- * This event is called when a player purchases a {@link Head}
- *
- * @author TheSilentPro
- * @see tsp.headdb.inventory.InventoryUtils#purchaseHead(Player, Head, int, String, String)
- */
-public class PlayerHeadPurchaseEvent extends Event implements Cancellable {
-
- private final HandlerList handlerList = new HandlerList();
- private boolean cancelled;
- private Player player;
- private Head head;
- private double cost;
-
- public PlayerHeadPurchaseEvent(Player player, Head head, double cost) {
- super(true);
- this.player = player;
- this.head = head;
- this.cost = cost;
- }
-
- public Player getPlayer() {
- return player;
- }
-
- public Head getHead() {
- return head;
- }
-
- public double getCost() {
- return cost;
- }
-
- public void setPlayer(Player player) {
- this.player = player;
- }
-
- public void setHead(Head head) {
- this.head = head;
- }
-
- public void setCost(double cost) {
- this.cost = cost;
- }
-
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
-
- @Override
- public void setCancelled(boolean b) {
- this.cancelled = b;
- }
-
- @Override
- public HandlerList getHandlers() {
- return handlerList;
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/GiveCommand.java b/src/main/java/tsp/headdb/command/GiveCommand.java
deleted file mode 100644
index 99cd4f8..0000000
--- a/src/main/java/tsp/headdb/command/GiveCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.implementation.Head;
-import tsp.headdb.util.Utils;
-
-public class GiveCommand implements HeadSubCommand {
-
- @Override
- public void handle(CommandSender sender, String[] args) {
- if (!sender.hasPermission("headdb.give")) {
- Utils.sendMessage(sender, getLocalization().getMessage("noPermission"));
- return;
- }
-
- if (args.length < 3) {
- Utils.sendMessage(sender, "&c/hdb give &6[amount]");
- return;
- }
-
- try {
- int id = Integer.parseInt(args[1]);
- Player target = Bukkit.getPlayer(args[2]);
- if (target == null) {
- Utils.sendMessage(sender, getLocalization().getMessage("invalidPlayer"));
- return;
- }
-
- int amount = 1;
- if (args.length > 3) {
- amount = Integer.parseInt(args[3]);
- }
-
- Head head = HeadAPI.getHeadByID(id);
- if (head == null) {
- Utils.sendMessage(sender, "&cCould not find head with id &e" + id);
- return;
- }
-
- ItemStack item = head.getMenuItem();
- item.setAmount(amount);
- target.getInventory().addItem(item);
- Utils.sendMessage(sender, "&7Gave &6" + target.getName() + " &ex" + amount + " " + head.getName());
- } catch (NumberFormatException nfe) {
- Utils.sendMessage(sender, "&cID/Amount must be a number!");
- }
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/HeadDBCommand.java b/src/main/java/tsp/headdb/command/HeadDBCommand.java
deleted file mode 100644
index da0f779..0000000
--- a/src/main/java/tsp/headdb/command/HeadDBCommand.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import tsp.headdb.HeadDB;
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.util.Localization;
-import tsp.headdb.util.Utils;
-
-public class HeadDBCommand implements CommandExecutor {
-
- private void handle(CommandSender sender, String[] args) {
- Localization localization = HeadDB.getInstance().getLocalization();
- if (args.length == 0) {
- if (!sender.hasPermission("headdb.open")) {
- Utils.sendMessage(sender, localization.getMessage("noPermission"));
- return;
- }
- if (!(sender instanceof Player player)) {
- Utils.sendMessage(sender, localization.getMessage("onlyPlayers"));
- return;
- }
-
- Utils.sendMessage(player, localization.getMessage("databaseOpen"));
- HeadAPI.openDatabase(player);
- return;
- }
-
- String sub = args[0];
- HeadSubCommand subCommand = null;
- if (sub.equalsIgnoreCase("info") || sub.equalsIgnoreCase("i")) {
- subCommand = new InfoCommand();
- } else if (sub.equalsIgnoreCase("reload") || sub.equalsIgnoreCase("r")) {
- subCommand = new ReloadCommand();
- } else if (sub.equalsIgnoreCase("search") || sub.equalsIgnoreCase("s")) {
- subCommand = new SearchCommand();
- } else if (sub.equalsIgnoreCase("tagsearch") || sub.equalsIgnoreCase("ts")) {
- subCommand = new TagSearchCommand();
- } else if (sub.equalsIgnoreCase("give") || sub.equalsIgnoreCase("g")) {
- subCommand = new GiveCommand();
- } else if (sub.equalsIgnoreCase("update") || sub.equalsIgnoreCase("u")) {
- subCommand = new UpdateCommand();
- }
-
- if (subCommand != null) {
- subCommand.handle(sender, args);
- return;
- }
-
- Utils.sendMessage(sender, " ");
- Utils.sendMessage(sender, "&c&lHeadDB &c- &5Commands");
- Utils.sendMessage(sender, "&7&oParameters:&c command &9(aliases)&c arguments... &7- Description");
- Utils.sendMessage(sender, "&7 > &c/hdb &7- Opens the database");
- Utils.sendMessage(sender, "&7 > &c/hdb info &9(i) &7- Plugin Information");
- Utils.sendMessage(sender, "&7 > &c/hdb reload &9(r) &7- Reloads the messages file");
- Utils.sendMessage(sender, "&7 > &c/hdb search &9(s) &c &7- Search for heads matching a name");
- Utils.sendMessage(sender, "&7 > &c/hdb tagsearch &9(ts) &c &7- Search for heads matching a tag");
- Utils.sendMessage(sender, "&7 > &c/hdb update &9(u) &7- Forcefully update the database");
- Utils.sendMessage(sender, "&7 > &c/hdb give &9(g) &c &6[amount] &7- Give player a head");
- Utils.sendMessage(sender, " ");
- }
-
- @Override
- public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
- handle(sender, args);
- return true;
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/command/HeadSubCommand.java b/src/main/java/tsp/headdb/command/HeadSubCommand.java
deleted file mode 100644
index 020f84f..0000000
--- a/src/main/java/tsp/headdb/command/HeadSubCommand.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.CommandSender;
-import tsp.headdb.HeadDB;
-import tsp.headdb.util.Localization;
-
-/**
- * An interface for a HeadDB sub-command
- *
- * @author TheSilentPro
- * @since 4.0.0
- */
-public interface HeadSubCommand {
-
- void handle(CommandSender sender, String[] args);
-
- default Localization getLocalization() {
- return HeadDB.getInstance().getLocalization();
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/InfoCommand.java b/src/main/java/tsp/headdb/command/InfoCommand.java
deleted file mode 100644
index 18a5694..0000000
--- a/src/main/java/tsp/headdb/command/InfoCommand.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.CommandSender;
-import tsp.headdb.HeadDB;
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.util.Utils;
-
-public class InfoCommand implements HeadSubCommand {
-
- @Override
- public void handle(CommandSender sender, String[] args) {
- // These should not be customizable
- Utils.sendMessage(sender, "&7Running &cHeadDB - " + HeadDB.getInstance().getDescription().getVersion());
- Utils.sendMessage(sender, "&7Created by &c" + HeadDB.getInstance().getDescription().getAuthors());
- Utils.sendMessage(sender, "&7There are currently &c" + HeadAPI.getHeads().size() + " &7heads in the database.");
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/ReloadCommand.java b/src/main/java/tsp/headdb/command/ReloadCommand.java
deleted file mode 100644
index 0665d6a..0000000
--- a/src/main/java/tsp/headdb/command/ReloadCommand.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.CommandSender;
-import tsp.headdb.HeadDB;
-import tsp.headdb.util.Utils;
-
-public class ReloadCommand implements HeadSubCommand {
-
- @Override
- public void handle(CommandSender sender, String[] args) {
- if (!sender.hasPermission("headdb.reload")) {
- Utils.sendMessage(sender, getLocalization().getMessage("noPermission"));
- return;
- }
-
- HeadDB.getInstance().getLocalization().load();
- Utils.sendMessage(sender, getLocalization().getMessage("reloadMessages"));
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/SearchCommand.java b/src/main/java/tsp/headdb/command/SearchCommand.java
deleted file mode 100644
index 792e276..0000000
--- a/src/main/java/tsp/headdb/command/SearchCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.util.Utils;
-
-public class SearchCommand implements HeadSubCommand {
-
- @Override
- public void handle(CommandSender sender, String[] args) {
- if (!sender.hasPermission("headdb.search")) {
- Utils.sendMessage(sender, getLocalization().getMessage("noPermission"));
- return;
- }
- if (!(sender instanceof Player player)) {
- Utils.sendMessage(sender, getLocalization().getMessage("onlyPlayers"));
- return;
- }
-
- if (args.length < 2) {
- Utils.sendMessage(player, "&c/hdb search ");
- return;
- }
-
- StringBuilder builder = new StringBuilder();
- for (int i = 1; i < args.length; i++) {
- builder.append(args[i]);
- if (i != args.length - 1) {
- builder.append(" ");
- }
- }
- String name = builder.toString();
- Utils.sendMessage(sender, "&7Searching for &e" + name);
- HeadAPI.openSearchDatabase(player, name);
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/TagSearchCommand.java b/src/main/java/tsp/headdb/command/TagSearchCommand.java
deleted file mode 100644
index bf601e2..0000000
--- a/src/main/java/tsp/headdb/command/TagSearchCommand.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.util.Utils;
-
-public class TagSearchCommand implements HeadSubCommand {
-
- @Override
- public void handle(CommandSender sender, String[] args) {
- if (!sender.hasPermission("headdb.tagsearch")) {
- Utils.sendMessage(sender, getLocalization().getMessage("noPermission"));
- return;
- }
-
- if (args.length < 2) {
- Utils.sendMessage(sender, "&c/hdb tagsearch ");
- return;
- }
-
- if (!(sender instanceof Player player)) {
- Utils.sendMessage(sender, getLocalization().getMessage("onlyPlayers"));
- return;
- }
-
- String tag = args[1];
- Utils.sendMessage(sender, "&7Searching for heads with tag &e" + tag);
- HeadAPI.openTagSearchDatabase(player, tag);
- }
-
-}
diff --git a/src/main/java/tsp/headdb/command/UpdateCommand.java b/src/main/java/tsp/headdb/command/UpdateCommand.java
deleted file mode 100644
index d3765ff..0000000
--- a/src/main/java/tsp/headdb/command/UpdateCommand.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package tsp.headdb.command;
-
-import org.bukkit.command.CommandSender;
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.util.Utils;
-
-import java.util.concurrent.TimeUnit;
-
-public class UpdateCommand implements HeadSubCommand {
-
- @Override
- public void handle(CommandSender sender, String[] args) {
- if (!sender.hasPermission("headdb.update")) {
- Utils.sendMessage(sender, getLocalization().getMessage("noPermission"));
- return;
- }
-
- Utils.sendMessage(sender, "&7Updating...");
- long start = System.currentTimeMillis();
- HeadAPI.getDatabase().update(heads -> {
- Utils.sendMessage(sender, "&7Done! Took: &a" + TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start) + " &7seconds");
- Utils.sendMessage(sender, "&7There are &a" + HeadAPI.getHeads().size() + " &7heads in the database!");
- });
- }
-
-}
diff --git a/src/main/java/tsp/headdb/core/api/HeadAPI.java b/src/main/java/tsp/headdb/core/api/HeadAPI.java
new file mode 100644
index 0000000..0de608c
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/api/HeadAPI.java
@@ -0,0 +1,33 @@
+package tsp.headdb.core.api;
+
+import tsp.headdb.HeadDB;
+import tsp.headdb.implementation.category.Category;
+import tsp.headdb.implementation.head.Head;
+import tsp.headdb.implementation.head.HeadDatabase;
+
+import java.util.List;
+import java.util.Map;
+
+public final class HeadAPI {
+
+ private HeadAPI() {}
+
+ private static final HeadDatabase database = new HeadDatabase(HeadDB.getInstance());
+
+ public static List getHeads(Category category) {
+ return database.getHeads().get(category);
+ }
+
+ public static Map> getHeads() {
+ return database.getHeads();
+ }
+
+ public static int getTotalHeads() {
+ return database.getSize();
+ }
+
+ public static HeadDatabase getDatabase() {
+ return database;
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/command/CommandMain.java b/src/main/java/tsp/headdb/core/command/CommandMain.java
new file mode 100644
index 0000000..913bcd1
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandMain.java
@@ -0,0 +1,86 @@
+package tsp.headdb.core.command;
+
+import org.bukkit.Material;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.command.RemoteConsoleCommandSender;
+import org.bukkit.entity.Player;
+
+import tsp.headdb.HeadDB;
+import tsp.headdb.core.api.HeadAPI;
+import tsp.headdb.implementation.category.Category;
+import tsp.smartplugin.builder.item.ItemBuilder;
+import tsp.smartplugin.inventory.Button;
+import tsp.smartplugin.inventory.single.Pane;
+import tsp.smartplugin.localization.TranslatableLocalization;
+import tsp.smartplugin.utils.InventoryUtils;
+import tsp.smartplugin.utils.StringUtils;
+import tsp.smartplugin.utils.Validate;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+public class CommandMain extends HeadDBCommand implements CommandExecutor {
+
+ private final TranslatableLocalization localization = HeadDB.getInstance().getLocalization();
+
+ public CommandMain() {
+ super("headdb", "headdb.command.open");
+ }
+
+ @Override
+ @ParametersAreNonnullByDefault
+ public void handle(CommandSender sender, String[] args) {
+ if (args.length == 0) {
+ if (!(sender instanceof Player player)) {
+ localization.sendConsoleMessage("noConsole");
+ return;
+ }
+
+ if (!player.hasPermission(getPermission())) {
+ sendMessage(sender, "noPermission");
+ return;
+ }
+ localization.sendMessage(player.getUniqueId(), "openDatabase");
+
+ Pane pane = new Pane(6, StringUtils.colorize(localization.getMessage(player.getUniqueId(), "menu.main.title").orElse("&cHeadDB &7(" + HeadAPI.getTotalHeads() + ")")).replace("%size%", HeadAPI.getTotalHeads() + ""));
+ InventoryUtils.fillBorder(pane.getInventory(), new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).name(" ").build());
+ for (Category category : Category.VALUES) {
+ pane.addButton(new Button(category.getItem(player.getUniqueId()), e -> {
+ if (e.getClick().isLeftClick()) {
+ // open category
+ e.getWhoClicked().sendMessage("clicked category: " + category.getName());
+ }
+
+ e.setCancelled(true);
+ }));
+ }
+
+ pane.open(player);
+ return;
+ }
+
+ HeadDB.getInstance().getCommandManager().getCommand(args[0]).ifPresentOrElse(command -> command.handle(sender, args), () -> sendMessage(sender, "invalidSubCommand"));
+ }
+
+ @ParametersAreNonnullByDefault
+ private void sendMessage(CommandSender sender, String key) {
+ Validate.notNull(sender, "Message sender can not be null!");
+ Validate.notNull(key, "Key can not be null!");
+
+ if (sender instanceof Player player) {
+ localization.sendMessage(player.getUniqueId(), key);
+ } else if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender){
+ localization.sendConsoleMessage(key);
+ }
+ }
+
+ @Override
+ @ParametersAreNonnullByDefault
+ public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
+ handle(sender, args);
+ return true;
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/command/CommandManager.java b/src/main/java/tsp/headdb/core/command/CommandManager.java
new file mode 100644
index 0000000..bbf5407
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandManager.java
@@ -0,0 +1,22 @@
+package tsp.headdb.core.command;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class CommandManager {
+
+ private final Map commands = new HashMap<>();
+
+ public void register(SubCommand command) {
+ this.commands.put(command.getName(), command);
+ }
+
+ public Optional getCommand(String name) {
+ return Optional.ofNullable(commands.get(name));
+ }
+
+ public Map getCommandsMap() {
+ return commands;
+ }
+}
diff --git a/src/main/java/tsp/headdb/core/command/HeadDBCommand.java b/src/main/java/tsp/headdb/core/command/HeadDBCommand.java
new file mode 100644
index 0000000..3380091
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/HeadDBCommand.java
@@ -0,0 +1,38 @@
+package tsp.headdb.core.command;
+
+import org.bukkit.command.CommandSender;
+
+import javax.annotation.Nullable;
+import java.util.Optional;
+
+public abstract class HeadDBCommand {
+
+ private final String name;
+ private final String permission;
+ private final String[] aliases;
+
+ public HeadDBCommand(String name, String permission, @Nullable String[] aliases) {
+ this.name = name;
+ this.permission = permission;
+ this.aliases = aliases;
+ }
+
+ public HeadDBCommand(String name, String permission) {
+ this(name, permission, null);
+ }
+
+ public abstract void handle(CommandSender sender, String[] args);
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPermission() {
+ return permission;
+ }
+
+ public Optional getAliases() {
+ return Optional.ofNullable(aliases);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/core/command/SubCommand.java b/src/main/java/tsp/headdb/core/command/SubCommand.java
new file mode 100644
index 0000000..d9a149f
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/SubCommand.java
@@ -0,0 +1,9 @@
+package tsp.headdb.core.command;
+
+public abstract class SubCommand extends HeadDBCommand {
+
+ public SubCommand(String name) {
+ super(name, "headdb.command." + name);
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/storage/PlayerData.java b/src/main/java/tsp/headdb/core/storage/PlayerData.java
new file mode 100644
index 0000000..bb0d62a
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/storage/PlayerData.java
@@ -0,0 +1,6 @@
+package tsp.headdb.core.storage;
+
+import java.util.Collection;
+import java.util.UUID;
+
+public record PlayerData(UUID uniqueId, String name, Collection favorites) {}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/core/storage/PlayerStorage.java b/src/main/java/tsp/headdb/core/storage/PlayerStorage.java
new file mode 100644
index 0000000..f74ce67
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/storage/PlayerStorage.java
@@ -0,0 +1,38 @@
+package tsp.headdb.core.storage;
+
+import org.bukkit.Bukkit;
+import org.jetbrains.annotations.NotNull;
+import tsp.headdb.HeadDB;
+import tsp.warehouse.storage.DataManager;
+import tsp.warehouse.storage.sql.SQLiteDataManager;
+
+import javax.annotation.Nullable;
+import java.io.File;
+import java.util.Collection;
+import java.util.concurrent.CompletableFuture;
+
+public class PlayerStorage extends SQLiteDataManager {
+
+ public PlayerStorage() {
+ super(new File(HeadDB.getInstance().getDataFolder(), "player_data.db"), null);
+ sendPreparedUpdate("CREATE TABLE IF NOT EXISTS data(uuid NOT NULL PRIMARY KEY VARCHAR(36), name TEXT, favorites TEXT)");
+ }
+
+ @Override
+ public CompletableFuture> load() {
+ return null;
+ }
+
+ @Override
+ public CompletableFuture save(Collection data) {
+ Bukkit.getScheduler().runTaskAsynchronously(HeadDB.getInstance(), () -> {
+ StringBuilder builder = new StringBuilder();
+ for (PlayerData entry : data) {
+ builder.append(String.format("(%s, %s, %s),", entry.uniqueId().toString(), entry.name(), entry.favorites().toString()));
+ }
+ sendPreparedUpdate("INSERT OR REPLACE INTO data VALUES" + builder.substring(0, builder.length() - 1) + ";").join();
+ });
+ return CompletableFuture.completedFuture(true);
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/task/DatabaseUpdateTask.java b/src/main/java/tsp/headdb/core/task/DatabaseUpdateTask.java
new file mode 100644
index 0000000..6b68113
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/task/DatabaseUpdateTask.java
@@ -0,0 +1,25 @@
+package tsp.headdb.core.task;
+
+import tsp.headdb.core.api.HeadAPI;
+import tsp.smartplugin.tasker.Task;
+
+@SuppressWarnings("ClassCanBeRecord")
+public class DatabaseUpdateTask implements Task {
+
+ private final long interval;
+
+ public DatabaseUpdateTask(long interval) {
+ this.interval = interval;
+ }
+
+ @Override
+ public void run() {
+ HeadAPI.getDatabase().update();
+ }
+
+ @Override
+ public long getRepeatInterval() {
+ return interval;
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/util/Utils.java b/src/main/java/tsp/headdb/core/util/Utils.java
new file mode 100644
index 0000000..1df47f0
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/util/Utils.java
@@ -0,0 +1,16 @@
+package tsp.headdb.core.util;
+
+import java.util.Optional;
+import java.util.UUID;
+
+public class Utils {
+
+ public static Optional validateUniqueId(String raw) {
+ try {
+ return Optional.of(UUID.fromString(raw));
+ } catch (IllegalArgumentException ignored) {
+ return Optional.empty();
+ }
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/economy/BasicEconomyProvider.java b/src/main/java/tsp/headdb/economy/BasicEconomyProvider.java
deleted file mode 100644
index f1b3e83..0000000
--- a/src/main/java/tsp/headdb/economy/BasicEconomyProvider.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package tsp.headdb.economy;
-
-import org.bukkit.entity.Player;
-
-import java.math.BigDecimal;
-import java.util.function.Consumer;
-
-/**
- * An interface for generalizing Economy Provider's
- *
- * @author TheSilentPro
- * @since 4.0.0
- * @see VaultProvider
- * @see TreasuryProvider
- */
-public interface BasicEconomyProvider {
-
- /**
- * Retrieve if the player can purchase a head using this economy provider
- *
- * @param player The player
- * @param cost The cost
- * @param result If the player has enough to purchase
- */
- default void canPurchase(Player player, BigDecimal cost, Consumer result) {
- result.accept(true);
- }
-
- /**
- * Charge the player a specific amount using this economy provider
- *
- * @param player The player
- * @param amount The amount
- * @param result If the transaction was successful
- */
- default void charge(Player player, BigDecimal amount, Consumer result) {
- result.accept(true);
- }
-
- /**
- * Convenience method for initializing economy
- *
- * @see VaultProvider#initProvider()
- * @see TreasuryProvider#initProvider()
- */
- void initProvider();
-
-}
diff --git a/src/main/java/tsp/headdb/economy/TreasuryProvider.java b/src/main/java/tsp/headdb/economy/TreasuryProvider.java
deleted file mode 100644
index 9d905cf..0000000
--- a/src/main/java/tsp/headdb/economy/TreasuryProvider.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package tsp.headdb.economy;
-
-import me.lokka30.treasury.api.common.service.Service;
-import me.lokka30.treasury.api.common.service.ServiceRegistry;
-import me.lokka30.treasury.api.economy.EconomyProvider;
-import me.lokka30.treasury.api.economy.account.PlayerAccount;
-import me.lokka30.treasury.api.economy.currency.Currency;
-import me.lokka30.treasury.api.economy.response.EconomyException;
-import me.lokka30.treasury.api.economy.response.EconomySubscriber;
-import me.lokka30.treasury.api.economy.transaction.EconomyTransactionInitiator;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-import tsp.headdb.HeadDB;
-import tsp.headdb.util.Log;
-
-import java.math.BigDecimal;
-import java.util.Optional;
-import java.util.function.Consumer;
-
-/**
- * A {@link BasicEconomyProvider} for Treasury
- *
- * @author TheSilentPro
- * @since 4.0.0
- */
-public class TreasuryProvider implements BasicEconomyProvider {
-
- private EconomyProvider provider;
- private EconomyTransactionInitiator> transactionInitiator;
- private Currency currency;
-
- @Override
- public void canPurchase(Player player, BigDecimal cost, Consumer result) {
- EconomySubscriber
- .asFuture(s -> provider.hasPlayerAccount(player.getUniqueId(), s))
- .thenCompose(val -> {
- if (Boolean.TRUE.equals(val)) {
- return EconomySubscriber.asFuture(s -> provider.retrievePlayerAccount(player.getUniqueId(), s));
- } else {
- return EconomySubscriber.asFuture(s -> provider.createPlayerAccount(player.getUniqueId(), s));
- }
- })
- .thenCompose(account -> EconomySubscriber.asFuture(s -> account.retrieveBalance(currency, s)))
- .whenComplete((bal, ex) -> result.accept(bal.compareTo(cost) >= 0));
- }
-
- @Override
- public void charge(Player player, BigDecimal amount, Consumer result) {
- EconomySubscriber
- .asFuture(s -> provider.hasPlayerAccount(player.getUniqueId(), s))
- .thenCompose(val -> {
- if (Boolean.TRUE.equals(val)) {
- return EconomySubscriber.asFuture(s -> provider.retrievePlayerAccount(player.getUniqueId(), s));
- } else {
- return EconomySubscriber.asFuture(s -> provider.createPlayerAccount(player.getUniqueId(), s));
- }
- }).whenComplete((account, ex) -> account.withdrawBalance(
- amount,
- transactionInitiator,
- currency,
- new EconomySubscriber() {
- @Override
- public void succeed(@NotNull BigDecimal bigDecimal) {
- result.accept(true);
- }
-
- @Override
- public void fail(@NotNull EconomyException exception) {
- result.accept(false);
- Log.error(ex);
- }
- }));
- }
-
- @Override
- public void initProvider() {
- Optional> service = ServiceRegistry.INSTANCE.serviceFor(EconomyProvider.class);
-
- if(!service.isPresent()) {
- Log.error("Unable to find a supported economy plugin for Treasury!");
- return;
- }
-
- provider = service.get().get();
- transactionInitiator = EconomyTransactionInitiator.createInitiator(EconomyTransactionInitiator.Type.PLUGIN, "HeadDB");
-
- String rawCurrency = HeadDB.getInstance().getConfig().getString("economy.currency");
- if (rawCurrency == null || rawCurrency.isEmpty()) {
- currency = provider.getPrimaryCurrency();
- } else {
- provider.getCurrencies().stream()
- .filter(c -> c.getIdentifier().equalsIgnoreCase(rawCurrency))
- .findFirst()
- .ifPresentOrElse(c -> currency = c, () -> Log.error("Could not find currency: " + rawCurrency));
- }
- }
-
-}
diff --git a/src/main/java/tsp/headdb/economy/VaultProvider.java b/src/main/java/tsp/headdb/economy/VaultProvider.java
deleted file mode 100644
index 1b7d6b6..0000000
--- a/src/main/java/tsp/headdb/economy/VaultProvider.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package tsp.headdb.economy;
-
-import net.milkbowl.vault.economy.Economy;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.RegisteredServiceProvider;
-import tsp.headdb.util.Log;
-import tsp.headdb.util.Utils;
-
-import java.math.BigDecimal;
-import java.util.function.Consumer;
-
-/**
- * A {@link BasicEconomyProvider} for Vault
- *
- * @author TheSilentPro
- * @since 4.0.0
- */
-public class VaultProvider implements BasicEconomyProvider {
-
- private Economy economy;
-
- @Override
- public void canPurchase(Player player, BigDecimal cost, Consumer result) {
- Utils.async(t -> result.accept(economy.has(player, cost.doubleValue())));
- }
-
- @Override
- public void charge(Player player, BigDecimal amount, Consumer result) {
- Utils.async(t -> result.accept(economy.withdrawPlayer(player, amount.doubleValue()).transactionSuccess()));
- }
-
- public void initProvider() {
- if (!Bukkit.getServer().getPluginManager().isPluginEnabled("Vault")) {
- Log.error("Vault is not installed!");
- return;
- }
-
- RegisteredServiceProvider economyProvider = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
- if (economyProvider == null) {
- Log.error("Could not find vault economy provider!");
- return;
- }
-
- economy = economyProvider.getProvider();
- }
-
- public Economy getProvider() {
- return economy;
- }
-
-}
diff --git a/src/main/java/tsp/headdb/implementation/Category.java b/src/main/java/tsp/headdb/implementation/Category.java
deleted file mode 100644
index a5d1d19..0000000
--- a/src/main/java/tsp/headdb/implementation/Category.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package tsp.headdb.implementation;
-
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-import tsp.headdb.api.HeadAPI;
-
-import javax.annotation.Nullable;
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * Represents a category for heads
- *
- * @author TheSilentPro
- */
-public enum Category {
-
- ALPHABET("alphabet", ChatColor.YELLOW, 20),
- ANIMALS("animals", ChatColor.DARK_AQUA, 21),
- BLOCKS("blocks", ChatColor.DARK_GRAY, 22),
- DECORATION("decoration", ChatColor.LIGHT_PURPLE, 23),
- FOOD_DRINKS("food-drinks", ChatColor.GOLD, 24),
- HUMANS("humans", ChatColor.DARK_BLUE, 29),
- HUMANOID("humanoid", ChatColor.AQUA, 30),
- MISCELLANEOUS("miscellaneous", ChatColor.DARK_GREEN, 31),
- MONSTERS("monsters", ChatColor.RED, 32),
- PLANTS("plants", ChatColor.GREEN, 33);
-
- private final String name;
- private final ChatColor color;
- private final int location;
- private static final Category[] cache = values();
-
- Category(String name, ChatColor color, int location) {
- this.name = name;
- this.color = color;
- this.location = location;
- }
-
- public String getName() {
- return name;
- }
-
- public ChatColor getColor() {
- return color;
- }
-
- public int getLocation() {
- return location;
- }
-
- /**
- * Retrieve the first valid head from a category
- *
- * @return First valid head
- */
- public ItemStack getItem() {
- Optional result = HeadAPI.getHeads(this).stream()
- .filter(Objects::nonNull)
- .findFirst();
-
- if (result.isPresent()) {
- return result.get().getMenuItem();
- } else {
- return new ItemStack(Material.PLAYER_HEAD);
- }
- }
-
- /**
- * Retrieve a {@link Category} by name
- *
- * @param name The name
- * @return The category if it exists. Else it returns null
- */
- @Nullable
- public static Category getByName(String name) {
- for (Category category : cache) {
- if (category.getName().equalsIgnoreCase(name)) {
- return category;
- }
- }
-
- return null;
- }
-
- public static Category[] getCache() {
- return cache;
- }
-
-}
diff --git a/src/main/java/tsp/headdb/implementation/DataSaveTask.java b/src/main/java/tsp/headdb/implementation/DataSaveTask.java
deleted file mode 100644
index 00ac241..0000000
--- a/src/main/java/tsp/headdb/implementation/DataSaveTask.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package tsp.headdb.implementation;
-
-import tsp.headdb.HeadDB;
-
-public class DataSaveTask implements Runnable {
-
- @Override
- public void run() {
- HeadDB.getInstance().getPlayerData().save();
- }
-}
diff --git a/src/main/java/tsp/headdb/implementation/DatabaseUpdateTask.java b/src/main/java/tsp/headdb/implementation/DatabaseUpdateTask.java
deleted file mode 100644
index 413711f..0000000
--- a/src/main/java/tsp/headdb/implementation/DatabaseUpdateTask.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package tsp.headdb.implementation;
-
-import tsp.headdb.api.HeadAPI;
-import tsp.headdb.util.Log;
-
-/**
- * Task that updates the database on an interval
- */
-public class DatabaseUpdateTask implements Runnable {
-
- @Override
- public void run() {
- HeadAPI.getDatabase().update(heads -> Log.info("Fetched " + HeadAPI.getHeads().size() + " heads!"));
- }
-
-}
diff --git a/src/main/java/tsp/headdb/implementation/Head.java b/src/main/java/tsp/headdb/implementation/Head.java
deleted file mode 100644
index 6a0315e..0000000
--- a/src/main/java/tsp/headdb/implementation/Head.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package tsp.headdb.implementation;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import org.apache.commons.lang.Validate;
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.SkullMeta;
-import tsp.headdb.util.Log;
-import tsp.headdb.util.Utils;
-
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
-import java.util.regex.Pattern;
-
-/**
- * Represents a Head that a player can obtain via the database
- *
- * @author TheSilentPro
- */
-public class Head {
-
- public static final Pattern SPLIT = Pattern.compile(",");
- private String name;
- private UUID uuid;
- private String value;
- private Category category;
- private int id;
- private List tags;
- private ItemStack menuItem;
-
- public Head() {}
-
- public Head(int id) {
- this.id = id;
- }
-
- public ItemStack getMenuItem() {
- if (menuItem == null) {
- Validate.notNull(name, "name must not be null!");
- Validate.notNull(uuid, "uuid must not be null!");
- Validate.notNull(value, "value must not be null!");
-
- ItemStack item = new ItemStack(Material.PLAYER_HEAD);
- SkullMeta meta = (SkullMeta) item.getItemMeta();
- meta.setDisplayName(Utils.colorize(category != null ? category.getColor() + name : "&8" + name));
- // set skull owner
- GameProfile profile = new GameProfile(uuid, name);
- profile.getProperties().put("textures", new Property("textures", value));
- Field profileField;
- try {
- profileField = meta.getClass().getDeclaredField("profile");
- profileField.setAccessible(true);
- profileField.set(meta, profile);
- } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) {
- Log.error("Could not set skull owner for " + uuid.toString() + " | Stack Trace:");
- Log.error(ex);
- }
-
- meta.setLore(Arrays.asList(
- Utils.colorize("&cID: " + id),
- Utils.colorize("&e" + buildTagLore(tags)),
- "",
- Utils.colorize("&8Right-Click to add/remove from favorites.")
- ));
-
- item.setItemMeta(meta);
- menuItem = item;
- }
-
- return menuItem;
- }
-
- public String getName() {
- return name;
- }
-
- public UUID getUniqueId() {
- return uuid;
- }
-
- public String getValue() {
- return value;
- }
-
- public Category getCategory() {
- return category;
- }
-
- public int getId() {
- return id;
- }
-
- public List getTags() {
- return tags;
- }
-
- public Head name(String name) {
- this.name = name;
- return this;
- }
-
- public Head uniqueId(UUID uuid) {
- this.uuid = uuid;
- return this;
- }
-
- public Head value(String value) {
- this.value = value;
- return this;
- }
-
- public Head category(Category category) {
- this.category = category;
- return this;
- }
-
- public Head id(int id) {
- this.id = id;
- return this;
- }
-
- public Head tags(String tags) {
- this.tags = Arrays.asList(SPLIT.split(tags));
- return this;
- }
-
- private String buildTagLore(List tags) {
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < tags.size(); i++) {
- builder.append(tags.get(i));
- if (i != tags.size() - 1) {
- builder.append(",");
- }
- }
-
- return builder.toString();
- }
-
-}
diff --git a/src/main/java/tsp/headdb/implementation/HeadDatabase.java b/src/main/java/tsp/headdb/implementation/HeadDatabase.java
deleted file mode 100644
index 8a72208..0000000
--- a/src/main/java/tsp/headdb/implementation/HeadDatabase.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package tsp.headdb.implementation;
-
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.plugin.java.JavaPlugin;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.json.simple.parser.JSONParser;
-import org.json.simple.parser.ParseException;
-import tsp.headdb.HeadDB;
-import tsp.headdb.api.event.DatabaseUpdateEvent;
-import tsp.headdb.util.Log;
-import tsp.headdb.util.Utils;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-import javax.annotation.Nonnull;
-
-/**
- * This is the Database that holds all heads
- *
- * @author TheSilentPro
- */
-// TODO: Optionals instead of null.
-public class HeadDatabase {
-
- private final JavaPlugin plugin;
- private final EnumMap> heads = new EnumMap<>(Category.class);
- private long refresh;
- private int timeout;
- private long updated;
- private int nextId; // Internal only
-
- public HeadDatabase(JavaPlugin plugin) {
- this.plugin = plugin;
- this.refresh = 3600;
- this.timeout = 5000;
- }
-
- public Head getHeadByValue(String value) {
- List fetched = getHeads();
- for (Head head : fetched) {
- if (head.getValue().equals(value)) {
- return head;
- }
- }
-
- return null;
- }
-
- public Head getHeadByID(int id) {
- List fetched = getHeads();
- for (Head head : fetched) {
- if (head.getId() == id) {
- return head;
- }
- }
-
- return null;
- }
-
- public Head getHeadByUniqueId(UUID uuid) {
- List fetched = getHeads();
- for (Head head : fetched) {
- if (head.getUniqueId().equals(uuid)) {
- return head;
- }
- }
-
- return null;
- }
-
- public List getHeadsByTag(String tag) {
- List result = new ArrayList<>();
- List fetched = getHeads();
- tag = tag.toLowerCase(Locale.ROOT);
- for (Head head : fetched) {
- for (String t : head.getTags()) {
- if (t.toLowerCase(Locale.ROOT).contains(tag)) {
- result.add(head);
- }
- }
- }
-
- return result;
- }
-
- public List getHeadsByName(Category category, String name) {
- List result = new ArrayList<>();
- List fetched = getHeads(category);
- for (Head head : fetched) {
- String hName = ChatColor.stripColor(head.getName().toLowerCase(Locale.ROOT));
- if (hName.contains(ChatColor.stripColor(name.toLowerCase(Locale.ROOT)))) {
- result.add(head);
- }
- }
-
- return result;
- }
-
- public List getHeadsByName(String name) {
- List result = new ArrayList<>();
- for (Category category : Category.getCache()) {
- result.addAll(getHeadsByName(category, name));
- }
-
- return result;
- }
-
- @Nonnull
- public List getHeads(Category category) {
- List result = heads.get(category);
- return result != null ? Collections.unmodifiableList(result) : Collections.emptyList();
- }
-
- /**
- * Gets all heads from the cache if available.
- *
- * @return List containing each head in its category.
- */
- @Nonnull
- public List getHeads() {
- List result = new ArrayList<>();
- for (Category category : heads.keySet()) {
- result.addAll(getHeads(category));
- }
- return result;
- }
-
- public void getHeadsNoCache(Consumer