Dieser Commit ist enthalten in:
Silent 2021-12-30 12:50:47 +01:00
Ursprung 5b250a91af
Commit b6a202e379
19 geänderte Dateien mit 365 neuen und 320 gelöschten Zeilen

16
pom.xml
Datei anzeigen

@ -6,7 +6,7 @@
<groupId>tsp.headdb</groupId> <groupId>tsp.headdb</groupId>
<artifactId>HeadDB</artifactId> <artifactId>HeadDB</artifactId>
<version>2.4.5</version> <version>3.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HeadDB</name> <name>HeadDB</name>
@ -43,12 +43,6 @@
<version>1.18-R0.1-SNAPSHOT</version> <version>1.18-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<!-- Mojang Auth Lib --> <!-- Mojang Auth Lib -->
<dependency> <dependency>
<groupId>com.mojang</groupId> <groupId>com.mojang</groupId>
@ -56,12 +50,6 @@
<version>1.5.21</version> <version>1.5.21</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Storage Lib -->
<dependency>
<groupId>com.github.simplix-softworks</groupId>
<artifactId>simplixstorage</artifactId>
<version>3.2.0</version>
</dependency>
<!-- AnvilGUI --> <!-- AnvilGUI -->
<dependency> <dependency>
<groupId>net.wesjd</groupId> <groupId>net.wesjd</groupId>
@ -111,7 +99,7 @@
<configuration> <configuration>
<transformers> <transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>tsp.headdb.HeadDB</mainClass> <mainClass>tsp.headdb.legacy.HeadDB</mainClass>
</transformer> </transformer>
</transformers> </transformers>
</configuration> </configuration>

Datei anzeigen

@ -1,32 +1,34 @@
package tsp.headdb; package tsp.headdb;
import de.leonhard.storage.Config; import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import tsp.headdb.api.HeadAPI; import tsp.headdb.api.HeadAPI;
import tsp.headdb.command.Command_headdb; import tsp.headdb.command.CommandHeadDB;
import tsp.headdb.listener.JoinListener; import tsp.headdb.listener.JoinListener;
import tsp.headdb.listener.PagedPaneListener;
import tsp.headdb.listener.MenuListener; import tsp.headdb.listener.MenuListener;
import tsp.headdb.listener.PagedPaneListener;
import tsp.headdb.storage.PlayerDataFile;
import tsp.headdb.util.Log; import tsp.headdb.util.Log;
import tsp.headdb.util.Metrics; import tsp.headdb.util.Metrics;
import tsp.headdb.util.Storage;
import org.bukkit.plugin.RegisteredServiceProvider;
import net.milkbowl.vault.economy.Economy;
public class HeadDB extends JavaPlugin { public class HeadDB extends JavaPlugin {
private static HeadDB instance; private static HeadDB instance;
private Storage storage; private Economy economy;
private Economy economy = null; private PlayerDataFile playerData;
@Override @Override
public void onEnable() { public void onEnable() {
instance = this; instance = this;
Log.info("Loading HeadDB - " + getDescription().getVersion()); Log.info("Loading HeadDB - " + getDescription().getVersion());
saveDefaultConfig(); saveDefaultConfig();
storage = new Storage().init(this);
if (storage.getConfig().getBoolean("economy.enable")) { this.playerData = new PlayerDataFile("player_data.json");
this.playerData.load();
if (getConfig().getBoolean("economy.enable")) {
Log.debug("Starting economy..."); Log.debug("Starting economy...");
this.economy = this.setupEconomy(); this.economy = this.setupEconomy();
if (this.economy == null) { if (this.economy == null) {
@ -36,29 +38,28 @@ public class HeadDB extends JavaPlugin {
} }
} }
if (storage.getConfig().getBoolean("fetchStartup")) { long refresh = getConfig().getLong("refresh") * 20;
if (storage.getConfig().getBoolean("asyncStartup")) { HeadAPI.getDatabase().setRefresh(refresh);
Log.debug("Initializing Database... (ASYNC)"); Bukkit.getScheduler().runTaskTimerAsynchronously(this, task ->
HeadAPI.getDatabase().updateAsync(); HeadAPI.getDatabase().updateAsync(heads -> Log.info("Fetched " + HeadAPI.getHeads().size() + " heads!")),
} else { 0L, refresh);
Log.debug("Initializing Database... (SYNC)");
HeadAPI.updateDatabase();
}
}
Log.debug("Registering listeners...");
new PagedPaneListener(this);
new MenuListener(this);
new JoinListener(this); new JoinListener(this);
new MenuListener(this);
new PagedPaneListener(this);
Log.debug("Registering commands..."); getCommand("headdb").setExecutor(new CommandHeadDB());
getCommand("headdb").setExecutor(new Command_headdb());
Log.debug("Starting metrics..."); Log.debug("Starting metrics...");
new Metrics(this, 9152); new Metrics(this, 9152);
Log.info("Done!"); Log.info("Done!");
} }
@Override
public void onDisable() {
this.playerData.save();
}
private Economy setupEconomy() { private Economy setupEconomy() {
if (!this.getServer().getPluginManager().isPluginEnabled("Vault")) return null; if (!this.getServer().getPluginManager().isPluginEnabled("Vault")) return null;
@ -68,16 +69,12 @@ public class HeadDB extends JavaPlugin {
return this.economy = economyProvider.getProvider(); return this.economy = economyProvider.getProvider();
} }
public Config getConfiguration() {
return storage.getConfig();
}
public Storage getStorage() {
return storage;
}
public Economy getEconomy() { public Economy getEconomy() {
return this.economy; return economy;
}
public PlayerDataFile getPlayerData() {
return playerData;
} }
public static HeadDB getInstance() { public static HeadDB getInstance() {

Datei anzeigen

@ -23,6 +23,7 @@ public class Head {
private Category category; private Category category;
private int id; private int id;
private List<String> tags; private List<String> tags;
private ItemStack itemStack;
public Head() {} public Head() {}
@ -31,35 +32,39 @@ public class Head {
} }
public ItemStack getItemStack() { public ItemStack getItemStack() {
Validate.notNull(name, "name must not be null!"); if (itemStack == null) {
Validate.notNull(uuid, "uuid must not be null!"); Validate.notNull(name, "name must not be null!");
Validate.notNull(value, "value 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); ItemStack item = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) item.getItemMeta(); SkullMeta meta = (SkullMeta) item.getItemMeta();
meta.setDisplayName(Utils.colorize(category != null ? category.getColor() + name : "&8" + name)); meta.setDisplayName(Utils.colorize(category != null ? category.getColor() + name : "&8" + name));
// set skull owner // set skull owner
GameProfile profile = new GameProfile(uuid, name); GameProfile profile = new GameProfile(uuid, name);
profile.getProperties().put("textures", new Property("textures", value)); profile.getProperties().put("textures", new Property("textures", value));
Field profileField; Field profileField;
try { try {
profileField = meta.getClass().getDeclaredField("profile"); profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true); profileField.setAccessible(true);
profileField.set(meta, profile); profileField.set(meta, profile);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) { } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) {
Log.error("Could not set skull owner for " + uuid.toString() + " | Stack Trace:"); Log.error("Could not set skull owner for " + uuid.toString() + " | Stack Trace:");
ex.printStackTrace(); ex.printStackTrace();
}
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);
itemStack = item;
} }
meta.setLore(Arrays.asList( return itemStack;
Utils.colorize("&cID: " + id),
Utils.colorize("&e" + buildTagLore(tags)),
"",
Utils.colorize("&8Right-Click to add/remove from favorites.")
));
item.setItemMeta(meta);
return item;
} }
public String getName() { public String getName() {
@ -86,36 +91,36 @@ public class Head {
return tags; return tags;
} }
public Head withName(String name) { public Head name(String name) {
this.name = name; this.name = name;
return this; return this;
} }
public Head withUniqueId(UUID uuid) { public Head uniqueId(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
return this; return this;
} }
public Head withValue(String value) { public Head value(String value) {
this.value = value; this.value = value;
return this; return this;
} }
public Head withCategory(Category category) { public Head category(Category category) {
this.category = category; this.category = category;
return this; return this;
} }
public Head withId(int id) { public Head id(int id) {
this.id = id; this.id = id;
return this; return this;
} }
public Head withTags(String tags) { public Head tags(String tags) {
this.tags = Arrays.asList(tags.split(",")); this.tags = Arrays.asList(tags.split(","));
return this; return this;
} }
private String buildTagLore(List<String> tags) { private String buildTagLore(List<String> tags) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (int i = 0; i < tags.size(); i++) { for (int i = 0; i < tags.size(); i++) {
@ -124,7 +129,7 @@ public class Head {
builder.append(","); builder.append(",");
} }
} }
return builder.toString(); return builder.toString();
} }

Datei anzeigen

@ -7,6 +7,7 @@ import tsp.headdb.HeadDB;
import tsp.headdb.database.Category; import tsp.headdb.database.Category;
import tsp.headdb.database.HeadDatabase; import tsp.headdb.database.HeadDatabase;
import tsp.headdb.inventory.InventoryUtils; import tsp.headdb.inventory.InventoryUtils;
import tsp.headdb.storage.PlayerDataFile;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@ -143,77 +144,34 @@ public final class HeadAPI {
public static List<Head> getHeads() { public static List<Head> getHeads() {
return database.getHeads(); return database.getHeads();
} }
/** public static void addFavoriteHead(UUID uuid, String textureValue) {
* Add a {@link Head} to a players favorites HeadDB.getInstance().getPlayerData().modifyFavorite(uuid, textureValue, PlayerDataFile.ModificationType.SET);
*
* @param uuid The UUID of the player
* @param id The ID of the head
*/
public static void addFavoriteHead(UUID uuid, int id) {
List<Integer> favs = HeadDB.getInstance().getConfiguration().getIntegerList(uuid.toString() + ".favorites");
if (!favs.contains(id)) {
favs.add(id);
}
HeadDB.getInstance().getStorage().getPlayerData().set(uuid.toString() + ".favorites", favs);
} }
/** public static void removeFavoriteHead(UUID uuid, String textureValue) {
* Remove a {@link Head} from a players favorites HeadDB.getInstance().getPlayerData().modifyFavorite(uuid, textureValue, PlayerDataFile.ModificationType.REMOVE);
*
* @param uuid The UUID of the player
* @param id The ID of the head
*/
public static void removeFavoriteHead(UUID uuid, int id) {
List<Integer> favs = HeadDB.getInstance().getStorage().getPlayerData().getIntegerList(uuid.toString() + ".favorites");
for (int i = 0; i < favs.size(); i++) {
if (favs.get(i) == id) {
favs.remove(i);
break;
}
}
HeadDB.getInstance().getStorage().getPlayerData().set(uuid.toString() + ".favorites", favs);
} }
/**
* Retrieve a {@link List} of favorite {@link Head} for a player
*
* @param uuid The UUID of the player
* @return List of favorite heads
*/
public static List<Head> getFavoriteHeads(UUID uuid) { public static List<Head> getFavoriteHeads(UUID uuid) {
List<Head> heads = new ArrayList<>(); List<Head> result = new ArrayList<>();
List<Integer> ids = HeadDB.getInstance().getStorage().getPlayerData().getIntegerList(uuid.toString() + ".favorites");
for (int id : ids) { List<String> textures = HeadDB.getInstance().getPlayerData().getFavoriteHeadsByTexture(uuid);
Head head = getHeadByID(id); for (String texture : textures) {
heads.add(head); result.add(HeadAPI.getHeadByValue(texture));
} }
return heads; return result;
} }
/**
* Retrieve a {@link List} of local heads.
* These heads are from players that have joined the server at least once.
*
* @return List of {@link LocalHead}'s
*/
public static List<LocalHead> getLocalHeads() { public static List<LocalHead> getLocalHeads() {
List<LocalHead> heads = new ArrayList<>(); List<LocalHead> result = new ArrayList<>();
for (String key : HeadDB.getInstance().getStorage().getPlayerData().singleLayerKeySet()) { for (String entry : HeadDB.getInstance().getPlayerData().getEntries()) {
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(key)); OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(entry));
heads.add(new LocalHead(player.getUniqueId()) result.add(new LocalHead(player.getUniqueId()).name(player.getName()));
.withName(player.getName()));
} }
return heads; return result;
}
/**
* Update the Head Database
*/
public static boolean updateDatabase() {
return database.update();
} }
} }

