diff --git a/.gitignore b/.gitignore
index 438e9c1..50c47b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@ target/
src/test/
dependency-reduced-pom.xml
+build.properties
+build/
.classpath
.project
diff --git a/LICENSE b/LICENSE
index 4012c74..54f3fb5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -14,7 +14,7 @@ copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
diff --git a/README.md b/README.md
index e553736..5ef191f 100644
--- a/README.md
+++ b/README.md
@@ -10,4 +10,4 @@ You may report issues on the [Issue Tracker](https://github.com/TheSilentPro/Hea
# API
All API methods can be found in the [HeadAPI](https://github.com/TheSilentPro/HeadDB/blob/master/src/main/java/tsp/headdb/api/HeadAPI.java) class.
-Alternatevly you may view the [javadocs](https://javadocs.pages.dev/headdb/4.0.0/tsp/headdb/api/HeadAPI).
+Alternatively you may view the [javadocs](https://javadocs.pages.dev/headdb/4.0.0/tsp/headdb/api/HeadAPI).
diff --git a/pom.xml b/pom.xml
index 3191aa6..ea96730 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,14 +9,22 @@
5.0.0
jar
+ HeadDB
+ Database with thousands of heads
+
UTF-8
17
17
+ TheSilentPro (Silent)
+ ${maven.build.timestamp}
- HeadDB
- Database with thousands of heads
+
+ scm:git:git@github.com:TheSilentPro/HeadDB.git
+ scm:git:git@github.com:TheSilentPro/HeadDB.git
+ git@github.com:TheSilentPro/HeadDB.git
+
@@ -63,15 +71,10 @@
-
- net.wesjd
- anvilgui
- 1.5.3-SNAPSHOT
-
com.github.TheSilentPro
SmartPlugin
- efc139dd46
+ e565e96a72
com.github.TheSilentPro
@@ -101,7 +104,8 @@
- HeadDB
+ ${project.name}
+
src/main/resources
@@ -110,6 +114,51 @@
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.10.1
+
+
+ ${maven.compiler.target}
+
+
+
+
+
+ org.codehaus.mojo
+ buildnumber-maven-plugin
+ 3.0.0
+
+
+ build-properties
+ validate
+
+ create
+ create-metadata
+
+
+
+
+ true
+ true
+
+ ${basedir}/build/buildNumber.properties
+ ${basedir}/build
+ build.properties
+
+ true
+ 7
+ 0
+
+ - buildNumber
+ - timestamp
+ - scmVersion
+
+
+
+
org.apache.maven.plugins
@@ -136,7 +185,37 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.3.2
+ 3.4.1
+
+
+ javadoc-generate
+ package
+
+ javadoc
+
+
+
+
+ public
+ none
+
+
+ org.spigotmc
+ spigot-api
+ 1.19.2-R0.1-SNAPSHOT
+
+
+ com.github.TheSilentPro
+ SmartPlugin
+ e565e96a72
+
+
+ com.github.TheSilentPro
+ Warehouse
+ f40f72cb19
+
+
+
diff --git a/src/main/java/tsp/headdb/HeadDB.java b/src/main/java/tsp/headdb/HeadDB.java
index 5a8439b..7449ea6 100644
--- a/src/main/java/tsp/headdb/HeadDB.java
+++ b/src/main/java/tsp/headdb/HeadDB.java
@@ -2,14 +2,20 @@ package tsp.headdb;
import tsp.headdb.core.command.CommandCategory;
import tsp.headdb.core.command.CommandHelp;
+import tsp.headdb.core.command.CommandInfo;
+import tsp.headdb.core.command.CommandLanguage;
import tsp.headdb.core.command.CommandMain;
import tsp.headdb.core.command.CommandManager;
import tsp.headdb.core.command.CommandSearch;
+import tsp.headdb.core.command.CommandSettings;
+import tsp.headdb.core.command.CommandTexture;
+import tsp.headdb.core.command.CommandUpdate;
import tsp.headdb.core.listener.PlayerJoinListener;
import tsp.headdb.core.storage.Storage;
import tsp.headdb.core.task.UpdateTask;
+import tsp.headdb.core.util.BuildProperties;
import tsp.smartplugin.SmartPlugin;
import tsp.smartplugin.inventory.PaneListener;
import tsp.smartplugin.localization.TranslatableLocalization;
@@ -22,6 +28,7 @@ public class HeadDB extends SmartPlugin {
private static HeadDB instance;
private PluginLogger logger;
+ private BuildProperties buildProperties;
private TranslatableLocalization localization;
private CommandManager commandManager;
private Storage storage;
@@ -31,19 +38,19 @@ public class HeadDB extends SmartPlugin {
instance = this;
instance.logger = new PluginLogger(this, getConfig().getBoolean("debug"));
instance.logger.info("Loading HeadDB - " + instance.getDescription().getVersion());
+ instance.buildProperties = new BuildProperties(this);
instance.saveDefaultConfig();
- instance.commandManager = new CommandManager();
new UpdateTask(getConfig().getLong("refresh", 3600L)).schedule(this);
-
instance.logger.info("Loaded " + loadLocalization() + " languages!");
instance.storage = new Storage();
- instance.storage.load();
+ //instance.storage.load();
new PaneListener(this);
new PlayerJoinListener();
+ instance.commandManager = new CommandManager();
loadCommands();
//noinspection ConstantConditions
instance.getCommand("headdb").setExecutor(new CommandMain());
@@ -74,6 +81,11 @@ public class HeadDB extends SmartPlugin {
new CommandHelp().register();
new CommandCategory().register();
new CommandSearch().register();
+ new CommandUpdate().register();
+ new CommandTexture().register();
+ new CommandLanguage().register();
+ new CommandSettings().register();
+ new CommandInfo().register();
}
public Storage getStorage() {
@@ -88,6 +100,10 @@ public class HeadDB extends SmartPlugin {
return localization;
}
+ public BuildProperties getBuildProperties() {
+ return buildProperties;
+ }
+
public PluginLogger getLog() {
return logger;
}
diff --git a/src/main/java/tsp/headdb/core/api/HeadAPI.java b/src/main/java/tsp/headdb/core/api/HeadAPI.java
index 2c227d6..ec14183 100644
--- a/src/main/java/tsp/headdb/core/api/HeadAPI.java
+++ b/src/main/java/tsp/headdb/core/api/HeadAPI.java
@@ -11,8 +11,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
public final class HeadAPI {
@@ -20,21 +18,25 @@ public final class HeadAPI {
private static final HeadDatabase database = new HeadDatabase(HeadDB.getInstance(), HeadProvider.HEAD_STORAGE);
- public static synchronized Optional getById(int id) {
- return getHeads().filter(head -> head.getId() == id).findFirst();
+ public static synchronized Optional getHeadById(int id) {
+ return getHeads().stream().filter(head -> head.getId() == id).findAny();
}
- public static synchronized Stream getHeads() {
+ public static synchronized Optional getHeadByTexture(String texture) {
+ return getHeads().stream().filter(head -> head.getTexture().equals(texture)).findAny();
+ }
+
+ public static List getHeads() {
List result = new ArrayList<>();
for (Category category : getHeadsMap().keySet()) {
- result.addAll(getHeads(category).collect(Collectors.toList()));
+ result.addAll(getHeads(category));
}
- return result.stream();
+ return result;
}
- public static synchronized Stream getHeads(Category category) {
- return getHeadsMap().get(category).stream();
+ public static List getHeads(Category category) {
+ return getHeadsMap().get(category);
}
public static synchronized Map> getHeadsMap() {
@@ -42,7 +44,7 @@ public final class HeadAPI {
}
public static int getTotalHeads() {
- return database.getSize();
+ return getHeads().size();
}
public static HeadDatabase getDatabase() {
diff --git a/src/main/java/tsp/headdb/core/command/CommandCategory.java b/src/main/java/tsp/headdb/core/command/CommandCategory.java
index 4958abf..2c2e453 100644
--- a/src/main/java/tsp/headdb/core/command/CommandCategory.java
+++ b/src/main/java/tsp/headdb/core/command/CommandCategory.java
@@ -2,23 +2,19 @@ package tsp.headdb.core.command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.bukkit.inventory.ItemStack;
import tsp.headdb.HeadDB;
import tsp.headdb.core.api.HeadAPI;
import tsp.headdb.core.util.Utils;
import tsp.headdb.implementation.category.Category;
import tsp.headdb.implementation.head.Head;
-import tsp.smartplugin.inventory.Button;
-import tsp.smartplugin.inventory.paged.PagedPane;
+import tsp.smartplugin.inventory.PagedPane;
import java.util.List;
-import java.util.stream.Collectors;
public class CommandCategory extends SubCommand {
public CommandCategory() {
- super("open", new String[]{"category", "c"});
+ super("open", new String[]{"o"});
}
@Override
@@ -35,17 +31,17 @@ public class CommandCategory extends SubCommand {
return;
}
- int page = 1;
- if (args[2] != null) {
+ int page = 0;
+ if (args.length >= 3) {
try {
- page = Integer.parseInt(args[2]);
+ page = Integer.parseInt(args[2]) - 1;
} catch (NumberFormatException ignored) {}
}
- List heads = HeadAPI.getHeads(category).collect(Collectors.toList());
- PagedPane main = new PagedPane(6, 6, Utils.translateTitle(getLocalization().getMessage(player.getUniqueId(), "menu.category.name").orElse(category.getName()), heads.size(), category.getName()));
+ List heads = HeadAPI.getHeads(category);
+ PagedPane main = Utils.createPaged(player, Utils.translateTitle(getLocalization().getMessage(player.getUniqueId(), "menu.category.name").orElse(category.getName()), heads.size(), category.getName()));
Utils.addHeads(player, category, main, heads);
- if (page > main.getPageAmount()) {
+ if (page < 0 || page > main.getPageAmount()) {
getLocalization().sendMessage(player.getUniqueId(), "invalidPageIndex", msg -> msg.replace("%pages%", String.valueOf(main.getPageAmount())));
return;
}
diff --git a/src/main/java/tsp/headdb/core/command/CommandHelp.java b/src/main/java/tsp/headdb/core/command/CommandHelp.java
index a5f882d..2828bd2 100644
--- a/src/main/java/tsp/headdb/core/command/CommandHelp.java
+++ b/src/main/java/tsp/headdb/core/command/CommandHelp.java
@@ -6,7 +6,7 @@ import tsp.smartplugin.player.PlayerUtils;
public class CommandHelp extends SubCommand {
public CommandHelp() {
- super("help");
+ super("help", new String[]{"h"});
}
@Override
@@ -15,7 +15,13 @@ public class CommandHelp extends SubCommand {
PlayerUtils.sendMessage(sender, "&7Format: /hdb &9(aliases) &c &7- Description");
PlayerUtils.sendMessage(sender, "&7Required: &c<> &7| Optional: &b[]");
PlayerUtils.sendMessage(sender, " ");
- PlayerUtils.sendMessage(sender, "&7/hdb &9open(category|c) &c &b[page] &7- Open a specific category.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9info(i) &7- Show plugin information.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9open(o) &c &b[page] &7- Open a specific category.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9search(s) &b(id:|tg:)&c &7- Search for specific heads.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9update(u) &7- Manually update the database.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9language(l) &7- Change your language.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9settings(st) &7- Open the settings menu.");
+ PlayerUtils.sendMessage(sender, "&7/hdb &9texture(t) &7- Get the texture for the head your item.");
PlayerUtils.sendMessage(sender, "&7<===============================================================>");
}
diff --git a/src/main/java/tsp/headdb/core/command/CommandInfo.java b/src/main/java/tsp/headdb/core/command/CommandInfo.java
new file mode 100644
index 0000000..4db5fd4
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandInfo.java
@@ -0,0 +1,27 @@
+package tsp.headdb.core.command;
+
+import org.bukkit.command.CommandSender;
+import tsp.headdb.HeadDB;
+import tsp.headdb.core.util.BuildProperties;
+import tsp.smartplugin.player.PlayerUtils;
+
+public class CommandInfo extends SubCommand {
+
+ public CommandInfo() {
+ super("info", new String[]{"i"});
+ }
+
+ @Override
+ public void handle(CommandSender sender, String[] args) {
+ if (HeadDB.getInstance().getConfig().getBoolean("showAdvancedPluginInfo")) {
+ BuildProperties build = HeadDB.getInstance().getBuildProperties();
+ PlayerUtils.sendMessage(sender, "&7Running &6HeadDB - " + build.getVersion() + " &7(&6Build " + build.getBuildNumber() + "&7)");
+ PlayerUtils.sendMessage(sender, "&7Created by &6" + HeadDB.getInstance().getDescription().getAuthors());
+ PlayerUtils.sendMessage(sender, "&7Compiled on &6" + build.getTimestamp() + " &7by &6" + build.getAuthor());
+ } else {
+ PlayerUtils.sendMessage(sender, "&7Running &6HeadDB &7by &6TheSilentPro (Silent)");
+ PlayerUtils.sendMessage(sender, "&7GitHub: &6https://github.com/TheSilentPro/HeadDB");
+ }
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/command/CommandLanguage.java b/src/main/java/tsp/headdb/core/command/CommandLanguage.java
new file mode 100644
index 0000000..f53fcca
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandLanguage.java
@@ -0,0 +1,57 @@
+package tsp.headdb.core.command;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import tsp.smartplugin.localization.Message;
+
+import java.util.Set;
+
+public class CommandLanguage extends SubCommand {
+
+ public CommandLanguage() {
+ super("language", new String[]{"l", "lang"});
+ }
+
+ @Override
+ public void handle(CommandSender sender, String[] args) {
+ String lang = "en";
+ if (args.length < 1) {
+ getLocalization().sendMessage(new Message()
+ .receiver(sender)
+ .text("invalidArguments")
+ );
+ return;
+ }
+
+ if (!getLocalization().getData().containsKey(lang)) {
+ getLocalization().sendMessage(new Message()
+ .receiver(sender)
+ .text("invalidLanguage")
+ .function(msg -> msg.replace("%languages%", toString(getLocalization().getData().keySet()))));
+ return;
+ }
+
+ if (!(sender instanceof Player player)) {
+ getLocalization().setConsoleLanguage(lang);
+ } else {
+ getLocalization().setLanguage(player.getUniqueId(), lang);
+ }
+
+ getLocalization().sendMessage(new Message().receiver(sender).text("languageChanged").function(msg -> msg.replace("%language%", lang)));
+ }
+
+ private String toString(Set set) {
+ String[] array = set.toArray(new String[0]);
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < array.length; i++) {
+ builder.append(array[i]);
+ if (i < array.length - 1) {
+ builder.append(",");
+ }
+ }
+
+ return builder.toString();
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/command/CommandMain.java b/src/main/java/tsp/headdb/core/command/CommandMain.java
index 1a3030b..d8e6769 100644
--- a/src/main/java/tsp/headdb/core/command/CommandMain.java
+++ b/src/main/java/tsp/headdb/core/command/CommandMain.java
@@ -1,7 +1,6 @@
package tsp.headdb.core.command;
import org.bukkit.Bukkit;
-import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@@ -9,14 +8,12 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.RemoteConsoleCommandSender;
import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
import tsp.headdb.HeadDB;
import tsp.headdb.core.api.HeadAPI;
import tsp.headdb.core.util.Utils;
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.inventory.Pane;
import tsp.smartplugin.localization.TranslatableLocalization;
import tsp.smartplugin.utils.Validate;
@@ -49,7 +46,7 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor {
for (Category category : Category.VALUES) {
pane.addButton(new Button(category.getItem(player.getUniqueId()), e -> {
if (e.isLeftClick()) {
- Bukkit.dispatchCommand(e.getWhoClicked(), "hdb open " + category.name());
+ Bukkit.dispatchCommand(e.getWhoClicked(), "hdb open " + category.getName());
} else if (e.isRightClick()) {
// todo: specific page
}
diff --git a/src/main/java/tsp/headdb/core/command/CommandManager.java b/src/main/java/tsp/headdb/core/command/CommandManager.java
index 54bef69..7d22096 100644
--- a/src/main/java/tsp/headdb/core/command/CommandManager.java
+++ b/src/main/java/tsp/headdb/core/command/CommandManager.java
@@ -4,7 +4,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Stream;
public class CommandManager {
diff --git a/src/main/java/tsp/headdb/core/command/CommandSearch.java b/src/main/java/tsp/headdb/core/command/CommandSearch.java
index c6b3503..dc5f1f5 100644
--- a/src/main/java/tsp/headdb/core/command/CommandSearch.java
+++ b/src/main/java/tsp/headdb/core/command/CommandSearch.java
@@ -5,10 +5,10 @@ import org.bukkit.entity.Player;
import tsp.headdb.core.api.HeadAPI;
import tsp.headdb.core.util.Utils;
import tsp.headdb.implementation.head.Head;
-import tsp.smartplugin.inventory.paged.PagedPane;
+import tsp.smartplugin.inventory.PagedPane;
+import java.util.ArrayList;
import java.util.List;
-import java.util.stream.Collectors;
public class CommandSearch extends SubCommand {
@@ -25,16 +25,38 @@ public class CommandSearch extends SubCommand {
StringBuilder builder = new StringBuilder();
for (int i = 1; i < args.length; i++) {
- builder.append(args[i]).append(" ");
+ builder.append(args[i]);
+ if (i != args.length - 1) {
+ builder.append(" ");
+ }
}
- String query = builder.toString();
- getLocalization().sendMessage(player.getUniqueId(), "searchCommand", msg -> msg.replace("%query%", query));
+ final String query = builder.toString();
- List heads = HeadAPI.getHeads().filter(head -> Utils.matches(head.getName(), query)).collect(Collectors.toList());
- PagedPane main = new PagedPane(6, 6, Utils.translateTitle(getLocalization().getMessage(player.getUniqueId(), "menu.search.name").orElse("&cHeadDB - &eSearch Results"), heads.size(), "None", query));
+ List heads = new ArrayList<>();
+ List headList = HeadAPI.getHeads();
+ if (query.length() > 3) {
+ if (query.startsWith("id:")) {
+ try {
+ HeadAPI.getHeadById(Integer.parseInt(query.substring(3))).ifPresent(heads::add);
+ } catch (NumberFormatException ignored) {
+ }
+ } else if (query.startsWith("tg:")) {
+ heads.addAll(headList.stream().filter(head -> Utils.matches(head.getTags(), query.substring(3))).toList());
+ } else {
+ // no query prefix
+ heads.addAll(headList.stream().filter(head -> Utils.matches(head.getName(), query.substring(3))).toList());
+ }
+ } else {
+ // query is <=3, no point in looking for prefixes
+ heads.addAll(headList.stream().filter(head -> Utils.matches(head.getName(), query.substring(3))).toList());
+ }
+
+ getLocalization().sendMessage(player.getUniqueId(), "searchCommand", msg -> msg.replace("%query%", query));
+ PagedPane main = Utils.createPaged(player, Utils.translateTitle(getLocalization().getMessage(player.getUniqueId(), "menu.search.name").orElse("&cHeadDB - &eSearch Results"), heads.size(), "None", query));
Utils.addHeads(player, null, main, heads);
getLocalization().sendMessage(player.getUniqueId(), "searchCommandResults", msg -> msg.replace("%size%", String.valueOf(heads.size())).replace("%query%", query));
+ main.open(player);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/core/command/CommandSettings.java b/src/main/java/tsp/headdb/core/command/CommandSettings.java
new file mode 100644
index 0000000..dc4015d
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandSettings.java
@@ -0,0 +1,47 @@
+package tsp.headdb.core.command;
+
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import tsp.headdb.core.util.Utils;
+import tsp.smartplugin.builder.item.ItemBuilder;
+import tsp.smartplugin.inventory.Button;
+import tsp.smartplugin.inventory.PagedPane;
+import tsp.smartplugin.inventory.Pane;
+import tsp.smartplugin.utils.StringUtils;
+
+import java.util.Set;
+
+public class CommandSettings extends SubCommand {
+
+ public CommandSettings() {
+ super("settings", new String[]{"st"});
+ }
+
+ @Override
+ public void handle(CommandSender sender, String[] args) {
+ if (!(sender instanceof Player player)) {
+ getLocalization().sendConsoleMessage("noConsole");
+ return;
+ }
+
+ Set langs = getLocalization().getData().keySet();
+ Pane pane = new Pane(1, StringUtils.colorize(getLocalization().getMessage(player.getUniqueId(), "menu.settings.name").orElse("&cHeadDB - Settings")));
+ pane.addButton(new Button(new ItemBuilder(Material.BOOK)
+ .name(getLocalization().getMessage(player.getUniqueId(), "menu.settings.language.name").orElse("&cLanguage"))
+ .setLore(getLocalization().getMessage(player.getUniqueId(), "menu.settings.language.available").orElse("&7Languages Available: &e%size%").replace("%size%", String.valueOf(langs.size())))
+ .build(), e -> {
+ PagedPane langPane = new PagedPane(4, 6, Utils.translateTitle(getLocalization().getMessage(player.getUniqueId(), "menu.settings.language.title").orElse("&cHeadDB &7- &eSelect Language").replace("%languages%", "%size%"), langs.size(), "Selector: Language"));
+ for (String lang : langs) {
+ langPane.addButton(new Button(new ItemBuilder(Material.PAPER)
+ .name(getLocalization().getMessage(player.getUniqueId(), "menu.settings.language.format").orElse(ChatColor.YELLOW + lang).replace("%language%", lang))
+ .build(), langEvent -> {
+ getLocalization().setLanguage(player.getUniqueId(), lang);
+ getLocalization().sendMessage(player.getUniqueId(), "languageChanged", msg -> msg.replace("%language%", lang));
+ }));
+ }
+ }));
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/command/CommandTexture.java b/src/main/java/tsp/headdb/core/command/CommandTexture.java
new file mode 100644
index 0000000..94dd857
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandTexture.java
@@ -0,0 +1,32 @@
+package tsp.headdb.core.command;
+
+import net.md_5.bungee.api.chat.ClickEvent;
+import net.md_5.bungee.api.chat.HoverEvent;
+import net.md_5.bungee.api.chat.TextComponent;
+import net.md_5.bungee.api.chat.hover.content.Text;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import tsp.headdb.core.util.Utils;
+
+public class CommandTexture extends SubCommand {
+
+ public CommandTexture() {
+ super("texture", new String[]{"t"});
+ }
+
+ @Override
+ public void handle(CommandSender sender, String[] args) {
+ if (!(sender instanceof Player player)) {
+ getLocalization().sendConsoleMessage("noConsole");
+ return;
+ }
+
+ Utils.getTexture(player.getInventory().getItemInMainHand()).ifPresentOrElse(texture -> getLocalization().getMessage(player.getUniqueId(), "itemTexture").ifPresent(message -> {
+ TextComponent component = new TextComponent(message.replace("%texture%", texture));
+ component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(getLocalization().getMessage(player.getUniqueId(), "copyTexture").orElse("Click to copy!"))));
+ component.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, texture));
+ player.spigot().sendMessage(component);
+ }), () -> getLocalization().sendMessage("itemNoTexture"));
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/command/CommandUpdate.java b/src/main/java/tsp/headdb/core/command/CommandUpdate.java
new file mode 100644
index 0000000..dd3ec93
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/command/CommandUpdate.java
@@ -0,0 +1,27 @@
+package tsp.headdb.core.command;
+
+import org.bukkit.command.CommandSender;
+import tsp.headdb.core.api.HeadAPI;
+import tsp.smartplugin.localization.Message;
+
+public class CommandUpdate extends SubCommand {
+
+ public CommandUpdate() {
+ super("update", new String[]{"u"});
+ }
+
+ @Override
+ public void handle(CommandSender sender, String[] args) {
+ getLocalization().sendMessage(new Message()
+ .receiver(sender)
+ .text("updateDatabase")
+ );
+
+ HeadAPI.getDatabase().update((time, heads) -> getLocalization().sendMessage(new Message()
+ .receiver(sender)
+ .text("updateDatabaseDone")
+ .function(msg -> msg.replace("%size%", String.valueOf(heads.size()).replace("%time%", String.valueOf(time)))))
+ );
+ }
+
+}
diff --git a/src/main/java/tsp/headdb/core/storage/HeadStorage.java b/src/main/java/tsp/headdb/core/storage/HeadStorage.java
index 7496607..643600a 100644
--- a/src/main/java/tsp/headdb/core/storage/HeadStorage.java
+++ b/src/main/java/tsp/headdb/core/storage/HeadStorage.java
@@ -61,6 +61,7 @@ public class HeadStorage extends SQLiteDataManager> {
));
}
+ //noinspection StringOperationCanBeSimplified
return sendPreparedUpdate("INSERT OR REPLACE INTO data VALUES" + builder.toString().substring(0, builder.length() - 1) + ";").thenApply(r -> true);
}
diff --git a/src/main/java/tsp/headdb/core/storage/Storage.java b/src/main/java/tsp/headdb/core/storage/Storage.java
index 8ad1a44..513acda 100644
--- a/src/main/java/tsp/headdb/core/storage/Storage.java
+++ b/src/main/java/tsp/headdb/core/storage/Storage.java
@@ -3,8 +3,6 @@ package tsp.headdb.core.storage;
import tsp.headdb.HeadDB;
import tsp.headdb.core.api.HeadAPI;
-import java.util.stream.Collectors;
-
public final class Storage {
private final HeadDB instance = HeadDB.getInstance();
@@ -24,7 +22,7 @@ public final class Storage {
public void save() {
playerStorage.save(playerStorage.getPlayers().values()).join();
- headStorage.save(HeadAPI.getHeads().collect(Collectors.toList())).join();
+ headStorage.save(HeadAPI.getHeads()).join();
}
public PlayerStorage getPlayerStorage() {
diff --git a/src/main/java/tsp/headdb/core/task/UpdateTask.java b/src/main/java/tsp/headdb/core/task/UpdateTask.java
index 1dd1fdd..2d0de6c 100644
--- a/src/main/java/tsp/headdb/core/task/UpdateTask.java
+++ b/src/main/java/tsp/headdb/core/task/UpdateTask.java
@@ -4,6 +4,8 @@ import tsp.headdb.HeadDB;
import tsp.headdb.core.api.HeadAPI;
import tsp.smartplugin.tasker.Task;
+import java.util.concurrent.TimeUnit;
+
@SuppressWarnings("ClassCanBeRecord")
public class UpdateTask implements Task {
@@ -15,7 +17,7 @@ public class UpdateTask implements Task {
@Override
public void run() {
- HeadAPI.getDatabase().update();
+ HeadAPI.getDatabase().update((time, heads) -> HeadDB.getInstance().getLog().debug("Fetched: " + heads.size() + " Heads | Provider: " + HeadAPI.getDatabase().getRequester().getProvider().name() + " | Time: " + time + "ms (" + TimeUnit.MILLISECONDS.toSeconds(time) + "s)"));
//HeadDB.getInstance().getStorage().save();
HeadDB.getInstance().getLog().debug("UpdateTask finished!");
}
diff --git a/src/main/java/tsp/headdb/core/util/BuildProperties.java b/src/main/java/tsp/headdb/core/util/BuildProperties.java
new file mode 100644
index 0000000..a84c6c4
--- /dev/null
+++ b/src/main/java/tsp/headdb/core/util/BuildProperties.java
@@ -0,0 +1,51 @@
+package tsp.headdb.core.util;
+
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * This class contains the properties of the build.
+ *
+ * @author TheSilentPro (Silent)
+ */
+public class BuildProperties {
+
+ private String version = "unknown";
+ private int buildNumber = 0;
+ private String timestamp = "unknown";
+ private String author = "unknown";
+
+ public BuildProperties(JavaPlugin plugin) {
+ InputStream in = plugin.getResource("plugin.yml");
+ if (in == null) {
+ plugin.getLogger().severe("Could not get plugin.yml to read build information.");
+ return;
+ }
+
+ YamlConfiguration data = YamlConfiguration.loadConfiguration(new InputStreamReader(in));
+ this.version = data.getString("version", "unknown");
+ this.buildNumber = data.getInt("build", 0);
+ this.timestamp = data.getString("buildTimestamp", "unknown");
+ this.author = data.getString("buildAuthor", "unknown");
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public int getBuildNumber() {
+ return buildNumber;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/tsp/headdb/core/util/Utils.java b/src/main/java/tsp/headdb/core/util/Utils.java
index 172636b..15ad225 100644
--- a/src/main/java/tsp/headdb/core/util/Utils.java
+++ b/src/main/java/tsp/headdb/core/util/Utils.java
@@ -1,17 +1,23 @@
package tsp.headdb.core.util;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.properties.Property;
+import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
import tsp.headdb.HeadDB;
+import tsp.headdb.core.api.HeadAPI;
import tsp.headdb.implementation.category.Category;
import tsp.headdb.implementation.head.Head;
import tsp.smartplugin.inventory.Button;
-import tsp.smartplugin.inventory.paged.PagedPane;
+import tsp.smartplugin.inventory.PagedPane;
import tsp.smartplugin.utils.StringUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
+import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Locale;
import java.util.Optional;
@@ -43,22 +49,33 @@ public class Utils {
}
public static boolean matches(String provided, String query) {
- provided = provided.toLowerCase(Locale.ROOT);
+ provided = ChatColor.stripColor(provided.toLowerCase(Locale.ROOT));
query = query.toLowerCase(Locale.ROOT);
return provided.equals(query)
|| provided.startsWith(query)
- || provided.contains(query)
- || provided.endsWith(query);
+ || provided.contains(query);
+ //|| provided.endsWith(query);
+ }
+
+ public static PagedPane createPaged(Player player, String title) {
+ PagedPane main = new PagedPane(4, 6, title);
+ main.getInventory().clear();
+ HeadAPI.getHeadByTexture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY1MmUyYjkzNmNhODAyNmJkMjg2NTFkN2M5ZjI4MTlkMmU5MjM2OTc3MzRkMThkZmRiMTM1NTBmOGZkYWQ1ZiJ9fX0=").ifPresent(head -> main.setBackItem(head.getItem(player.getUniqueId())));
+ HeadAPI.getHeadByTexture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q5MWY1MTI2NmVkZGM2MjA3ZjEyYWU4ZDdhNDljNWRiMDQxNWFkYTA0ZGFiOTJiYjc2ODZhZmRiMTdmNGQ0ZSJ9fX0=").ifPresent(head -> main.setCurrentItem(head.getItem(player.getUniqueId())));
+ HeadAPI.getHeadByTexture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmEzYjhmNjgxZGFhZDhiZjQzNmNhZThkYTNmZTgxMzFmNjJhMTYyYWI4MWFmNjM5YzNlMDY0NGFhNmFiYWMyZiJ9fX0=").ifPresent(head -> main.setNextItem(head.getItem(player.getUniqueId())));
+ return main;
}
@ParametersAreNonnullByDefault
public static void addHeads(Player player, @Nullable Category category, PagedPane pane, Collection heads) {
+ pane.getInventory().clear();
for (Head head : heads) {
ItemStack item = head.getItem(player.getUniqueId());
- pane.addButton(new Button(head.getItem(player.getUniqueId()), e -> {
+ pane.addButton(new Button(item, e -> {
+ e.setCancelled(true);
+
if (category != null && instance.getConfig().getBoolean("requireCategoryPermission") && !player.hasPermission("headdb.category." + category.getName())) {
instance.getLocalization().sendMessage(player.getUniqueId(), "noPermission");
- e.setCancelled(true);
return;
}
@@ -71,10 +88,31 @@ public class Utils {
} else if (e.isRightClick()) {
// todo: favorites
}
-
- e.setCancelled(true);
}));
}
}
+ public static Optional getTexture(ItemStack head) {
+ ItemMeta meta = head.getItemMeta();
+ if (meta == null) {
+ return Optional.empty();
+ }
+
+ try {
+ Field profileField = meta.getClass().getDeclaredField("profile");
+ profileField.setAccessible(true);
+ GameProfile profile = (GameProfile) profileField.get(meta);
+ if (profile == null) {
+ return Optional.empty();
+ }
+
+ return profile.getProperties().get("textures").stream()
+ .filter(p -> p.getValue().equals("textures"))
+ .findAny()
+ .map(Property::getName);
+ } catch (NoSuchFieldException | SecurityException | IllegalAccessException e ) {
+ return Optional.empty();
+ }
+ }
+
}
diff --git a/src/main/java/tsp/headdb/implementation/category/Category.java b/src/main/java/tsp/headdb/implementation/category/Category.java
index d0b8f70..e789b86 100644
--- a/src/main/java/tsp/headdb/implementation/category/Category.java
+++ b/src/main/java/tsp/headdb/implementation/category/Category.java
@@ -51,12 +51,12 @@ public enum Category {
@Nonnull
public ItemStack getItem(UUID receiver) {
if (item == null) {
- HeadAPI.getHeads(this).findFirst()
+ HeadAPI.getHeads(this).stream().findFirst()
.ifPresentOrElse(head -> item = new ItemBuilder(head.getItem(receiver))
- .name(Utils.translateTitle(HeadDB.getInstance().getLocalization().getMessage(receiver, "menu.category.name").orElse("&e" + getName()), HeadAPI.getHeads(this).toList().size(), getName().toUpperCase(Locale.ROOT)))
- .setLore("")
+ .name(Utils.translateTitle(HeadDB.getInstance().getLocalization().getMessage(receiver, "menu.category.name").orElse("&e" + getName()), HeadAPI.getHeads(this).size(), getName().toUpperCase(Locale.ROOT)))
+ .setLore((String[]) null)
.build(),
- () -> item = new ItemBuilder(Material.BARRIER).name(getName().toUpperCase(Locale.ROOT)).build());
+ () -> item = new ItemBuilder(Material.PLAYER_HEAD).name(getName().toUpperCase(Locale.ROOT)).build());
}
return item;
diff --git a/src/main/java/tsp/headdb/implementation/head/Head.java b/src/main/java/tsp/headdb/implementation/head/Head.java
index 7cef1ed..8ee432c 100644
--- a/src/main/java/tsp/headdb/implementation/head/Head.java
+++ b/src/main/java/tsp/headdb/implementation/head/Head.java
@@ -46,16 +46,15 @@ public class Head {
TranslatableLocalization localization = HeadDB.getInstance().getLocalization();
item = new ItemBuilder(Material.PLAYER_HEAD)
.name(localization.getMessage(receiver, "menu.head.name").orElse("&e" + name.toUpperCase(Locale.ROOT)).replace("%name%", name))
- .setLore("&7Tags: &e" + tags)
+ .setLore("&cID: " + id, "&7Tags: &e" + tags)
.build();
ItemMeta meta = item.getItemMeta();
GameProfile profile = new GameProfile(uniqueId, name);
profile.getProperties().put("textures", new Property("textures", texture));
- Field profileField;
try {
//noinspection ConstantConditions
- profileField = meta.getClass().getDeclaredField("profile");
+ Field profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
profileField.set(meta, profile);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) {
@@ -65,6 +64,7 @@ public class Head {
item.setItemMeta(meta);
}
+
return item;
}
diff --git a/src/main/java/tsp/headdb/implementation/head/HeadDatabase.java b/src/main/java/tsp/headdb/implementation/head/HeadDatabase.java
index 47a8684..f5f5490 100644
--- a/src/main/java/tsp/headdb/implementation/head/HeadDatabase.java
+++ b/src/main/java/tsp/headdb/implementation/head/HeadDatabase.java
@@ -7,12 +7,13 @@ import tsp.headdb.implementation.category.Category;
import tsp.headdb.implementation.requester.HeadProvider;
import tsp.headdb.implementation.requester.Requester;
-import java.io.IOException;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class HeadDatabase {
@@ -22,7 +23,6 @@ public class HeadDatabase {
private final Requester requester;
private final Map> heads;
private long timestamp;
- private int size;
public HeadDatabase(JavaPlugin plugin, HeadProvider provider) {
this.plugin = plugin;
@@ -35,30 +35,28 @@ public class HeadDatabase {
return heads;
}
- public void getHeadsNoCache(Consumer