mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-19 14:59:20 +00:00
Started using plugin messages internally. Started subcommand refactor
This commit is contained in:
@@ -34,6 +34,7 @@ object Versions {
|
|||||||
const val snakeyamlVersion = "1.28"
|
const val snakeyamlVersion = "1.28"
|
||||||
const val cloudVersion = "1.5.0"
|
const val cloudVersion = "1.5.0"
|
||||||
const val bstatsVersion = "3.0.0"
|
const val bstatsVersion = "3.0.0"
|
||||||
|
const val mbassadorVersion = "1.3.2"
|
||||||
|
|
||||||
const val javaWebsocketVersion = "1.5.2"
|
const val javaWebsocketVersion = "1.5.2"
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ dependencies {
|
|||||||
api("cloud.commandframework", "cloud-core", Versions.cloudVersion)
|
api("cloud.commandframework", "cloud-core", Versions.cloudVersion)
|
||||||
api("org.yaml", "snakeyaml", Versions.snakeyamlVersion)
|
api("org.yaml", "snakeyaml", Versions.snakeyamlVersion)
|
||||||
api("org.bstats", "bstats-base", Versions.bstatsVersion)
|
api("org.bstats", "bstats-base", Versions.bstatsVersion)
|
||||||
|
api("net.engio", "mbassador", Versions.mbassadorVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// present on all platforms
|
// present on all platforms
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.engio.mbassy.bus.common.PubSubSupport;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.InstanceHolder;
|
import org.geysermc.floodgate.api.InstanceHolder;
|
||||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||||
@@ -43,6 +44,7 @@ import org.geysermc.floodgate.api.packet.PacketHandlers;
|
|||||||
import org.geysermc.floodgate.config.ConfigLoader;
|
import org.geysermc.floodgate.config.ConfigLoader;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
|
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||||
import org.geysermc.floodgate.link.PlayerLinkLoader;
|
import org.geysermc.floodgate.link.PlayerLinkLoader;
|
||||||
import org.geysermc.floodgate.module.ConfigLoadedModule;
|
import org.geysermc.floodgate.module.ConfigLoadedModule;
|
||||||
import org.geysermc.floodgate.module.PostInitializeModule;
|
import org.geysermc.floodgate.module.PostInitializeModule;
|
||||||
@@ -130,6 +132,8 @@ public class FloodgatePlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean disable() {
|
public boolean disable() {
|
||||||
|
guice.getInstance(PubSubSupport.class).publish(new ShutdownEvent());
|
||||||
|
|
||||||
if (injector != null && injector.canRemoveInjection()) {
|
if (injector != null && injector.canRemoveInjection()) {
|
||||||
try {
|
try {
|
||||||
if (!injector.removeInjection()) {
|
if (!injector.removeInjection()) {
|
||||||
@@ -139,9 +143,6 @@ public class FloodgatePlatform {
|
|||||||
logger.error("Failed to remove the injection!", exception);
|
logger.error("Failed to remove the injection!", exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guice.getInstance(NewsChecker.class).shutdown();
|
|
||||||
api.getPlayerLink().stop();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,24 +25,14 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.api;
|
package org.geysermc.floodgate.api;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
|
||||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
|
|
||||||
public final class ProxyFloodgateApi extends SimpleFloodgateApi {
|
public final class ProxyFloodgateApi extends SimpleFloodgateApi {
|
||||||
private final FloodgateCipher cipher;
|
@Inject
|
||||||
|
private FloodgateCipher cipher;
|
||||||
public ProxyFloodgateApi(
|
|
||||||
PluginMessageManager pluginMessageManager,
|
|
||||||
FloodgateConfigHolder configHolder,
|
|
||||||
FloodgateLogger logger,
|
|
||||||
FloodgateCipher cipher) {
|
|
||||||
super(pluginMessageManager, configHolder, logger);
|
|
||||||
this.cipher = cipher;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] createEncryptedData(BedrockData bedrockData) {
|
public byte[] createEncryptedData(BedrockData bedrockData) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ import com.google.common.cache.CacheBuilder;
|
|||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.geysermc.cumulus.form.Form;
|
import org.geysermc.cumulus.form.Form;
|
||||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
@@ -47,10 +47,9 @@ import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
|||||||
import org.geysermc.floodgate.pluginmessage.channel.FormChannel;
|
import org.geysermc.floodgate.pluginmessage.channel.FormChannel;
|
||||||
import org.geysermc.floodgate.pluginmessage.channel.TransferChannel;
|
import org.geysermc.floodgate.pluginmessage.channel.TransferChannel;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpClient;
|
||||||
import org.geysermc.floodgate.util.Utils;
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class SimpleFloodgateApi implements FloodgateApi {
|
public class SimpleFloodgateApi implements FloodgateApi {
|
||||||
private final Map<UUID, FloodgatePlayer> players = new HashMap<>();
|
private final Map<UUID, FloodgatePlayer> players = new HashMap<>();
|
||||||
private final Cache<UUID, FloodgatePlayer> pendingRemove =
|
private final Cache<UUID, FloodgatePlayer> pendingRemove =
|
||||||
@@ -58,9 +57,10 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
|||||||
.expireAfterWrite(20, TimeUnit.SECONDS)
|
.expireAfterWrite(20, TimeUnit.SECONDS)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final PluginMessageManager pluginMessageManager;
|
@Inject private PluginMessageManager pluginMessageManager;
|
||||||
private final FloodgateConfigHolder configHolder;
|
@Inject private FloodgateConfigHolder configHolder;
|
||||||
private final FloodgateLogger logger;
|
@Inject private HttpClient httpClient;
|
||||||
|
@Inject private FloodgateLogger logger;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPlayerPrefix() {
|
public String getPlayerPrefix() {
|
||||||
@@ -148,7 +148,7 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
|||||||
return Utils.failedFuture(new IllegalStateException("Received an invalid gamertag"));
|
return Utils.failedFuture(new IllegalStateException("Received an invalid gamertag"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return HttpUtils.asyncGet(Constants.GET_XUID_URL + gamertag)
|
return httpClient.asyncGet(Constants.GET_XUID_URL + gamertag)
|
||||||
.thenApply(result -> {
|
.thenApply(result -> {
|
||||||
JsonObject response = result.getResponse();
|
JsonObject response = result.getResponse();
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<String> getGamertagFor(long xuid) {
|
public CompletableFuture<String> getGamertagFor(long xuid) {
|
||||||
return HttpUtils.asyncGet(Constants.GET_GAMERTAG_URL + xuid)
|
return httpClient.asyncGet(Constants.GET_GAMERTAG_URL + xuid)
|
||||||
.thenApply(result -> {
|
.thenApply(result -> {
|
||||||
JsonObject response = result.getResponse();
|
JsonObject response = result.getResponse();
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,11 @@ import org.geysermc.floodgate.player.UserAudience;
|
|||||||
import org.geysermc.floodgate.player.audience.ProfileAudience;
|
import org.geysermc.floodgate.player.audience.ProfileAudience;
|
||||||
import org.geysermc.floodgate.player.audience.ProfileAudienceArgument;
|
import org.geysermc.floodgate.player.audience.ProfileAudienceArgument;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpClient;
|
||||||
|
|
||||||
public class WhitelistCommand implements FloodgateCommand {
|
public class WhitelistCommand implements FloodgateCommand {
|
||||||
@Inject private FloodgateConfig config;
|
@Inject private FloodgateConfig config;
|
||||||
|
@Inject private HttpClient httpClient;
|
||||||
@Inject private FloodgateLogger logger;
|
@Inject private FloodgateLogger logger;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -128,7 +129,7 @@ public class WhitelistCommand implements FloodgateCommand {
|
|||||||
final String strippedName = name;
|
final String strippedName = name;
|
||||||
|
|
||||||
// We need to get the UUID of the player if it's not manually specified
|
// We need to get the UUID of the player if it's not manually specified
|
||||||
HttpUtils.asyncGet(Constants.GET_XUID_URL + name)
|
httpClient.asyncGet(Constants.GET_XUID_URL + name)
|
||||||
.whenComplete((result, error) -> {
|
.whenComplete((result, error) -> {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
sender.sendMessage(Message.API_UNAVAILABLE);
|
sender.sendMessage(Message.API_UNAVAILABLE);
|
||||||
|
|||||||
@@ -29,20 +29,40 @@ import static org.geysermc.floodgate.util.Constants.COLOR_CHAR;
|
|||||||
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
|
import org.geysermc.floodgate.command.util.Permission;
|
||||||
|
import org.geysermc.floodgate.platform.command.FloodgateSubCommand;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpClient;
|
||||||
import org.geysermc.floodgate.util.HttpUtils.HttpResponse;
|
import org.geysermc.floodgate.util.HttpClient.HttpResponse;
|
||||||
import org.geysermc.floodgate.util.Utils;
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
final class FirewallCheckSubcommand {
|
final class FirewallCheckSubcommand extends FloodgateSubCommand {
|
||||||
private FirewallCheckSubcommand() {}
|
@Inject
|
||||||
|
private HttpClient httpClient;
|
||||||
|
|
||||||
static void executeFirewall(CommandContext<UserAudience> context) {
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "firewall";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Check if your outgoing firewall allows Floodgate to work properly";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Permission permission() {
|
||||||
|
return Permission.COMMAND_MAIN_FIREWALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext<UserAudience> context) {
|
||||||
UserAudience sender = context.getSender();
|
UserAudience sender = context.getSender();
|
||||||
executeChecks(
|
executeChecks(
|
||||||
globalApiCheck(sender)
|
globalApiCheck(sender)
|
||||||
@@ -54,12 +74,12 @@ final class FirewallCheckSubcommand {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BooleanSupplier globalApiCheck(UserAudience sender) {
|
private BooleanSupplier globalApiCheck(UserAudience sender) {
|
||||||
return executeFirewallText(
|
return executeFirewallText(
|
||||||
sender, "global api",
|
sender, "global api",
|
||||||
() -> {
|
() -> {
|
||||||
HttpResponse<JsonElement> response =
|
HttpResponse<JsonElement> response =
|
||||||
HttpUtils.get(Constants.HEALTH_URL, JsonElement.class);
|
httpClient.get(Constants.HEALTH_URL, JsonElement.class);
|
||||||
|
|
||||||
if (!response.isCodeOk()) {
|
if (!response.isCodeOk()) {
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
@@ -70,7 +90,7 @@ final class FirewallCheckSubcommand {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BooleanSupplier executeFirewallText(
|
private BooleanSupplier executeFirewallText(
|
||||||
UserAudience sender, String name, Runnable runnable) {
|
UserAudience sender, String name, Runnable runnable) {
|
||||||
return () -> {
|
return () -> {
|
||||||
sender.sendMessage(COLOR_CHAR + "eTesting " + name + "...");
|
sender.sendMessage(COLOR_CHAR + "eTesting " + name + "...");
|
||||||
@@ -86,9 +106,7 @@ final class FirewallCheckSubcommand {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompletableFuture<Pair<Integer, Integer>> executeChecks(
|
private CompletableFuture<Pair<Integer, Integer>> executeChecks(BooleanSupplier... checks) {
|
||||||
BooleanSupplier... checks) {
|
|
||||||
|
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
AtomicInteger okCount = new AtomicInteger();
|
AtomicInteger okCount = new AtomicInteger();
|
||||||
AtomicInteger failCount = new AtomicInteger();
|
AtomicInteger failCount = new AtomicInteger();
|
||||||
|
|||||||
@@ -32,14 +32,25 @@ import cloud.commandframework.Command;
|
|||||||
import cloud.commandframework.Command.Builder;
|
import cloud.commandframework.Command.Builder;
|
||||||
import cloud.commandframework.CommandManager;
|
import cloud.commandframework.CommandManager;
|
||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.geysermc.floodgate.command.util.Permission;
|
import org.geysermc.floodgate.command.util.Permission;
|
||||||
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
||||||
|
import org.geysermc.floodgate.platform.command.FloodgateSubCommand;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
|
|
||||||
public final class MainCommand implements FloodgateCommand {
|
public final class MainCommand implements FloodgateCommand {
|
||||||
|
private final List<FloodgateSubCommand> subCommands = new ArrayList<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public void createSubCommands(FirewallCheckSubcommand firewallCheckSubcommand) {
|
||||||
|
//todo move subcommand logic to a separate class
|
||||||
|
subCommands.clear();
|
||||||
|
subCommands.add(firewallCheckSubcommand);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
Builder<UserAudience> builder = commandManager.commandBuilder(
|
Builder<UserAudience> builder = commandManager.commandBuilder(
|
||||||
@@ -49,11 +60,11 @@ public final class MainCommand implements FloodgateCommand {
|
|||||||
.permission(Permission.COMMAND_MAIN.get())
|
.permission(Permission.COMMAND_MAIN.get())
|
||||||
.handler(this::execute);
|
.handler(this::execute);
|
||||||
|
|
||||||
for (SubCommand subCommand : SubCommand.VALUES) {
|
for (FloodgateSubCommand subCommand : subCommands) {
|
||||||
commandManager.command(builder
|
commandManager.command(builder
|
||||||
.literal(subCommand.name().toLowerCase(Locale.ROOT), subCommand.description)
|
.literal(subCommand.name().toLowerCase(Locale.ROOT), subCommand.description())
|
||||||
.permission(subCommand.permission.get())
|
.permission(subCommand.permission().get())
|
||||||
.handler(subCommand.executor::accept)
|
.handler(subCommand::execute)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,27 +76,15 @@ public final class MainCommand implements FloodgateCommand {
|
|||||||
public void execute(CommandContext<UserAudience> context) {
|
public void execute(CommandContext<UserAudience> context) {
|
||||||
StringBuilder helpMessage = new StringBuilder("Available subcommands are:\n");
|
StringBuilder helpMessage = new StringBuilder("Available subcommands are:\n");
|
||||||
|
|
||||||
for (SubCommand subCommand : SubCommand.VALUES) {
|
for (FloodgateSubCommand subCommand : subCommands) {
|
||||||
if (context.getSender().hasPermission(subCommand.permission.get())) {
|
if (context.getSender().hasPermission(subCommand.permission().get())) {
|
||||||
helpMessage.append('\n').append(COLOR_CHAR).append('b')
|
helpMessage.append('\n').append(COLOR_CHAR).append('b')
|
||||||
.append(subCommand.name().toLowerCase(Locale.ROOT))
|
.append(subCommand.name().toLowerCase(Locale.ROOT))
|
||||||
.append(COLOR_CHAR).append("f - ").append(COLOR_CHAR).append('7')
|
.append(COLOR_CHAR).append("f - ").append(COLOR_CHAR).append('7')
|
||||||
.append(subCommand.description);
|
.append(subCommand.description());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getSender().sendMessage(helpMessage.toString());
|
context.getSender().sendMessage(helpMessage.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
enum SubCommand {
|
|
||||||
FIREWALL("Check if your outgoing firewall allows Floodgate to work properly",
|
|
||||||
Permission.COMMAND_MAIN_FIREWALL, FirewallCheckSubcommand::executeFirewall);
|
|
||||||
|
|
||||||
static final SubCommand[] VALUES = values();
|
|
||||||
|
|
||||||
final String description;
|
|
||||||
final Permission permission;
|
|
||||||
final Consumer<CommandContext<UserAudience>> executor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.floodgate.event;
|
||||||
|
|
||||||
|
public class ShutdownEvent {
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.floodgate.event.util;
|
||||||
|
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.matcher.AbstractMatcher;
|
||||||
|
import net.engio.mbassy.listener.Listener;
|
||||||
|
|
||||||
|
public class ListenerAnnotationMatcher extends AbstractMatcher<TypeLiteral<?>> {
|
||||||
|
@Override
|
||||||
|
public boolean matches(TypeLiteral<?> typeLiteral) {
|
||||||
|
Class<?> rawType = typeLiteral.getRawType();
|
||||||
|
return rawType.isAnnotationPresent(Listener.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,8 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.engio.mbassy.listener.Handler;
|
||||||
|
import net.engio.mbassy.listener.Listener;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.link.LinkRequest;
|
import org.geysermc.floodgate.api.link.LinkRequest;
|
||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
@@ -41,8 +43,10 @@ import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
|||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.database.config.DatabaseConfig;
|
import org.geysermc.floodgate.database.config.DatabaseConfig;
|
||||||
import org.geysermc.floodgate.database.config.DatabaseConfigLoader;
|
import org.geysermc.floodgate.database.config.DatabaseConfigLoader;
|
||||||
|
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||||
import org.geysermc.floodgate.util.InjectorHolder;
|
import org.geysermc.floodgate.util.InjectorHolder;
|
||||||
|
|
||||||
|
@Listener
|
||||||
public abstract class CommonPlayerLink implements PlayerLink {
|
public abstract class CommonPlayerLink implements PlayerLink {
|
||||||
@Getter(AccessLevel.PROTECTED)
|
@Getter(AccessLevel.PROTECTED)
|
||||||
private final ExecutorService executorService = Executors.newFixedThreadPool(11);
|
private final ExecutorService executorService = Executors.newFixedThreadPool(11);
|
||||||
@@ -102,4 +106,9 @@ public abstract class CommonPlayerLink implements PlayerLink {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Handler
|
||||||
|
public void onShutdown(ShutdownEvent ignored) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,19 +29,23 @@ import static org.geysermc.floodgate.util.Constants.GET_BEDROCK_LINK;
|
|||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpClient;
|
||||||
import org.geysermc.floodgate.util.HttpUtils.DefaultHttpResponse;
|
import org.geysermc.floodgate.util.HttpClient.DefaultHttpResponse;
|
||||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||||
import org.geysermc.floodgate.util.Utils;
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class GlobalPlayerLinking extends CommonPlayerLink {
|
public class GlobalPlayerLinking extends CommonPlayerLink {
|
||||||
|
@Inject
|
||||||
|
private HttpClient httpClient;
|
||||||
|
|
||||||
private PlayerLink databaseImpl;
|
private PlayerLink databaseImpl;
|
||||||
|
|
||||||
public void setDatabaseImpl(PlayerLink databaseImpl) {
|
public void setDatabaseImpl(PlayerLink databaseImpl) {
|
||||||
@@ -94,7 +98,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
|||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.supplyAsync(
|
||||||
() -> {
|
() -> {
|
||||||
DefaultHttpResponse response =
|
DefaultHttpResponse response =
|
||||||
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
httpClient.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
||||||
|
|
||||||
// either the global api is down or it failed to return link
|
// either the global api is down or it failed to return link
|
||||||
if (!response.isCodeOk()) {
|
if (!response.isCodeOk()) {
|
||||||
@@ -144,7 +148,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
|||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.supplyAsync(
|
||||||
() -> {
|
() -> {
|
||||||
DefaultHttpResponse response =
|
DefaultHttpResponse response =
|
||||||
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
httpClient.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
||||||
|
|
||||||
if (!response.isCodeOk()) {
|
if (!response.isCodeOk()) {
|
||||||
getLogger().error(
|
getLogger().error(
|
||||||
|
|||||||
@@ -28,10 +28,17 @@ package org.geysermc.floodgate.module;
|
|||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
import com.google.inject.spi.InjectionListener;
|
||||||
|
import com.google.inject.spi.TypeEncounter;
|
||||||
|
import com.google.inject.spi.TypeListener;
|
||||||
import io.netty.util.AttributeKey;
|
import io.netty.util.AttributeKey;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.engio.mbassy.bus.MBassador;
|
||||||
|
import net.engio.mbassy.bus.common.PubSubSupport;
|
||||||
|
import net.engio.mbassy.bus.error.IPublicationErrorHandler.ConsoleLogger;
|
||||||
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||||
@@ -48,29 +55,46 @@ import org.geysermc.floodgate.crypto.AesKeyProducer;
|
|||||||
import org.geysermc.floodgate.crypto.Base64Topping;
|
import org.geysermc.floodgate.crypto.Base64Topping;
|
||||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||||
import org.geysermc.floodgate.crypto.KeyProducer;
|
import org.geysermc.floodgate.crypto.KeyProducer;
|
||||||
|
import org.geysermc.floodgate.event.util.ListenerAnnotationMatcher;
|
||||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||||
import org.geysermc.floodgate.news.NewsChecker;
|
import org.geysermc.floodgate.news.NewsChecker;
|
||||||
import org.geysermc.floodgate.packet.PacketHandlersImpl;
|
import org.geysermc.floodgate.packet.PacketHandlersImpl;
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
|
||||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
||||||
import org.geysermc.floodgate.skin.SkinApplier;
|
import org.geysermc.floodgate.skin.SkinApplier;
|
||||||
import org.geysermc.floodgate.skin.SkinUploadManager;
|
import org.geysermc.floodgate.skin.SkinUploadManager;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
|
import org.geysermc.floodgate.util.HttpClient;
|
||||||
import org.geysermc.floodgate.util.LanguageManager;
|
import org.geysermc.floodgate.util.LanguageManager;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CommonModule extends AbstractModule {
|
public class CommonModule extends AbstractModule {
|
||||||
|
private final PubSubSupport<Object> eventBus = new MBassador<>(new ConsoleLogger(true));
|
||||||
private final Path dataDirectory;
|
private final Path dataDirectory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
bind(PubSubSupport.class).toInstance(eventBus);
|
||||||
|
// register every class that has the Listener annotation
|
||||||
|
bindListener(new ListenerAnnotationMatcher(), new TypeListener() {
|
||||||
|
@Override
|
||||||
|
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
|
||||||
|
encounter.register((InjectionListener<I>) eventBus::subscribe);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bind(HttpClient.class).in(Singleton.class);
|
||||||
|
|
||||||
bind(FloodgateApi.class).to(SimpleFloodgateApi.class);
|
bind(FloodgateApi.class).to(SimpleFloodgateApi.class);
|
||||||
bind(PlatformInjector.class).to(CommonPlatformInjector.class);
|
bind(PlatformInjector.class).to(CommonPlatformInjector.class);
|
||||||
|
|
||||||
bind(HandshakeHandlers.class).to(HandshakeHandlersImpl.class);
|
bind(HandshakeHandlers.class).to(HandshakeHandlersImpl.class);
|
||||||
|
bind(HandshakeHandlersImpl.class).in(Singleton.class);
|
||||||
|
|
||||||
bind(PacketHandlers.class).to(PacketHandlersImpl.class);
|
bind(PacketHandlers.class).to(PacketHandlersImpl.class);
|
||||||
bind(PacketHandlersImpl.class).asEagerSingleton();
|
bind(PacketHandlersImpl.class).asEagerSingleton();
|
||||||
|
|
||||||
|
bind(NewsChecker.class).in(Singleton.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@@ -116,12 +140,6 @@ public class CommonModule extends AbstractModule {
|
|||||||
return new LanguageManager(configHolder, logger);
|
return new LanguageManager(configHolder, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
public HandshakeHandlersImpl handshakeHandlers() {
|
|
||||||
return new HandshakeHandlersImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public FloodgateHandshakeHandler handshakeHandler(
|
public FloodgateHandshakeHandler handshakeHandler(
|
||||||
@@ -154,8 +172,16 @@ public class CommonModule extends AbstractModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public NewsChecker newsChecker(CommandUtil commandUtil, FloodgateLogger logger) {
|
@Named("gitBranch")
|
||||||
return new NewsChecker(commandUtil, logger, Constants.GIT_BRANCH, Constants.BUILD_NUMBER);
|
public String gitBranch() {
|
||||||
|
return Constants.GIT_BRANCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Named("buildNumber")
|
||||||
|
public int buildNumber() {
|
||||||
|
return Constants.BUILD_NUMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -31,12 +31,8 @@ import com.google.inject.name.Named;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
|
||||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
|
||||||
|
|
||||||
public final class ProxyCommonModule extends CommonModule {
|
public final class ProxyCommonModule extends CommonModule {
|
||||||
public ProxyCommonModule(Path dataDirectory) {
|
public ProxyCommonModule(Path dataDirectory) {
|
||||||
@@ -46,7 +42,9 @@ public final class ProxyCommonModule extends CommonModule {
|
|||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
||||||
|
|
||||||
bind(SimpleFloodgateApi.class).to(ProxyFloodgateApi.class);
|
bind(SimpleFloodgateApi.class).to(ProxyFloodgateApi.class);
|
||||||
|
bind(ProxyFloodgateApi.class).in(Singleton.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@@ -55,14 +53,4 @@ public final class ProxyCommonModule extends CommonModule {
|
|||||||
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
||||||
return ProxyFloodgateConfig.class;
|
return ProxyFloodgateConfig.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
public ProxyFloodgateApi proxyFloodgateApi(
|
|
||||||
PluginMessageManager pluginMessageManager,
|
|
||||||
FloodgateConfigHolder configHolder,
|
|
||||||
FloodgateLogger logger,
|
|
||||||
FloodgateCipher cipher) {
|
|
||||||
return new ProxyFloodgateApi(pluginMessageManager, configHolder, logger, cipher);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,29 +30,22 @@ import com.google.inject.Singleton;
|
|||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
|
||||||
|
|
||||||
public final class ServerCommonModule extends CommonModule {
|
public final class ServerCommonModule extends CommonModule {
|
||||||
public ServerCommonModule(Path dataDirectory) {
|
public ServerCommonModule(Path dataDirectory) {
|
||||||
super(dataDirectory);
|
super(dataDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(SimpleFloodgateApi.class).in(Singleton.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("configClass")
|
@Named("configClass")
|
||||||
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
||||||
return FloodgateConfig.class;
|
return FloodgateConfig.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
public SimpleFloodgateApi floodgateApi(
|
|
||||||
PluginMessageManager pluginMessageManager,
|
|
||||||
FloodgateConfigHolder configHolder,
|
|
||||||
FloodgateLogger logger) {
|
|
||||||
return new SimpleFloodgateApi(pluginMessageManager, configHolder, logger);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ package org.geysermc.floodgate.news;
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.name.Named;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -35,34 +37,40 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import net.engio.mbassy.listener.Handler;
|
||||||
|
import net.engio.mbassy.listener.Listener;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
|
import org.geysermc.floodgate.command.util.Permission;
|
||||||
|
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||||
import org.geysermc.floodgate.news.data.AnnouncementData;
|
import org.geysermc.floodgate.news.data.AnnouncementData;
|
||||||
import org.geysermc.floodgate.news.data.BuildSpecificData;
|
import org.geysermc.floodgate.news.data.BuildSpecificData;
|
||||||
import org.geysermc.floodgate.news.data.CheckAfterData;
|
import org.geysermc.floodgate.news.data.CheckAfterData;
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpClient;
|
||||||
import org.geysermc.floodgate.util.HttpUtils.HttpResponse;
|
import org.geysermc.floodgate.util.HttpClient.HttpResponse;
|
||||||
import org.geysermc.floodgate.command.util.Permission;
|
|
||||||
|
|
||||||
|
@Listener
|
||||||
public class NewsChecker {
|
public class NewsChecker {
|
||||||
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
|
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
|
||||||
private final CommandUtil commandUtil;
|
|
||||||
private final FloodgateLogger logger;
|
|
||||||
|
|
||||||
private final Map<Integer, NewsItem> activeNewsItems = new HashMap<>();
|
private final Map<Integer, NewsItem> activeNewsItems = new HashMap<>();
|
||||||
private final String branch;
|
|
||||||
private final int build;
|
@Inject
|
||||||
|
private CommandUtil commandUtil;
|
||||||
|
@Inject
|
||||||
|
private HttpClient httpClient;
|
||||||
|
@Inject
|
||||||
|
private FloodgateLogger logger;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Named("gitBranch")
|
||||||
|
private String branch;
|
||||||
|
@Inject
|
||||||
|
@Named("buildNumber")
|
||||||
|
private int build;
|
||||||
|
|
||||||
private boolean firstCheck;
|
private boolean firstCheck;
|
||||||
|
|
||||||
public NewsChecker(CommandUtil commandUtil, FloodgateLogger logger, String branch, int build) {
|
|
||||||
this.commandUtil = commandUtil;
|
|
||||||
this.logger = logger;
|
|
||||||
this.branch = branch;
|
|
||||||
this.build = build;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
executorService.scheduleWithFixedDelay(this::checkNews, 0, 30, TimeUnit.MINUTES);
|
executorService.scheduleWithFixedDelay(this::checkNews, 0, 30, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
@@ -72,10 +80,10 @@ public class NewsChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkNews() {
|
private void checkNews() {
|
||||||
HttpResponse<JsonArray> response =
|
HttpResponse<JsonArray> response = httpClient.getSilent(
|
||||||
HttpUtils.getSilent(
|
Constants.NEWS_OVERVIEW_URL + Constants.NEWS_PROJECT_NAME,
|
||||||
Constants.NEWS_OVERVIEW_URL + Constants.NEWS_PROJECT_NAME,
|
JsonArray.class
|
||||||
JsonArray.class);
|
);
|
||||||
|
|
||||||
JsonArray array = response.getResponse();
|
JsonArray array = response.getResponse();
|
||||||
|
|
||||||
@@ -197,4 +205,9 @@ public class NewsChecker {
|
|||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Handler
|
||||||
|
public void onShutdown(ShutdownEvent ignored) {
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.floodgate.platform.command;
|
||||||
|
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import org.geysermc.floodgate.command.util.Permission;
|
||||||
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
|
|
||||||
|
public abstract class FloodgateSubCommand {
|
||||||
|
public abstract String name();
|
||||||
|
|
||||||
|
public abstract String description();
|
||||||
|
|
||||||
|
public abstract Permission permission();
|
||||||
|
|
||||||
|
public abstract void execute(CommandContext<UserAudience> context);
|
||||||
|
}
|
||||||
@@ -37,34 +37,38 @@ import java.util.concurrent.Executors;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.engio.mbassy.listener.Handler;
|
||||||
|
import net.engio.mbassy.listener.Listener;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||||
|
|
||||||
// resources are properly closed and ignoring the original stack trace is intended
|
// resources are properly closed and ignoring the original stack trace is intended
|
||||||
@SuppressWarnings({"PMD.CloseResource", "PMD.PreserveStackTrace"})
|
@SuppressWarnings({"PMD.CloseResource", "PMD.PreserveStackTrace"})
|
||||||
public class HttpUtils {
|
@Listener
|
||||||
private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
|
public class HttpClient {
|
||||||
|
|
||||||
private static final Gson GSON = new Gson();
|
|
||||||
private static final String USER_AGENT = "GeyserMC/Floodgate";
|
private static final String USER_AGENT = "GeyserMC/Floodgate";
|
||||||
|
|
||||||
public static CompletableFuture<DefaultHttpResponse> asyncGet(String urlString) {
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||||
return CompletableFuture.supplyAsync(() -> get(urlString), EXECUTOR_SERVICE);
|
private final Gson gson = new Gson();
|
||||||
|
|
||||||
|
public CompletableFuture<DefaultHttpResponse> asyncGet(String urlString) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> get(urlString), executorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DefaultHttpResponse get(String urlString) {
|
public DefaultHttpResponse get(String urlString) {
|
||||||
return readDefaultResponse(request(urlString));
|
return readDefaultResponse(request(urlString));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> HttpResponse<T> get(String urlString, Class<T> clazz) {
|
public <T> HttpResponse<T> get(String urlString, Class<T> clazz) {
|
||||||
return readResponse(request(urlString), clazz);
|
return readResponse(request(urlString), clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> HttpResponse<T> getSilent(String urlString, Class<T> clazz) {
|
public <T> HttpResponse<T> getSilent(String urlString, Class<T> clazz) {
|
||||||
return readResponseSilent(request(urlString), clazz);
|
return readResponseSilent(request(urlString), clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpURLConnection request(String urlString) {
|
private HttpURLConnection request(String urlString) {
|
||||||
HttpURLConnection connection;
|
HttpURLConnection connection;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -88,7 +92,7 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static <T> HttpResponse<T> readResponse(HttpURLConnection connection, Class<T> clazz) {
|
private <T> HttpResponse<T> readResponse(HttpURLConnection connection, Class<T> clazz) {
|
||||||
InputStreamReader streamReader = createReader(connection);
|
InputStreamReader streamReader = createReader(connection);
|
||||||
if (streamReader == null) {
|
if (streamReader == null) {
|
||||||
return new HttpResponse<>(-1, null);
|
return new HttpResponse<>(-1, null);
|
||||||
@@ -96,7 +100,7 @@ public class HttpUtils {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int responseCode = connection.getResponseCode();
|
int responseCode = connection.getResponseCode();
|
||||||
T response = GSON.fromJson(streamReader, clazz);
|
T response = gson.fromJson(streamReader, clazz);
|
||||||
return new HttpResponse<>(responseCode, response);
|
return new HttpResponse<>(responseCode, response);
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
return new HttpResponse<>(-1, null);
|
return new HttpResponse<>(-1, null);
|
||||||
@@ -109,9 +113,7 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static <T> HttpResponse<T> readResponseSilent(
|
private <T> HttpResponse<T> readResponseSilent(HttpURLConnection connection, Class<T> clazz) {
|
||||||
HttpURLConnection connection,
|
|
||||||
Class<T> clazz) {
|
|
||||||
try {
|
try {
|
||||||
return readResponse(connection, clazz);
|
return readResponse(connection, clazz);
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
@@ -120,7 +122,7 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static DefaultHttpResponse readDefaultResponse(HttpURLConnection connection) {
|
private DefaultHttpResponse readDefaultResponse(HttpURLConnection connection) {
|
||||||
InputStreamReader streamReader = createReader(connection);
|
InputStreamReader streamReader = createReader(connection);
|
||||||
if (streamReader == null) {
|
if (streamReader == null) {
|
||||||
return new DefaultHttpResponse(-1, null);
|
return new DefaultHttpResponse(-1, null);
|
||||||
@@ -128,7 +130,7 @@ public class HttpUtils {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int responseCode = connection.getResponseCode();
|
int responseCode = connection.getResponseCode();
|
||||||
JsonObject response = GSON.fromJson(streamReader, JsonObject.class);
|
JsonObject response = gson.fromJson(streamReader, JsonObject.class);
|
||||||
return new DefaultHttpResponse(responseCode, response);
|
return new DefaultHttpResponse(responseCode, response);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
throw new RuntimeException("Failed to read response", exception);
|
throw new RuntimeException("Failed to read response", exception);
|
||||||
@@ -141,7 +143,7 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static InputStreamReader createReader(HttpURLConnection connection) {
|
private InputStreamReader createReader(HttpURLConnection connection) {
|
||||||
InputStream stream;
|
InputStream stream;
|
||||||
try {
|
try {
|
||||||
stream = connection.getInputStream();
|
stream = connection.getInputStream();
|
||||||
@@ -160,6 +162,11 @@ public class HttpUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Handler
|
||||||
|
public void onShutdown(ShutdownEvent ignored) {
|
||||||
|
executorService.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public static class HttpResponse<T> {
|
public static class HttpResponse<T> {
|
||||||
@@ -29,6 +29,7 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
@@ -69,4 +70,9 @@ public final class VelocityPlugin {
|
|||||||
new PluginMessageModule()
|
new PluginMessageModule()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onProxyShutdown(ProxyShutdownEvent event) {
|
||||||
|
platform.disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user