Mirror von
https://github.com/TheSilentPro/HeadDB.git
synchronisiert 2024-12-26 02:50:07 +01:00
start work for rc1
Dieser Commit ist enthalten in:
Ursprung
396a6ba858
Commit
796652ed95
2
pom.xml
2
pom.xml
@ -80,7 +80,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.TheSilentPro</groupId>
|
||||
<artifactId>Warehouse</artifactId>
|
||||
<version>f40f72cb19</version>
|
||||
<version>882b42fc75</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.wesjd</groupId>
|
||||
|
@ -1,5 +1,6 @@
|
||||
package tsp.headdb;
|
||||
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import tsp.headdb.core.command.CommandCategory;
|
||||
import tsp.headdb.core.command.CommandGive;
|
||||
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.VaultProvider;
|
||||
import tsp.headdb.core.listener.PlayerJoinListener;
|
||||
import tsp.headdb.core.storage.Storage;
|
||||
import tsp.headdb.core.task.UpdateTask;
|
||||
|
||||
import tsp.headdb.core.util.BuildProperties;
|
||||
@ -35,6 +37,7 @@ public class HeadDB extends SmartPlugin {
|
||||
private PluginLogger logger;
|
||||
private BuildProperties buildProperties;
|
||||
private TranslatableLocalization localization;
|
||||
private Storage storage;
|
||||
private BasicEconomyProvider economyProvider;
|
||||
private CommandManager commandManager;
|
||||
|
||||
@ -49,15 +52,14 @@ public class HeadDB extends SmartPlugin {
|
||||
new UpdateTask(getConfig().getLong("refresh", 86400L)).schedule(this);
|
||||
instance.logger.info("Loaded " + loadLocalization() + " languages!");
|
||||
|
||||
instance.initStorage();
|
||||
instance.initEconomy();
|
||||
|
||||
new PaneListener(this);
|
||||
new PlayerJoinListener();
|
||||
//new PlayerJoinListener();
|
||||
|
||||
instance.commandManager = new CommandManager();
|
||||
loadCommands();
|
||||
//noinspection ConstantConditions
|
||||
instance.getCommand("headdb").setExecutor(new CommandMain());
|
||||
|
||||
new Metrics(this, 9152);
|
||||
ensureLatestVersion();
|
||||
@ -66,7 +68,9 @@ public class HeadDB extends SmartPlugin {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// todo: save storage
|
||||
if (storage != null) {
|
||||
storage.getPlayerStorage().suspend();
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
instance.localization = new TranslatableLocalization(this, "messages");
|
||||
try {
|
||||
@ -108,6 +119,16 @@ public class HeadDB extends SmartPlugin {
|
||||
}
|
||||
|
||||
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 CommandCategory().register();
|
||||
new CommandSearch().register();
|
||||
@ -119,6 +140,12 @@ public class HeadDB extends SmartPlugin {
|
||||
new CommandInfo().register();
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
public Storage getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public CommandManager getCommandManager() {
|
||||
return commandManager;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package tsp.headdb.core.api;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import tsp.headdb.HeadDB;
|
||||
import tsp.headdb.core.storage.PlayerData;
|
||||
import tsp.headdb.core.util.Utils;
|
||||
import tsp.headdb.implementation.category.Category;
|
||||
import tsp.headdb.implementation.head.Head;
|
||||
@ -18,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -152,7 +154,7 @@ public final class HeadAPI {
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
@ -161,6 +163,24 @@ public final class HeadAPI {
|
||||
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.
|
||||
*
|
||||
|
@ -80,7 +80,7 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor, TabCo
|
||||
}
|
||||
})
|
||||
.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())
|
||||
.open(player);
|
||||
}
|
||||
@ -90,7 +90,20 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor, TabCo
|
||||
// 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 -> {
|
||||
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 -> {
|
||||
@ -140,8 +153,6 @@ public class CommandMain extends HeadDBCommand implements CommandExecutor, TabCo
|
||||
}
|
||||
|
||||
player.getInventory().addItem(localItem);
|
||||
} else if (le.isRightClick()) {
|
||||
// todo: remove from favorites
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ public final class PlayerJoinListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
// todo: favorites
|
||||
//HeadDB.getInstance().getStorage().getPlayerStorage().register(new PlayerData(event.getPlayer().getUniqueId(), ""));
|
||||
}
|
||||
|
||||
|
20
src/main/java/tsp/headdb/core/storage/HeadDBThreadFactory.java
Normale Datei
20
src/main/java/tsp/headdb/core/storage/HeadDBThreadFactory.java
Normale Datei
@ -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());
|
||||
}
|
||||
|
||||
}
|
7
src/main/java/tsp/headdb/core/storage/PlayerData.java
Normale Datei
7
src/main/java/tsp/headdb/core/storage/PlayerData.java
Normale Datei
@ -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 {}
|
62
src/main/java/tsp/headdb/core/storage/PlayerStorage.java
Normale Datei
62
src/main/java/tsp/headdb/core/storage/PlayerStorage.java
Normale Datei
@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
src/main/java/tsp/headdb/core/storage/Storage.java
Normale Datei
24
src/main/java/tsp/headdb/core/storage/Storage.java
Normale Datei
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,8 @@ import tsp.headdb.core.api.HeadAPI;
|
||||
import tsp.headdb.core.api.event.HeadPurchaseEvent;
|
||||
import tsp.headdb.core.economy.BasicEconomyProvider;
|
||||
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.head.Head;
|
||||
import tsp.smartplugin.inventory.Button;
|
||||
@ -33,6 +35,7 @@ import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
@ -121,7 +124,7 @@ public class Utils {
|
||||
|
||||
purchase(player, head, amount);
|
||||
} else if (e.isRightClick()) {
|
||||
// todo: favorites
|
||||
HeadDB.getInstance().getStorage().getPlayerStorage().get(player.getUniqueId()).orElse(new PlayerData(player.getUniqueId(), new HashSet<>())).favorites().add(head.getTexture());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import tsp.headdb.implementation.requester.Requester;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class HeadDatabase {
|
||||
@ -16,14 +17,14 @@ public class HeadDatabase {
|
||||
private final JavaPlugin plugin;
|
||||
private final BukkitScheduler scheduler;
|
||||
private final Requester requester;
|
||||
private final Map<Category, List<Head>> heads;
|
||||
private final ConcurrentHashMap<Category, List<Head>> heads;
|
||||
private long timestamp;
|
||||
|
||||
public HeadDatabase(JavaPlugin plugin, HeadProvider provider) {
|
||||
this.plugin = plugin;
|
||||
this.scheduler = plugin.getServer().getScheduler();
|
||||
this.requester = new Requester(plugin, provider);
|
||||
this.heads = new HashMap<>();
|
||||
this.heads = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public Map<Category, List<Head>> getHeads() {
|
||||
|
@ -1,14 +1,15 @@
|
||||
# How often the database should be updated in seconds.
|
||||
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
|
||||
|
||||
# If enabled categories will require a permission to be used
|
||||
# If enabled categories will require a permission to be used.
|
||||
# Permission: headdb.category.<category>
|
||||
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
|
||||
|
||||
# Economy Options
|
||||
@ -28,7 +29,7 @@ economy:
|
||||
monsters: 100
|
||||
plants: 100
|
||||
|
||||
# Command Configuration. Supports PlaceholderAPI
|
||||
# Command Configuration. Supports PlaceholderAPI.
|
||||
commands:
|
||||
# Commands to run ONLY if the purchase is successful.
|
||||
# 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.
|
||||
fallback: true
|
||||
|
||||
# Shows more plugin information in /hdb info
|
||||
# Shows more plugin information. (/hdb info)
|
||||
showAdvancedPluginInfo: true
|
||||
|
||||
# Storage Options
|
||||
storage:
|
||||
# Amount of threads in the executor pool used for storage.
|
||||
threads: 2
|
||||
|
||||
# Debug Mode
|
||||
debug: false
|
@ -17,7 +17,7 @@ itemTexture: "&7Texture: &6%texture%"
|
||||
itemNoTexture: "&cThis item does not have a texture!"
|
||||
copyTexture: "&6Click to copy texture!"
|
||||
|
||||
#
|
||||
# Only shown if economy is enabled
|
||||
processPayment: "&7Purchasing &6%name% &7for &6%cost%&7! Please wait..."
|
||||
completePayment: "&7Received &6%name% &7for &6%cost%"
|
||||
|
||||
@ -34,6 +34,8 @@ menu:
|
||||
lore:
|
||||
- "&7Left-Click to open"
|
||||
- "&7Right-Click to open specific page"
|
||||
favorites:
|
||||
name: "&6Favorites"
|
||||
search:
|
||||
name: "&6Search"
|
||||
local:
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren