From 1677c5d2e4bdc428dc5d548cb2543454eb9a8ca3 Mon Sep 17 00:00:00 2001 From: Silent Date: Sun, 6 Nov 2022 15:07:15 +0100 Subject: [PATCH] fuck buildnumber maven --- .gitignore | 2 + LICENSE | 2 +- README.md | 2 +- pom.xml | 99 +++++++++++++++++-- src/main/java/tsp/headdb/HeadDB.java | 22 ++++- .../java/tsp/headdb/core/api/HeadAPI.java | 22 +++-- .../headdb/core/command/CommandCategory.java | 20 ++-- .../tsp/headdb/core/command/CommandHelp.java | 10 +- .../tsp/headdb/core/command/CommandInfo.java | 27 +++++ .../headdb/core/command/CommandLanguage.java | 57 +++++++++++ .../tsp/headdb/core/command/CommandMain.java | 7 +- .../headdb/core/command/CommandManager.java | 1 - .../headdb/core/command/CommandSearch.java | 38 +++++-- .../headdb/core/command/CommandSettings.java | 47 +++++++++ .../headdb/core/command/CommandTexture.java | 32 ++++++ .../headdb/core/command/CommandUpdate.java | 27 +++++ .../tsp/headdb/core/storage/HeadStorage.java | 1 + .../java/tsp/headdb/core/storage/Storage.java | 4 +- .../java/tsp/headdb/core/task/UpdateTask.java | 4 +- .../tsp/headdb/core/util/BuildProperties.java | 51 ++++++++++ src/main/java/tsp/headdb/core/util/Utils.java | 54 ++++++++-- .../implementation/category/Category.java | 8 +- .../tsp/headdb/implementation/head/Head.java | 6 +- .../implementation/head/HeadDatabase.java | 24 +++-- .../implementation/requester/Requester.java | 1 - src/main/resources/config.yml | 5 +- src/main/resources/messages/en.yml | 21 +++- src/main/resources/plugin.yml | 4 + 28 files changed, 510 insertions(+), 88 deletions(-) create mode 100644 src/main/java/tsp/headdb/core/command/CommandInfo.java create mode 100644 src/main/java/tsp/headdb/core/command/CommandLanguage.java create mode 100644 src/main/java/tsp/headdb/core/command/CommandSettings.java create mode 100644 src/main/java/tsp/headdb/core/command/CommandTexture.java create mode 100644 src/main/java/tsp/headdb/core/command/CommandUpdate.java create mode 100644 src/main/java/tsp/headdb/core/util/BuildProperties.java 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.source} + ${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>> heads) { + public void getHeadsNoCache(BiConsumer>> heads) { getScheduler().runTaskAsynchronously(plugin, () -> { + long start = System.currentTimeMillis(); Map> result = new HashMap<>(); for (Category category : Category.VALUES) { requester.fetchAndResolve(category, response -> result.put(category, response)); } - heads.accept(result); + heads.accept(System.currentTimeMillis() - start, result); }); } - public void update() { - getHeadsNoCache(result -> { - heads.putAll(result); + public void update(BiConsumer>> fetched) { + getHeadsNoCache((elapsed, result) -> { + synchronized (heads) { + heads.putAll(result); + } timestamp = System.currentTimeMillis(); - size = heads.values().size(); - HeadDB.getInstance().getLog().debug("Fetched: " + heads.size() + " Heads | Provider: " + getRequester().getProvider().name()); + fetched.accept(elapsed, result); }); } - public int getSize() { - return size; - } - public long getTimestamp() { return timestamp; } diff --git a/src/main/java/tsp/headdb/implementation/requester/Requester.java b/src/main/java/tsp/headdb/implementation/requester/Requester.java index 23819ed..c8dada1 100644 --- a/src/main/java/tsp/headdb/implementation/requester/Requester.java +++ b/src/main/java/tsp/headdb/implementation/requester/Requester.java @@ -20,7 +20,6 @@ import java.util.List; import java.util.UUID; import java.util.function.Consumer; -@SuppressWarnings("ClassCanBeRecord") public class Requester { private final JavaPlugin plugin; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ebcf583..452e35b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -89,7 +89,7 @@ ui: local: location: 41 item: COMPASS - # Item used to fill unused slots in the categories menu. AIR is supported. You can use head: instead of item: here. + # Item used to fill unused slots in the categories' menu. AIR is supported. You can use head: instead of item: here. fill: item: BLACK_STAINED_GLASS_PANE sound: @@ -154,5 +154,8 @@ headProvider: "HEAD_STORAGE" # The archive is static (manually updated) so some heads may be missing, this will only be used when all else fails. fallback: true +# Shows more plugin information in /hdb info +showAdvancedPluginInfo: true + # Debug Mode debug: false \ No newline at end of file diff --git a/src/main/resources/messages/en.yml b/src/main/resources/messages/en.yml index 6c73b22..bc874a0 100644 --- a/src/main/resources/messages/en.yml +++ b/src/main/resources/messages/en.yml @@ -6,8 +6,16 @@ invalidCategory: "&cInvalid Category!" invalidPageIndex: "&cThat page is out of bounds! Max: %pages%" openDatabase: "&7Opening &cHeadDatabase&7..." +updateDatabase: "&7Updating..." +updateDatabaseDone: "&7Database was updated! Heads: &6%size% &7| Took: &a%time%" searchCommand: "&7Searching for heads matching: &e%query%" searchCommandResults: "&7Found &e%size% &7matches!" +itemTexture: "&7Texture: %texture%" +itemNoTexture: "&cThis item does not have a texture!" +copyTexture: "&6Click to copy texture!" + +invalidLanguage: "&cInvalid Language! Available: &e%languages%" +languageChanged: "&7Your language was set to: &e%language%" menu: main: @@ -21,4 +29,15 @@ menu: head: name: "&e%name%" search: - name: "&cHeadDB &7- &eSearch: %query% &7(%size%)" \ No newline at end of file + name: "&cHeadDB &7- &eSearch: %query% &7(%size%)" + settings: + name: "&cHeadDB &7- &eSettings" + language: + # Setting name + name: "&cLanguage" + # Available languages lore + available: "&7Languages Available: &e%size%" + # Title of the language selection inventory + title: "&cHeadDB &7- &eLanguages &7(%size%)" + # Language item name + format: "&e%language%" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 57dbcb9..14fdbe0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -8,6 +8,10 @@ api-version: 1.19 author: TheSilentPro (Silent) spigot-id: 84967 +build: ${build.number} +buildTimestamp: ${build.timestamp} +buildAuthor: ${build.author} + libraries: - "com.google.code.gson:gson:2.10"