mirror of
https://github.com/xHyroM/lighteco.git
synced 2024-11-24 07:41:05 +01:00
refactor: one currency, one table (#2)
* refactor: rewrite how users are loaded * finish * feat: use \' instead ` in CREATE_TABLE * fix: remove record if user has zero balance * add housekeeper * feat: add housekeeper config
This commit is contained in:
parent
2e20dee652
commit
8112b41d12
36 changed files with 367 additions and 346 deletions
|
@ -1,13 +1,10 @@
|
||||||
package dev.xhyrom.lighteco.api.manager;
|
package dev.xhyrom.lighteco.api.manager;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.api.model.currency.Currency;
|
import dev.xhyrom.lighteco.api.model.currency.Currency;
|
||||||
import dev.xhyrom.lighteco.api.model.user.User;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public interface CurrencyManager {
|
public interface CurrencyManager {
|
||||||
/**
|
/**
|
||||||
|
@ -31,14 +28,4 @@ public interface CurrencyManager {
|
||||||
* @param currency the currency to register
|
* @param currency the currency to register
|
||||||
*/
|
*/
|
||||||
void registerCurrency(@NonNull Currency currency);
|
void registerCurrency(@NonNull Currency currency);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the top users for a currency.
|
|
||||||
*
|
|
||||||
* @implNote This method is not cached. It fetches the data from the database every time it is called.
|
|
||||||
* @param currency the currency to get the top users for
|
|
||||||
* @param length the length of the list
|
|
||||||
* @return a future that completes with the top users (sorted from highest to lowest balance)
|
|
||||||
*/
|
|
||||||
CompletableFuture<List<User>> getTopUsers(@NonNull Currency currency, int length);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import dev.xhyrom.lighteco.api.model.user.User;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface StorageProvider {
|
public interface StorageProvider {
|
||||||
|
@ -23,9 +22,8 @@ public interface StorageProvider {
|
||||||
*/
|
*/
|
||||||
void shutdown() throws Exception;
|
void shutdown() throws Exception;
|
||||||
|
|
||||||
|
default void registerCurrency(@NonNull Currency currency) throws Exception {}
|
||||||
@NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception;
|
@NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception;
|
||||||
void saveUser(@NonNull User user) throws Exception;
|
void saveUser(@NonNull User user) throws Exception;
|
||||||
void saveUsers(@NonNull User... users) throws Exception;
|
void saveUsers(@NonNull User... users) throws Exception;
|
||||||
|
|
||||||
@NonNull List<User> getTopUsers(Currency currency, int length) throws Exception;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger;
|
||||||
import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter;
|
import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -58,6 +59,12 @@ public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr
|
||||||
return this.loader.getDataFolder().toPath();
|
return this.loader.getDataFolder().toPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayerOnline(UUID uniqueId) {
|
||||||
|
Player player = this.loader.getServer().getPlayer(uniqueId);
|
||||||
|
return player != null && player.isOnline();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UUID> getOnlinePlayers() {
|
public List<UUID> getOnlinePlayers() {
|
||||||
return this.loader.getServer().getOnlinePlayers().stream()
|
return this.loader.getServer().getOnlinePlayers().stream()
|
||||||
|
|
|
@ -3,15 +3,9 @@ package dev.xhyrom.lighteco.bukkittest;
|
||||||
import dev.xhyrom.lighteco.api.LightEco;
|
import dev.xhyrom.lighteco.api.LightEco;
|
||||||
import dev.xhyrom.lighteco.api.LightEcoProvider;
|
import dev.xhyrom.lighteco.api.LightEcoProvider;
|
||||||
import dev.xhyrom.lighteco.api.manager.CurrencyManager;
|
import dev.xhyrom.lighteco.api.manager.CurrencyManager;
|
||||||
import dev.xhyrom.lighteco.api.model.user.User;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public class TestPlugin extends JavaPlugin implements Listener {
|
public class TestPlugin extends JavaPlugin implements Listener {
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
@ -22,7 +16,6 @@ public class TestPlugin extends JavaPlugin implements Listener {
|
||||||
|
|
||||||
currencyManager.registerCurrency(new TestCurrency());
|
currencyManager.registerCurrency(new TestCurrency());
|
||||||
currencyManager.registerCurrency(new TestCurrency2());
|
currencyManager.registerCurrency(new TestCurrency2());
|
||||||
getServer().getPluginManager().registerEvents(this, this);
|
|
||||||
|
|
||||||
getLogger().info("TestCurrency registered!");
|
getLogger().info("TestCurrency registered!");
|
||||||
|
|
||||||
|
@ -31,15 +24,4 @@ public class TestPlugin extends JavaPlugin implements Listener {
|
||||||
provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test"));
|
provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test"));
|
||||||
provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test2"));
|
provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onChat(AsyncPlayerChatEvent event) {
|
|
||||||
LightEco provider = LightEcoProvider.get();
|
|
||||||
CurrencyManager currencyManager = provider.getCurrencyManager();
|
|
||||||
CompletableFuture<List<User>> topusers = currencyManager.getTopUsers(currencyManager.getCurrency("money"), 5);
|
|
||||||
|
|
||||||
for (User user : topusers.join()) {
|
|
||||||
event.getPlayer().sendMessage(user.getUniqueId() + " ("+ user.getUsername() +") " + ": " + user.getBalance(currencyManager.getCurrency("money")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,10 @@ package dev.xhyrom.lighteco.common.api.impl;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.api.manager.CurrencyManager;
|
import dev.xhyrom.lighteco.api.manager.CurrencyManager;
|
||||||
import dev.xhyrom.lighteco.api.model.currency.Currency;
|
import dev.xhyrom.lighteco.api.model.currency.Currency;
|
||||||
import dev.xhyrom.lighteco.api.model.user.User;
|
|
||||||
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public class ApiCurrencyManager extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.currency.CurrencyManager> implements CurrencyManager {
|
public class ApiCurrencyManager extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.currency.CurrencyManager> implements CurrencyManager {
|
||||||
public ApiCurrencyManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.currency.CurrencyManager handler) {
|
public ApiCurrencyManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.currency.CurrencyManager handler) {
|
||||||
|
@ -36,10 +33,4 @@ public class ApiCurrencyManager extends ApiAbstractManager<dev.xhyrom.lighteco.c
|
||||||
dev.xhyrom.lighteco.common.model.currency.Currency internal = new dev.xhyrom.lighteco.common.model.currency.Currency(currency);
|
dev.xhyrom.lighteco.common.model.currency.Currency internal = new dev.xhyrom.lighteco.common.model.currency.Currency(currency);
|
||||||
this.handler.registerCurrency(internal);
|
this.handler.registerCurrency(internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<List<User>> getTopUsers(@NonNull Currency currency, int length) {
|
|
||||||
dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getIfLoaded(currency.getIdentifier());
|
|
||||||
return this.handler.getTopUsers(internal, length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ public class ApiUserManager extends ApiAbstractManager<dev.xhyrom.lighteco.commo
|
||||||
super(plugin, handler);
|
super(plugin, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User wrap(dev.xhyrom.lighteco.common.model.user.User handler) {
|
private User wrap(dev.xhyrom.lighteco.common.model.user.User handler) {
|
||||||
|
this.plugin.getUserManager().getHousekeeper().registerUsage(handler.getUniqueId());
|
||||||
return handler.getProxy();
|
return handler.getProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ public class ApiUserManager extends ApiAbstractManager<dev.xhyrom.lighteco.commo
|
||||||
@Override
|
@Override
|
||||||
public @NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId, String username) {
|
public @NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId, String username) {
|
||||||
return this.plugin.getStorage().loadUser(uniqueId, username)
|
return this.plugin.getStorage().loadUser(uniqueId, username)
|
||||||
.thenApply(ApiUserManager::wrap);
|
.thenApply(this::wrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
33
common/src/main/java/dev/xhyrom/lighteco/common/cache/ExpiringSet.java
vendored
Normal file
33
common/src/main/java/dev/xhyrom/lighteco/common/cache/ExpiringSet.java
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package dev.xhyrom.lighteco.common.cache;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ExpiringSet<T> {
|
||||||
|
private final Cache<T, Long> cache;
|
||||||
|
private final long lifetime;
|
||||||
|
|
||||||
|
public ExpiringSet(long duration, TimeUnit unit) {
|
||||||
|
this.cache = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterWrite(duration, unit)
|
||||||
|
.build();
|
||||||
|
this.lifetime = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(T item) {
|
||||||
|
boolean present = contains(item);
|
||||||
|
this.cache.put(item, System.currentTimeMillis() + this.lifetime);
|
||||||
|
return !present;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(T item) {
|
||||||
|
Long timeout = this.cache.getIfPresent(item);
|
||||||
|
return timeout != null && timeout > System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(T item) {
|
||||||
|
this.cache.invalidate(item);
|
||||||
|
}
|
||||||
|
}
|
7
common/src/main/java/dev/xhyrom/lighteco/common/cache/RedisBackedMap.java
vendored
Normal file
7
common/src/main/java/dev/xhyrom/lighteco/common/cache/RedisBackedMap.java
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package dev.xhyrom.lighteco.common.cache;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class RedisBackedMap<T, U> extends HashMap<T, U> {
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package dev.xhyrom.lighteco.common.config;
|
package dev.xhyrom.lighteco.common.config;
|
||||||
|
|
||||||
|
import dev.xhyrom.lighteco.common.config.housekeeper.HousekeeperConfig;
|
||||||
import dev.xhyrom.lighteco.common.config.message.MessageConfig;
|
import dev.xhyrom.lighteco.common.config.message.MessageConfig;
|
||||||
import dev.xhyrom.lighteco.common.config.storage.StorageConfig;
|
import dev.xhyrom.lighteco.common.config.storage.StorageConfig;
|
||||||
import eu.okaeri.configs.OkaeriConfig;
|
import eu.okaeri.configs.OkaeriConfig;
|
||||||
|
@ -23,6 +24,10 @@ public class Config extends OkaeriConfig {
|
||||||
@Comment("Messages")
|
@Comment("Messages")
|
||||||
public MessageConfig messages = new MessageConfig();
|
public MessageConfig messages = new MessageConfig();
|
||||||
|
|
||||||
|
@Comment("Housekeeper")
|
||||||
|
@Comment("Task that runs periodically to clean up the cache.")
|
||||||
|
public HousekeeperConfig housekeeper = new HousekeeperConfig();
|
||||||
|
|
||||||
@Comment("Debug mode")
|
@Comment("Debug mode")
|
||||||
@Comment("Prints additional information to the console.")
|
@Comment("Prints additional information to the console.")
|
||||||
public boolean debug = false;
|
public boolean debug = false;
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package dev.xhyrom.lighteco.common.config.housekeeper;
|
||||||
|
|
||||||
|
import eu.okaeri.configs.OkaeriConfig;
|
||||||
|
import eu.okaeri.configs.annotation.Comment;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class HousekeeperConfig extends OkaeriConfig {
|
||||||
|
@Comment("How long should the cache be kept after the last write")
|
||||||
|
public int expireAfterWrite = 300;
|
||||||
|
public TimeUnit expireAfterWriteUnit = TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
@Comment("How often should housekeeper run")
|
||||||
|
public int runInterval = 60;
|
||||||
|
public TimeUnit runIntervalUnit = TimeUnit.SECONDS;
|
||||||
|
}
|
|
@ -1,18 +1,13 @@
|
||||||
package dev.xhyrom.lighteco.common.manager.currency;
|
package dev.xhyrom.lighteco.common.manager.currency;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.api.model.user.User;
|
|
||||||
import dev.xhyrom.lighteco.common.manager.Manager;
|
import dev.xhyrom.lighteco.common.manager.Manager;
|
||||||
import dev.xhyrom.lighteco.common.model.currency.Currency;
|
import dev.xhyrom.lighteco.common.model.currency.Currency;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public interface CurrencyManager extends Manager<String, Currency> {
|
public interface CurrencyManager extends Manager<String, Currency> {
|
||||||
@NonNull Collection<Currency> getRegisteredCurrencies();
|
@NonNull Collection<Currency> getRegisteredCurrencies();
|
||||||
|
|
||||||
void registerCurrency(@NonNull Currency currency);
|
void registerCurrency(@NonNull Currency currency);
|
||||||
|
|
||||||
CompletableFuture<List<User>> getTopUsers(@NonNull Currency currency, int length);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package dev.xhyrom.lighteco.common.manager.currency;
|
package dev.xhyrom.lighteco.common.manager.currency;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.api.model.user.User;
|
|
||||||
import dev.xhyrom.lighteco.common.manager.SingleManager;
|
import dev.xhyrom.lighteco.common.manager.SingleManager;
|
||||||
import dev.xhyrom.lighteco.common.model.currency.Currency;
|
import dev.xhyrom.lighteco.common.model.currency.Currency;
|
||||||
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public class StandardCurrencyManager extends SingleManager<String, Currency> implements CurrencyManager {
|
public class StandardCurrencyManager extends SingleManager<String, Currency> implements CurrencyManager {
|
||||||
private final LightEcoPlugin plugin;
|
private final LightEcoPlugin plugin;
|
||||||
|
@ -37,11 +34,10 @@ public class StandardCurrencyManager extends SingleManager<String, Currency> imp
|
||||||
if (this.isLoaded(currency.getIdentifier()))
|
if (this.isLoaded(currency.getIdentifier()))
|
||||||
throw new IllegalArgumentException("Currency with identifier " + currency.getIdentifier() + " already registered");
|
throw new IllegalArgumentException("Currency with identifier " + currency.getIdentifier() + " already registered");
|
||||||
|
|
||||||
|
if (this.plugin.getConfig().debug)
|
||||||
|
this.plugin.getBootstrap().getLogger().info("Registering currency " + currency.getIdentifier());
|
||||||
|
|
||||||
|
this.plugin.getStorage().registerCurrencySync(currency.getProxy());
|
||||||
this.map.put(currency.getIdentifier(), currency);
|
this.map.put(currency.getIdentifier(), currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<List<User>> getTopUsers(@NonNull Currency currency, int length) {
|
|
||||||
return this.plugin.getStorage().getTopUsers(currency.getProxy(), length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,29 @@ package dev.xhyrom.lighteco.common.manager.user;
|
||||||
import dev.xhyrom.lighteco.common.manager.ConcurrentManager;
|
import dev.xhyrom.lighteco.common.manager.ConcurrentManager;
|
||||||
import dev.xhyrom.lighteco.common.model.user.User;
|
import dev.xhyrom.lighteco.common.model.user.User;
|
||||||
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class StandardUserManager extends ConcurrentManager<UUID, User> implements UserManager {
|
public class StandardUserManager extends ConcurrentManager<UUID, User> implements UserManager {
|
||||||
private final LightEcoPlugin plugin;
|
private final LightEcoPlugin plugin;
|
||||||
|
@Getter
|
||||||
|
private final UserHousekeeper housekeeper;
|
||||||
|
|
||||||
public StandardUserManager(LightEcoPlugin plugin) {
|
public StandardUserManager(LightEcoPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.housekeeper = new UserHousekeeper(plugin, this, UserHousekeeper.timeoutSettings(
|
||||||
|
this.plugin.getConfig().housekeeper.expireAfterWrite,
|
||||||
|
this.plugin.getConfig().housekeeper.expireAfterWriteUnit
|
||||||
|
));
|
||||||
|
|
||||||
|
this.plugin.getBootstrap().getScheduler().asyncRepeating(
|
||||||
|
this.housekeeper,
|
||||||
|
this.plugin.getConfig().housekeeper.runInterval,
|
||||||
|
this.plugin.getConfig().housekeeper.runIntervalUnit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,11 +35,15 @@ public class StandardUserManager extends ConcurrentManager<UUID, User> implement
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<User> loadUser(UUID uniqueId) {
|
public CompletableFuture<User> loadUser(UUID uniqueId) {
|
||||||
|
this.plugin.getUserManager().getHousekeeper().registerUsage(uniqueId);
|
||||||
|
|
||||||
return loadUser(uniqueId, null);
|
return loadUser(uniqueId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<User> loadUser(UUID uniqueId, String username) {
|
public CompletableFuture<User> loadUser(UUID uniqueId, String username) {
|
||||||
|
this.plugin.getUserManager().getHousekeeper().registerUsage(uniqueId);
|
||||||
|
|
||||||
return this.plugin.getStorage().loadUser(uniqueId, username);
|
return this.plugin.getStorage().loadUser(uniqueId, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package dev.xhyrom.lighteco.common.manager.user;
|
||||||
|
|
||||||
|
import dev.xhyrom.lighteco.common.cache.ExpiringSet;
|
||||||
|
import dev.xhyrom.lighteco.common.model.user.User;
|
||||||
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class UserHousekeeper implements Runnable {
|
||||||
|
private final LightEcoPlugin plugin;
|
||||||
|
private final UserManager userManager;
|
||||||
|
|
||||||
|
private final ExpiringSet<UUID> recentlyUsed;
|
||||||
|
|
||||||
|
public UserHousekeeper(LightEcoPlugin plugin, UserManager userManager, TimeoutSettings timeoutSettings) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.userManager = userManager;
|
||||||
|
this.recentlyUsed = new ExpiringSet<>(timeoutSettings.duration, timeoutSettings.unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerUsage(UUID uuid) {
|
||||||
|
this.recentlyUsed.add(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (UUID entry : this.userManager.keys()) {
|
||||||
|
cleanup(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup(UUID uuid) {
|
||||||
|
if (this.recentlyUsed.contains(uuid) || this.plugin.getBootstrap().isPlayerOnline(uuid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = this.userManager.getIfLoaded(uuid);
|
||||||
|
if (user == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user is dirty (has unsaved changes), don't unload
|
||||||
|
if (user.isDirty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.plugin.getConfig().debug) {
|
||||||
|
this.plugin.getBootstrap().getLogger().info("Unloading data for " + uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userManager.unload(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeoutSettings timeoutSettings(long duration, TimeUnit unit) {
|
||||||
|
return new TimeoutSettings(duration, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class TimeoutSettings {
|
||||||
|
private final long duration;
|
||||||
|
private final TimeUnit unit;
|
||||||
|
|
||||||
|
TimeoutSettings(long duration, TimeUnit unit) {
|
||||||
|
this.duration = duration;
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,12 @@ package dev.xhyrom.lighteco.common.manager.user;
|
||||||
import dev.xhyrom.lighteco.common.manager.Manager;
|
import dev.xhyrom.lighteco.common.manager.Manager;
|
||||||
import dev.xhyrom.lighteco.common.model.user.User;
|
import dev.xhyrom.lighteco.common.model.user.User;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface UserManager extends Manager<UUID, User> {
|
public interface UserManager extends Manager<UUID, User> {
|
||||||
|
UserHousekeeper getHousekeeper();
|
||||||
|
|
||||||
CompletableFuture<Void> saveUser(User user);
|
CompletableFuture<Void> saveUser(User user);
|
||||||
CompletableFuture<Void> saveUsers(User... users);
|
CompletableFuture<Void> saveUsers(User... users);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package dev.xhyrom.lighteco.common.model.user;
|
package dev.xhyrom.lighteco.common.model.user;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.common.api.impl.ApiUser;
|
import dev.xhyrom.lighteco.common.api.impl.ApiUser;
|
||||||
|
import dev.xhyrom.lighteco.common.cache.RedisBackedMap;
|
||||||
import dev.xhyrom.lighteco.common.model.currency.Currency;
|
import dev.xhyrom.lighteco.common.model.currency.Currency;
|
||||||
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -15,6 +16,7 @@ import java.util.UUID;
|
||||||
@Getter
|
@Getter
|
||||||
public class User {
|
public class User {
|
||||||
private final LightEcoPlugin plugin;
|
private final LightEcoPlugin plugin;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final ApiUser proxy = new ApiUser(this);
|
private final ApiUser proxy = new ApiUser(this);
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@ public class User {
|
||||||
@Setter
|
@Setter
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
private final HashMap<Currency, BigDecimal> balances = new HashMap<>();
|
private final HashMap<Currency, BigDecimal> balances = new RedisBackedMap<>();
|
||||||
|
|
||||||
public User(LightEcoPlugin plugin, UUID uniqueId) {
|
public User(LightEcoPlugin plugin, UUID uniqueId) {
|
||||||
this(plugin, uniqueId, null);
|
this(plugin, uniqueId, null);
|
||||||
|
@ -45,6 +47,10 @@ public class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) {
|
public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) {
|
||||||
|
this.setBalance(currency, balance, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance, boolean force) {
|
||||||
if (balance.compareTo(BigDecimal.ZERO) < 0) {
|
if (balance.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
throw new IllegalArgumentException("Balance cannot be negative");
|
throw new IllegalArgumentException("Balance cannot be negative");
|
||||||
}
|
}
|
||||||
|
@ -52,7 +58,8 @@ public class User {
|
||||||
balance = balance.setScale(currency.fractionalDigits(), RoundingMode.DOWN);
|
balance = balance.setScale(currency.fractionalDigits(), RoundingMode.DOWN);
|
||||||
balances.put(currency, balance);
|
balances.put(currency, balance);
|
||||||
|
|
||||||
this.setDirty(true);
|
if (!force)
|
||||||
|
this.setDirty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException {
|
public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException {
|
||||||
|
|
|
@ -28,8 +28,6 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin {
|
||||||
private UserSaveTask userSaveTask;
|
private UserSaveTask userSaveTask;
|
||||||
|
|
||||||
public final void load() {
|
public final void load() {
|
||||||
this.dependencyManager = new DependencyManagerImpl(this);
|
|
||||||
|
|
||||||
this.config = ConfigManager.create(Config.class, it -> {
|
this.config = ConfigManager.create(Config.class, it -> {
|
||||||
it.withConfigurer(new YamlSnakeYamlConfigurer());
|
it.withConfigurer(new YamlSnakeYamlConfigurer());
|
||||||
it.withBindFile(this.getBootstrap().getDataDirectory().resolve("config.yml"));
|
it.withBindFile(this.getBootstrap().getDataDirectory().resolve("config.yml"));
|
||||||
|
@ -37,6 +35,8 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin {
|
||||||
it.saveDefaults();
|
it.saveDefaults();
|
||||||
it.load(true);
|
it.load(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.dependencyManager = new DependencyManagerImpl(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void enable() {
|
public final void enable() {
|
||||||
|
|
|
@ -13,6 +13,7 @@ public interface LightEcoBootstrap {
|
||||||
PluginLogger getLogger();
|
PluginLogger getLogger();
|
||||||
SchedulerAdapter getScheduler();
|
SchedulerAdapter getScheduler();
|
||||||
Path getDataDirectory();
|
Path getDataDirectory();
|
||||||
|
boolean isPlayerOnline(UUID uniqueId);
|
||||||
List<UUID> getOnlinePlayers();
|
List<UUID> getOnlinePlayers();
|
||||||
InputStream getResourceStream(String filename);
|
InputStream getResourceStream(String filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.xhyrom.lighteco.common.storage;
|
package dev.xhyrom.lighteco.common.storage;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.common.model.user.User;
|
import dev.xhyrom.lighteco.api.model.currency.Currency;
|
||||||
import dev.xhyrom.lighteco.api.storage.StorageProvider;
|
import dev.xhyrom.lighteco.api.storage.StorageProvider;
|
||||||
|
import dev.xhyrom.lighteco.common.model.user.User;
|
||||||
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
import dev.xhyrom.lighteco.common.util.ThrowableRunnable;
|
import dev.xhyrom.lighteco.common.util.ThrowableRunnable;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
@ -86,6 +86,14 @@ public class Storage {
|
||||||
return future(() -> this.provider.saveUsers(users));
|
return future(() -> this.provider.saveUsers(users));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void registerCurrencySync(Currency currency) {
|
||||||
|
try {
|
||||||
|
this.provider.registerCurrency(currency);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to register currency", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void saveUsersSync(dev.xhyrom.lighteco.api.model.user.User... users) {
|
public void saveUsersSync(dev.xhyrom.lighteco.api.model.user.User... users) {
|
||||||
try {
|
try {
|
||||||
this.provider.saveUsers(users);
|
this.provider.saveUsers(users);
|
||||||
|
@ -93,10 +101,4 @@ public class Storage {
|
||||||
throw new RuntimeException("Failed to save users", e);
|
throw new RuntimeException("Failed to save users", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return ApiUser instead of User
|
|
||||||
// We don't do anything with this
|
|
||||||
public CompletableFuture<List<dev.xhyrom.lighteco.api.model.user.User>> getTopUsers(dev.xhyrom.lighteco.api.model.currency.Currency currency, int length) {
|
|
||||||
return future(() -> this.provider.getTopUsers(currency, length));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package dev.xhyrom.lighteco.common.storage.provider.memory;
|
package dev.xhyrom.lighteco.common.storage.provider.memory;
|
||||||
|
|
||||||
import dev.xhyrom.lighteco.api.model.currency.Currency;
|
|
||||||
import dev.xhyrom.lighteco.api.model.user.User;
|
import dev.xhyrom.lighteco.api.model.user.User;
|
||||||
import dev.xhyrom.lighteco.api.storage.StorageProvider;
|
import dev.xhyrom.lighteco.api.storage.StorageProvider;
|
||||||
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
||||||
|
@ -8,10 +7,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MemoryStorageProvider implements StorageProvider {
|
public class MemoryStorageProvider implements StorageProvider {
|
||||||
|
@ -53,16 +49,6 @@ public class MemoryStorageProvider implements StorageProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull List<User> getTopUsers(Currency currency, int length) throws Exception {
|
|
||||||
return userDatabase.values().stream().sorted((user1, user2) -> {
|
|
||||||
BigDecimal balance1 = user1.getBalance(currency);
|
|
||||||
BigDecimal balance2 = user2.getBalance(currency);
|
|
||||||
|
|
||||||
return balance1.compareTo(balance2);
|
|
||||||
}).limit(length).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private User createUser(UUID uniqueId, String username, User data) {
|
private User createUser(UUID uniqueId, String username, User data) {
|
||||||
dev.xhyrom.lighteco.common.model.user.User user = this.plugin.getUserManager().getOrMake(uniqueId);
|
dev.xhyrom.lighteco.common.model.user.User user = this.plugin.getUserManager().getOrMake(uniqueId);
|
||||||
if (username != null)
|
if (username != null)
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
// Implementation from LuckPerms
|
|
||||||
// https://github.com/LuckPerms/LuckPerms/blob/master/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SchemaReader.java
|
|
||||||
// Copyright (c) lucko (Luck) <lucko@lucko.me>
|
|
||||||
// Copyright (c) contributors
|
|
||||||
// Under MIT License
|
|
||||||
|
|
||||||
package dev.xhyrom.lighteco.common.storage.provider.sql;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public final class SchemaReader {
|
|
||||||
public static List<String> getStatements(InputStream is) throws IOException {
|
|
||||||
List<String> queries = new LinkedList<>();
|
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
if (line.startsWith("--") || line.startsWith("#")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append(line);
|
|
||||||
|
|
||||||
// check for end of declaration
|
|
||||||
if (line.endsWith(";")) {
|
|
||||||
sb.deleteCharAt(sb.length() - 1);
|
|
||||||
|
|
||||||
String result = sb.toString().trim();
|
|
||||||
if (!result.isEmpty()) {
|
|
||||||
queries.add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset
|
|
||||||
sb = new StringBuilder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queries;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,22 +4,28 @@ import dev.xhyrom.lighteco.common.storage.StorageType;
|
||||||
|
|
||||||
public enum SqlStatements {
|
public enum SqlStatements {
|
||||||
SAVE_USER_LOCAL_CURRENCY(
|
SAVE_USER_LOCAL_CURRENCY(
|
||||||
"INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?3;",
|
"INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;",
|
||||||
"INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON DUPLICATE KEY UPDATE balance=?3;",
|
"INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON DUPLICATE KEY UPDATE balance=?2;",
|
||||||
"INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance=?;",
|
"INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?, ?) ON DUPLICATE KEY UPDATE balance=?;",
|
||||||
"INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?;"
|
"INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;"
|
||||||
),
|
),
|
||||||
SAVE_USER_GLOBAL_CURRENCY(
|
SAVE_USER_GLOBAL_CURRENCY(
|
||||||
"INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?3;",
|
"INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;",
|
||||||
"INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON DUPLICATE KEY UPDATE balance=?3;",
|
"INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON DUPLICATE KEY UPDATE balance=?2;",
|
||||||
"INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance=?;",
|
"INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?, ?) ON DUPLICATE KEY UPDATE balance=?;",
|
||||||
"INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?;"
|
"INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;"
|
||||||
),
|
),
|
||||||
LOAD_WHOLE_USER(
|
LOAD_LOCAL_CURRENCY_USER(
|
||||||
"SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ?1 UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ?1 ) AS combined_currencies;",
|
"SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1",
|
||||||
"SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ?1 UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ?1 ) AS combined_currencies;",
|
"SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1",
|
||||||
"SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ? UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ? ) AS combined_currencies;",
|
"SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?",
|
||||||
null // same as mariadb
|
"SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1"
|
||||||
|
),
|
||||||
|
LOAD_GLOBAL_CURRENCY_USER(
|
||||||
|
"SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1",
|
||||||
|
"SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1",
|
||||||
|
"SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?",
|
||||||
|
"SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1"
|
||||||
);
|
);
|
||||||
|
|
||||||
public final String sqlite;
|
public final String sqlite;
|
||||||
|
|
|
@ -10,11 +10,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.*;
|
import java.sql.Connection;
|
||||||
import java.util.ArrayList;
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -22,11 +22,19 @@ import java.util.function.Function;
|
||||||
public class SqlStorageProvider implements StorageProvider {
|
public class SqlStorageProvider implements StorageProvider {
|
||||||
private static String SAVE_USER_LOCAL_CURRENCY;
|
private static String SAVE_USER_LOCAL_CURRENCY;
|
||||||
private static String SAVE_USER_GLOBAL_CURRENCY;
|
private static String SAVE_USER_GLOBAL_CURRENCY;
|
||||||
private static String LOAD_WHOLE_USER;
|
|
||||||
private static final String GET_TOP_X_USERS_LOCAL = "SELECT uuid, balance FROM {prefix}_{context}_users WHERE currency_identifier = ? ORDER BY balance DESC LIMIT ?;";
|
private static String LOAD_LOCAL_CURRENCY_USER;
|
||||||
private static final String GET_TOP_X_USERS_GLOBAL = "SELECT uuid, balance FROM {prefix}_users WHERE currency_identifier = ? ORDER BY balance DESC LIMIT ?;";
|
private static String LOAD_GLOBAL_CRRENCY_USER;
|
||||||
private static final String DELETE_GLOBAL_USER_IF_BALANCE = "DELETE FROM {prefix}_{context}_users WHERE uuid = ? AND currency_identifier = ? AND balance = ?;";
|
|
||||||
private static final String DELETE_LOCAL_USER_IF_BALANCE = "DELETE FROM {prefix}_{context}_users WHERE uuid = ? AND currency_identifier = ? AND balance = ?;";
|
private static final String DELETE_LOCAL_USER = "DELETE FROM {prefix}_local_{context}_{currency}_users WHERE uuid = ?;";
|
||||||
|
private static final String DELETE_GLOBAL_USER = "DELETE FROM {prefix}_global_{currency}_users WHERE uuid = ?;";
|
||||||
|
private static final String CREATE_TABLE = """
|
||||||
|
CREATE TABLE IF NOT EXISTS '{prefix}_{table}' (
|
||||||
|
'uuid' VARCHAR(36) NOT NULL,
|
||||||
|
'balance' DECIMAL(10, 2) NOT NULL,
|
||||||
|
PRIMARY KEY (`uuid`)
|
||||||
|
);
|
||||||
|
""".trim();
|
||||||
|
|
||||||
private final LightEcoPlugin plugin;
|
private final LightEcoPlugin plugin;
|
||||||
private final ConnectionFactory connectionFactory;
|
private final ConnectionFactory connectionFactory;
|
||||||
|
@ -44,33 +52,13 @@ public class SqlStorageProvider implements StorageProvider {
|
||||||
final StorageType implementationName = this.connectionFactory.getImplementationName();
|
final StorageType implementationName = this.connectionFactory.getImplementationName();
|
||||||
SAVE_USER_LOCAL_CURRENCY = SqlStatements.SAVE_USER_LOCAL_CURRENCY.get(implementationName);
|
SAVE_USER_LOCAL_CURRENCY = SqlStatements.SAVE_USER_LOCAL_CURRENCY.get(implementationName);
|
||||||
SAVE_USER_GLOBAL_CURRENCY = SqlStatements.SAVE_USER_GLOBAL_CURRENCY.get(implementationName);
|
SAVE_USER_GLOBAL_CURRENCY = SqlStatements.SAVE_USER_GLOBAL_CURRENCY.get(implementationName);
|
||||||
LOAD_WHOLE_USER = SqlStatements.LOAD_WHOLE_USER.get(implementationName);
|
LOAD_LOCAL_CURRENCY_USER = SqlStatements.LOAD_LOCAL_CURRENCY_USER.get(implementationName);
|
||||||
|
LOAD_GLOBAL_CRRENCY_USER = SqlStatements.LOAD_GLOBAL_CURRENCY_USER.get(implementationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws Exception {
|
public void init() {
|
||||||
this.connectionFactory.init(this.plugin);
|
this.connectionFactory.init(this.plugin);
|
||||||
|
|
||||||
List<String> statements;
|
|
||||||
String schemaFileName = "schema/" + this.connectionFactory.getImplementationName().name().toLowerCase() + ".sql";
|
|
||||||
try (InputStream is = this.plugin.getBootstrap().getResourceStream(schemaFileName)) {
|
|
||||||
if (is == null)
|
|
||||||
throw new IOException("Failed to load schema file: " + schemaFileName);
|
|
||||||
|
|
||||||
statements = SchemaReader.getStatements(is).stream()
|
|
||||||
.map(this.statementProcessor)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
try (Connection c = this.connectionFactory.getConnection()) {
|
|
||||||
try (Statement s = c.createStatement()) {
|
|
||||||
for (String statement : statements) {
|
|
||||||
s.addBatch(statement);
|
|
||||||
}
|
|
||||||
|
|
||||||
s.executeBatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,6 +66,31 @@ public class SqlStorageProvider implements StorageProvider {
|
||||||
this.connectionFactory.shutdown();
|
this.connectionFactory.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerCurrency(dev.xhyrom.lighteco.api.model.currency.@NonNull Currency currency) throws Exception {
|
||||||
|
StringBuilder tableName = new StringBuilder();
|
||||||
|
|
||||||
|
if (currency.getType() == dev.xhyrom.lighteco.api.model.currency.Currency.Type.LOCAL) {
|
||||||
|
tableName.append("local_{context}_");
|
||||||
|
tableName.append(currency.getIdentifier());
|
||||||
|
} else {
|
||||||
|
tableName.append("global_");
|
||||||
|
tableName.append(currency.getIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
tableName.append("_users");
|
||||||
|
|
||||||
|
try (Connection c = this.connectionFactory.getConnection()) {
|
||||||
|
try (PreparedStatement ps = c.prepareStatement(
|
||||||
|
this.statementProcessor.apply(CREATE_TABLE
|
||||||
|
.replace("{table}", tableName.toString())
|
||||||
|
)
|
||||||
|
)) {
|
||||||
|
ps.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception {
|
public @NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception {
|
||||||
String uniqueIdString = uniqueId.toString();
|
String uniqueIdString = uniqueId.toString();
|
||||||
|
@ -85,21 +98,50 @@ public class SqlStorageProvider implements StorageProvider {
|
||||||
if (username != null)
|
if (username != null)
|
||||||
user.setUsername(username);
|
user.setUsername(username);
|
||||||
|
|
||||||
|
StringBuilder query = new StringBuilder();
|
||||||
|
List<Currency> currencies = this.plugin.getCurrencyManager().getRegisteredCurrencies().stream().toList();
|
||||||
|
int size = this.plugin.getCurrencyManager().getRegisteredCurrencies().size();
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
Currency currency = currencies.get(i);
|
||||||
|
|
||||||
|
switch (currency.getType()) {
|
||||||
|
case GLOBAL -> query.append(
|
||||||
|
this.statementProcessor.apply(LOAD_GLOBAL_CRRENCY_USER
|
||||||
|
.replace("{currency}", currency.getIdentifier())
|
||||||
|
).replace("{identifier}", "'"+currency.getIdentifier()+"'")
|
||||||
|
);
|
||||||
|
case LOCAL -> query.append(
|
||||||
|
this.statementProcessor.apply(LOAD_LOCAL_CURRENCY_USER
|
||||||
|
.replace("{currency}", currency.getIdentifier())
|
||||||
|
).replace("{identifier}", "'"+currency.getIdentifier()+"'")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != size - 1) {
|
||||||
|
query.append(" UNION ALL ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try (Connection c = this.connectionFactory.getConnection()) {
|
try (Connection c = this.connectionFactory.getConnection()) {
|
||||||
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(LOAD_WHOLE_USER))) {
|
try (PreparedStatement ps = c.prepareStatement(query.toString())) {
|
||||||
ps.setString(1, uniqueIdString);
|
if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) {
|
||||||
if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName()))
|
for (int i = 0; i < size; i++) {
|
||||||
ps.setString(2, uniqueIdString);
|
ps.setString(i + 1, uniqueIdString);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ps.setString(1, uniqueIdString);
|
||||||
|
}
|
||||||
|
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
|
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
String currencyIdentifier = rs.getString("currency_identifier");
|
String identifier = rs.getString("name");
|
||||||
Currency currency = this.plugin.getCurrencyManager().getIfLoaded(currencyIdentifier);
|
Currency currency = this.plugin.getCurrencyManager().getIfLoaded(identifier);
|
||||||
|
|
||||||
BigDecimal balance = rs.getBigDecimal("balance");
|
BigDecimal balance = rs.getBigDecimal("balance");
|
||||||
|
|
||||||
user.setBalance(currency, balance);
|
user.setBalance(currency, balance, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +172,7 @@ public class SqlStorageProvider implements StorageProvider {
|
||||||
for (User user : users) {
|
for (User user : users) {
|
||||||
String uniqueIdString = user.getUniqueId().toString();
|
String uniqueIdString = user.getUniqueId().toString();
|
||||||
|
|
||||||
saveBalances(c, user, uniqueIdString);
|
saveBalances(c, user, uniqueIdString, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
c.commit();
|
c.commit();
|
||||||
|
@ -141,96 +183,73 @@ public class SqlStorageProvider implements StorageProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void saveBalances(Connection c, User user, String uniqueIdString) throws SQLException {
|
||||||
public @NonNull List<User> getTopUsers(dev.xhyrom.lighteco.api.model.currency.Currency apiCurrency, int length) throws Exception {
|
saveBalances(c, user, uniqueIdString, true);
|
||||||
Currency currency = this.plugin.getCurrencyManager().getIfLoaded(apiCurrency.getIdentifier());
|
|
||||||
String statement = currency.getType() == dev.xhyrom.lighteco.api.model.currency.Currency.Type.GLOBAL
|
|
||||||
? GET_TOP_X_USERS_GLOBAL
|
|
||||||
: GET_TOP_X_USERS_LOCAL;
|
|
||||||
|
|
||||||
try (Connection c = this.connectionFactory.getConnection()) {
|
|
||||||
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(statement))) {
|
|
||||||
ps.setString(1, currency.getIdentifier());
|
|
||||||
ps.setInt(2, length);
|
|
||||||
|
|
||||||
ResultSet rs = ps.executeQuery();
|
|
||||||
|
|
||||||
List<User> users = new ArrayList<>();
|
|
||||||
while (rs.next()) {
|
|
||||||
String uniqueIdString = rs.getString("uuid");
|
|
||||||
UUID uniqueId = UUID.fromString(uniqueIdString);
|
|
||||||
|
|
||||||
BigDecimal balance = rs.getBigDecimal("balance");
|
|
||||||
|
|
||||||
dev.xhyrom.lighteco.common.model.user.User user = this.plugin.getUserManager().getOrMake(uniqueId);
|
|
||||||
user.setBalance(currency, balance);
|
|
||||||
|
|
||||||
users.add(user.getProxy());
|
|
||||||
}
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveBalances(Connection c, User user, String uniqueIdString) throws SQLException {
|
private void saveBalances(Connection c, User user, String uniqueIdString, boolean transactions) throws SQLException {
|
||||||
try (PreparedStatement psGlobal = c.prepareStatement(this.statementProcessor.apply(SAVE_USER_GLOBAL_CURRENCY));
|
if (transactions)
|
||||||
PreparedStatement psLocal = c.prepareStatement(this.statementProcessor.apply(SAVE_USER_LOCAL_CURRENCY));
|
c.setAutoCommit(false);
|
||||||
PreparedStatement psDeleteGlobal = c.prepareStatement(this.statementProcessor.apply(DELETE_GLOBAL_USER_IF_BALANCE));
|
|
||||||
PreparedStatement psDeleteLocal = c.prepareStatement(this.statementProcessor.apply(DELETE_LOCAL_USER_IF_BALANCE))) {
|
|
||||||
|
|
||||||
for (Currency currency : this.plugin.getCurrencyManager().getRegisteredCurrencies()) {
|
for (Currency currency : this.plugin.getCurrencyManager().getRegisteredCurrencies()) {
|
||||||
BigDecimal balance = user.getBalance(currency.getProxy());
|
BigDecimal balance = user.getBalance(currency.getProxy());
|
||||||
|
|
||||||
if (balance.compareTo(BigDecimal.ZERO) == 0) {
|
|
||||||
switch (currency.getType()) {
|
|
||||||
case GLOBAL -> {
|
|
||||||
psDeleteGlobal.setString(1, uniqueIdString);
|
|
||||||
psDeleteGlobal.setString(2, currency.getIdentifier());
|
|
||||||
psDeleteGlobal.setBigDecimal(3, balance);
|
|
||||||
|
|
||||||
psDeleteGlobal.addBatch();
|
|
||||||
}
|
|
||||||
case LOCAL -> {
|
|
||||||
psDeleteLocal.setString(1, uniqueIdString);
|
|
||||||
psDeleteLocal.setString(2, currency.getIdentifier());
|
|
||||||
psDeleteLocal.setBigDecimal(3, balance);
|
|
||||||
|
|
||||||
psDeleteLocal.addBatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (balance.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
switch (currency.getType()) {
|
switch (currency.getType()) {
|
||||||
case GLOBAL -> {
|
case GLOBAL -> {
|
||||||
psGlobal.setString(1, uniqueIdString);
|
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(DELETE_GLOBAL_USER
|
||||||
psGlobal.setString(2, currency.getIdentifier());
|
.replace("{currency}", currency.getIdentifier())))) {
|
||||||
psGlobal.setBigDecimal(3, balance);
|
ps.setString(1, uniqueIdString);
|
||||||
if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName()))
|
|
||||||
psGlobal.setBigDecimal(4, balance);
|
|
||||||
|
|
||||||
psGlobal.addBatch();
|
ps.execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case LOCAL -> {
|
case LOCAL -> {
|
||||||
psLocal.setString(1, uniqueIdString);
|
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(DELETE_LOCAL_USER
|
||||||
psLocal.setString(2, currency.getIdentifier());
|
.replace("{currency}", currency.getIdentifier())))) {
|
||||||
psLocal.setBigDecimal(3, balance);
|
ps.setString(1, uniqueIdString);
|
||||||
if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName()))
|
|
||||||
psLocal.setBigDecimal(4, balance);
|
|
||||||
|
|
||||||
psLocal.addBatch();
|
ps.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (currency.getType()) {
|
||||||
|
case GLOBAL -> {
|
||||||
|
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(SAVE_USER_GLOBAL_CURRENCY
|
||||||
|
.replace("{currency}", currency.getIdentifier())))) {
|
||||||
|
ps.setString(1, uniqueIdString);
|
||||||
|
ps.setBigDecimal(2, balance);
|
||||||
|
if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName()))
|
||||||
|
ps.setBigDecimal(3, balance);
|
||||||
|
|
||||||
|
ps.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case LOCAL -> {
|
||||||
|
try (PreparedStatement psLocal = c.prepareStatement(this.statementProcessor.apply(SAVE_USER_LOCAL_CURRENCY
|
||||||
|
.replace("{currency}", currency.getIdentifier())))) {
|
||||||
|
psLocal.setString(1, uniqueIdString);
|
||||||
|
psLocal.setBigDecimal(2, balance);
|
||||||
|
if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName()))
|
||||||
|
psLocal.setBigDecimal(3, balance);
|
||||||
|
|
||||||
|
psLocal.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
psGlobal.executeBatch();
|
if (transactions) {
|
||||||
psLocal.executeBatch();
|
try {
|
||||||
psDeleteGlobal.executeBatch();
|
c.commit();
|
||||||
psDeleteLocal.executeBatch();
|
} catch (SQLException e) {
|
||||||
} catch (SQLException e) {
|
c.rollback();
|
||||||
throw new SQLException("Failed to save user " + user.getUniqueId(), e);
|
throw new SQLException("Failed to save user " + user.getUniqueId(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFact
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
abstract class FileConnectionFactory implements ConnectionFactory {
|
abstract class FileConnectionFactory implements ConnectionFactory {
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
|
@ -34,9 +33,4 @@ abstract class FileConnectionFactory implements ConnectionFactory {
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<String, String> getStatementProcessor() {
|
|
||||||
return s -> s.replace('\'', '`');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ import dev.xhyrom.lighteco.common.storage.StorageType;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class SqliteConnectionFactory extends FileConnectionFactory {
|
public class SqliteConnectionFactory extends FileConnectionFactory {
|
||||||
private Constructor<?> connectionConstructor;
|
private Constructor<?> connectionConstructor;
|
||||||
|
@ -52,4 +52,9 @@ public class SqliteConnectionFactory extends FileConnectionFactory {
|
||||||
throw new SQLException("Failed to create connection", e);
|
throw new SQLException("Failed to create connection", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function<String, String> getStatementProcessor() {
|
||||||
|
return s -> s.replace('\'', '`');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari;
|
||||||
import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
|
import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
|
||||||
import dev.xhyrom.lighteco.common.storage.StorageType;
|
import dev.xhyrom.lighteco.common.storage.StorageType;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class MariaDBConnectionFactory extends DriverBasedHikariConnectionFactory {
|
public class MariaDBConnectionFactory extends DriverBasedHikariConnectionFactory {
|
||||||
public MariaDBConnectionFactory(StorageDataConfig configuration) {
|
public MariaDBConnectionFactory(StorageDataConfig configuration) {
|
||||||
super(configuration);
|
super(configuration);
|
||||||
|
@ -27,4 +29,9 @@ public class MariaDBConnectionFactory extends DriverBasedHikariConnectionFactory
|
||||||
protected String driverJdbcIdentifier() {
|
protected String driverJdbcIdentifier() {
|
||||||
return "mariadb";
|
return "mariadb";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function<String, String> getStatementProcessor() {
|
||||||
|
return s -> s.replace('\'', '`');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
|
||||||
import dev.xhyrom.lighteco.common.storage.StorageType;
|
import dev.xhyrom.lighteco.common.storage.StorageType;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class MySQLConnectionFactory extends DriverBasedHikariConnectionFactory {
|
public class MySQLConnectionFactory extends DriverBasedHikariConnectionFactory {
|
||||||
public MySQLConnectionFactory(StorageDataConfig configuration) {
|
public MySQLConnectionFactory(StorageDataConfig configuration) {
|
||||||
|
@ -51,4 +52,9 @@ public class MySQLConnectionFactory extends DriverBasedHikariConnectionFactory {
|
||||||
// data types in any of our schemas/queries.
|
// data types in any of our schemas/queries.
|
||||||
properties.putIfAbsent("serverTimezone", "UTC");
|
properties.putIfAbsent("serverTimezone", "UTC");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function<String, String> getStatementProcessor() {
|
||||||
|
return s -> s.replace('\'', '`');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,6 @@ public class PostgreSQLConnectionFactory extends DriverBasedHikariConnectionFact
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Function<String, String> getStatementProcessor() {
|
public Function<String, String> getStatementProcessor() {
|
||||||
return s -> s.replace("\'", "\"");
|
return s -> s.replace('\'', '`');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,15 +26,15 @@ public class UserSaveTask implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
for (User user : users) {
|
||||||
|
user.setDirty(false);
|
||||||
|
}
|
||||||
|
|
||||||
this.plugin.getStorage().saveUsersSync(
|
this.plugin.getStorage().saveUsersSync(
|
||||||
Arrays.stream(users)
|
Arrays.stream(users)
|
||||||
.map(User::getProxy)
|
.map(User::getProxy)
|
||||||
.toArray(dev.xhyrom.lighteco.api.model.user.User[]::new)
|
.toArray(dev.xhyrom.lighteco.api.model.user.User[]::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
for (User user : users) {
|
|
||||||
user.setDirty(false);
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
this.plugin.getBootstrap().getLogger().error("Failed to save users", e);
|
this.plugin.getBootstrap().getLogger().error("Failed to save users", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_{context}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
|
@ -1,13 +0,0 @@
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_{context}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
|
@ -1,13 +0,0 @@
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_{context}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
|
@ -1,13 +0,0 @@
|
||||||
CREATE TABLE IF NOT EXISTS "{prefix}_users" (
|
|
||||||
"uuid" VARCHAR(36) NOT NULL,
|
|
||||||
"currency_identifier" VARCHAR(255) NOT NULL,
|
|
||||||
"balance" DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY ("uuid", "currency_identifier")
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "{prefix}_{context}_users" (
|
|
||||||
"uuid" VARCHAR(36) NOT NULL,
|
|
||||||
"currency_identifier" VARCHAR(255) NOT NULL,
|
|
||||||
"balance" DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY ("uuid", "currency_identifier")
|
|
||||||
);
|
|
|
@ -1,13 +0,0 @@
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `{prefix}_{context}_users` (
|
|
||||||
`uuid` VARCHAR(36) NOT NULL,
|
|
||||||
`currency_identifier` VARCHAR(255) NOT NULL,
|
|
||||||
`balance` DECIMAL(10, 2) NOT NULL,
|
|
||||||
PRIMARY KEY (`uuid`, `currency_identifier`)
|
|
||||||
);
|
|
|
@ -123,9 +123,6 @@ public class Vault extends AbstractEconomy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can happen on background
|
|
||||||
this.provider.getUserManager().saveUser(user);
|
|
||||||
|
|
||||||
return new EconomyResponse(
|
return new EconomyResponse(
|
||||||
amount,
|
amount,
|
||||||
bigDecimalToDouble(user.getBalance(currency)),
|
bigDecimalToDouble(user.getBalance(currency)),
|
||||||
|
|
|
@ -59,6 +59,11 @@ public class SpongeLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayerOnline(UUID uniqueId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UUID> getOnlinePlayers() {
|
public List<UUID> getOnlinePlayers() {
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in a new issue