Reworked everything to be much easier to read and just over all better (didnt rewrite the ranks part tho)

This commit is contained in:
2023-06-27 04:37:56 +02:00
parent fb41198073
commit 84e306f45f
39 changed files with 1500 additions and 1708 deletions
@@ -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;
}
}
@@ -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<SubCommand> subCommands;
private final ProxyServer proxyServer;
private final ListBoosters listBoosters;
CompletableFuture<Suggestions> buildRemainingString(SuggestionsBuilder builder, Collection<String> 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<String> suggest(Invocation invocation) {
String[] args = invocation.arguments();
List<String> 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<String> finalizeSuggest(List<String> possibleValues, String remaining) {
List<String> 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<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("booster")
.requires(ctx -> ctx.hasPermission("command.proxy.booster"))
.executes(context -> { //TODO put these messages in config
String message = "Active boosters:\n<active_boosters>\n\nQueued boosters:\n<queued_boosters>";
String activeBooster = "<type> activated by <activator> until <end_time> [UTC], boosts <multiplier> times";
String queuedBooster = "<type> queued by <activator> starts at <start_time> [UTC] and will be active for <duration>, boosts <multiplier> times";
List<Component> activeBoosterComponents = new ArrayList<>();
List<Component> queuedBoosterComponents = new ArrayList<>();
for (Booster booster : VelocityBoosterStorage.getVelocityBoosterStorage().getBoosters().values()) {
long expiryTime = new Date().getTime() + booster.getDuration();
TagResolver.Builder tagResolver = TagResolver.builder();
List<TagResolver> 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.<CommandSource, String>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.<CommandSource, String>argument("booster", StringArgumentType.string())
.suggests((context, builder) -> buildRemainingString(builder, Arrays.stream(BoosterType.values())
.map(BoosterType::getBoosterName)
.collect(Collectors.toList())))
.then(RequiredArgumentBuilder.<CommandSource, Integer>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.<CommandSource, Double>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));
}
}
}
}
@@ -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);
}
}
@@ -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<CommandSource> command = LiteralArgumentBuilder
@@ -65,7 +68,7 @@ public class DonorRankCommand {
})
.then(RequiredArgumentBuilder.<CommandSource, String>argument("rank", StringArgumentType.string())
.suggests((context, builder) -> {
Collection<String> possibleValues = new ArrayList<>(Config.donorRanks);
Collection<String> 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())));
}
});
@@ -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<String> suggest(String[] args, CommandSource source);
String getHelpMessage();
}
@@ -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<String> 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 "<red>Invalid arg length</red>"; //TODO implement
}
}
@@ -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<Component> activeBoosters = BoosterParser.parseBoosters(logger, boosterCache.getAllActiveBoosters(),
Config.BOOSTER_MESSAGES.ACTIVE_BOOSTER_PART, true);
List<Component> 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<String> suggest(String[] args, CommandSource source) {
return List.of();
}
@Override
public String getHelpMessage() {
return ""; //TODO implement
}
}
@@ -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<String> suggest(String[] args, CommandSource source) {
return List.of();
}
@Override
public String getHelpMessage() {
return ""; //TODO implement
}
}
@@ -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<Booster> 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<Booster> boosters = VelocityBoosterStorage.getVelocityBoosterStorage().getBoosters(getType());
if (boosters.isEmpty())
return;
List<Booster> 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<Booster> 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;
}
}
@@ -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<Booster> queuedBoosters;
private static List<Booster> 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("<green>Booster <booster> ended!</green>", 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<Booster> getActiveBoosters() {
return activeBoosters;
}
public List<Booster> getQueuedBoosters() {
return queuedBoosters;
}
public List<Booster> 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();
}
}
@@ -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;
}
}
@@ -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<Booster> 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();
}
}