Datei anzeigen

@ -68,13 +68,13 @@ public class LocalHead extends Head {
} }
@Override @Override
public LocalHead withUniqueId(UUID uuid) { public LocalHead uniqueId(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
return this; return this;
} }
@Override @Override
public LocalHead withName(String name) { public LocalHead name(String name) {
this.name = name; this.name = name;
return this; return this;
} }

Datei anzeigen

@ -13,7 +13,8 @@ import tsp.headdb.util.Utils;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class Command_headdb implements CommandExecutor { // TODO: Cleaner way to handle this command
public class CommandHeadDB implements CommandExecutor {
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
@ -28,16 +29,16 @@ public class Command_headdb implements CommandExecutor {
} }
Player player = (Player) sender; Player player = (Player) sender;
Utils.sendMessage(player, "Opening &cHead Database"); Utils.sendMessage(player, "&7Opening &cHead Database");
HeadAPI.openDatabase(player); HeadAPI.openDatabase(player);
return true; return true;
} }
String sub = args[0]; String sub = args[0];
if (sub.equalsIgnoreCase("info") || sub.equalsIgnoreCase("i")) { if (sub.equalsIgnoreCase("info") || sub.equalsIgnoreCase("i")) {
Utils.sendMessage(sender, "Running &cHeadDB v" + HeadDB.getInstance().getDescription().getVersion()); Utils.sendMessage(sender, "&7Running &cHeadDB - " + HeadDB.getInstance().getDescription().getVersion());
Utils.sendMessage(sender, "Created by &c" + HeadDB.getInstance().getDescription().getAuthors()); Utils.sendMessage(sender, "&7Created by &c" + HeadDB.getInstance().getDescription().getAuthors());
Utils.sendMessage(sender, "There are currently &c" + HeadAPI.getHeads().size() + " &7heads in the database."); Utils.sendMessage(sender, "&7There are currently &c" + HeadAPI.getHeads().size() + " &7heads in the database.");
return true; return true;
} }
@ -64,7 +65,7 @@ public class Command_headdb implements CommandExecutor {
} }
} }
String name = builder.toString(); String name = builder.toString();
Utils.sendMessage(sender, "Searching for &e" + name); Utils.sendMessage(sender, "&7Searching for &e" + name);
HeadAPI.openSearchDatabase(player, name); HeadAPI.openSearchDatabase(player, name);
return true; return true;
} }
@ -85,7 +86,7 @@ public class Command_headdb implements CommandExecutor {
Player player = (Player) sender; Player player = (Player) sender;
String tag = args[1]; String tag = args[1];
Utils.sendMessage(sender, "Searching for heads with tag &e" + tag); Utils.sendMessage(sender, "&7Searching for heads with tag &e" + tag);
HeadAPI.openTagSearchDatabase(player, tag); HeadAPI.openTagSearchDatabase(player, tag);
return true; return true;
} }
@ -136,38 +137,24 @@ public class Command_headdb implements CommandExecutor {
Utils.sendMessage(sender, "Updating..."); Utils.sendMessage(sender, "Updating...");
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
boolean result = HeadAPI.updateDatabase(); HeadAPI.getDatabase().updateAsync(heads -> {
if (result) { Utils.sendMessage(sender, "&7Done! Took: &a" + TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start) + " &7seconds");
Utils.sendMessage(sender, "&aDone! Took: " + TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start) + " seconds"); Utils.sendMessage(sender, "&7There are &a" + HeadAPI.getHeads() + " &7heads in the database!");
} else { });
Utils.sendMessage(sender, "&cFailed! Check console for errors.");
}
return true;
}
if (sub.equalsIgnoreCase("updateasync") || sub.equalsIgnoreCase("ua")) {
if (!sender.hasPermission("headdb.update")) {
Utils.sendMessage(sender, "&cNo permission!");
return true;
}
Utils.sendMessage(sender, "Updating...");
HeadAPI.getDatabase().updateAsync();
return true; return true;
} }
Utils.sendMessage(sender, " "); Utils.sendMessage(sender, " ");
Utils.sendMessage(sender, "&c&lHeadDB &c- &5Commands"); Utils.sendMessage(sender, "&c&lHeadDB &c- &5Commands");
Utils.sendMessage(sender, "&7&oParameters:&c command &9(aliases)&c arguments... &7- Description"); Utils.sendMessage(sender, "&7&oParameters:&c command &9(aliases)&c arguments... &7- Description");
Utils.sendMessage(sender, " > &c/hdb &7- Opens the database"); Utils.sendMessage(sender, "&7 > &c/hdb &7- Opens the database");
Utils.sendMessage(sender, " > &c/hdb info &9(i) &7- Plugin Information"); Utils.sendMessage(sender, "&7 > &c/hdb info &9(i) &7- Plugin Information");
Utils.sendMessage(sender, " > &c/hdb search &9(s) &c<name> &7- Search for heads matching a name"); Utils.sendMessage(sender, "&7 > &c/hdb search &9(s) &c<name> &7- Search for heads matching a name");
Utils.sendMessage(sender, " > &c/hdb tagsearch &9(ts) &c<tag> &7- Search for heads matching a tag"); Utils.sendMessage(sender, "&7 > &c/hdb tagsearch &9(ts) &c<tag> &7- Search for heads matching a tag");
Utils.sendMessage(sender, " > &c/hdb update &9(u) &7- Forcefully update the database"); Utils.sendMessage(sender, "&7 > &c/hdb update &9(u) &7- Forcefully update the database");
Utils.sendMessage(sender, " > &c/hdb updateasync &9(ua) &7- Forcefully update the database ASYNCHRONOUSLY"); Utils.sendMessage(sender, "&7 > &c/hdb give &9(g) &c<id> <player> &6[amount] &7- Give player a head");
Utils.sendMessage(sender, " > &c/hdb give &9(g) &c<id> <player> &6[amount] &7- Give player a head");
Utils.sendMessage(sender, " "); Utils.sendMessage(sender, " ");
return true; return true;
} }
} }

