3
0
Mirror von https://github.com/TheSilentPro/HeadDB.git synchronisiert 2024-12-26 19:02:39 +01:00

start work for rc1

Dieser Commit ist enthalten in:
Silent 2022-11-13 03:07:05 +01:00
Ursprung 396a6ba858
Commit 796652ed95
13 geänderte Dateien mit 202 neuen und 20 gelöschten Zeilen

Datei anzeigen

@ -80,7 +80,7 @@
<dependency> <dependency>
<groupId>com.github.TheSilentPro</groupId> <groupId>com.github.TheSilentPro</groupId>
<artifactId>Warehouse</artifactId> <artifactId>Warehouse</artifactId>
<version>f40f72cb19</version> <version>882b42fc75</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.wesjd</groupId> <groupId>net.wesjd</groupId>

Datei anzeigen

@ -1,5 +1,6 @@
package tsp.headdb; package tsp.headdb;
import org.bukkit.command.PluginCommand;
import tsp.headdb.core.command.CommandCategory; import tsp.headdb.core.command.CommandCategory;
import tsp.headdb.core.command.CommandGive; import tsp.headdb.core.command.CommandGive;
import tsp.headdb.core.command.CommandHelp; import tsp.headdb.core.command.CommandHelp;
@ -15,6 +16,7 @@ import tsp.headdb.core.command.CommandUpdate;
import tsp.headdb.core.economy.BasicEconomyProvider; import tsp.headdb.core.economy.BasicEconomyProvider;
import tsp.headdb.core.economy.VaultProvider; import tsp.headdb.core.economy.VaultProvider;
import tsp.headdb.core.listener.PlayerJoinListener; import tsp.headdb.core.listener.PlayerJoinListener;
import tsp.headdb.core.storage.Storage;
import tsp.headdb.core.task.UpdateTask; import tsp.headdb.core.task.UpdateTask;
import tsp.headdb.core.util.BuildProperties; import tsp.headdb.core.util.BuildProperties;
@ -35,6 +37,7 @@ public class HeadDB extends SmartPlugin {
private PluginLogger logger; private PluginLogger logger;
private BuildProperties buildProperties; private BuildProperties buildProperties;
private TranslatableLocalization localization; private TranslatableLocalization localization;
private Storage storage;
private BasicEconomyProvider economyProvider; private BasicEconomyProvider economyProvider;
private CommandManager commandManager; private CommandManager commandManager;
@ -49,15 +52,14 @@ public class HeadDB extends SmartPlugin {
new UpdateTask(getConfig().getLong("refresh", 86400L)).schedule(this); new UpdateTask(getConfig().getLong("refresh", 86400L)).schedule(this);
instance.logger.info("Loaded " + loadLocalization() + " languages!"); instance.logger.info("Loaded " + loadLocalization() + " languages!");
instance.initStorage();
instance.initEconomy(); instance.initEconomy();
new PaneListener(this); new PaneListener(this);
new PlayerJoinListener(); //new PlayerJoinListener();
instance.commandManager = new CommandManager(); instance.commandManager = new CommandManager();
loadCommands(); loadCommands();
//noinspection ConstantConditions
instance.getCommand("headdb").setExecutor(new CommandMain());
new Metrics(this, 9152); new Metrics(this, 9152);
ensureLatestVersion(); ensureLatestVersion();
@ -66,7 +68,9 @@ public class HeadDB extends SmartPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
// todo: save storage if (storage != null) {
storage.getPlayerStorage().suspend();
}
} }
private void ensureLatestVersion() { private void ensureLatestVersion() {
@ -78,6 +82,13 @@ public class HeadDB extends SmartPlugin {
}); });
} }
// Loaders
private void initStorage() {
storage = new Storage(getConfig().getInt("storage.threads"));
storage.getPlayerStorage().init();
}
private int loadLocalization() { private int loadLocalization() {
instance.localization = new TranslatableLocalization(this, "messages"); instance.localization = new TranslatableLocalization(this, "messages");
try { try {
@ -108,6 +119,16 @@ public class HeadDB extends SmartPlugin {
} }
private void loadCommands() { private void loadCommands() {
PluginCommand main = getCommand("headdb");
if (main != null) {
main.setExecutor(new CommandMain());
main.setTabCompleter(new CommandMain());
} else {
instance.logger.error("Could not find main 'headdb' command!");
this.setEnabled(false);
return;
}
new CommandHelp().register(); new CommandHelp().register();
new CommandCategory().register(); new CommandCategory().register();
new CommandSearch().register(); new CommandSearch().register();
@ -119,6 +140,12 @@ public class HeadDB extends SmartPlugin {
new CommandInfo().register(); new CommandInfo().register();
} }
// Getters
public Storage getStorage() {
return storage;
}
public CommandManager getCommandManager() { public CommandManager getCommandManager() {
return commandManager; return commandManager;
} }

Datei anzeigen

@ -3,6 +3,7 @@ package tsp.headdb.core.api;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import tsp.headdb.HeadDB; import tsp.headdb.HeadDB;
import tsp.headdb.core.storage.PlayerData;
import tsp.headdb.core.util.Utils; import tsp.headdb.core.util.Utils;
import tsp.headdb.implementation.category.Category; import tsp.headdb.implementation.category.Category;
import tsp.headdb.implementation.head.Head; import tsp.headdb.implementation.head.Head;
@ -18,6 +19,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -152,7 +154,7 @@ public final class HeadAPI {
/** /**
* Retrieve a {@link Set} of local heads. * Retrieve a {@link Set} of local heads.
* Note that this calculates the heads on every try. * Note that this calculates the heads on every call.
* *
* @return {@link Set<LocalHead> Local Heads} * @return {@link Set<LocalHead> Local Heads}
*/ */
@ -161,6 +163,24 @@ public final class HeadAPI {
return Arrays.stream(Bukkit.getOfflinePlayers()).map(player -> new LocalHead(player.getUniqueId(), player.getName())).collect(Collectors.toSet()); return Arrays.stream(Bukkit.getOfflinePlayers()).map(player -> new LocalHead(player.getUniqueId(), player.getName())).collect(Collectors.toSet());
} }
/**
* Retrieve a {@link Set} of favorite heads for the specified {@link UUID player id}.
* Note that this calculates the heads on every call.
*
* @param player The players id
* @return {@link Set<Head> Favorite Heads}
*/
@Nonnull
public static List<Head> getFavoriteHeads(UUID player) {
List<Head> result = new ArrayList<>();
Optional<PlayerData> data = HeadDB.getInstance().getStorage().getPlayerStorage().get(player);
data.ifPresent(playerData -> playerData.favorites()
.forEach(texture -> getHeadByTexture(texture)
.ifPresent(result::add))
);
return result;
}
/** /**
* Retrieve the main {@link HeadDatabase} used by the plugin. * Retrieve the main {@link HeadDatabase} used by the plugin.
* *

Datei anzeigen

@ -80,7 +80,7 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor, TabCo
} }
}) })
.text("Query") .text("Query")
.title(getLocalization().getMessage(player.getUniqueId(), "menu.main.category.page.name").orElse("Enter page")) .title(StringUtils.colorize(getLocalization().getMessage(player.getUniqueId(), "menu.main.category.page.name").orElse("Enter page")))
.plugin(getInstance()) .plugin(getInstance())
.open(player); .open(player);
} }
@ -90,7 +90,20 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor, TabCo
// Set meta buttons // Set meta buttons
pane.setButton(getInstance().getConfig().getInt("gui.main.meta.favorites.slot"), new Button(Utils.getItemFromConfig("gui.main.meta.favorites.item", Material.BOOK), e -> { pane.setButton(getInstance().getConfig().getInt("gui.main.meta.favorites.slot"), new Button(Utils.getItemFromConfig("gui.main.meta.favorites.item", Material.BOOK), e -> {
e.setCancelled(true); e.setCancelled(true);
// TODO: favorites List<Head> heads = HeadAPI.getFavoriteHeads(player.getUniqueId());
PagedPane main = Utils.createPaged(player, Utils.translateTitle(getLocalization().getMessage(player.getUniqueId(), "menu.main.favorites").orElse("Favorites"), heads.size(), "Favorites"));
for (Head head : heads) {
main.addButton(new Button(head.getItem(player.getUniqueId()), fe -> {
if (fe.isLeftClick()) {
ItemStack favoriteItem = head.getItem(player.getUniqueId());
if (fe.isShiftClick()) {
favoriteItem.setAmount(64);
}
player.getInventory().addItem(favoriteItem);
}
}));
}
})); }));
pane.setButton(getInstance().getConfig().getInt("gui.main.meta.search.slot"), new Button(Utils.getItemFromConfig("gui.main.meta.search.item", Material.DARK_OAK_SIGN), e -> { pane.setButton(getInstance().getConfig().getInt("gui.main.meta.search.slot"), new Button(Utils.getItemFromConfig("gui.main.meta.search.item", Material.DARK_OAK_SIGN), e -> {
@ -140,8 +153,6 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor, TabCo
} }
player.getInventory().addItem(localItem); player.getInventory().addItem(localItem);
} else if (le.isRightClick()) {
// todo: remove from favorites
} }
})); }));
} }

Datei anzeigen

@ -14,7 +14,6 @@ public final class PlayerJoinListener implements Listener {
@EventHandler @EventHandler
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
// todo: favorites
//HeadDB.getInstance().getStorage().getPlayerStorage().register(new PlayerData(event.getPlayer().getUniqueId(), "")); //HeadDB.getInstance().getStorage().getPlayerStorage().register(new PlayerData(event.getPlayer().getUniqueId(), ""));
} }

Datei anzeigen

@ -0,0 +1,20 @@
package tsp.headdb.core.storage;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public final class HeadDBThreadFactory implements ThreadFactory {
private HeadDBThreadFactory() {}
public static final HeadDBThreadFactory FACTORY = new HeadDBThreadFactory();
private final AtomicInteger ID = new AtomicInteger(1);
@Override
public Thread newThread(@NotNull Runnable r) {
return new Thread(r, "headdb-thread-" + ID.getAndIncrement());
}
}

Datei anzeigen

@ -0,0 +1,7 @@
package tsp.headdb.core.storage;
import java.io.Serializable;
import java.util.Set;
import java.util.UUID;
public record PlayerData(UUID uniqueId, Set<String> favorites) implements Serializable {}

Datei anzeigen

@ -0,0 +1,62 @@
package tsp.headdb.core.storage;
import tsp.headdb.HeadDB;
import tsp.warehouse.storage.file.SerializableFileDataManager;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
public class PlayerStorage extends SerializableFileDataManager<Collection<PlayerData>> {
private final Map<UUID, PlayerData> players = new HashMap<>();
public PlayerStorage(Storage storage) {
super(new File("data/players.data"), storage.getExecutor());
}
public void set(PlayerData data) {
this.players.put(data.uniqueId(), data);
}
public Optional<PlayerData> get(UUID uuid) {
return Optional.ofNullable(players.get(uuid));
}
public Map<UUID, PlayerData> getPlayersMap() {
return Collections.unmodifiableMap(players);
}
public void init() {
load().whenComplete((data, ex) -> {
for (PlayerData entry : data) {
players.put(entry.uniqueId(), entry);
}
HeadDB.getInstance().getLog().debug("Loaded " + players.values().size() + " player data!");
});
}
public void backup() {
save(players.values()).whenComplete((success, ex) -> HeadDB.getInstance().getLog().debug("Saved " + players.values().size() + " player data!"));
}
public void suspend() {
Boolean saved = save(players.values())
.exceptionally(ex -> {
HeadDB.getInstance().getLog().error("Failed to save player data! | Stack Trace: ");
ex.printStackTrace();
return false;
})
.join();
if (Boolean.TRUE.equals(saved)) {
HeadDB.getInstance().getLog().debug("Saved " + players.values().size() + " player data!");
}
}
}

Datei anzeigen

@ -0,0 +1,24 @@
package tsp.headdb.core.storage;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class Storage {
private final Executor executor;
private final PlayerStorage playerStorage;
public Storage(int threads) {
executor = Executors.newFixedThreadPool(threads, HeadDBThreadFactory.FACTORY);
playerStorage = new PlayerStorage(this);
}
public PlayerStorage getPlayerStorage() {
return playerStorage;
}
public Executor getExecutor() {
return executor;
}
}

Datei anzeigen

@ -15,6 +15,8 @@ import tsp.headdb.core.api.HeadAPI;
import tsp.headdb.core.api.event.HeadPurchaseEvent; import tsp.headdb.core.api.event.HeadPurchaseEvent;
import tsp.headdb.core.economy.BasicEconomyProvider; import tsp.headdb.core.economy.BasicEconomyProvider;
import tsp.headdb.core.hook.Hooks; import tsp.headdb.core.hook.Hooks;
import tsp.headdb.core.storage.PlayerData;
import tsp.headdb.core.storage.PlayerStorage;
import tsp.headdb.implementation.category.Category; import tsp.headdb.implementation.category.Category;
import tsp.headdb.implementation.head.Head; import tsp.headdb.implementation.head.Head;
import tsp.smartplugin.inventory.Button; import tsp.smartplugin.inventory.Button;
@ -33,6 +35,7 @@ import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Optional; import java.util.Optional;
@ -121,7 +124,7 @@ public class Utils {
purchase(player, head, amount); purchase(player, head, amount);
} else if (e.isRightClick()) { } else if (e.isRightClick()) {
// todo: favorites HeadDB.getInstance().getStorage().getPlayerStorage().get(player.getUniqueId()).orElse(new PlayerData(player.getUniqueId(), new HashSet<>())).favorites().add(head.getTexture());
} }
})); }));
} }

Datei anzeigen

@ -9,6 +9,7 @@ import tsp.headdb.implementation.requester.Requester;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
public class HeadDatabase { public class HeadDatabase {
@ -16,14 +17,14 @@ public class HeadDatabase {
private final JavaPlugin plugin; private final JavaPlugin plugin;
private final BukkitScheduler scheduler; private final BukkitScheduler scheduler;
private final Requester requester; private final Requester requester;
private final Map<Category, List<Head>> heads; private final ConcurrentHashMap<Category, List<Head>> heads;
private long timestamp; private long timestamp;
public HeadDatabase(JavaPlugin plugin, HeadProvider provider) { public HeadDatabase(JavaPlugin plugin, HeadProvider provider) {
this.plugin = plugin; this.plugin = plugin;
this.scheduler = plugin.getServer().getScheduler(); this.scheduler = plugin.getServer().getScheduler();
this.requester = new Requester(plugin, provider); this.requester = new Requester(plugin, provider);
this.heads = new HashMap<>(); this.heads = new ConcurrentHashMap<>();
} }
public Map<Category, List<Head>> getHeads() { public Map<Category, List<Head>> getHeads() {

Datei anzeigen

@ -1,14 +1,15 @@
# How often the database should be updated in seconds. # How often the database should be updated in seconds.
refresh: 86400 refresh: 86400
# If local heads should be enabled. Only starts keeping track of joined players when enabled! # If local heads should be enabled.
# Local heads are heads from players that have joined your server at least once.
localHeads: true localHeads: true
# If enabled categories will require a permission to be used # If enabled categories will require a permission to be used.
# Permission: headdb.category.<category> # Permission: headdb.category.<category>
requireCategoryPermission: false requireCategoryPermission: false
# If enabled, the menu will close after purchasing a head (even if the purchase fails) # If enabled, the menu will close after purchasing a head (even if the purchase fails).
closeOnPurchase: false closeOnPurchase: false
# Economy Options # Economy Options
@ -28,7 +29,7 @@ economy:
monsters: 100 monsters: 100
plants: 100 plants: 100
# Command Configuration. Supports PlaceholderAPI # Command Configuration. Supports PlaceholderAPI.
commands: commands:
# Commands to run ONLY if the purchase is successful. # Commands to run ONLY if the purchase is successful.
# They are run as CONSOLE after the player has receiver the head in their inventory. # They are run as CONSOLE after the player has receiver the head in their inventory.
@ -83,8 +84,13 @@ gui:
# The archive is static so some heads may be missing, this will only be used when all else fails. # The archive is static so some heads may be missing, this will only be used when all else fails.
fallback: true fallback: true
# Shows more plugin information in /hdb info # Shows more plugin information. (/hdb info)
showAdvancedPluginInfo: true showAdvancedPluginInfo: true
# Storage Options
storage:
# Amount of threads in the executor pool used for storage.
threads: 2
# Debug Mode # Debug Mode
debug: false debug: false

Datei anzeigen

@ -17,7 +17,7 @@ itemTexture: "&7Texture: &6%texture%"
itemNoTexture: "&cThis item does not have a texture!" itemNoTexture: "&cThis item does not have a texture!"
copyTexture: "&6Click to copy texture!" copyTexture: "&6Click to copy texture!"
# # Only shown if economy is enabled
processPayment: "&7Purchasing &6%name% &7for &6%cost%&7! Please wait..." processPayment: "&7Purchasing &6%name% &7for &6%cost%&7! Please wait..."
completePayment: "&7Received &6%name% &7for &6%cost%" completePayment: "&7Received &6%name% &7for &6%cost%"
@ -34,6 +34,8 @@ menu:
lore: lore:
- "&7Left-Click to open" - "&7Left-Click to open"
- "&7Right-Click to open specific page" - "&7Right-Click to open specific page"
favorites:
name: "&6Favorites"
search: search:
name: "&6Search" name: "&6Search"
local: local: