diff --git a/api/src/main/java/com/alttd/boosterapi/Booster.java b/api/src/main/java/com/alttd/boosterapi/Booster.java deleted file mode 100644 index 601e668..0000000 --- a/api/src/main/java/com/alttd/boosterapi/Booster.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.alttd.boosterapi; - -import java.util.UUID; - -public interface Booster extends Comparable { - - boolean isActive(); - - void setActive(Boolean active); - - BoosterType getType(); - - void setType(BoosterType boosterType); - - double getMultiplier(); - - void setMultiplier(double multiplier); - - Long getStartingTime(); - - void setStartingTime(long startingTime); - - Long getEndTime(); - - Long getDuration(); - - void setDuration(long duration); - - String getActivator(); - - void setActivator(String activationReason); - - long getTimeRemaining(); - - UUID getUUID(); - - void stopBooster(); - - void saveBooster(); - - void finish(); - - boolean finished(); -} diff --git a/api/src/main/java/com/alttd/boosterapi/BoosterAPI.java b/api/src/main/java/com/alttd/boosterapi/BoosterAPI.java index 5c1241a..9929310 100644 --- a/api/src/main/java/com/alttd/boosterapi/BoosterAPI.java +++ b/api/src/main/java/com/alttd/boosterapi/BoosterAPI.java @@ -1,11 +1,12 @@ package com.alttd.boosterapi; +import com.alttd.boosterapi.util.Logger; import net.luckperms.api.LuckPerms; public interface BoosterAPI { - static BoosterAPI get() { - return BoosterImplementation.get(); + static BoosterAPI get(Logger logger) { + return BoosterImplementation.get(logger); } LuckPerms getLuckPerms(); diff --git a/api/src/main/java/com/alttd/boosterapi/BoosterImplementation.java b/api/src/main/java/com/alttd/boosterapi/BoosterImplementation.java index e886556..cabea4a 100644 --- a/api/src/main/java/com/alttd/boosterapi/BoosterImplementation.java +++ b/api/src/main/java/com/alttd/boosterapi/BoosterImplementation.java @@ -1,28 +1,28 @@ package com.alttd.boosterapi; import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.config.ServerConfig; -import com.alttd.boosterapi.database.Database; +import com.alttd.boosterapi.util.Logger; import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPermsProvider; public class BoosterImplementation implements BoosterAPI { private static BoosterAPI instance; + private final Logger logger; private LuckPerms luckPerms; - private Database database; - public BoosterImplementation() { + private BoosterImplementation(Logger logger) { instance = this; + this.logger = logger; reloadConfig(); luckPerms = getLuckPerms(); } - public static BoosterAPI get() { + public static BoosterAPI get(Logger logger) { if (instance == null) - instance = new BoosterImplementation(); + instance = new BoosterImplementation(logger); return instance; } @@ -35,7 +35,7 @@ public class BoosterImplementation implements BoosterAPI { @Override public void reloadConfig() { - Config.init(); + Config.reload(logger); } } diff --git a/api/src/main/java/com/alttd/boosterapi/BoosterType.java b/api/src/main/java/com/alttd/boosterapi/BoosterType.java deleted file mode 100644 index 131aef0..0000000 --- a/api/src/main/java/com/alttd/boosterapi/BoosterType.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.alttd.boosterapi; - -import java.util.List; - -public enum BoosterType { - - /** - * MCMMO - implies all mcmmo skills are boosted - */ - MCMMO("mcmmo"), - - ACROBATICS("acrobatics"), - ALCHEMY("alchemy"), - ARCHERY("archery"), - AXES("axes"), - EXCAVATION("excavation"), - FISHING("fishing"), - HERBALISM("herbalism"), - MINING("mining"), - REPAIR("repair"), - SALVAGE("salvage"), - SMELTING("smelting"), - SWORDS("swords"), - TAMING("taming"), - UNARMED("unarmed"), - WOODCUTTING("woodcutting"), - - /** - * MYPET - Boosts MyPet exp gains - */ - MYPET("mypet"), - /** - * VANILLAXP - increases exp gained by killing mobs - */ - VANILLAXP("vanillaxp"), - /** - * LUCK - Boosts luck based vanilla features - * Caps at max vanilla enchant + 1 - * Boosts: - * - Mining with Fortune - * - Adds 1 extra looting level to any mob kills - * - Boosts luck of the sea by 1 - */ - LUCK("luck"), - /** - * PHANTOM - Disables phantom spawns while this booster is active - */ - PHANTOM("phantom"), - /** - * IDK - */ - UNKNOWN("unknown"); - - public final String BoosterName; - BoosterType(String BoosterName) { - this.BoosterName = BoosterName; - } - - public String getBoosterName() { - return this.BoosterName; - } - - public static BoosterType getByName(String text) { - for (BoosterType type : BoosterType.values()) { - if (type.BoosterName.equalsIgnoreCase(text)) { - return type; - } - } - return UNKNOWN; - } - - public static List getAllMcMMOBoosters() { - return List.of(BoosterType.ACROBATICS, - BoosterType.ALCHEMY, - BoosterType.ARCHERY, - BoosterType.AXES, - BoosterType.EXCAVATION, - BoosterType.FISHING, - BoosterType.HERBALISM, - BoosterType.MINING, - BoosterType.REPAIR, - BoosterType.SALVAGE, - BoosterType.SMELTING, - BoosterType.SWORDS, - BoosterType.TAMING, - BoosterType.UNARMED, - BoosterType.WOODCUTTING); - } - -} diff --git a/api/src/main/java/com/alttd/boosterapi/config/AbstractConfig.java b/api/src/main/java/com/alttd/boosterapi/config/AbstractConfig.java new file mode 100644 index 0000000..e458414 --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/config/AbstractConfig.java @@ -0,0 +1,161 @@ +package com.alttd.boosterapi.config; + +import com.alttd.boosterapi.util.Logger; +import io.leangen.geantyref.TypeToken; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.ConfigurationOptions; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.yaml.NodeStyle; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +@SuppressWarnings({"unused", "SameParameterValue"}) +abstract class AbstractConfig { + File file; + private static final Pattern PATH_PATTERN = Pattern.compile("\\."); + private static YamlConfigurationLoader configLoader; + public static ConfigurationNode config; + private static Logger logger = null; + private static File CONFIG_FILE; + + AbstractConfig(File file, String filename, Logger logger, Class clazz) { + AbstractConfig.logger = logger; + init(new File(file.getPath()), filename, clazz); + } + + private void init(File file, String filename, Class clazz) { + this.file = file; + CONFIG_FILE = new File(file, "config.yml"); + configLoader = YamlConfigurationLoader.builder() + .file(CONFIG_FILE) + .nodeStyle(NodeStyle.BLOCK) + .build(); + if (!CONFIG_FILE.getParentFile().exists()) { + if(!CONFIG_FILE.getParentFile().mkdirs()) { + return; + } + } + if (!CONFIG_FILE.exists()) { + try { + if(!CONFIG_FILE.createNewFile()) { + return; + } + } catch (IOException error) { + error.printStackTrace(); + } + } + + try { + config = configLoader.load(ConfigurationOptions.defaults().header("").shouldCopyDefaults(false)); + } catch (IOException e) { + e.printStackTrace(); + } + + readConfig(clazz, null); + try { + configLoader.save(config); + } catch (IOException e) { + e.printStackTrace(); + } + } + + protected void readConfig(Class clazz, Object instance) { + for (Class declaredClass : clazz.getDeclaredClasses()) { + for (Method method : declaredClass.getDeclaredMethods()) { + if (Modifier.isPrivate(method.getModifiers())) { + if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { + try { + method.setAccessible(true); + method.invoke(instance); + } catch (InvocationTargetException ex) { + throw new RuntimeException(ex.getCause()); + } catch (Exception ex) { + if (logger != null) + logger.severe("Error invoking %.", method.toString()); + ex.printStackTrace(); + } + } + } + } + } + + saveConfig(); + } + + private static void saveConfig() { + try { + configLoader.save(config); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + private static Object[] splitPath(String key) { + return PATH_PATTERN.split(key); + } + + private static void set(String prefix, String path, Object def) { + path = prefix + path; + if(config.node(splitPath(path)).virtual()) { + try { + config.node(splitPath(path)).set(def); + } catch (SerializationException e) { + e.printStackTrace(); + } + } + saveConfig(); + } + + protected static void setString(String path, String def) { + try { + if(config.node(splitPath(path)).virtual()) + config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def); + } catch(SerializationException ex) { + ex.printStackTrace(); + } + } + + protected static boolean getBoolean(String prefix, String path, boolean def) { + set(prefix, path, def); + return config.node(splitPath(path)).getBoolean(def); + } + + protected static double getDouble(String prefix, String path, double def) { + set(prefix, path, def); + return config.node(splitPath(path)).getDouble(def); + } + + protected static int getInt(String prefix, String path, int def) { + set(prefix, path, def); + return config.node(splitPath(path)).getInt(def); + } + + protected static String getString(String prefix, String path, String def) { + setString(path, def); + return config.node(splitPath(path)).getString(def); + } + + protected static Long getLong(String prefix, String path, Long def) { + set(prefix, path, def); + return config.node(splitPath(path)).getLong(def); + } + + protected static List getList(String prefix, String path, T def) { + try { + set(prefix, path, def); + return config.node(splitPath(path)).getList(TypeToken.get(String.class)); + } catch(SerializationException ex) { + ex.printStackTrace(); + } + return new ArrayList<>(); + } + +} \ No newline at end of file diff --git a/api/src/main/java/com/alttd/boosterapi/config/BoosterFileStorage.java b/api/src/main/java/com/alttd/boosterapi/config/BoosterFileStorage.java new file mode 100644 index 0000000..4679ec4 --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/config/BoosterFileStorage.java @@ -0,0 +1,167 @@ +package com.alttd.boosterapi.config; + +import com.alttd.boosterapi.data.Booster; +import com.alttd.boosterapi.data.BoosterType; +import com.alttd.boosterapi.util.Logger; +import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +import java.io.File; +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class BoosterFileStorage { + + private File CONFIG_FILE; + private final Logger logger; + public BoosterFileStorage(Logger logger) { + this.logger = logger; + logger.info("Preparing booster file storage..."); + init(); + } + + private void init() { + File CONFIG_PATH = new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "Boosters"); + if (!CONFIG_PATH.exists()) { + if (!CONFIG_PATH.mkdir()) + logger.severe("Unable to create json storage directory"); + } + CONFIG_FILE = new File(CONFIG_PATH, "storage.json"); + if (!CONFIG_FILE.exists()) { + try { + if (!CONFIG_FILE.createNewFile()) + logger.severe("Unable to create json storeage file"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + } + + public synchronized List reload() { + logger.debug("Reloading boosters..."); + return loadBoosters(); + } + + private List loadBoosters() { + List boosters = new LinkedList<>(); + + try { + JsonParser parser = new JsonFactory().createParser(CONFIG_FILE); + if (parser == null) { + logger.warning("Unable to load in boosters from storage file."); + return boosters; + } + parser.nextToken(); + while (parser.currentToken() != null && parser.currentToken().isStructStart()) { + Optional optionalBooster = loadBooster(parser); + if (optionalBooster.isEmpty()) + continue; + Booster booster = optionalBooster.get(); + logger.debug("Loading booster:" + booster.getBoosterType()); + boosters.add(booster); + if (parser.nextToken() != null && !parser.currentToken().isStructEnd()) { + logger.warning("Last loaded booster had more data than expected, skipping it..."); + while (!parser.nextToken().isStructEnd()) + ; + } + parser.nextToken(); + } + parser.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return boosters; + } + + public Optional loadBooster(JsonParser parser) throws IOException { + JsonToken jsonToken = parser.getCurrentToken(); + if (!jsonToken.isStructStart()) + return error("Didn't find struct start"); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"boosterUUID".equals(parser.getCurrentName())) + return error("Didn't find boosterUUID at expected location"); + parser.nextValue(); + UUID boosterUUID = UUID.fromString(parser.getValueAsString()); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"activatorName".equals(parser.getCurrentName())) + return error("Didn't find activatorName at expected location"); + parser.nextValue(); + String activatorName = parser.getValueAsString(); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"boosterType".equals(parser.getCurrentName())) + return error("Didn't find boosterType at expected location"); + parser.nextValue(); + BoosterType boosterType = BoosterType.getByName(parser.getValueAsString()); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"startingTime".equals(parser.getCurrentName())) + return error("Didn't find startingTime at expected location"); + parser.nextValue(); + Instant startingTime = Instant.ofEpochMilli(parser.getValueAsLong()); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"duration".equals(parser.getCurrentName())) + return error("Didn't find duration at expected location"); + parser.nextValue(); + Duration duration = Duration.ofMillis(parser.getValueAsLong()); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"multiplier".equals(parser.getCurrentName())) + return error("Didn't find multiplier at expected location"); + parser.nextValue(); + double multiplier = parser.getValueAsDouble(); + + jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.FIELD_NAME || !"running".equals(parser.getCurrentName())) + return error("Didn't find running at expected location"); + parser.nextValue(); + boolean running = parser.getValueAsBoolean(); + parser.nextValue(); + + return Optional.of(new Booster(boosterUUID, activatorName, boosterType, startingTime, duration, multiplier, running)); + } + + private Optional error(String error) { + logger.severe(error); + return Optional.empty(); + } + + public synchronized void saveBoosters(List boosters) { + try { + JsonGenerator generator = new JsonFactory().createGenerator(CONFIG_FILE, JsonEncoding.UTF8); + for (Booster booster : boosters) { + saveBooster(booster, generator); + } + generator.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + private void saveBooster(Booster booster, JsonGenerator generator) throws IOException { + generator.writeStartObject(); + + generator.writeStringField("boosterUUID", booster.getBoosterUUID().toString()); + generator.writeStringField("activatorName", booster.getActivatorName()); + generator.writeStringField("boosterType", booster.getBoosterType().getBoosterName()); + generator.writeNumberField("startingTime", booster.getStartingTime().toEpochMilli()); + generator.writeNumberField("duration", booster.getDuration().toMillis()); + generator.writeNumberField("multiplier", booster.getMultiplier()); + generator.writeBooleanField("running", booster.getRunning()); + + generator.writeEndObject(); + } +} diff --git a/api/src/main/java/com/alttd/boosterapi/config/BoosterStorage.java b/api/src/main/java/com/alttd/boosterapi/config/BoosterStorage.java deleted file mode 100644 index db888ab..0000000 --- a/api/src/main/java/com/alttd/boosterapi/config/BoosterStorage.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.alttd.boosterapi.config; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.util.ALogger; -import com.fasterxml.jackson.core.JsonEncoding; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; - -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -public abstract class BoosterStorage { - - private File CONFIG_FILE; - private final Map boosters; - protected BoosterStorage() { - ALogger.info("Loading boosters..."); - init(); - boosters = loadBoosters(); - if (Config.DEBUG) { - for (Booster value : boosters.values()) { - ALogger.info(value.getType().BoosterName); - } - } - } - private void init() { - File CONFIG_PATH = new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "Boosters"); - if (!CONFIG_PATH.exists()) { - if (!CONFIG_PATH.mkdir()) - ALogger.error("Unable to create json storage directory"); - } - CONFIG_FILE = new File(CONFIG_PATH, "storage.json"); - if (!CONFIG_FILE.exists()) { - try { - if (!CONFIG_FILE.createNewFile()) - ALogger.error("Unable to create json storeage file"); - } catch (IOException e) { - e.printStackTrace(); - } - } - - ObjectMapper mapper = new ObjectMapper(); - mapper.enable(SerializationFeature.INDENT_OUTPUT); - } - - public void reload() { - if (Config.DEBUG) - ALogger.info("Reloading boosters..."); - boosters.clear(); - boosters.putAll(loadBoosters()); - } - - public synchronized Map getBoosters() { - return boosters; - } - - public synchronized Map loadBoosters() { - Map boosters = new HashMap<>(); - - try { - JsonParser parser = new JsonFactory().createParser(CONFIG_FILE); - if (parser == null) { - ALogger.warn("Unable to load in boosters from storage file."); - return boosters; - } - parser.nextToken(); - while (parser.currentToken() != null && parser.currentToken().isStructStart()) { - Booster booster = loadBooster(parser); - if (Config.DEBUG) - ALogger.info("Loading booster [" + booster.getType() + "] activated by [" + booster.getActivator()+ "]."); - if (booster.getTimeRemaining() < 1) - continue; - boosters.put(booster.getUUID(), booster); - if (parser.nextToken() != null && !parser.currentToken().isStructEnd()) { - ALogger.warn("Last loaded booster had more data than expected, skipping it..."); - while (!parser.nextToken().isStructEnd()) - ; - } - parser.nextToken(); - } - parser.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return boosters; - } - - public abstract Booster loadBooster(JsonParser parser) throws IOException; - - public synchronized void saveBoosters(Collection boosters) { - try { - JsonGenerator generator = new JsonFactory().createGenerator(CONFIG_FILE, JsonEncoding.UTF8); - Date date = new Date(); - for (Booster booster : boosters) { - if (booster.finished() || (booster.isActive() && new Date(booster.getEndTime()).before(date))) - continue; - saveBooster(booster, generator); - } - generator.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public void saveBoosters() { - saveBoosters(boosters.values()); - } - - private void saveBooster(Booster booster, JsonGenerator generator) throws IOException { - generator.writeStartObject(); - - generator.writeStringField("uuid", booster.getUUID().toString()); - generator.writeStringField("activator", booster.getActivator()); - generator.writeStringField("type", booster.getType().getBoosterName()); - generator.writeNumberField("startingTime", booster.getStartingTime()); - generator.writeNumberField("duration", booster.getDuration()); - generator.writeNumberField("multiplier", booster.getMultiplier()); - generator.writeBooleanField("active", booster.isActive()); - generator.writeBooleanField("finished", booster.finished()); - - generator.writeEndObject(); - } - - public synchronized Collection getBoosters(BoosterType type) { - return boosters.values().stream().filter(booster -> booster.getType().equals(type)).collect(Collectors.toList()); - } - - public synchronized void add(Booster booster) { - boosters.put(booster.getUUID(), booster); - }; -} diff --git a/api/src/main/java/com/alttd/boosterapi/config/Config.java b/api/src/main/java/com/alttd/boosterapi/config/Config.java index 5766f9c..a74506c 100755 --- a/api/src/main/java/com/alttd/boosterapi/config/Config.java +++ b/api/src/main/java/com/alttd/boosterapi/config/Config.java @@ -1,210 +1,291 @@ package com.alttd.boosterapi.config; -import com.alttd.boosterapi.util.ALogger; -import io.leangen.geantyref.TypeToken; -import net.kyori.adventure.text.Component; -import org.spongepowered.configurate.ConfigurationNode; -import org.spongepowered.configurate.ConfigurationOptions; -import org.spongepowered.configurate.serialize.SerializationException; -import org.spongepowered.configurate.yaml.NodeStyle; -import org.spongepowered.configurate.yaml.YamlConfigurationLoader; +import com.alttd.boosterapi.util.Logger; import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.regex.Pattern; +import java.util.List; -public final class Config { - private static final Pattern PATH_PATTERN = Pattern.compile("\\."); - private static final String HEADER = ""; +public final class Config extends AbstractConfig { - private static File CONFIG_FILE; - public static ConfigurationNode config; - public static YamlConfigurationLoader configLoader; + private static Config config; - static int version; - static boolean verbose; + Config(Logger logger) { + super( + new File(System.getProperty("user.home") + File.separator + + "share" + File.separator + + "configs" + File.separator + + "Boosters"), + "config.yml", logger, Config.class); + } - public static File CONFIGPATH; - public static void init() { - CONFIGPATH = new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "Boosters"); - CONFIG_FILE = new File(CONFIGPATH, "config.yml"); - configLoader = YamlConfigurationLoader.builder() - .file(CONFIG_FILE) - .nodeStyle(NodeStyle.BLOCK) - .build(); - if (!CONFIG_FILE.getParentFile().exists()) { - if(!CONFIG_FILE.getParentFile().mkdirs()) { - return; - } - } - if (!CONFIG_FILE.exists()) { - try { - if(!CONFIG_FILE.createNewFile()) { - return; - } - } catch (IOException error) { - error.printStackTrace(); - } - } + public static void reload(Logger logger) { + config = new Config(logger); + config.readConfig(Config.class, null); + } - try { - config = configLoader.load(ConfigurationOptions.defaults().header(HEADER)); - } catch (IOException e) { - e.printStackTrace(); - } + public static class LOGGING { + private static final String prefix = "logging."; - verbose = getBoolean("verbose", true); - version = getInt("config-version", 1); + public static boolean PRINT_DEBUG = false; + public static boolean PRINT_WARNINGS = true; - readConfig(Config.class, null); - try { - configLoader.save(config); - } catch (IOException e) { - e.printStackTrace(); + private static void load() { + PRINT_DEBUG = config.getBoolean(prefix, "print-debug", PRINT_DEBUG); + PRINT_WARNINGS = config.getBoolean(prefix, "print-warnings", PRINT_WARNINGS); } } - public static void readConfig(Class clazz, Object instance) { - for (Method method : clazz.getDeclaredMethods()) { - if (Modifier.isPrivate(method.getModifiers())) { - if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { - try { - method.setAccessible(true); - method.invoke(instance); - } catch (InvocationTargetException | IllegalAccessException ex) { - ALogger.fatal("Error reading config", ex); - } - } - } - } - saveConfig(); - } + public static class SETTINGS { + private static final String prefix = "settings"; - public static void saveConfig() { - try { - configLoader.save(config); - } catch (IOException ex) { - ALogger.fatal("Error saving config", ex); + public static int UPDATE_FREQUENCY_MINUTES = 1; + public static String PLUGIN_MESSAGE_CHANNEL = "altitude:boosterplugin"; + public static long BOOST_ANNOUNCE_CHANNEL = -1L; + public static List DONOR_RANKS = List.of("count", "viceroy", "duke", "archduke"); + + private static void load() { + UPDATE_FREQUENCY_MINUTES = config.getInt(prefix, "update-frequency-minutes", UPDATE_FREQUENCY_MINUTES); + BOOST_ANNOUNCE_CHANNEL = config.getLong(prefix, "boost-announce-channel", BOOST_ANNOUNCE_CHANNEL); + PLUGIN_MESSAGE_CHANNEL = config.getString(prefix, "plugin-message-channel", PLUGIN_MESSAGE_CHANNEL); + DONOR_RANKS = config.getList(prefix, "donor-ranks", DONOR_RANKS); } } - private static Object[] splitPath(String key) { - return PATH_PATTERN.split(key); - } + public static class GENERIC_MESSAGES { + private static final String prefix = "generic-messages"; - private static void set(String path, Object def) { - if(config.node(splitPath(path)).virtual()) { - try { - config.node(splitPath(path)).set(def); - } catch (SerializationException e) { - } + public static String NO_PERMISSION = "You do not have permission to do that command."; + public static String PLAYER_NOT_FOUND = " is not a valid player."; + public static String RELOADED = "Reloaded config."; + + private static void load() { + NO_PERMISSION = config.getString(prefix, "no-permission", NO_PERMISSION); + PLAYER_NOT_FOUND = config.getString(prefix, "player-not-found", PLAYER_NOT_FOUND); + RELOADED = config.getString(prefix, "reloaded", RELOADED); } } - private static void setString(String path, String def) { - try { - if(config.node(splitPath(path)).virtual()) - config.node(splitPath(path)).set(TypeToken.get(String.class), def); - } catch(SerializationException ex) { + public static class BOOSTER_MESSAGES { + private static final String prefix = "booster-messages"; + + public static String LIST_BOOSTER_MESSAGE = "Active boosters:\n\n\nQueued boosters:\n"; + public static String ACTIVE_BOOSTER_PART = " activated by until [UTC], boosts times"; + public static String QUEUED_BOOSTER_PART = " queued by will be active for , boosts times"; + public static String BOOST_SERVER_MESSAGE = "* activated an booster!"; + + private static void load() { + LIST_BOOSTER_MESSAGE = config.getString(prefix, "list-booster-message", LIST_BOOSTER_MESSAGE); + ACTIVE_BOOSTER_PART = config.getString(prefix, "active-booster-part", ACTIVE_BOOSTER_PART); + QUEUED_BOOSTER_PART = config.getString(prefix, "queued-booster-part", QUEUED_BOOSTER_PART); + BOOST_SERVER_MESSAGE = config.getString(prefix, "boost-server-message", BOOST_SERVER_MESSAGE); } } - private static boolean getBoolean(String path, boolean def) { - set(path, def); - return config.node(splitPath(path)).getBoolean(def); - } + public static class DONOR_RANK_MESSAGES { + private static final String prefix = "donor-rank-messages"; - private static double getDouble(String path, double def) { - set(path, def); - return config.node(splitPath(path)).getDouble(def); - } + public static String INVALID_USER = " does not exist."; + public static String INVALID_ACTION = " is not a valid action user promote or demote."; + public static String INVALID_DONOR_RANK = " is not a valid donor rank."; + public static String DEMOTE_MESSAGE = "Your rank was refunded and removed. Contact staff if you're unsure what caused this."; + public static String PROMOTE_MESSAGE = "Thank you for your support! We applied the rank to your account."; - private static int getInt(String path, int def) { - set(path, def); - return config.node(splitPath(path)).getInt(def); - } - - private static String getString(String path, String def) { - setString(path, def); - return config.node(splitPath(path)).getString(def); - } - - private static Long getLong(String path, Long def) { - set(path, def); - return config.node(splitPath(path)).getLong(def); - } - - private static List getList(String path, T def) { - try { - set(path, def); - return config.node(splitPath(path)).getList(TypeToken.get(String.class)); - } catch(SerializationException ex) { + private static void load() { + INVALID_USER = config.getString(prefix, "invalid-user", INVALID_USER); + INVALID_ACTION = config.getString(prefix, "invalid-action", INVALID_ACTION); + INVALID_DONOR_RANK = config.getString(prefix, "invalid-donor-rank", INVALID_DONOR_RANK); + DEMOTE_MESSAGE = config.getString(prefix, "demote-message", DEMOTE_MESSAGE); + PROMOTE_MESSAGE = config.getString(prefix, "promote-message", PROMOTE_MESSAGE); } - return new ArrayList<>(); } - /** ONLY EDIT ANYTHING BELOW THIS LINE **/ - public static String driver = "com.mysql.cj.jdbc.Driver"; - public static String host = "13.11.1.78"; - public static String port = "3306"; - public static String database = "McTestSql"; - public static String user = "root"; - public static String password = "foobar"; - public static String options = "?MaxPooledStatements=250&useSSL=false&autoReconnect=true&maxReconnects=3"; - private static void databaseSettings() { - String path = "database."; - driver = getString(path + "driver", driver); - host = getString(path + "host", host); - port = getString(path + "port", port); - database = getString(path + "database", database); - user = getString(path + "user", user); - password = getString(path + "password", password); - options = getString(path + "options", options); - } - - public static Long activeTaskCheckFrequency = 1L; - public static Long taskCheckFrequency = 1L; - private static void boosterTaskSettings() { - activeTaskCheckFrequency = getLong("task.queue-frequency", activeTaskCheckFrequency); - taskCheckFrequency = getLong("task.check-frequency", taskCheckFrequency); - } - - public static String pluginMessageChannel = "altitude:boosterplugin"; - private static void pluginMessageSettings() { - pluginMessageChannel = getString("settings.message-channel", pluginMessageChannel); - } - - public static long BOOST_ANNOUNCE_CHANNEL = -1; - private static void announceChannels() { - BOOST_ANNOUNCE_CHANNEL = getLong("settings.boost-announce-channel", BOOST_ANNOUNCE_CHANNEL); - } - - public static List donorRanks = new ArrayList<>(); - private static void loadDonorStuff() { - donorRanks = getList("donor.ranks", donorRanks); - } - - public static String INVALID_USER = " does not exist."; - public static String INVALID_ACTION = " is not a valid action user promote or demote."; - public static String INVALID_DONOR_RANK = " is not a valid donor rank."; - public static String DEMOTE_MESSAGE = "Your rank was refunded and removed. Contact staff if you're unsure what caused this."; - public static String PROMOTE_MESSAGE = "Thank you for your support! We applied the rank to your account."; - public static String BOOST_SERVER_MESSAGE = "* activated an booster!"; - private static void loadMessages() { - INVALID_USER = getString("messages.invalid-user", INVALID_USER); - INVALID_ACTION = getString("messages.invalid-action", INVALID_ACTION); - INVALID_DONOR_RANK = getString("messages.invalid-donor-rank", INVALID_DONOR_RANK); - DEMOTE_MESSAGE = getString("messages.demote", DEMOTE_MESSAGE); - PROMOTE_MESSAGE = getString("messages.promote", PROMOTE_MESSAGE); - BOOST_SERVER_MESSAGE = getString("messages.boost-server", BOOST_SERVER_MESSAGE); - } - - public static boolean DEBUG = false; - private static void loadSettings() { - DEBUG = getBoolean("settings.debug", DEBUG); - } +// private static final Pattern PATH_PATTERN = Pattern.compile("\\."); +// private static final String HEADER = ""; +// +// private static File CONFIG_FILE; +// public static ConfigurationNode config; +// public static YamlConfigurationLoader configLoader; +// +// static int version; +// static boolean verbose; +// +// public static File CONFIGPATH; +// public static void init() { +// CONFIGPATH = new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "Boosters"); +// CONFIG_FILE = new File(CONFIGPATH, "config.yml"); +// configLoader = YamlConfigurationLoader.builder() +// .file(CONFIG_FILE) +// .nodeStyle(NodeStyle.BLOCK) +// .build(); +// if (!CONFIG_FILE.getParentFile().exists()) { +// if(!CONFIG_FILE.getParentFile().mkdirs()) { +// return; +// } +// } +// if (!CONFIG_FILE.exists()) { +// try { +// if(!CONFIG_FILE.createNewFile()) { +// return; +// } +// } catch (IOException error) { +// error.printStackTrace(); +// } +// } +// +// try { +// config = configLoader.load(ConfigurationOptions.defaults().header(HEADER)); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// +// verbose = getBoolean("verbose", true); +// version = getInt("config-version", 1); +// +// readConfig(Config.class, null); +// try { +// configLoader.save(config); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// +// public static void readConfig(Class clazz, Object instance) { +// for (Method method : clazz.getDeclaredMethods()) { +// if (Modifier.isPrivate(method.getModifiers())) { +// if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { +// try { +// method.setAccessible(true); +// method.invoke(instance); +// } catch (InvocationTargetException | IllegalAccessException ex) { +// ALogger.fatal("Error reading config", ex); +// } +// } +// } +// } +// saveConfig(); +// } +// +// public static void saveConfig() { +// try { +// configLoader.save(config); +// } catch (IOException ex) { +// ALogger.fatal("Error saving config", ex); +// } +// } +// +// private static Object[] splitPath(String key) { +// return PATH_PATTERN.split(key); +// } +// +// private static void set(String path, Object def) { +// if(config.node(splitPath(path)).virtual()) { +// try { +// config.node(splitPath(path)).set(def); +// } catch (SerializationException e) { +// } +// } +// } +// +// private static void setString(String path, String def) { +// try { +// if(config.node(splitPath(path)).virtual()) +// config.node(splitPath(path)).set(TypeToken.get(String.class), def); +// } catch(SerializationException ex) { +// } +// } +// +// private static boolean getBoolean(String path, boolean def) { +// set(path, def); +// return config.node(splitPath(path)).getBoolean(def); +// } +// +// private static double getDouble(String path, double def) { +// set(path, def); +// return config.node(splitPath(path)).getDouble(def); +// } +// +// private static int getInt(String path, int def) { +// set(path, def); +// return config.node(splitPath(path)).getInt(def); +// } +// +// private static String getString(String path, String def) { +// setString(path, def); +// return config.node(splitPath(path)).getString(def); +// } +// +// private static Long getLong(String path, Long def) { +// set(path, def); +// return config.node(splitPath(path)).getLong(def); +// } +// +// private static List getList(String path, T def) { +// try { +// set(path, def); +// return config.node(splitPath(path)).getList(TypeToken.get(String.class)); +// } catch(SerializationException ex) { +// } +// return new ArrayList<>(); +// } +// +// /** ONLY EDIT ANYTHING BELOW THIS LINE **/ +// public static String driver = "com.mysql.cj.jdbc.Driver"; +// public static String host = "13.11.1.78"; +// public static String port = "3306"; +// public static String database = "McTestSql"; +// public static String user = "root"; +// public static String password = "foobar"; +// public static String options = "?MaxPooledStatements=250&useSSL=false&autoReconnect=true&maxReconnects=3"; +// private static void databaseSettings() { +// String path = "database."; +// driver = getString(path + "driver", driver); +// host = getString(path + "host", host); +// port = getString(path + "port", port); +// database = getString(path + "database", database); +// user = getString(path + "user", user); +// password = getString(path + "password", password); +// options = getString(path + "options", options); +// } +// +// public static Long activeTaskCheckFrequency = 1L; +// public static Long taskCheckFrequency = 1L; +// private static void boosterTaskSettings() { +// activeTaskCheckFrequency = getLong("task.queue-frequency", activeTaskCheckFrequency); +// taskCheckFrequency = getLong("task.check-frequency", taskCheckFrequency); +// } +// +// public static String pluginMessageChannel = "altitude:boosterplugin"; +// private static void pluginMessageSettings() { +// pluginMessageChannel = getString("settings.message-channel", pluginMessageChannel); +// } +// +// public static long BOOST_ANNOUNCE_CHANNEL = -1; +// private static void announceChannels() { +// BOOST_ANNOUNCE_CHANNEL = getLong("settings.boost-announce-channel", BOOST_ANNOUNCE_CHANNEL); +// } +// +// public static List donorRanks = new ArrayList<>(); +// private static void loadDonorStuff() { +// donorRanks = getList("donor.ranks", donorRanks); +// } +// +// public static String INVALID_USER = " does not exist."; +// public static String INVALID_ACTION = " is not a valid action user promote or demote."; +// public static String INVALID_DONOR_RANK = " is not a valid donor rank."; +// public static String DEMOTE_MESSAGE = "Your rank was refunded and removed. Contact staff if you're unsure what caused this."; +// public static String PROMOTE_MESSAGE = "Thank you for your support! We applied the rank to your account."; +// public static String BOOST_SERVER_MESSAGE = "* activated an booster!"; +// private static void loadMessages() { +// INVALID_USER = getString("messages.invalid-user", INVALID_USER); +// INVALID_ACTION = getString("messages.invalid-action", INVALID_ACTION); +// INVALID_DONOR_RANK = getString("messages.invalid-donor-rank", INVALID_DONOR_RANK); +// DEMOTE_MESSAGE = getString("messages.demote", DEMOTE_MESSAGE); +// PROMOTE_MESSAGE = getString("messages.promote", PROMOTE_MESSAGE); +// BOOST_SERVER_MESSAGE = getString("messages.boost-server", BOOST_SERVER_MESSAGE); +// } +// +// public static boolean DEBUG = false; +// private static void loadSettings() { +// DEBUG = getBoolean("settings.debug", DEBUG); +// } } diff --git a/api/src/main/java/com/alttd/boosterapi/config/ServerConfig.java b/api/src/main/java/com/alttd/boosterapi/config/ServerConfig.java deleted file mode 100755 index 855ffff..0000000 --- a/api/src/main/java/com/alttd/boosterapi/config/ServerConfig.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.alttd.boosterapi.config; - -import io.leangen.geantyref.TypeToken; -import org.spongepowered.configurate.serialize.SerializationException; - -import java.util.regex.Pattern; - -public final class ServerConfig { - private static final Pattern PATH_PATTERN = Pattern.compile("\\."); - - private final String serverName; - private final String configPath; - private final String defaultPath; - - public ServerConfig(String serverName) { - this.serverName = serverName; - this.configPath = "server-settings." + this.serverName + "."; - this.defaultPath = "server-settings.default."; - init(); - } - - public void init() { - Config.readConfig(ServerConfig.class, this); - Config.saveConfig(); - } - - public static Object[] splitPath(String key) { - return PATH_PATTERN.split(key); - } - - private static void set(String path, Object def) { - if(Config.config.node(splitPath(path)).virtual()) { - try { - Config.config.node(splitPath(path)).set(def); - } catch (SerializationException ex) { - } - } - } - - private static void setString(String path, String def) { - try { - if(Config.config.node(splitPath(path)).virtual()) - Config.config.node(splitPath(path)).set(TypeToken.get(String.class), def); - } catch(SerializationException ex) { - } - } - - private boolean getBoolean(String path, boolean def) { - set(defaultPath +path, def); - return Config.config.node(splitPath(configPath+path)).getBoolean( - Config.config.node(splitPath(defaultPath +path)).getBoolean(def)); - } - - private double getDouble(String path, double def) { - set(defaultPath +path, def); - return Config.config.node(splitPath(configPath+path)).getDouble( - Config.config.node(splitPath(defaultPath +path)).getDouble(def)); - } - - private int getInt(String path, int def) { - set(defaultPath +path, def); - return Config.config.node(splitPath(configPath+path)).getInt( - Config.config.node(splitPath(defaultPath +path)).getInt(def)); - } - - private String getString(String path, String def) { - set(defaultPath +path, def); - return Config.config.node(splitPath(configPath+path)).getString( - Config.config.node(splitPath(defaultPath +path)).getString(def)); - } - - /** DO NOT EDIT ANYTHING ABOVE **/ - -} diff --git a/api/src/main/java/com/alttd/boosterapi/data/Booster.java b/api/src/main/java/com/alttd/boosterapi/data/Booster.java new file mode 100644 index 0000000..889b336 --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/data/Booster.java @@ -0,0 +1,120 @@ +package com.alttd.boosterapi.data; + +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; +import java.util.Objects; + +public class Booster implements Comparable { + + private final UUID boosterUUID; + private final String activatorName; + private Instant startingTime; + private Duration duration; + private final BoosterType boosterType; + private final Double multiplier; + private Boolean running; + + public Booster(UUID boosterUUID, BoosterType boosterType, String reason, Duration duration, double multiplier) { + this.boosterUUID = boosterUUID; + this.boosterType = boosterType; + this.activatorName = reason; + this.duration = duration; + this.multiplier = multiplier; + this.running = false; + this.startingTime = Instant.now(); + } + + public Booster(BoosterType type, String playerName, Duration duration, double multiplier) { + this(UUID.randomUUID(), type, playerName, duration, multiplier); + } + + public Booster(UUID boosterUUID, String activatorName, BoosterType boosterType, Instant startingTime, + Duration duration, double multiplier, boolean running) { + this.boosterUUID = boosterUUID; + this.activatorName = activatorName; + this.boosterType = boosterType; + this.startingTime = startingTime; + this.duration = duration; + this.multiplier = multiplier; + this.running = running; + } + + public void updateDuration() { + Instant stopTime = Instant.now(); + Duration elapsedTime = Duration.between(startingTime, stopTime); + duration = duration.minus(elapsedTime); + } + + public double useMultiplier(double exp) { + return exp * (multiplier + 1); + } + + public UUID getBoosterUUID() { + return boosterUUID; + } + + public String getActivatorName() { + return activatorName; + } + + public Instant getStartingTime() { + return startingTime; + } + + public Duration getDuration() { + return duration; + } + + public BoosterType getBoosterType() { + return boosterType; + } + + public Double getMultiplier() { + return multiplier; + } + + public Boolean getRunning() { + return running; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Booster other = (Booster) o; + return Objects.equals(boosterUUID, other.boosterUUID); + } + + @Override + public int hashCode() { + return Objects.hash(boosterUUID); + } + + @Override + public int compareTo(@NotNull Booster other) { + int multiplierComparison = Double.compare(other.multiplier, this.multiplier); + if (multiplierComparison != 0) { + return multiplierComparison; + } + + return this.duration.compareTo(other.duration); + } + + @Override + public String toString() { + return "Booster{" + + "boosterUUID=" + boosterUUID + + ", activatorName='" + activatorName + '\'' + + ", startingTime=" + startingTime + + ", duration=" + duration + + ", boosterType=" + boosterType + + ", multiplier=" + multiplier + + ", running=" + running + + '}'; + } +} diff --git a/api/src/main/java/com/alttd/boosterapi/data/BoosterCache.java b/api/src/main/java/com/alttd/boosterapi/data/BoosterCache.java new file mode 100644 index 0000000..b9d9ab0 --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/data/BoosterCache.java @@ -0,0 +1,111 @@ +package com.alttd.boosterapi.data; + +import com.alttd.boosterapi.config.BoosterFileStorage; + +import java.time.Duration; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class BoosterCache { + + private final HashMap> boosters = new HashMap<>(); + private final BoosterFileStorage boosterFileStorage; + + public BoosterCache(BoosterFileStorage boosterFileStorage) { + this.boosterFileStorage = boosterFileStorage; + reloadBoosters(); + } + + public synchronized void reloadBoosters() { + boosters.clear(); + List allBoosters = boosterFileStorage.reload(); + for (Booster booster : allBoosters) { + LinkedList list = boosters.getOrDefault(booster.getBoosterType(), new LinkedList<>()); + list.add(booster); + boosters.put(booster.getBoosterType(), list); + } + updateOrder(); + } + + private void updateOrder() { + for (BoosterType boosterType : boosters.keySet()) { + updateOrder(boosterType); + } + } + + private void updateOrder(BoosterType boosterType) { + if (!boosters.containsKey(boosterType)) { + return; + } + LinkedList list = boosters.get(boosterType); + list.sort(Booster::compareTo); + } + + public synchronized Optional getActiveBooster(BoosterType boosterType) { + if (!boosters.containsKey(boosterType)) + return Optional.empty(); + LinkedList list = boosters.get(boosterType); + if (list.isEmpty()) + return Optional.empty(); + return Optional.of(list.get(0)); + } + + public synchronized List getAllActiveBoosters() { + return boosters.values().stream() + .filter(list -> !list.isEmpty()) + .map(list -> list.get(0)) + .collect(Collectors.toList()); + } + + public synchronized List getAllQueuedBoosters() { + return boosters.values().stream() + .filter(list -> list.size() > 1) + .map(list -> list.subList(1, list.size())) + .flatMap(List::stream) + .collect(Collectors.toList()); + } + + public synchronized void addNewBooster(BoosterType boosterType, String activatorName, Duration duration, double multiplier) { + List childBoosters = boosterType.getChildBoosters(); + if (!childBoosters.isEmpty()) { + addNewBoosters(childBoosters, activatorName, duration, multiplier); + return; + } + Booster booster = new Booster(boosterType, activatorName, duration, multiplier); + LinkedList list = boosters.getOrDefault(boosterType, new LinkedList<>()); + list.addLast(booster); + boosters.put(boosterType, list); + updateOrder(boosterType); + boosterFileStorage.saveBoosters(boosters.values().stream().flatMap(List::stream).collect(Collectors.toList())); + } + + private void addNewBoosters(List boosterTypes, String activatorName, Duration duration, double multiplier) { + for (BoosterType boosterType : boosterTypes) { + Booster booster = new Booster(boosterType, activatorName, duration, multiplier); + LinkedList list = boosters.getOrDefault(boosterType, new LinkedList<>()); + list.addLast(booster); + boosters.put(boosterType, list); + updateOrder(boosterType); + } + boosterFileStorage.saveBoosters(boosters.values().stream().flatMap(List::stream).collect(Collectors.toList())); + } + + public synchronized void finishBooster(Booster booster) { + BoosterType boosterType = booster.getBoosterType(); + LinkedList list = boosters.get(boosterType); + if (list == null) + return; + list.removeIf(filterBooster -> filterBooster.getBoosterUUID().equals(booster.getBoosterUUID())); + boosters.put(boosterType, list); + updateOrder(boosterType); + boosterFileStorage.saveBoosters(boosters.values().stream().flatMap(List::stream).collect(Collectors.toList())); + } + + public synchronized void updateAndSave() { + getAllActiveBoosters().forEach(Booster::updateDuration); //TODO test if this needs to be re-added to the map (it shouldn't afaik) + boosterFileStorage.saveBoosters(boosters.values().stream().flatMap(List::stream).collect(Collectors.toList())); + } +} diff --git a/api/src/main/java/com/alttd/boosterapi/data/BoosterType.java b/api/src/main/java/com/alttd/boosterapi/data/BoosterType.java new file mode 100644 index 0000000..b71065e --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/data/BoosterType.java @@ -0,0 +1,80 @@ +package com.alttd.boosterapi.data; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public enum BoosterType { + + /** + * MCMMO - implies all mcmmo skills are boosted + */ + MCMMO("mcmmo", null), + + ACROBATICS("acrobatics", MCMMO), + ALCHEMY("alchemy", MCMMO), + ARCHERY("archery", MCMMO), + AXES("axes", MCMMO), + EXCAVATION("excavation", MCMMO), + FISHING("fishing", MCMMO), + HERBALISM("herbalism", MCMMO), + MINING("mining", MCMMO), + REPAIR("repair", MCMMO), + SALVAGE("salvage", MCMMO), + SMELTING("smelting", MCMMO), + SWORDS("swords", MCMMO), + TAMING("taming", MCMMO), + UNARMED("unarmed", MCMMO), + WOODCUTTING("woodcutting", MCMMO), + + /** + * MYPET - Boosts MyPet exp gains + */ + MYPET("mypet", null), + /** + * VANILLAXP - increases exp gained by killing mobs + */ + VANILLAXP("vanillaxp", null), + /** + * LUCK - Boosts luck based vanilla features + * Caps at max vanilla enchant + 1 + * Boosts: + * - Mining with Fortune + * - Adds 1 extra looting level to any mob kills + * - Boosts luck of the sea by 1 + */ + LUCK("luck", null), + /** + * PHANTOM - Disables phantom spawns while this booster is active + */ + PHANTOM("phantom", null), + /** + * IDK + */ + UNKNOWN("unknown", null); + + public final String BoosterName; + public final BoosterType parent; + BoosterType(String BoosterName, BoosterType parent) { + this.BoosterName = BoosterName; + this.parent = parent; + } + + public String getBoosterName() { + return this.BoosterName; + } + + public static BoosterType getByName(String text) { + for (BoosterType type : BoosterType.values()) { + if (type.BoosterName.equalsIgnoreCase(text)) { + return type; + } + } + return UNKNOWN; + } + + public List getChildBoosters() { + return Arrays.stream(BoosterType.values()).filter(boosterType -> boosterType.parent == this).collect(Collectors.toList()); + } + +} diff --git a/api/src/main/java/com/alttd/boosterapi/database/Database.java b/api/src/main/java/com/alttd/boosterapi/database/Database.java deleted file mode 100644 index de44b8f..0000000 --- a/api/src/main/java/com/alttd/boosterapi/database/Database.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.alttd.boosterapi.database; - -import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.ALogger; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; - -public class Database { - - private static Connection connection; - - public static Connection getConnection() { - if (connection == null) { - try { - Class.forName(Config.driver); - - connection = DriverManager.getConnection("jdbc:mysql://" + Config.host + ":" + Config.port + "/" + Config.database + Config.options, Config.user, Config.password); - } catch (ClassNotFoundException | SQLException ex) { - ALogger.fatal("Failed to connect to sql.", ex); - } - } - return connection; - } - - public void disconnect() { - if (connection != null) { - try { - connection.close(); - - connection = null; - - } catch (SQLException ex) { - ALogger.fatal("Failed to disconnect from sql.", ex); - } - } - } - -} diff --git a/api/src/main/java/com/alttd/boosterapi/util/ALogger.java b/api/src/main/java/com/alttd/boosterapi/util/ALogger.java deleted file mode 100755 index ef9ccf9..0000000 --- a/api/src/main/java/com/alttd/boosterapi/util/ALogger.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.alttd.boosterapi.util; - -public class ALogger { - - private static org.slf4j.Logger logger = null; - - public static void init(org.slf4j.Logger log) { - logger = log; - } - - public static void warn(String message) { - logger.warn(message); - } - - public static void info(String message) { - logger.info(message); - } - - public static void error(String message) { - logger.error(message); - } - - public static void fatal(String error, Exception exception) { - error(error + "\n" + exception); - } -} diff --git a/api/src/main/java/com/alttd/boosterapi/util/BoosterParser.java b/api/src/main/java/com/alttd/boosterapi/util/BoosterParser.java new file mode 100644 index 0000000..5d462ad --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/util/BoosterParser.java @@ -0,0 +1,32 @@ +package com.alttd.boosterapi.util; + +import com.alttd.boosterapi.data.Booster; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; + +import java.text.DateFormat; +import java.util.List; +import java.util.stream.Collectors; + +public class BoosterParser { + + private final static MiniMessage miniMessage = MiniMessage.miniMessage(); + + public static List parseBoosters(Logger logger, List boosters, String message, boolean active) { + return boosters.stream().map(booster -> { + logger.debug("processing booster: " + booster); + TagResolver resolver = TagResolver.resolver( + Placeholder.unparsed("type", booster.getBoosterType().getBoosterName()), + Placeholder.unparsed("activator", booster.getActivatorName()), + Placeholder.unparsed("start_time", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(booster.getStartingTime().toEpochMilli())), + Placeholder.unparsed("duration", booster.getDuration().toHours() + " hours"), + Placeholder.unparsed("multiplier", String.valueOf(booster.getMultiplier())), + Placeholder.unparsed("end_time", active ? DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(booster.getStartingTime().toEpochMilli() + booster.getDuration().toMillis()) : "unknown") + ); + return miniMessage.deserialize(message, resolver); + }).collect(Collectors.toList()); + } + +} diff --git a/api/src/main/java/com/alttd/boosterapi/util/Logger.java b/api/src/main/java/com/alttd/boosterapi/util/Logger.java new file mode 100644 index 0000000..f63b735 --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/util/Logger.java @@ -0,0 +1,43 @@ +package com.alttd.boosterapi.util; + +import com.alttd.boosterapi.config.Config; + +public class Logger { + + private final org.slf4j.Logger logger; + + static private final String RESET = "\u001B[0m"; + static private final String GREEN = "\u001B[32m"; + static private final String TEAL = "\u001B[36m"; + + public Logger(org.slf4j.Logger logger) { + this.logger = logger; + } + + public void debug(String debug, String... variables) { + if (!Config.LOGGING.PRINT_DEBUG) + return; + logger.info(TEAL + replace(debug, variables) + RESET); + } + + public void info(String info, String... variables) { + logger.info(GREEN + replace(info, variables) + RESET); + } + + public void warning(String warning, String... variables) { + if (!Config.LOGGING.PRINT_WARNINGS) + return; + logger.warn(replace(warning, variables)); + } + + public void severe(String severe, String... variables) { + logger.error(replace(severe, variables)); + } + + private String replace(String text, String... variables) { + for (String variable : variables) { + text = text.replaceFirst("%", variable); + } + return text; + } +} diff --git a/api/src/main/java/com/alttd/boosterapi/util/StringModifier.java b/api/src/main/java/com/alttd/boosterapi/util/StringModifier.java new file mode 100644 index 0000000..3034426 --- /dev/null +++ b/api/src/main/java/com/alttd/boosterapi/util/StringModifier.java @@ -0,0 +1,11 @@ +package com.alttd.boosterapi.util; + +public class StringModifier { + + public static String capitalize(String string) { + if (string.length() <= 1) + return string.toUpperCase(); + string = string.toLowerCase(); + return string.substring(0, 1).toUpperCase() + string.toLowerCase().substring(1); + } +} diff --git a/api/src/main/java/com/alttd/boosterapi/util/Utils.java b/api/src/main/java/com/alttd/boosterapi/util/Utils.java deleted file mode 100644 index da560d2..0000000 --- a/api/src/main/java/com/alttd/boosterapi/util/Utils.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.alttd.boosterapi.util; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; - -public class Utils { - - public static Component parseMiniMessage(String message, TagResolver placeholders) { - MiniMessage miniMessage = MiniMessage.miniMessage(); - if (placeholders == null) { - return miniMessage.deserialize(message); - } else { - return miniMessage.deserialize(message, placeholders); - } - } - - public static String capitalize(String string) { - if (string.length() <= 1) - return string.toUpperCase(); - string = string.toLowerCase(); - return string.substring(0, 1).toUpperCase() + string.toLowerCase().substring(1); - } -} diff --git a/plugin/src/main/java/com/alttd/boosters/BoostersPlugin.java b/plugin/src/main/java/com/alttd/boosters/BoostersPlugin.java index 3c0e793..9ea1aa1 100644 --- a/plugin/src/main/java/com/alttd/boosters/BoostersPlugin.java +++ b/plugin/src/main/java/com/alttd/boosters/BoostersPlugin.java @@ -1,53 +1,38 @@ package com.alttd.boosters; -import com.alttd.boosterapi.BoosterAPI; -import com.alttd.boosterapi.BoosterImplementation; +import com.alttd.boosterapi.config.BoosterFileStorage; import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.ALogger; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.Logger; import com.alttd.boosters.commands.BoosterCommand; -import com.alttd.boosters.listeners.MCmmoListener; import com.alttd.boosters.listeners.MyPetListener; import com.alttd.boosters.listeners.PhantomSpawnListener; import com.alttd.boosters.listeners.PluginMessage; -import com.alttd.boosters.managers.BoosterManager; -import com.alttd.boosters.storage.ServerBoosterStorage; +import com.alttd.boosters.listeners.mcMMOListener; import org.bukkit.command.CommandExecutor; import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; public final class BoostersPlugin extends JavaPlugin { - private static BoostersPlugin instance; - private static BoosterAPI boosterAPI; - private static BoosterManager boosterManager; - @Override public void onEnable() { - instance = this; - ALogger.init(getSLF4JLogger()); - boosterAPI = new BoosterImplementation(); - boosterManager = new BoosterManager(); + Logger logger = new Logger(getSLF4JLogger()); + BoosterCache boosterCache = new BoosterCache(new BoosterFileStorage(logger)); if (getServer().getPluginManager().isPluginEnabled("MyPet")) { - registerListener(new MyPetListener()); + registerListener(new MyPetListener(boosterCache)); } if (getServer().getPluginManager().isPluginEnabled("mcMMO")) { - registerListener(new MCmmoListener()); + registerListener(new mcMMOListener(boosterCache)); } - registerListener(new PhantomSpawnListener()); + registerListener(new PhantomSpawnListener(boosterCache)); - getServer().getMessenger().registerOutgoingPluginChannel(this, Config.pluginMessageChannel); - getServer().getMessenger().registerIncomingPluginChannel(this, Config.pluginMessageChannel, new PluginMessage()); - registerCommand("listboosters", new BoosterCommand()); - ServerBoosterStorage.getServerBoosterStorage(); //this loads the boosters in - } - - @Override - public void onDisable() { - instance = null; - boosterAPI = null; + getServer().getMessenger().registerOutgoingPluginChannel(this, Config.SETTINGS.PLUGIN_MESSAGE_CHANNEL); + getServer().getMessenger().registerIncomingPluginChannel(this, Config.SETTINGS.PLUGIN_MESSAGE_CHANNEL, new PluginMessage(logger, boosterCache)); + registerCommand("listboosters", new BoosterCommand(boosterCache, logger)); } public void registerListener(Listener... listeners) { @@ -59,16 +44,4 @@ public final class BoostersPlugin extends JavaPlugin { public void registerCommand(String commandName, CommandExecutor CommandExecutor) { getCommand(commandName).setExecutor(CommandExecutor); } - - public static BoostersPlugin getInstance() { - return instance; - } - - public BoosterAPI getAPI() { - return boosterAPI; - } - - public BoosterManager getBoosterManager() { - return boosterManager; - } } diff --git a/plugin/src/main/java/com/alttd/boosters/commands/BoosterCommand.java b/plugin/src/main/java/com/alttd/boosters/commands/BoosterCommand.java index b52bbc3..975f92a 100644 --- a/plugin/src/main/java/com/alttd/boosters/commands/BoosterCommand.java +++ b/plugin/src/main/java/com/alttd/boosters/commands/BoosterCommand.java @@ -1,7 +1,9 @@ package com.alttd.boosters.commands; -import com.alttd.boosterapi.Booster; -import com.alttd.boosters.storage.ServerBoosterStorage; +import com.alttd.boosterapi.config.Config; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.BoosterParser; +import com.alttd.boosterapi.util.Logger; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -10,15 +12,18 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.text.DateFormat; -import java.util.*; -import java.util.concurrent.TimeUnit; - public class BoosterCommand implements CommandExecutor { - private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private final BoosterCache boosterCache; + private final Logger logger; + + public BoosterCommand(BoosterCache boosterCache, Logger logger) { + this.boosterCache = boosterCache; + this.logger = logger; + } @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { @@ -26,31 +31,19 @@ public class BoosterCommand implements CommandExecutor { commandSender.sendMiniMessage("You don't have permission for this command", null); return true; } - String message = "Active boosters:\n\n\nQueued boosters:\n"; - String activeBooster = " activated by until [UTC], boosts times"; - String queuedBooster = " queued by starts at [UTC] and will be active for , boosts times"; - List activeBoosterComponents = new ArrayList<>(); - List queuedBoosterComponents = new ArrayList<>(); - for (Booster booster : ServerBoosterStorage.getServerBoosterStorage().getBoosters().values()) { - long expiryTime = new Date().getTime() + booster.getDuration(); - TagResolver templates = TagResolver.resolver( - Placeholder.unparsed("type", booster.getType().getBoosterName()), - Placeholder.unparsed("activator", booster.getActivator()), - Placeholder.unparsed("start_time", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(booster.getStartingTime())), - Placeholder.unparsed("duration", TimeUnit.MILLISECONDS.toHours(booster.getDuration()) + " hours"), - Placeholder.unparsed("multiplier", String.valueOf(booster.getMultiplier())), - Placeholder.unparsed("end_time", booster.isActive() ? DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(expiryTime) : "unknown") - ); - if (booster.isActive()) - activeBoosterComponents.add(miniMessage.deserialize(activeBooster, templates)); - else if (!booster.finished()) - queuedBoosterComponents.add(miniMessage.deserialize(queuedBooster, templates)); - } - commandSender.sendMiniMessage(message, TagResolver.resolver( - Placeholder.component("active_boosters", Component.join(JoinConfiguration.newlines(), activeBoosterComponents)), - Placeholder.component("queued_boosters", Component.join(JoinConfiguration.newlines(), queuedBoosterComponents)) - )); + commandSender.sendMiniMessage(Config.BOOSTER_MESSAGES.LIST_BOOSTER_MESSAGE, TagResolver.resolver( + Placeholder.component("active_boosters", Component.join(JoinConfiguration.newlines(), + BoosterParser.parseBoosters(logger, boosterCache.getAllActiveBoosters(), + Config.BOOSTER_MESSAGES.ACTIVE_BOOSTER_PART, true))), + Placeholder.component("queued_boosters", Component.join(JoinConfiguration.newlines(), + BoosterParser.parseBoosters(logger, boosterCache.getAllQueuedBoosters(), + Config.BOOSTER_MESSAGES.QUEUED_BOOSTER_PART, false)))) + ); + + if (!(commandSender instanceof Player)) + boosterCache.reloadBoosters(); return true; } + } diff --git a/plugin/src/main/java/com/alttd/boosters/data/ServerBooster.java b/plugin/src/main/java/com/alttd/boosters/data/ServerBooster.java deleted file mode 100644 index 6938e35..0000000 --- a/plugin/src/main/java/com/alttd/boosters/data/ServerBooster.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.alttd.boosters.data; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.util.ALogger; -import org.jetbrains.annotations.NotNull; - -import java.util.Date; -import java.util.UUID; - -public class ServerBooster implements Booster { - - private UUID uuid; - private String activator; - private Long startingTime; - private long duration; - private BoosterType boosterType; - private Double multiplier; - private Boolean active; - private Boolean finished; - - public ServerBooster(UUID uuid, BoosterType boosterType, String reason, long duration, double multiplier) { - this.uuid = uuid; - this.boosterType = boosterType; - this.activator = reason; - this.duration = duration; - this.multiplier = multiplier; - this.active = false; - this.finished = false; - } - - public ServerBooster(BoosterType type, String playerName, long duration, double multiplier) { - this(UUID.randomUUID(), type, playerName, duration, multiplier); - } - - public ServerBooster(UUID uuid, String activator, BoosterType boosterType, long startingTime, long duration, double multiplier, boolean active, boolean finished) { - this.uuid = uuid; - this.activator = activator; - this.boosterType = boosterType; - this.startingTime = startingTime; - this.duration = duration; - this.multiplier = multiplier; - this.active = active; - this.finished = finished; - } - - @Override - public boolean isActive() { - return active; - } - - @Override - public void setActive(Boolean active) { - this.startingTime = new Date().getTime(); - this.active = active; - } - - @Override - public BoosterType getType() { - return boosterType; - } - - @Override - public void setType(BoosterType boosterType) { - this.boosterType = boosterType; - } - - @Override - public double getMultiplier() { - return multiplier; - } - - @Override - public void setMultiplier(double multiplier) { - this.multiplier = multiplier; - } - - @Override - public Long getStartingTime() { - return startingTime; - } - - @Override - public void setStartingTime(long startingTime) { - this.startingTime = startingTime; - } - - @Override - public Long getEndTime() { - return startingTime + duration; - } - - @Override - public Long getDuration() { - return duration; - } - - @Override - public void setDuration(long duration) { - this.duration = duration; - } - - @Override - public String getActivator() { - return activator; - } - - @Override - public void setActivator(String activationReason) { - this.activator = activationReason; - } - - @Override - public long getTimeRemaining() { - if(active) { - return startingTime + duration - System.currentTimeMillis(); - } - return duration; - } - - @Override - public UUID getUUID() { - return uuid; - } - - @Override - public void stopBooster() { - setDuration(getTimeRemaining()); - setActive(false); - } - - @Override - public void saveBooster() { - ALogger.error("Tried saving booster from server instead of proxy, only proxy should handle saving boosters"); - } - - @Override - public void finish() { - finished = true; - stopBooster(); - } - - @Override - public boolean finished() { - return false; - } - - - @Override - public int compareTo(@NotNull Object o) { - Booster booster = (Booster) o; - if (booster.getMultiplier() < getMultiplier()) - return -1; - if (booster.getMultiplier() > getMultiplier()) - return 1; - return booster.isActive() ? 1 : -1; - } -} diff --git a/plugin/src/main/java/com/alttd/boosters/listeners/MCmmoListener.java b/plugin/src/main/java/com/alttd/boosters/listeners/MCmmoListener.java index 42962be..94207cd 100755 --- a/plugin/src/main/java/com/alttd/boosters/listeners/MCmmoListener.java +++ b/plugin/src/main/java/com/alttd/boosters/listeners/MCmmoListener.java @@ -1,32 +1,32 @@ package com.alttd.boosters.listeners; -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosters.BoostersPlugin; -import com.alttd.boosters.managers.BoosterManager; +import com.alttd.boosterapi.data.Booster; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.data.BoosterType; import com.gmail.nossr50.events.experience.McMMOPlayerXpGainEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -public class MCmmoListener implements Listener { +import java.util.Optional; + +public class mcMMOListener implements Listener { + + private final BoosterCache boosterCache; + + public mcMMOListener(BoosterCache boosterCache) { + this.boosterCache = boosterCache; + } + @EventHandler public void onMcMMOExperienceEvent(McMMOPlayerXpGainEvent event) { - BoosterManager bm = BoostersPlugin.getInstance().getBoosterManager(); - if (bm.isBoosted(BoosterType.MCMMO)) { - Booster b = bm.getBooster(BoosterType.MCMMO); - double multiplier = b.getMultiplier() + 1; - event.setRawXpGained(Math.round(event.getRawXpGained() * multiplier)); - return; - } String skillName = event.getSkill().name(); BoosterType type = BoosterType.getByName(skillName); - if (bm.isBoosted(type)) { - Booster b = bm.getBooster(type); - double multiplier = b.getMultiplier() + 1; - event.setRawXpGained(Math.round(event.getRawXpGained() * multiplier)); + Optional optionalBooster = boosterCache.getActiveBooster(type); + if (optionalBooster.isEmpty()) return; - } + + Booster booster = optionalBooster.get(); + event.setRawXpGained(Math.round(booster.useMultiplier(event.getRawXpGained()))); } - // TODO : add individual mcmmo skill boosters } diff --git a/plugin/src/main/java/com/alttd/boosters/listeners/MyPetListener.java b/plugin/src/main/java/com/alttd/boosters/listeners/MyPetListener.java index a235293..858a8af 100755 --- a/plugin/src/main/java/com/alttd/boosters/listeners/MyPetListener.java +++ b/plugin/src/main/java/com/alttd/boosters/listeners/MyPetListener.java @@ -1,26 +1,34 @@ package com.alttd.boosters.listeners; -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosters.BoostersPlugin; -import com.alttd.boosters.managers.BoosterManager; +import com.alttd.boosterapi.data.Booster; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.data.BoosterType; import de.Keyle.MyPet.api.event.MyPetExpEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import java.util.Optional; + public class MyPetListener implements Listener { + private final BoosterCache boosterCache; + + public MyPetListener(BoosterCache boosterCache) { + this.boosterCache = boosterCache; + } + @EventHandler public void onMyPetExpEvent(MyPetExpEvent event) { double exp = event.getPet().getExp(); if (exp == 0) { return; } - BoosterManager bm = BoostersPlugin.getInstance().getBoosterManager(); - if(bm.isBoosted(BoosterType.MYPET)) { - Booster b = bm.getBooster(BoosterType.MYPET); - double multiplier = b.getMultiplier() + 1; - event.setExp(event.getExp() * multiplier); - } + + Optional myPetBooster = boosterCache.getActiveBooster(BoosterType.MYPET); + if (myPetBooster.isEmpty()) + return; + + Booster booster = myPetBooster.get(); + event.setExp(booster.useMultiplier(exp)); } } diff --git a/plugin/src/main/java/com/alttd/boosters/listeners/PhantomSpawnListener.java b/plugin/src/main/java/com/alttd/boosters/listeners/PhantomSpawnListener.java index 6e09cbb..e0f944b 100755 --- a/plugin/src/main/java/com/alttd/boosters/listeners/PhantomSpawnListener.java +++ b/plugin/src/main/java/com/alttd/boosters/listeners/PhantomSpawnListener.java @@ -1,7 +1,7 @@ package com.alttd.boosters.listeners; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosters.BoostersPlugin; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.data.BoosterType; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -9,11 +9,17 @@ import org.bukkit.event.Listener; public class PhantomSpawnListener implements Listener { + private final BoosterCache boosterCache; + + public PhantomSpawnListener(BoosterCache boosterCache) { + this.boosterCache = boosterCache; + } + @EventHandler public void onPhantomPreSpawn(com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event) { Entity spawningEntity = event.getSpawningEntity(); - if (spawningEntity instanceof Player player - && BoostersPlugin.getInstance().getBoosterManager().isBoosted(BoosterType.PHANTOM)) { + if (spawningEntity instanceof Player + && boosterCache.getActiveBooster(BoosterType.PHANTOM).isPresent()) { event.setCancelled(true); event.setShouldAbortSpawn(true); } diff --git a/plugin/src/main/java/com/alttd/boosters/listeners/PluginMessage.java b/plugin/src/main/java/com/alttd/boosters/listeners/PluginMessage.java index 10ffdc0..ef28912 100644 --- a/plugin/src/main/java/com/alttd/boosters/listeners/PluginMessage.java +++ b/plugin/src/main/java/com/alttd/boosters/listeners/PluginMessage.java @@ -1,61 +1,34 @@ package com.alttd.boosters.listeners; -import com.alttd.boosterapi.Booster; import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.ALogger; -import com.alttd.boosters.storage.ServerBoosterStorage; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.Logger; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteStreams; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; -import java.util.UUID; - public class PluginMessage implements PluginMessageListener { + private final Logger logger; + private final BoosterCache boosterCache; + + public PluginMessage(Logger logger, BoosterCache boosterCache) { + this.logger = logger; + this.boosterCache = boosterCache; + } + @Override public void onPluginMessageReceived(String channel, Player player, byte[] bytes) { - if(!channel.equals(Config.pluginMessageChannel)) return; - if (Config.DEBUG) - ALogger.info("Received plugin message"); + if(!channel.equals(Config.SETTINGS.PLUGIN_MESSAGE_CHANNEL)) + return; + logger.debug("Received plugin message"); ByteArrayDataInput in = ByteStreams.newDataInput(bytes); String subChannel = in.readUTF(); - switch (subChannel) { - case "activate" -> { - UUID uuid = UUID.fromString(in.readUTF()); - Booster booster = ServerBoosterStorage.getServerBoosterStorage().getBoosters().get(uuid); - if (booster == null) { - ServerBoosterStorage.getServerBoosterStorage().reload(); - booster = ServerBoosterStorage.getServerBoosterStorage().getBoosters().get(uuid); - } - if (booster == null) { - ALogger.warn("Unable to load and activate booster [" + uuid + "]"); - break; - } - booster.setActive(true); - } - case "finish" -> { - UUID uuid = UUID.fromString(in.readUTF()); - Booster booster = ServerBoosterStorage.getServerBoosterStorage().getBoosters().get(uuid); - if (booster == null) { - ALogger.error("Tried to finish booster that was never loaded [" + uuid + "]"); - break; - } - booster.finish(); - } - case "stop" -> { - UUID uuid = UUID.fromString(in.readUTF()); - Booster booster = ServerBoosterStorage.getServerBoosterStorage().getBoosters().get(uuid); - if (booster == null) { - ALogger.error("Tried to stop booster that was never loaded [" + uuid + "]"); - break; - } - booster.stopBooster(); - } - case "reload" -> { - ServerBoosterStorage.getServerBoosterStorage().reload(); - } - default -> {} + if (subChannel.equals("reload")) { + boosterCache.reloadBoosters(); + } else { + logger.severe("Received invalid plugin message"); } } } diff --git a/plugin/src/main/java/com/alttd/boosters/managers/BoosterManager.java b/plugin/src/main/java/com/alttd/boosters/managers/BoosterManager.java deleted file mode 100644 index 97e9879..0000000 --- a/plugin/src/main/java/com/alttd/boosters/managers/BoosterManager.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.alttd.boosters.managers; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.config.Config; -import com.alttd.boosters.BoostersPlugin; -import com.alttd.boosters.storage.ServerBoosterStorage; -import org.bukkit.scheduler.BukkitRunnable; - -public class BoosterManager { - - public BoosterManager() { - new BukkitRunnable() { - @Override - public void run() { - for (Booster booster: ServerBoosterStorage.getServerBoosterStorage().getBoosters().values()) { - if (!booster.isActive()) - continue; - if (booster.getTimeRemaining() > 0) continue; - booster.finish(); - } - } - }.runTaskTimerAsynchronously(BoostersPlugin.getInstance(), 0, Config.activeTaskCheckFrequency * 20); - } - - public boolean isBoosted(BoosterType type) { - for (Booster b : ServerBoosterStorage.getServerBoosterStorage().getBoosters().values()) { - if (b.getType() == type && b.isActive()) { - return true; - } - } - return false; - } - - public Booster getBooster(BoosterType type) { - for (Booster b : ServerBoosterStorage.getServerBoosterStorage().getBoosters().values()) { - if (b.getType() == type && b.isActive()) { - return b; - } - } - return null; - } -} diff --git a/plugin/src/main/java/com/alttd/boosters/storage/ServerBoosterStorage.java b/plugin/src/main/java/com/alttd/boosters/storage/ServerBoosterStorage.java deleted file mode 100644 index 80d2620..0000000 --- a/plugin/src/main/java/com/alttd/boosters/storage/ServerBoosterStorage.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.alttd.boosters.storage; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.config.BoosterStorage; -import com.alttd.boosterapi.util.ALogger; -import com.alttd.boosters.data.ServerBooster; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; - -import java.io.IOException; -import java.util.UUID; - -public class ServerBoosterStorage extends BoosterStorage { - - private static ServerBoosterStorage serverBoosterStorage = null; - - public static ServerBoosterStorage getServerBoosterStorage() { - if (serverBoosterStorage == null) - serverBoosterStorage = new ServerBoosterStorage(); - return serverBoosterStorage; - } - - private ServerBoosterStorage() { - super(); - } - - @Override - public Booster loadBooster(JsonParser parser) throws IOException { - JsonToken jsonToken = parser.getCurrentToken(); - if (!jsonToken.isStructStart()) - return error("Didn't find struct start"); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"uuid".equals(parser.getCurrentName())) - return error("Didn't find uuid at expected location"); - parser.nextValue(); - UUID uuid = UUID.fromString(parser.getValueAsString()); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"activator".equals(parser.getCurrentName())) - return error("Didn't find activator at expected location"); - parser.nextValue(); - String activator = parser.getValueAsString(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"type".equals(parser.getCurrentName())) - return error("Didn't find type at expected location"); - parser.nextValue(); - BoosterType boosterType = BoosterType.getByName(parser.getValueAsString()); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"startingTime".equals(parser.getCurrentName())) - return error("Didn't find startingTime at expected location"); - parser.nextValue(); - long startingTime = parser.getValueAsLong(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"duration".equals(parser.getCurrentName())) - return error("Didn't find duration at expected location"); - parser.nextValue(); - long duration = parser.getValueAsLong(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"multiplier".equals(parser.getCurrentName())) - return error("Didn't find multiplier at expected location"); - parser.nextValue(); - double multiplier = parser.getValueAsDouble(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"active".equals(parser.getCurrentName())) - return error("Didn't find active at expected location"); - parser.nextValue(); - boolean active = parser.getValueAsBoolean(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"finished".equals(parser.getCurrentName())) - return error("Didn't find finished at expected location"); - parser.nextValue(); - boolean finished = parser.getValueAsBoolean(); - return new ServerBooster(uuid, activator, boosterType, startingTime, duration, multiplier, active, finished); - } - - private static Booster error(String error) { - ALogger.error(error); - return null; - } -} diff --git a/velocity/src/main/java/com/alttd/vboosters/VelocityBoosters.java b/velocity/src/main/java/com/alttd/vboosters/VelocityBoosters.java index 4b5ee32..ed7ec7c 100644 --- a/velocity/src/main/java/com/alttd/vboosters/VelocityBoosters.java +++ b/velocity/src/main/java/com/alttd/vboosters/VelocityBoosters.java @@ -2,12 +2,14 @@ package com.alttd.vboosters; import com.alttd.boosterapi.BoosterAPI; import com.alttd.boosterapi.BoosterImplementation; -import com.alttd.boosterapi.util.ALogger; +import com.alttd.boosterapi.config.BoosterFileStorage; +import com.alttd.boosterapi.config.Config; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.Logger; import com.alttd.vboosters.commands.BoosterCommand; import com.alttd.vboosters.commands.DonorRankCommand; import com.alttd.vboosters.listeners.PluginMessageListener; -import com.alttd.vboosters.managers.BoosterManager; -import com.alttd.vboosters.storage.VelocityBoosterStorage; +import com.alttd.vboosters.task.BoosterTask; import com.google.inject.Inject; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; @@ -17,7 +19,6 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; -import org.slf4j.Logger; // TODO use the version created in build.gradle.kts @Plugin(id = "boosterplugin", name = "BoosterPlugin", version = "1.0.0", @@ -32,34 +33,34 @@ public class VelocityBoosters { private final Logger logger; private BoosterAPI boosterAPI; - private BoosterManager boosterManager; + private BoosterCache boosterCache; - private ChannelIdentifier channelIdentifier = MinecraftChannelIdentifier.from("altitude:boosterplugin"); + private final ChannelIdentifier channelIdentifier = MinecraftChannelIdentifier.from( + Config.SETTINGS.PLUGIN_MESSAGE_CHANNEL); @Inject - public VelocityBoosters(ProxyServer proxyServer, Logger proxyLogger) { + public VelocityBoosters(ProxyServer proxyServer, org.slf4j.Logger proxyLogger) { plugin = this; server = proxyServer; - logger = proxyLogger; + this.logger = new Logger(proxyLogger); } @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) { - ALogger.init(logger); - boosterAPI = new BoosterImplementation(); - boosterManager = new BoosterManager(this); + boosterAPI = BoosterImplementation.get(logger); + this.boosterCache = new BoosterCache(new BoosterFileStorage(logger)); server.getChannelRegistrar().register(channelIdentifier); server.getEventManager().register(this, new PluginMessageListener(channelIdentifier)); loadCommands(); reloadConfig(); - VelocityBoosterStorage.getVelocityBoosterStorage(); //this loads the boosters in + new BoosterTask(logger, boosterCache).init(); } @Subscribe public void onShutdown(ProxyShutdownEvent event) { - boosterManager.saveAllBoosters(); + boosterCache.updateAndSave(); } public void reloadConfig() { @@ -80,16 +81,12 @@ public class VelocityBoosters { public void loadCommands() { // all (proxy)commands go here - new BoosterCommand(server); - new DonorRankCommand(server); + server.getCommandManager().register("booster", new BoosterCommand(server, boosterCache, logger)); + new DonorRankCommand(server, logger); } public ChannelIdentifier getChannelIdentifier() { return channelIdentifier; } - public BoosterManager getBoosterManager() { - return boosterManager; - } - } diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/BoosterCommand.java b/velocity/src/main/java/com/alttd/vboosters/commands/BoosterCommand.java index 7f7f0ba..986d203 100755 --- a/velocity/src/main/java/com/alttd/vboosters/commands/BoosterCommand.java +++ b/velocity/src/main/java/com/alttd/vboosters/commands/BoosterCommand.java @@ -1,159 +1,107 @@ package com.alttd.vboosters.commands; -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.Utils; -import com.alttd.proxydiscordlink.bot.api.DiscordSendMessage; -import com.alttd.proxydiscordlink.lib.net.dv8tion.jda.api.entities.templates.Template; -import com.alttd.vboosters.VelocityBoosters; -import com.alttd.vboosters.data.VelocityBooster; -import com.alttd.vboosters.managers.BoosterManager; -import com.alttd.vboosters.storage.VelocityBoosterStorage; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import com.mojang.brigadier.arguments.DoubleArgumentType; -import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.Logger; +import com.alttd.vboosters.commands.boosterSubcommands.Activate; +import com.alttd.vboosters.commands.boosterSubcommands.ListBoosters; +import com.alttd.vboosters.commands.boosterSubcommands.Reload; import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import com.mojang.brigadier.tree.LiteralCommandNode; -import com.velocitypowered.api.command.BrigadierCommand; -import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.command.SimpleCommand; import com.velocitypowered.api.proxy.ProxyServer; -import com.velocitypowered.api.util.GameProfile; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; -import java.text.DateFormat; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -public class BoosterCommand { +public class BoosterCommand extends Command implements SimpleCommand { + private final List subCommands; + private final ProxyServer proxyServer; + private final ListBoosters listBoosters; - CompletableFuture buildRemainingString(SuggestionsBuilder builder, Collection possibleValues) { - if (possibleValues.isEmpty()) - return Suggestions.empty(); + public BoosterCommand(ProxyServer proxyServer, BoosterCache boosterCache, Logger logger) { + this.proxyServer = proxyServer; + listBoosters = new ListBoosters(logger, boosterCache); + subCommands = Arrays.asList( + new Activate(proxyServer, boosterCache, logger), + new Reload(logger), + listBoosters); + } + + @Override + public void execute(Invocation invocation) { + String[] args = invocation.arguments(); + CommandSource source = invocation.source(); + + if (!source.hasPermission("booster.use")) { + source.sendMessage(parseMessage(Config.GENERIC_MESSAGES.NO_PERMISSION)); + return; + } + + if (args.length == 0) { + listBoosters.execute(args, source); + return; + } + + subCommands.stream() + .filter(subCommand -> subCommand.getName().equalsIgnoreCase(args[0])) + .findFirst() + .ifPresentOrElse(subCommand -> { + if (source.hasPermission(subCommand.getPermission())) + subCommand.execute(args, source); + else + source.sendMessage(parseMessage(Config.GENERIC_MESSAGES.NO_PERMISSION)); + }, () -> { + if (!source.hasPermission(listBoosters.getPermission())) { + source.sendMessage(parseMessage(Config.GENERIC_MESSAGES.NO_PERMISSION)); + return; + } + listBoosters.execute(args, source); + }); + } + + @Override + public List suggest(Invocation invocation) { + String[] args = invocation.arguments(); + List suggest = new ArrayList<>(); + + if (!invocation.source().hasPermission("party.use")) + return suggest; + else if (args.length == 0) { + subCommands.stream() + .filter(subCommand -> invocation.source().hasPermission(subCommand.getPermission())) + .forEach(subCommand -> suggest.add(subCommand.getName())); + } else if (args.length == 1) { + subCommands.stream() + .filter(subCommand -> invocation.source().hasPermission(subCommand.getPermission())) + .filter(subCommand -> subCommand.getName().startsWith(args[0].toLowerCase())) + .forEach(subCommand -> suggest.add(subCommand.getName())); + } else { + subCommands.stream() + .filter(subCommand -> invocation.source().hasPermission(subCommand.getPermission())) + .filter(subCommand -> subCommand.getName().equalsIgnoreCase(args[0])) + .findFirst() + .ifPresent(subCommand -> suggest.addAll(subCommand.suggest(args, invocation.source()))); + } + + if (args.length == 0) + return suggest; + else + return finalizeSuggest(suggest, args[args.length - 1]); + } + + public List finalizeSuggest(List possibleValues, String remaining) { + List finalValues = new ArrayList<>(); - String remaining = builder.getRemaining().toLowerCase(); for (String str : possibleValues) { - if (str.toLowerCase().startsWith(remaining)) { - builder.suggest(StringArgumentType.escapeIfRequired(str)); + if (str.toLowerCase().startsWith(remaining.toLowerCase())) { + finalValues.add(StringArgumentType.escapeIfRequired(str)); } } - return builder.buildFuture(); + return finalValues; } - private static MiniMessage miniMessage = MiniMessage.miniMessage(); - public BoosterCommand(ProxyServer proxyServer) { - LiteralCommandNode command = LiteralArgumentBuilder - .literal("booster") - .requires(ctx -> ctx.hasPermission("command.proxy.booster")) - .executes(context -> { //TODO put these messages in config - String message = "Active boosters:\n\n\nQueued boosters:\n"; - String activeBooster = " activated by until [UTC], boosts times"; - String queuedBooster = " queued by starts at [UTC] and will be active for , boosts times"; - List activeBoosterComponents = new ArrayList<>(); - List queuedBoosterComponents = new ArrayList<>(); - for (Booster booster : VelocityBoosterStorage.getVelocityBoosterStorage().getBoosters().values()) { - long expiryTime = new Date().getTime() + booster.getDuration(); - TagResolver.Builder tagResolver = TagResolver.builder(); - - List templates = new ArrayList<>(List.of( - Placeholder.unparsed("type", booster.getType().getBoosterName()), - Placeholder.unparsed("activator", booster.getActivator()), - Placeholder.unparsed("start_time", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(booster.getStartingTime())), - Placeholder.unparsed("duration", TimeUnit.MILLISECONDS.toHours(booster.getDuration()) + " hours"), - Placeholder.unparsed("multiplier", String.valueOf(booster.getMultiplier())))); - - if (booster.isActive()) - templates.add(Placeholder.unparsed("end_time", DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(expiryTime))); - else - templates.add(Placeholder.unparsed("end_time", "unknown")); - - for (TagResolver tagResolver1 : templates) - tagResolver.resolver(tagResolver1); // cheaty and lazy way I know - - if (booster.isActive()) - activeBoosterComponents.add(miniMessage.deserialize(activeBooster, tagResolver.build())); - else if (!booster.finished()) - queuedBoosterComponents.add(miniMessage.deserialize(queuedBooster, tagResolver.build())); - - } - Component separator = miniMessage.deserialize("\n"); - context.getSource().sendMessage(miniMessage.deserialize(message, TagResolver.resolver( - Placeholder.component("active_boosters", Component.join(JoinConfiguration.separator(separator), activeBoosterComponents)), - Placeholder.component("queued_boosters", Component.join(JoinConfiguration.separator(separator), queuedBoosterComponents)) - ))); - return 1; - }) - .then(RequiredArgumentBuilder.argument("username", StringArgumentType.string()) - .requires(ctx -> ctx.hasPermission("command.proxy.booster.manage")) - .suggests((context, builder) -> buildRemainingString(builder, proxyServer.getAllPlayers().stream() - .map(Player::getGameProfile) - .map(GameProfile::getName) - .collect(Collectors.toList()))) - .then(RequiredArgumentBuilder.argument("booster", StringArgumentType.string()) - .suggests((context, builder) -> buildRemainingString(builder, Arrays.stream(BoosterType.values()) - .map(BoosterType::getBoosterName) - .collect(Collectors.toList()))) - .then(RequiredArgumentBuilder.argument("time", IntegerArgumentType.integer(0, 525960)) - .suggests((context, builder) -> buildRemainingString(builder, List.of("60", "120", "180", "240", "300", "360", - "420", "480", "540", "600", "660", "720", "780", "840", "900", "960", "1020", "1080", "1140", "1200", "1260", "1320", "1380", "1440"))) - .then(RequiredArgumentBuilder.argument("multiplier", DoubleArgumentType.doubleArg(0, 10)) - .suggests((context, builder) -> buildRemainingString(builder, List.of("0.5", "1", "1.5", "2"))) - .executes(context -> { //TODO make messages configurable - String username = context.getArgument("username", String.class); - BoosterType boosterType = BoosterType.getByName(context.getArgument("booster", String.class)); - long duration = TimeUnit.MINUTES.toMillis(context.getArgument("time", Integer.class)); - double multiplier = context.getArgument("multiplier", Double.class); - if (boosterType.equals(BoosterType.MCMMO)) - addAllMcMMOBoosters(username, duration, multiplier); - else - VelocityBoosters.getPlugin().getBoosterManager().addBooster(new VelocityBooster(boosterType, username, duration, multiplier)); - - String boosterName = Utils.capitalize(boosterType.getBoosterName()); - String msg = "[" + username + "] purchased booster of type [" + boosterName + "]"; //Add to config for discord only - DiscordSendMessage.sendEmbed(Config.BOOST_ANNOUNCE_CHANNEL, "Booster Purchased", msg); - - TagResolver templates = TagResolver.resolver( - Placeholder.unparsed("player", username), - Placeholder.unparsed("booster", boosterName)); - VelocityBoosters.getPlugin().getProxy().sendMessage(MiniMessage.miniMessage() - .deserialize(Config.BOOST_SERVER_MESSAGE, templates)); - VelocityBoosters.getPlugin().getLogger().info(msg); - return 1; - }) - ) - ) - ) - ) -// .executes(context -> 1) - .build(); - - BrigadierCommand brigadierCommand = new BrigadierCommand(command); - - CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand); - - CommandMeta meta = metaBuilder.build(); - - proxyServer.getCommandManager().register(meta, brigadierCommand); - } - - private void addAllMcMMOBoosters(String username, long duration, double multiplier) { - BoosterManager boosterManager = VelocityBoosters.getPlugin().getBoosterManager(); - for (BoosterType boosterType : BoosterType.getAllMcMMOBoosters()) { - boosterManager.addBooster(new VelocityBooster(boosterType, username, duration, multiplier)); - } - } -} +} \ No newline at end of file diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/Command.java b/velocity/src/main/java/com/alttd/vboosters/commands/Command.java new file mode 100644 index 0000000..30ff593 --- /dev/null +++ b/velocity/src/main/java/com/alttd/vboosters/commands/Command.java @@ -0,0 +1,17 @@ +package com.alttd.vboosters.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; + +public abstract class Command { + + private final MiniMessage miniMessage = MiniMessage.miniMessage(); + + protected Component parseMessage(String message, TagResolver.Single... placeholders) { + if (placeholders.length == 0) + return miniMessage.deserialize(message); + return miniMessage.deserialize(message, placeholders); + } + +} diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/DonorRankCommand.java b/velocity/src/main/java/com/alttd/vboosters/commands/DonorRankCommand.java index f5e3ac1..afd9552 100644 --- a/velocity/src/main/java/com/alttd/vboosters/commands/DonorRankCommand.java +++ b/velocity/src/main/java/com/alttd/vboosters/commands/DonorRankCommand.java @@ -2,7 +2,8 @@ package com.alttd.vboosters.commands; import com.alttd.boosterapi.BoosterAPI; import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.Utils; +import com.alttd.boosterapi.util.Logger; +import com.alttd.boosterapi.util.StringModifier; import com.alttd.vboosters.VelocityBoosters; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; @@ -28,8 +29,10 @@ import java.util.Collection; public class DonorRankCommand { private final MiniMessage miniMessage; + private final Logger logger; - public DonorRankCommand(ProxyServer proxyServer) { + public DonorRankCommand(ProxyServer proxyServer, Logger logger) { + this.logger = logger; miniMessage = MiniMessage.miniMessage(); LiteralCommandNode command = LiteralArgumentBuilder @@ -65,7 +68,7 @@ public class DonorRankCommand { }) .then(RequiredArgumentBuilder.argument("rank", StringArgumentType.string()) .suggests((context, builder) -> { - Collection possibleValues = new ArrayList<>(Config.donorRanks); + Collection possibleValues = new ArrayList<>(Config.SETTINGS.DONOR_RANKS); String remaining = builder.getRemaining().toLowerCase(); for (String str : possibleValues) { if (str.toLowerCase().startsWith(remaining)) { @@ -79,19 +82,19 @@ public class DonorRankCommand { String username = context.getArgument("username", String.class); String action = context.getArgument("action", String.class); String rank = context.getArgument("rank", String.class).toLowerCase(); - LuckPerms luckPerms = BoosterAPI.get().getLuckPerms(); + LuckPerms luckPerms = BoosterAPI.get(logger).getLuckPerms(); User user = luckPerms.getUserManager().getUser(username); //TODO test if this works with username if (user == null) { commandSource.sendMessage(miniMessage.deserialize( - Config.INVALID_USER, + Config.DONOR_RANK_MESSAGES.INVALID_USER, Placeholder.unparsed("player", username))); return 1; } - if (!Config.donorRanks.contains(rank)) { + if (!Config.SETTINGS.DONOR_RANKS.contains(rank)) { commandSource.sendMessage(miniMessage.deserialize( - Config.INVALID_DONOR_RANK, + Config.DONOR_RANK_MESSAGES.INVALID_DONOR_RANK, Placeholder.unparsed("rank", rank))); return 1; } @@ -99,7 +102,7 @@ public class DonorRankCommand { switch (action) { case "promote" -> promote(user, rank); case "demote" -> demote(user, rank); - default -> commandSource.sendMessage(miniMessage.deserialize(Config.INVALID_ACTION)); + default -> commandSource.sendMessage(miniMessage.deserialize(Config.DONOR_RANK_MESSAGES.INVALID_ACTION)); } return 1; }) @@ -119,18 +122,18 @@ public class DonorRankCommand { } private void promote(User user, String rank) { - LuckPerms luckPerms = BoosterAPI.get().getLuckPerms(); + LuckPerms luckPerms = BoosterAPI.get(logger).getLuckPerms(); user.getNodes(NodeType.INHERITANCE).stream() .filter(Node::getValue) .forEach(node -> { - if (Config.donorRanks.contains(node.getGroupName())) + if (Config.SETTINGS.DONOR_RANKS.contains(node.getGroupName())) user.data().remove(node); }); user.data().add(InheritanceNode.builder(rank).build()); VelocityBoosters.getPlugin().getProxy().getPlayer(user.getUniqueId()).ifPresent(player -> { if (player.isActive()) { - player.sendMessage(miniMessage.deserialize(Config.PROMOTE_MESSAGE, - Placeholder.unparsed("rank", Utils.capitalize(rank)), + player.sendMessage(miniMessage.deserialize(Config.DONOR_RANK_MESSAGES.PROMOTE_MESSAGE, + Placeholder.unparsed("rank", StringModifier.capitalize(rank)), Placeholder.unparsed("player", player.getUsername()))); } }); @@ -138,17 +141,17 @@ public class DonorRankCommand { } private void demote(User user, String rank) { - LuckPerms luckPerms = BoosterAPI.get().getLuckPerms(); + LuckPerms luckPerms = BoosterAPI.get(logger).getLuckPerms(); user.getNodes(NodeType.INHERITANCE).stream() .filter(Node::getValue) .forEach(node -> { - if (Config.donorRanks.contains(node.getGroupName())) + if (Config.SETTINGS.DONOR_RANKS.contains(node.getGroupName())) user.data().remove(node); }); VelocityBoosters.getPlugin().getProxy().getPlayer(user.getUniqueId()).ifPresent(player -> { if (player.isActive()) { - player.sendMessage(miniMessage.deserialize(Config.DEMOTE_MESSAGE, - Placeholder.unparsed("rank", Utils.capitalize(rank)), + player.sendMessage(miniMessage.deserialize(Config.DONOR_RANK_MESSAGES.DEMOTE_MESSAGE, + Placeholder.unparsed("rank", StringModifier.capitalize(rank)), Placeholder.unparsed("player", player.getUsername()))); } }); diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/SubCommand.java b/velocity/src/main/java/com/alttd/vboosters/commands/SubCommand.java new file mode 100644 index 0000000..0d8b7bd --- /dev/null +++ b/velocity/src/main/java/com/alttd/vboosters/commands/SubCommand.java @@ -0,0 +1,21 @@ +package com.alttd.vboosters.commands; + +import com.velocitypowered.api.command.CommandSource; + +import java.util.List; + +public interface SubCommand{ + + String getName(); + + default String getPermission() { + return "boosters." + getName(); + } + + void execute(String[] args, CommandSource source); + + List suggest(String[] args, CommandSource source); + + String getHelpMessage(); + +} diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/Activate.java b/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/Activate.java new file mode 100644 index 0000000..5e0a583 --- /dev/null +++ b/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/Activate.java @@ -0,0 +1,115 @@ +package com.alttd.vboosters.commands.boosterSubcommands; + +import com.alttd.boosterapi.config.Config; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.data.BoosterType; +import com.alttd.boosterapi.util.Logger; +import com.alttd.boosterapi.util.StringModifier; +import com.alttd.proxydiscordlink.bot.api.DiscordSendMessage; +import com.alttd.vboosters.VelocityBoosters; +import com.alttd.vboosters.commands.Command; +import com.alttd.vboosters.commands.SubCommand; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import com.velocitypowered.api.command.CommandSource; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class Activate extends Command implements SubCommand { + + private final ProxyServer proxyServer; + private final BoosterCache boosterCache; + private final Logger logger; + + public Activate(ProxyServer proxyServer, BoosterCache boosterCache, Logger logger) { + this.proxyServer = proxyServer; + this.boosterCache = boosterCache; + this.logger = logger; + } + + @Override + public String getName() { + return "activate"; + } + + @Override + public void execute(String[] args, CommandSource source) { + if (args.length != 5) { + source.sendMessage(parseMessage(getHelpMessage())); + return; + } + String activatorName = args[1]; + BoosterType boosterType = BoosterType.getByName(args[2]); + Duration duration; + try { + int minuteDuration = Integer.parseInt(args[3]); + duration = Duration.ofMinutes(minuteDuration); + } catch (NumberFormatException e) { + source.sendMessage(parseMessage(getHelpMessage())); + return; + } + double multiplier; + + try { + multiplier = Double.parseDouble(args[4]); + } catch (NumberFormatException e) { + source.sendMessage(parseMessage(getHelpMessage())); + return; + } + + boosterCache.addNewBooster(boosterType, activatorName, duration, multiplier); + + String boosterName = StringModifier.capitalize(boosterType.getBoosterName()); + String msg = "[" + activatorName + "] purchased booster of type [" + boosterName + "]"; //Add to config for discord only + + DiscordSendMessage.sendEmbed(Config.SETTINGS.BOOST_ANNOUNCE_CHANNEL, "Booster Purchased", msg); + VelocityBoosters.getPlugin().getProxy().sendMessage(parseMessage(Config.BOOSTER_MESSAGES.BOOST_SERVER_MESSAGE, + Placeholder.unparsed("player", activatorName), Placeholder.unparsed("booster", boosterName))); + logger.info(msg); + + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("reload"); + VelocityBoosters.getPlugin().getProxy().getAllServers() + .forEach(registeredServer -> registeredServer.sendPluginMessage(VelocityBoosters.getPlugin().getChannelIdentifier(), out.toByteArray())); + } + + @Override + public List suggest(String[] args, CommandSource source) { + switch (args.length) { + case 2 -> { + return proxyServer.getAllPlayers().stream() + .map(Player::getUsername) + .collect(Collectors.toList()); + } + case 3 -> { + return Arrays.stream(BoosterType.values()) + .map(BoosterType::getBoosterName) + .collect(Collectors.toList()); + } + case 4 -> { + return IntStream.iterate(60, i -> i <= 1440, i -> i + 60) + .boxed() + .map(Object::toString) + .collect(Collectors.toList()); + } + case 5 -> { + return List.of("0.5", "1", "1.5", "2"); + } + default -> { + return List.of(); + } + } + } + + @Override + public String getHelpMessage() { + return "Invalid arg length"; //TODO implement + } +} diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/ListBoosters.java b/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/ListBoosters.java new file mode 100644 index 0000000..5617ed5 --- /dev/null +++ b/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/ListBoosters.java @@ -0,0 +1,53 @@ +package com.alttd.vboosters.commands.boosterSubcommands; + +import com.alttd.boosterapi.config.Config; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.BoosterParser; +import com.alttd.boosterapi.util.Logger; +import com.alttd.vboosters.commands.Command; +import com.alttd.vboosters.commands.SubCommand; +import com.velocitypowered.api.command.CommandSource; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import java.util.List; + +public class ListBoosters extends Command implements SubCommand { + + private final Logger logger; + private final BoosterCache boosterCache; + + public ListBoosters(Logger logger, BoosterCache boosterCache) { + this.logger = logger; + this.boosterCache = boosterCache; + } + + @Override + public String getName() { + return "list"; + } + + @Override + public void execute(String[] args, CommandSource source) { + List activeBoosters = BoosterParser.parseBoosters(logger, boosterCache.getAllActiveBoosters(), + Config.BOOSTER_MESSAGES.ACTIVE_BOOSTER_PART, true); + List queuedBoosters = BoosterParser.parseBoosters(logger, boosterCache.getAllQueuedBoosters(), + Config.BOOSTER_MESSAGES.QUEUED_BOOSTER_PART, false); + + source.sendMessage(parseMessage(Config.BOOSTER_MESSAGES.LIST_BOOSTER_MESSAGE, + Placeholder.component("active_boosters", Component.join(JoinConfiguration.newlines(), activeBoosters)), + Placeholder.component("queued_boosters", Component.join(JoinConfiguration.newlines(), queuedBoosters)) + )); + } + + @Override + public List suggest(String[] args, CommandSource source) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return ""; //TODO implement + } +} diff --git a/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/Reload.java b/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/Reload.java new file mode 100644 index 0000000..9cc6dfd --- /dev/null +++ b/velocity/src/main/java/com/alttd/vboosters/commands/boosterSubcommands/Reload.java @@ -0,0 +1,40 @@ +package com.alttd.vboosters.commands.boosterSubcommands; + +import com.alttd.boosterapi.config.Config; +import com.alttd.boosterapi.util.Logger; +import com.alttd.vboosters.commands.Command; +import com.alttd.vboosters.commands.SubCommand; +import com.velocitypowered.api.command.CommandSource; + +import java.util.List; + +public class Reload extends Command implements SubCommand { + + private final Logger logger; + + public Reload(Logger logger) { + this.logger = logger; + } + + + @Override + public String getName() { + return "reload"; + } + + @Override + public void execute(String[] args, CommandSource source) { + Config.reload(logger); + source.sendMessage(parseMessage(Config.GENERIC_MESSAGES.RELOADED)); + } + + @Override + public List suggest(String[] args, CommandSource source) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return ""; //TODO implement + } +} diff --git a/velocity/src/main/java/com/alttd/vboosters/data/VelocityBooster.java b/velocity/src/main/java/com/alttd/vboosters/data/VelocityBooster.java deleted file mode 100644 index 26b00c4..0000000 --- a/velocity/src/main/java/com/alttd/vboosters/data/VelocityBooster.java +++ /dev/null @@ -1,213 +0,0 @@ -package com.alttd.vboosters.data; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.config.BoosterStorage; -import com.alttd.vboosters.VelocityBoosters; -import com.alttd.vboosters.storage.VelocityBoosterStorage; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import com.velocitypowered.api.proxy.messages.ChannelIdentifier; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.List; -import java.util.Date; -import java.util.UUID; -import java.util.stream.Collectors; - -public class VelocityBooster implements Booster { - - private UUID uuid; - private String activator; - private Long startingTime; - private long duration; - private BoosterType boosterType; - private Double multiplier; - private Boolean active; - private Boolean finished; - - public VelocityBooster(UUID uuid, BoosterType boosterType, String reason, long duration, double multiplier) { - this.uuid = uuid; - this.boosterType = boosterType; - this.activator = reason; - this.duration = duration; - this.multiplier = multiplier; - this.active = false; - this.finished = false; - this.startingTime = new Date().getTime(); - } - - public VelocityBooster(BoosterType type, String playerName, long duration, double multiplier) { - this(UUID.randomUUID(), type, playerName, duration, multiplier); - } - - public VelocityBooster(UUID uuid, String activator, BoosterType boosterType, long startingTime, - long duration, double multiplier, boolean active, boolean finished) { - this.uuid = uuid; - this.activator = activator; - this.boosterType = boosterType; - this.startingTime = startingTime; - this.duration = duration; - this.multiplier = multiplier; - this.active = active; - this.finished = finished; - } - - @Override - public boolean isActive() { - return active; - } - - @Override - public void setActive(Boolean active) { - this.active = active; - updateQueue(); - } - - @Override - public BoosterType getType() { - return boosterType; - } - - @Override - public void setType(BoosterType boosterType) { - this.boosterType = boosterType; - } - - @Override - public double getMultiplier() { - return multiplier; - } - - @Override - public void setMultiplier(double multiplier) { - this.multiplier = multiplier; - } - - @Override - public Long getStartingTime() { - return startingTime; - } - - @Override - public void setStartingTime(long startingTime) { - this.startingTime = startingTime; - } - - @Override - public Long getEndTime() { - return startingTime + duration; - } - - @Override - public Long getDuration() { - return duration; - } - - @Override - public void setDuration(long duration) { - this.duration = duration; - } - - @Override - public String getActivator() { - return activator; - } - - @Override - public void setActivator(String activationReason) { - this.activator = activationReason; - } - - @Override - public long getTimeRemaining() { - if(active) { - return startingTime + duration - System.currentTimeMillis(); - } - return duration; - } - - @Override - public UUID getUUID() { - return uuid; - } - - @Override - public void stopBooster() { //TODO stop it on the servers as well - setDuration(getTimeRemaining()); - setActive(false); - saveBooster(); - if (!finished) { - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - out.writeUTF("finish"); - out.writeUTF(uuid.toString()); - VelocityBoosters.getPlugin().getProxy().getAllServers() - .forEach(registeredServer -> registeredServer.sendPluginMessage(VelocityBoosters.getPlugin().getChannelIdentifier(), out.toByteArray())); - } - } - - @Override - public void saveBooster() { - VelocityBoosterStorage vbs = VelocityBoosterStorage.getVelocityBoosterStorage(); - vbs.getBoosters().put(uuid, this); - } - - public void finish() { //TODO finish it on the servers as well - finished = true; - stopBooster(); - updateQueue(); //Deletes inactive boosters - List collect = VelocityBoosterStorage.getVelocityBoosterStorage().getBoosters(boosterType).stream().sorted().collect(Collectors.toList()); - if (collect.size() <= 1) - return; - Booster booster = collect.get(1); - booster.setActive(true); - //TODO send plugin message that this is finished - } - - @Override - public boolean finished() { - return finished; - } - - public void updateQueue() { - Collection boosters = VelocityBoosterStorage.getVelocityBoosterStorage().getBoosters(getType()); - if (boosters.isEmpty()) - return; - List collect = boosters.stream().sorted().collect(Collectors.toList()); - Booster booster = collect.get(0); - if (!booster.isActive()) { - booster.setActive(true); - booster.setStartingTime(new Date().getTime()); - } - if (collect.size() > 1) - fixTimes(collect); - - VelocityBoosterStorage.getVelocityBoosterStorage().saveBoosters(); - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - out.writeUTF("reload"); - VelocityBoosters.getPlugin().getProxy().getAllServers() - .forEach(registeredServer -> registeredServer.sendPluginMessage(VelocityBoosters.getPlugin().getChannelIdentifier(), out.toByteArray())); - } - - private void fixTimes(List sorted) { - for (int i = 0; i < sorted.size() - 1; i++) { - Booster booster = sorted.get(i + 1); - if (booster.isActive()) { //Disable active boosters that shouldn't be active and update their duration - booster.setActive(false); - booster.setDuration(booster.getEndTime() - booster.getStartingTime()); - } - booster.setStartingTime(sorted.get(i).getEndTime()); - } - } - - @Override - public int compareTo(@NotNull Object o) { - Booster booster = (Booster) o; - if (booster.getMultiplier() < getMultiplier()) - return -1; - if (booster.getMultiplier() > getMultiplier()) - return 1; - return booster.isActive() ? 1 : -1; - } -} diff --git a/velocity/src/main/java/com/alttd/vboosters/managers/BoosterManager.java b/velocity/src/main/java/com/alttd/vboosters/managers/BoosterManager.java deleted file mode 100644 index 9f4c35f..0000000 --- a/velocity/src/main/java/com/alttd/vboosters/managers/BoosterManager.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.alttd.vboosters.managers; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.ALogger; -import com.alttd.vboosters.VelocityBoosters; -import com.alttd.vboosters.data.VelocityBooster; -import com.alttd.vboosters.storage.VelocityBoosterStorage; -import com.mysql.cj.log.Log; -import com.velocitypowered.api.scheduler.ScheduledTask; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -public class BoosterManager { - - private VelocityBoosters plugin; - - private static List queuedBoosters; - private static List activeBoosters; - private static ScheduledTask boostersTask; - - public BoosterManager(VelocityBoosters velocityBoosters) { - plugin = velocityBoosters; - activeBoosters = new ArrayList<>(); - queuedBoosters = new ArrayList<>(); - /* - * This is mainly used to count down the active boosters and - * let backend servers know if one should be activated/deactivated - */ - boostersTask = plugin.getProxy().getScheduler().buildTask(plugin, () -> { - for (Booster booster: getActiveBoosters()) { - if (booster.getTimeRemaining() > 0) continue; - booster.finish(); - - plugin.getProxy().sendMessage(MiniMessage.miniMessage().deserialize("Booster ended!", Placeholder.unparsed("booster", booster.getType().getBoosterName()))); - // send data to the backend servers to let them know the booster is no longer active - } - getActiveBoosters().removeIf(Booster::finished); - for (BoosterType type : BoosterType.values()) { - if (!isBoosted(type)) { // activate a queud booster if needed - Booster queuedBooster = getHighestBooster(type); - if (queuedBooster == null) - continue; - activateBooster(queuedBooster); - // send an update to the backend servers to let them know this booster is active - } - } - getQueuedBoosters().removeIf(Booster::finished); - }).repeat(Config.activeTaskCheckFrequency, TimeUnit.SECONDS).schedule(); - } - - public void loadBoosters() { - // load boosters from datastorage and check them one by one to activate them - for (BoosterType type : BoosterType.values()) { - if (isBoosted(type)) { - Booster activeBooster = getBoosted(type); - Booster queuedBooster = getHighestBooster(type); - if (queuedBooster != null && queuedBooster.getMultiplier() > activeBooster.getMultiplier()) { - swapBooster(activeBooster, queuedBooster); - } - } else { - Booster queuedBooster = getHighestBooster(type); - if(queuedBooster == null) - continue; - activateBooster(queuedBooster); - } - } - } - - public void addBooster(Booster booster) { -// BoosterType type = booster.getType(); -// if (isBoosted(type)) { -// Booster activeBooster = getBoosted(type); -// Booster queuedBooster = getHighestBooster(type); -// if (queuedBooster != null && queuedBooster.getMultiplier() > activeBooster.getMultiplier()) { -// swapBooster(activeBooster, queuedBooster); -// } -// } else { -// activateBooster(booster); -// } - VelocityBoosterStorage.getVelocityBoosterStorage().add(booster); - if (booster instanceof VelocityBooster velocityBooster) - velocityBooster.updateQueue(); - else - ALogger.error("Tried to add a not velocity booster from velocity"); - } - - public void removeBooster(Booster booster) { - activeBoosters.remove(booster); - booster.stopBooster(); - } - - public void swapBooster(Booster activeBooster, Booster queuedBooster) { - deactivateBooster(activeBooster); - activateBooster(queuedBooster); - } - - public void activateBooster(Booster booster) { - queuedBoosters.remove(booster); - activeBoosters.add(booster); - booster.setActive(true); - } - - public void deactivateBooster(Booster booster) { - if (booster.isActive()) - queuedBoosters.add(booster); - activeBoosters.remove(booster); - booster.setActive(false); - } - - public boolean isBoosted(BoosterType type) { - for (Booster b : activeBoosters) { - if (b.getType() == type && b.isActive()) { - return true; - } - } - return false; - } - - public Booster getBoosted(BoosterType type) { - for (Booster b : activeBoosters) { - if (b.getType() == type && b.isActive()) { - return b; - } - } - return null; - } - - public Booster getHighestBooster(BoosterType type) { - return getQueuedBooster(type).stream().max(Comparator.comparing(Booster::getMultiplier)).orElse(null); - } - - public List getActiveBoosters() { - return activeBoosters; - } - - public List getQueuedBoosters() { - return queuedBoosters; - } - - public List getQueuedBooster(BoosterType type) { - return getQueuedBoosters().stream().filter(booster -> booster.getType() == type).collect(Collectors.toList()); - } - - public void saveAllBoosters() { - for (Booster b : activeBoosters) { - b.stopBooster(); - } - for (Booster b : queuedBoosters) { - b.saveBooster(); - } - activeBoosters.clear(); - queuedBoosters.clear(); - } - -} diff --git a/velocity/src/main/java/com/alttd/vboosters/storage/VelocityBoosterStorage.java b/velocity/src/main/java/com/alttd/vboosters/storage/VelocityBoosterStorage.java deleted file mode 100644 index 824e728..0000000 --- a/velocity/src/main/java/com/alttd/vboosters/storage/VelocityBoosterStorage.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.alttd.vboosters.storage; - -import com.alttd.boosterapi.Booster; -import com.alttd.boosterapi.BoosterType; -import com.alttd.boosterapi.config.BoosterStorage; -import com.alttd.boosterapi.config.Config; -import com.alttd.boosterapi.util.ALogger; -import com.alttd.vboosters.data.VelocityBooster; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; - -import java.io.IOException; -import java.util.UUID; - -public class VelocityBoosterStorage extends BoosterStorage { - - private static VelocityBoosterStorage velocityBoosterStorage = null; - - public static VelocityBoosterStorage getVelocityBoosterStorage() { - if (velocityBoosterStorage == null) - velocityBoosterStorage = new VelocityBoosterStorage(); - return velocityBoosterStorage; - } - - private VelocityBoosterStorage() { - super(); - } - - @Override - public Booster loadBooster(JsonParser parser) throws IOException { - JsonToken jsonToken = parser.getCurrentToken(); - if (!jsonToken.isStructStart()) - return error("Didn't find struct start"); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"uuid".equals(parser.getCurrentName())) - return error("Didn't find uuid at expected location"); - parser.nextValue(); - UUID uuid = UUID.fromString(parser.getValueAsString()); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"activator".equals(parser.getCurrentName())) - return error("Didn't find activator at expected location"); - parser.nextValue(); - String activator = parser.getValueAsString(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"type".equals(parser.getCurrentName())) - return error("Didn't find type at expected location"); - parser.nextValue(); - BoosterType boosterType = BoosterType.getByName(parser.getValueAsString()); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"startingTime".equals(parser.getCurrentName())) - return error("Didn't find startingTime at expected location"); - parser.nextValue(); - long startingTime = parser.getValueAsLong(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"duration".equals(parser.getCurrentName())) - return error("Didn't find duration at expected location"); - parser.nextValue(); - long duration = parser.getValueAsLong(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"multiplier".equals(parser.getCurrentName())) - return error("Didn't find multiplier at expected location"); - parser.nextValue(); - double multiplier = parser.getValueAsDouble(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"active".equals(parser.getCurrentName())) - return error("Didn't find active at expected location"); - parser.nextValue(); - boolean active = parser.getValueAsBoolean(); - - jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.FIELD_NAME || !"finished".equals(parser.getCurrentName())) - return error("Didn't find finished at expected location"); - parser.nextValue(); - boolean finished = parser.getValueAsBoolean(); - return new VelocityBooster(uuid, activator, boosterType, startingTime, duration, multiplier, active, finished); - } - - private static Booster error(String error) { - ALogger.error(error); - return null; - } -} diff --git a/velocity/src/main/java/com/alttd/vboosters/task/BoosterTask.java b/velocity/src/main/java/com/alttd/vboosters/task/BoosterTask.java index 2e571d2..ce5cfae 100644 --- a/velocity/src/main/java/com/alttd/vboosters/task/BoosterTask.java +++ b/velocity/src/main/java/com/alttd/vboosters/task/BoosterTask.java @@ -1,23 +1,54 @@ package com.alttd.vboosters.task; +import com.alttd.boosterapi.data.Booster; import com.alttd.boosterapi.config.Config; +import com.alttd.boosterapi.data.BoosterCache; +import com.alttd.boosterapi.util.Logger; import com.alttd.vboosters.VelocityBoosters; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import java.time.Duration; +import java.time.Instant; +import java.util.List; import java.util.concurrent.TimeUnit; public class BoosterTask { private VelocityBoosters plugin; + private final Logger logger; + private final BoosterCache boosterCache; - public BoosterTask() { + public BoosterTask(Logger logger, BoosterCache boosterCache) { super(); + this.logger = logger; + this.boosterCache = boosterCache; plugin = VelocityBoosters.getPlugin(); } - public void init() { - plugin.getProxy().getScheduler().buildTask(plugin, () -> { + private void run() { + boolean update = false; + List values = boosterCache.getAllActiveBoosters(); + for (Booster booster : values) { + logger.debug("Handling booster: " + booster); + Instant currentTime = Instant.now(); + Duration elapsedTime = Duration.between(booster.getStartingTime(), currentTime); + if (elapsedTime.compareTo(booster.getDuration()) >= 0) { + logger.debug("No time remaining, finishing booster: " + booster); + boosterCache.finishBooster(booster); + update = true; + } + } + if (!update) + return; + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("reload"); + plugin.getProxy().getAllServers() + .forEach(registeredServer -> registeredServer.sendPluginMessage(VelocityBoosters.getPlugin().getChannelIdentifier(), out.toByteArray())); + } - }).repeat(Config.taskCheckFrequency, TimeUnit.SECONDS).schedule(); + public void init() { + plugin.getProxy().getScheduler().buildTask(plugin, this::run).repeat(Config.SETTINGS.UPDATE_FREQUENCY_MINUTES, TimeUnit.MINUTES).schedule(); } }