Datei anzeigen

@ -25,7 +25,7 @@ public enum Category {
private final ChatColor color; private final ChatColor color;
private final int location; private final int location;
private final Map<Category, Head> item = new HashMap<>(); private final Map<Category, Head> item = new HashMap<>();
private static final Category[] values = values(); public static final Category[] cache = values();
Category(String name, ChatColor color, int location) { Category(String name, ChatColor color, int location) {
this.name = name; this.name = name;
@ -55,7 +55,7 @@ public enum Category {
} }
public static Category getByName(String name) { public static Category getByName(String name) {
for (Category category : values) { for (Category category : cache) {
if (category.getName().equalsIgnoreCase(name)) { if (category.getName().equalsIgnoreCase(name)) {
return category; return category;
} }
@ -64,8 +64,4 @@ public enum Category {
return null; return null;
} }
public static Category[] getValues() {
return values;
}
} }

Datei anzeigen

@ -23,8 +23,8 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* This is the Database that holds all heads * This is the Database that holds all heads
@ -127,7 +127,14 @@ public class HeadDatabase {
@Nonnull @Nonnull
public List<Head> getHeads() { public List<Head> getHeads() {
if (HEADS.isEmpty() || isLastUpdateOld()) { if (HEADS.isEmpty() || isLastUpdateOld()) {
update(); // Technically this should never be reached due to the update task in the main class.
updateAsync(result -> {
if (result != null) {
for (Category category : result.keySet()) {
HEADS.put(category, result.get(category));
}
}
});
} }
List<Head> heads = new ArrayList<>(); List<Head> heads = new ArrayList<>();
@ -137,92 +144,80 @@ public class HeadDatabase {
return heads; return heads;
} }
/** public void getHeadsNoCacheAsync(Consumer<Map<Category, List<Head>>> resultSet) {
* Gets all heads from the api provider Bukkit.getScheduler().runTaskAsynchronously(plugin, task -> {
* Log.debug("[" + plugin.getName() + "] Updating database... ");
* @return Map containing each head in its category. Returns null if the fetching failed. Map<Category, List<Head>> result = new HashMap<>();
*/ Category[] categories = Category.cache;
@Nullable
public Map<Category, List<Head>> getHeadsNoCache() {
Map<Category, List<Head>> result = new HashMap<>();
Category[] categories = Category.getValues();
int id = 1; int id = 1;
for (Category category : categories) { for (Category category : categories) {
Log.debug("Caching heads from: " + category.getName()); Log.debug("Caching heads from: " + category.getName());
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
List<Head> heads = new ArrayList<>(); List<Head> heads = new ArrayList<>();
try { try {
String line; String line;
StringBuilder response = new StringBuilder(); StringBuilder response = new StringBuilder();
URLConnection connection = new URL("https://minecraft-heads.com/scripts/api.php?cat=" + category.getName() + "&tags=true").openConnection(); URLConnection connection = new URL("https://minecraft-heads.com/scripts/api.php?cat=" + category.getName() + "&tags=true").openConnection();
connection.setConnectTimeout(timeout); connection.setConnectTimeout(timeout);
connection.setRequestProperty("User-Agent", plugin.getName() + "-DatabaseUpdater"); connection.setRequestProperty("User-Agent", plugin.getName() + "-DatabaseUpdater");
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
while ((line = in.readLine()) != null) { while ((line = in.readLine()) != null) {
response.append(line); response.append(line);
}
} }
} JSONParser parser = new JSONParser();
JSONParser parser = new JSONParser(); JSONArray array = (JSONArray) parser.parse(response.toString());
JSONArray array = (JSONArray) parser.parse(response.toString()); for (Object o : array) {
for (Object o : array) { JSONObject obj = (JSONObject) o;
JSONObject obj = (JSONObject) o; String rawUUID = obj.get("uuid").toString();
String rawUUID = obj.get("uuid").toString();
UUID uuid; UUID uuid;
if (Utils.validateUniqueId(rawUUID)) { if (Utils.validateUniqueId(rawUUID)) {
uuid = UUID.fromString(rawUUID); uuid = UUID.fromString(rawUUID);
} else { } else {
Log.debug("UUID " + rawUUID + " is invalid. Using random one for head id: " + id); uuid = UUID.randomUUID();
uuid = UUID.randomUUID(); }
Head head = new Head(id)
.name(obj.get("name").toString())
.uniqueId(uuid)
.value(obj.get("value").toString())
.tags(obj.get("tags") != null ? obj.get("tags").toString() : "None")
.category(category);
id++;
heads.add(head);
} }
Head head = new Head(id) long elapsed = (System.currentTimeMillis() - start);
.withName(obj.get("name").toString()) Log.debug(category.getName() + " -> Done! Time: " + elapsed + "ms (" + TimeUnit.MILLISECONDS.toSeconds(elapsed) + "s)");
.withUniqueId(uuid) } catch (ParseException | IOException e) {
.withValue(obj.get("value").toString()) Log.error("[" + plugin.getName() + "] Failed to fetch heads (no-cache) | Stack Trace:");
.withTags(obj.get("tags") != null ? obj.get("tags").toString() : "None") e.printStackTrace();
.withCategory(category);
id++;
heads.add(head);
} }
long elapsed = (System.currentTimeMillis() - start); updated = System.nanoTime();
Log.debug(category.getName() + " -> Done! Time: " + elapsed + "ms (" + TimeUnit.MILLISECONDS.toSeconds(elapsed) + "s)"); result.put(category, heads);
} catch (ParseException | IOException e) {
Log.error("Failed to fetch heads (no-cache) | Stack Trace:");
e.printStackTrace();
return null;
} }
updated = System.nanoTime(); resultSet.accept(result);
result.put(category, heads); });
}
return result;
} }
/** public void updateAsync(Consumer<Map<Category, List<Head>>> result) {
* Updates the cached heads Bukkit.getScheduler().runTaskAsynchronously(plugin, task -> getHeadsNoCacheAsync(heads -> {
* if (heads == null) {
* @return Returns true if the update was successful. Log.error("[" + plugin.getName() + "] Failed to update database! Check above for any errors.");
*/ result.accept(null);
public boolean update() { return;
Map<Category, List<Head>> heads = getHeadsNoCache(); }
if (heads == null) {
Log.error("Failed to update database! Check above for any errors.");
return false;
}
HEADS.clear(); HEADS.clear();
HEADS.putAll(heads); HEADS.putAll(heads);
return true; result.accept(heads);
} }));
public void updateAsync() {
Bukkit.getScheduler().runTaskAsynchronously(plugin, this::update);
} }
/** /**

Datei anzeigen

@ -4,7 +4,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import tsp.headdb.api.Head; import tsp.headdb.api.Head;
/** /**
@ -62,7 +61,7 @@ public class PlayerHeadPurchaseEvent extends Event implements Cancellable {
} }
@Override @Override
public @NotNull HandlerList getHandlers() { public HandlerList getHandlers() {
return handlerList; return handlerList;
} }

Datei anzeigen

@ -33,8 +33,8 @@ public class InventoryUtils {
if (uiLocation.containsKey(category)) return uiLocation.get(category); if (uiLocation.containsKey(category)) return uiLocation.get(category);
// Try to get the value from the config file. // Try to get the value from the config file.
if (HeadDB.getInstance().getConfiguration().contains("ui.category." + category + ".location")) { if (HeadDB.getInstance().getConfig().contains("ui.category." + category + ".location")) {
uiLocation.put(category, HeadDB.getInstance().getConfiguration().getInt("ui.category." + category + ".location")); uiLocation.put(category, HeadDB.getInstance().getConfig().getInt("ui.category." + category + ".location"));
return uiLocation.get(category); return uiLocation.get(category);
} }
@ -48,8 +48,8 @@ public class InventoryUtils {
if (uiItem.containsKey(category)) return uiItem.get(category); if (uiItem.containsKey(category)) return uiItem.get(category);
// Try to get a head from the config file. // Try to get a head from the config file.
if (HeadDB.getInstance().getConfiguration().contains("ui.category." + category + ".head")) { if (HeadDB.getInstance().getConfig().contains("ui.category." + category + ".head")) {
int id = HeadDB.getInstance().getConfiguration().getInt("ui.category." + category + ".head"); int id = HeadDB.getInstance().getConfig().getInt("ui.category." + category + ".head");
Head head = HeadAPI.getHeadByID(id); Head head = HeadAPI.getHeadByID(id);
if (head != null) { if (head != null) {
uiItem.put(category, head.getItemStack()); uiItem.put(category, head.getItemStack());
@ -58,8 +58,8 @@ public class InventoryUtils {
} }
// Try to get an item from the config file. // Try to get an item from the config file.
if (HeadDB.getInstance().getConfiguration().contains("ui.category." + category + ".item")) { if (HeadDB.getInstance().getConfig().contains("ui.category." + category + ".item")) {
String cfg = HeadDB.getInstance().getConfiguration().getString("ui.category." + category + ".item"); String cfg = HeadDB.getInstance().getConfig().getString("ui.category." + category + ".item");
Material mat = Material.matchMaterial(cfg); Material mat = Material.matchMaterial(cfg);
// AIR is allowed as the fill material for the menu, but not as a category item. // AIR is allowed as the fill material for the menu, but not as a category item.
@ -112,9 +112,9 @@ public class InventoryUtils {
purchaseHead(player, head, 1, head.getCategory().getName(), head.getName()); purchaseHead(player, head, 1, head.getCategory().getName(), head.getName());
} }
if (e.getClick() == ClickType.RIGHT) { if (e.getClick() == ClickType.RIGHT) {
HeadAPI.removeFavoriteHead(player.getUniqueId(), head.getId()); HeadAPI.removeFavoriteHead(player.getUniqueId(), head.getValue());
openFavoritesMenu(player); openFavoritesMenu(player);
Utils.sendMessage(player, "Removed &e" + head.getName() + " &7from favorites."); Utils.sendMessage(player, "&7Removed &e" + head.getName() + " &7from favorites.");
} }
})); }));
} }
@ -136,8 +136,8 @@ public class InventoryUtils {
purchaseHead(player, head, 1, head.getCategory().getName(), head.getName()); purchaseHead(player, head, 1, head.getCategory().getName(), head.getName());
} }
if (e.getClick() == ClickType.RIGHT) { if (e.getClick() == ClickType.RIGHT) {
HeadAPI.addFavoriteHead(player.getUniqueId(), head.getId()); HeadAPI.addFavoriteHead(player.getUniqueId(), head.getValue());
Utils.sendMessage(player, "Added &e" + head.getName() + " &7to favorites."); Utils.sendMessage(player, "&7Added &e" + head.getName() + " &7to favorites.");
} }
})); }));
} }
@ -160,8 +160,8 @@ public class InventoryUtils {
purchaseHead(player, head, 1, head.getCategory().getName(), head.getName()); purchaseHead(player, head, 1, head.getCategory().getName(), head.getName());
} }
if (e.getClick() == ClickType.RIGHT) { if (e.getClick() == ClickType.RIGHT) {
HeadAPI.addFavoriteHead(player.getUniqueId(), head.getId()); HeadAPI.addFavoriteHead(player.getUniqueId(), head.getValue());
Utils.sendMessage(player, "Added &e" + head.getName() + " &7to favorites."); Utils.sendMessage(player, "&7Added &e" + head.getName() + " &7to favorites.");
} }
})); }));
} }
@ -183,8 +183,8 @@ public class InventoryUtils {
purchaseHead(player, head, 1, head.getCategory().getName(), head.getName()); purchaseHead(player, head, 1, head.getCategory().getName(), head.getName());
} }
if (e.getClick() == ClickType.RIGHT) { if (e.getClick() == ClickType.RIGHT) {
HeadAPI.addFavoriteHead(player.getUniqueId(), head.getId()); HeadAPI.addFavoriteHead(player.getUniqueId(), head.getValue());
Utils.sendMessage(player, "Added &e" + head.getName() + " &8to favorites."); Utils.sendMessage(player, "&7Added &e" + head.getName() + " &7to favorites.");
} }
})); }));
} }
@ -195,7 +195,7 @@ public class InventoryUtils {
public static void openDatabase(Player player) { public static void openDatabase(Player player) {
Inventory inventory = Bukkit.createInventory(null, 54, Utils.colorize("&c&lHeadDB &8(" + HeadAPI.getHeads().size() + ")")); Inventory inventory = Bukkit.createInventory(null, 54, Utils.colorize("&c&lHeadDB &8(" + HeadAPI.getHeads().size() + ")"));
for (Category category : Category.getValues()) { for (Category category : Category.cache) {
ItemStack item = getUIItem(category.getName(), category.getItem()); ItemStack item = getUIItem(category.getName(), category.getItem());
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName(Utils.colorize(category.getColor() + "&l" + category.getName().toUpperCase())); meta.setDisplayName(Utils.colorize(category.getColor() + "&l" + category.getName().toUpperCase()));
@ -273,7 +273,7 @@ public class InventoryUtils {
if (player.hasPermission("headdb.economy.free") || player.hasPermission("headdb.economy." + category + ".free")) return 0; if (player.hasPermission("headdb.economy.free") || player.hasPermission("headdb.economy." + category + ".free")) return 0;
// Otherwise, get the price for this category from the config file. // Otherwise, get the price for this category from the config file.
return HeadDB.getInstance().getConfiguration().getDouble("economy.cost." + category); return HeadDB.getInstance().getConfig().getDouble("economy.cost." + category);
} }
public static boolean processPayment(Player player, int amount, String category, String description) { public static boolean processPayment(Player player, int amount, String category, String description) {
@ -282,7 +282,7 @@ public class InventoryUtils {
// If economy is disabled or no plugin is present, the item is free. // If economy is disabled or no plugin is present, the item is free.
// Don't mention receiving it for free in this case, since it is always free. // Don't mention receiving it for free in this case, since it is always free.
if (economy == null) { if (economy == null) {
player.sendMessage(String.format("You received %d x %s!", amount, description)); Utils.sendMessage(player, String.format("&7You received &e%d &7x &e%s!", amount, description));
return true; return true;
} }
@ -292,15 +292,15 @@ public class InventoryUtils {
if (cost > 0) { if (cost > 0) {
if (economy.has(player, cost)) { if (economy.has(player, cost)) {
economy.withdrawPlayer(player, cost); economy.withdrawPlayer(player, cost);
player.sendMessage(String.format("You purchased %d x %s for %.2f %s!", amount, description, cost, economy.currencyNamePlural())); player.sendMessage(String.format("&7You purchased &e%d &7x &e%s &7for &e%.2f %s!", amount, description, cost, economy.currencyNamePlural()));
return true; return true;
} }
player.sendMessage(String.format("You do not have enough %s to purchase %d x %s.", economy.currencyNamePlural(), amount, description)); Utils.sendMessage(player, String.format("&7You do not have enough &e%s &cto purchase &e%d &cx &e%s.", economy.currencyNamePlural(), amount, description));
return false; return false;
} }
// Otherwise, the item is free. // Otherwise, the item is free.
player.sendMessage(String.format("You received %d x %s for free!", amount, description)); Utils.sendMessage(player, String.format("&7You received &e%d &7x &e%s &7for &efree&7!", amount, description));
return true; return true;
} }

Datei anzeigen

@ -4,19 +4,21 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import tsp.headdb.HeadDB; import tsp.headdb.HeadDB;
import tsp.headdb.storage.PlayerDataFile;
public class JoinListener implements Listener { public class JoinListener implements Listener {
public JoinListener(HeadDB plugin) { public JoinListener(HeadDB plugin) {
// If local heads are disabled, there is no need for this listener. // If local heads are disabled, there is no need for this listener.
if (HeadDB.getInstance().getConfiguration().getBoolean("localHeads")) { if (HeadDB.getInstance().getConfig().getBoolean("localHeads")) {
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }
} }
@EventHandler @EventHandler
public void onJoin(PlayerJoinEvent e) { public void onJoin(PlayerJoinEvent e) {
HeadDB.getInstance().getStorage().getPlayerData().set(e.getPlayer().getUniqueId().toString() + ".username", e.getPlayer().getName()); HeadDB.getInstance().getPlayerData().modifyUsername(e.getPlayer().getUniqueId(), e.getPlayer().getName(), PlayerDataFile.ModificationType.SET);
HeadDB.getInstance().getPlayerData().save();
} }
} }

Datei anzeigen

@ -44,6 +44,7 @@ public class MenuListener implements Listener {
player.closeInventory(); player.closeInventory();
return; return;
} }
player.sendMessage("Clicked on favorites!");
InventoryUtils.openFavoritesMenu(player); InventoryUtils.openFavoritesMenu(player);
return; return;
} }

Datei anzeigen

@ -0,0 +1,149 @@
package tsp.headdb.storage;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import tsp.headdb.HeadDB;
import tsp.headdb.util.Log;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class PlayerDataFile {
private final File file;
private JsonObject main;
public PlayerDataFile(String name) {
HeadDB plugin = HeadDB.getInstance();
// This check avoids warning in console
if (plugin.getResource(name) != null && !new File(plugin.getDataFolder() + "/" + name).exists()) {
plugin.saveResource(name, false);
}
this.file = new File(plugin.getDataFolder() + "/" + name);
}
@Nonnull
public List<String> getFavoriteHeadsByTexture(UUID uuid) {
List<String> result = new ArrayList<>();
if (main.has(uuid.toString()) && main.get(uuid.toString()).getAsJsonObject().has("favorites")) {
JsonArray favorites = main.get(uuid.toString()).getAsJsonObject().get("favorites").getAsJsonArray();
for (int i = 0; i < favorites.size(); i++) {
String str = favorites.get(i).toString();
Log.debug("str: " + str.substring(1, str.length() - 1));
result.add(str.substring(1, str.length() - 1));
}
}
return result;
}
public void modifyFavorite(UUID uuid, String textureValue, ModificationType modificationType) {
JsonObject userObject;
if (main.has(uuid.toString())) {
userObject = main.get(uuid.toString()).getAsJsonObject();
} else {
userObject = new JsonObject();
}
JsonArray favorites;
if (userObject.has("favorites")) {
favorites = userObject.get("favorites").getAsJsonArray();
} else {
favorites = new JsonArray();
}
JsonPrimitive value = new JsonPrimitive(textureValue);
if (modificationType == ModificationType.SET) {
if (favorites.contains(value)) {
// Head is already in the list, no need to modify it
return;
}
favorites.add(value);
} else if (modificationType == ModificationType.REMOVE) {
if (!favorites.contains(value)) {
// Head is not in the list, no need to modify it
return;
}
favorites.remove(value);
}
userObject.add("favorites", favorites);
main.add(uuid.toString(), userObject);
}
@Nullable
public String getUsername(UUID uuid) {
return main.get(uuid.toString()).getAsJsonObject().get("username").toString();
}
public Set<String> getEntries() {
return main.keySet();
}
public void modifyUsername(UUID uuid, String username, ModificationType modificationType) {
JsonObject userObject;
if (main.has(uuid.toString())) {
userObject = main.get(uuid.toString()).getAsJsonObject();
} else {
userObject = new JsonObject();
}
if (modificationType == ModificationType.SET) {
userObject.addProperty("username", username);
} else {
userObject.remove("username");
}
main.add(uuid.toString(), userObject);
}
public void load() {
try {
main = new JsonParser().parse(new FileReader(file)).getAsJsonObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public void save() {
FileWriter writer;
try {
writer = new FileWriter(file);
writer.write(main.toString());
writer.close();
} catch (IOException e) {
Log.error("Failed to save player_data.json contents!");
Log.error(e);
}
}
public File getFile() {
return file;
}
public void validateFile() {
if (!file.exists()) {
HeadDB.getInstance().saveResource(file.getName(), false);
}
}
public enum ModificationType {
SET,
REMOVE;
}
}

Datei anzeigen

@ -35,7 +35,7 @@ public class Log {
} }
public static void log(LogLevel level, String message) { public static void log(LogLevel level, String message) {
if (level == LogLevel.DEBUG && !HeadDB.getInstance().getStorage().getConfig().getBoolean("debug")) { if (level == LogLevel.DEBUG && !HeadDB.getInstance().getConfig().getBoolean("debug")) {
return; return;
} }
Bukkit.getConsoleSender().sendMessage(Utils.colorize("&7[&9&l" + name + "&7] " + level.getColor() + "[" + level.name() + "]: " + message)); Bukkit.getConsoleSender().sendMessage(Utils.colorize("&7[&9&l" + name + "&7] " + level.getColor() + "[" + level.name() + "]: " + message));

Datei anzeigen

@ -1,27 +0,0 @@
package tsp.headdb.util;
import de.leonhard.storage.Config;
import de.leonhard.storage.Json;
import de.leonhard.storage.LightningBuilder;
import org.bukkit.plugin.java.JavaPlugin;
public class Storage {
private Config config;
private Json playerdata;
public Storage init(JavaPlugin plugin) {
config = LightningBuilder.fromPath("config.yml", plugin.getDataFolder().getAbsolutePath()).createConfig().addDefaultsFromInputStream();
playerdata = LightningBuilder.fromPath("playerdata.json", plugin.getDataFolder().getAbsolutePath()).createJson();
return this;
}
public Config getConfig() {
return config;
}
public Json getPlayerData() {
return playerdata;
}
}

Datei anzeigen

@ -24,7 +24,7 @@ public class Utils {
} }
public static String colorize(String string) { public static String colorize(String string) {
return ChatColor.translateAlternateColorCodes('&', ChatColor.GRAY + string); return ChatColor.translateAlternateColorCodes('&', string);
} }
} }

Datei anzeigen

@ -1,13 +1,7 @@
# When enabled heads will be fetched from startup, otherwise when the /hdb command is ran # How often the database should be updated in seconds.
fetchStartup: true
# When enabled, heads will be fetched async (Startup Only)
asyncStartup: true
# If the cached heads are older than these amount of seconds, the plugin will refresh the database
refresh: 3600 refresh: 3600
# If local heads should be enabled. Only keeps track of joined players when enabled! # If local heads should be enabled. Only starts keeping track of joined players when enabled!
localHeads: true localHeads: true
# Economy options # Economy options

Datei anzeigen

@ -0,0 +1 @@
{}

Datei anzeigen

@ -11,7 +11,7 @@ commands:
headdb: headdb:
usage: /headdb <arguments> usage: /headdb <arguments>
description: Open the database description: Open the database
aliases: [hdb, headdatabase] aliases: [hdb, headdatabase, headmenu]
permissions: permissions:
headdb.admin: headdb.admin: