From aa46ee6dbc2b0e3f2ec0887d8f108dfce78ef0f2 Mon Sep 17 00:00:00 2001 From: Austin Mayes Date: Sat, 19 Jan 2019 21:34:37 -0600 Subject: [PATCH] Implement server requests (#8) * Implement server request API * Add local server request * Finish up server requests --- .../tc/oc/api/message/MessagesManifest.java | 5 +++ .../api/message/types/UseServerRequest.java | 13 ++++++ .../api/message/types/UseServerResponse.java | 28 ++++++++++++ .../tc/oc/api/servers/NullServerService.java | 6 +++ .../java/tc/oc/api/servers/ServerService.java | 4 ++ .../minecraft/servers/LocalServerService.java | 11 +++-- .../java/tc/oc/api/ocn/OCNServerService.java | 12 ++++- .../bungee/commands/ServerCommands.java | 45 ++++++++++++++++++- .../rotation/AbstractRotationProvider.java | 2 +- 9 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 API/api/src/main/java/tc/oc/api/message/types/UseServerRequest.java create mode 100644 API/api/src/main/java/tc/oc/api/message/types/UseServerResponse.java diff --git a/API/api/src/main/java/tc/oc/api/message/MessagesManifest.java b/API/api/src/main/java/tc/oc/api/message/MessagesManifest.java index ce1b6d8..4a59f6b 100644 --- a/API/api/src/main/java/tc/oc/api/message/MessagesManifest.java +++ b/API/api/src/main/java/tc/oc/api/message/MessagesManifest.java @@ -13,6 +13,8 @@ import tc.oc.api.message.types.PlayGameRequest; import tc.oc.api.message.types.PlayerTeleportRequest; import tc.oc.api.message.types.Reply; import tc.oc.api.message.types.UpdateMultiResponse; +import tc.oc.api.message.types.UseServerRequest; +import tc.oc.api.message.types.UseServerResponse; import tc.oc.api.servers.ServerSearchRequest; import tc.oc.api.sessions.BadNickname; import tc.oc.api.sessions.SessionChange; @@ -47,5 +49,8 @@ public class MessagesManifest extends HybridManifest { messages.register(PlayGameRequest.class); messages.register(CycleRequest.class); messages.register(CycleResponse.class); + + messages.register(UseServerRequest.class); + messages.register(UseServerResponse.class); } } diff --git a/API/api/src/main/java/tc/oc/api/message/types/UseServerRequest.java b/API/api/src/main/java/tc/oc/api/message/types/UseServerRequest.java new file mode 100644 index 0000000..162ec2c --- /dev/null +++ b/API/api/src/main/java/tc/oc/api/message/types/UseServerRequest.java @@ -0,0 +1,13 @@ +package tc.oc.api.message.types; + +import javax.annotation.Nonnull; +import tc.oc.api.annotations.Serialize; +import tc.oc.api.message.Message; +import tc.oc.api.queue.MessageDefaults; + +@Serialize +@MessageDefaults.RoutingKey("use_server") +@MessageDefaults.ExpirationMillis(10000) +public interface UseServerRequest extends Message { + @Nonnull String user_id(); +} diff --git a/API/api/src/main/java/tc/oc/api/message/types/UseServerResponse.java b/API/api/src/main/java/tc/oc/api/message/types/UseServerResponse.java new file mode 100644 index 0000000..52f4b89 --- /dev/null +++ b/API/api/src/main/java/tc/oc/api/message/types/UseServerResponse.java @@ -0,0 +1,28 @@ +package tc.oc.api.message.types; + +import javax.annotation.Nullable; +import tc.oc.api.annotations.Serialize; + +@Serialize +public interface UseServerResponse extends Reply { + String server_name(); + boolean now(); + + UseServerResponse EMPTY = new UseServerResponse() { + @Override public String server_name() { + return "default"; + } + + @Override public boolean success() { + return true; + } + + @Nullable @Override public String error() { + return null; + } + + @Override public boolean now() { + return false; + } + }; +} diff --git a/API/api/src/main/java/tc/oc/api/servers/NullServerService.java b/API/api/src/main/java/tc/oc/api/servers/NullServerService.java index fa6e11a..b60a867 100644 --- a/API/api/src/main/java/tc/oc/api/servers/NullServerService.java +++ b/API/api/src/main/java/tc/oc/api/servers/NullServerService.java @@ -4,6 +4,8 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import tc.oc.api.docs.Server; import tc.oc.api.docs.virtual.ServerDoc; +import tc.oc.api.message.types.UseServerRequest; +import tc.oc.api.message.types.UseServerResponse; import tc.oc.api.model.NullModelService; public class NullServerService extends NullModelService implements ServerService { @@ -12,4 +14,8 @@ public class NullServerService extends NullModelService doBungeeMetric(BungeeMetricRequest request) { return Futures.immediateFuture(null); } + + @Override public ListenableFuture requestServer(UseServerRequest request) { + return Futures.immediateFuture(UseServerResponse.EMPTY); + } } diff --git a/API/api/src/main/java/tc/oc/api/servers/ServerService.java b/API/api/src/main/java/tc/oc/api/servers/ServerService.java index d844c89..03fa73c 100644 --- a/API/api/src/main/java/tc/oc/api/servers/ServerService.java +++ b/API/api/src/main/java/tc/oc/api/servers/ServerService.java @@ -3,9 +3,13 @@ package tc.oc.api.servers; import com.google.common.util.concurrent.ListenableFuture; import tc.oc.api.docs.Server; import tc.oc.api.docs.virtual.ServerDoc; +import tc.oc.api.message.types.UseServerRequest; +import tc.oc.api.message.types.UseServerResponse; import tc.oc.api.model.ModelService; public interface ServerService extends ModelService { ListenableFuture doBungeeMetric(BungeeMetricRequest request); + + ListenableFuture requestServer(UseServerRequest request); } diff --git a/API/minecraft/src/main/java/tc/oc/api/minecraft/servers/LocalServerService.java b/API/minecraft/src/main/java/tc/oc/api/minecraft/servers/LocalServerService.java index 6551ffe..b3ee0eb 100644 --- a/API/minecraft/src/main/java/tc/oc/api/minecraft/servers/LocalServerService.java +++ b/API/minecraft/src/main/java/tc/oc/api/minecraft/servers/LocalServerService.java @@ -9,12 +9,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import tc.oc.api.docs.Server; import tc.oc.api.docs.virtual.ServerDoc; -import tc.oc.api.message.types.FindMultiRequest; -import tc.oc.api.message.types.FindMultiResponse; -import tc.oc.api.message.types.FindRequest; -import tc.oc.api.message.types.PartialModelUpdate; -import tc.oc.api.message.types.UpdateMultiRequest; -import tc.oc.api.message.types.UpdateMultiResponse; +import tc.oc.api.message.types.*; import tc.oc.api.model.NullModelService; import tc.oc.api.servers.BungeeMetricRequest; import tc.oc.api.servers.ServerService; @@ -54,4 +49,8 @@ public class LocalServerService extends NullModelService requestServer(UseServerRequest request) { + return Futures.immediateFuture(UseServerResponse.EMPTY); + } } diff --git a/API/ocn/src/main/java/tc/oc/api/ocn/OCNServerService.java b/API/ocn/src/main/java/tc/oc/api/ocn/OCNServerService.java index 12e1a4b..598468c 100644 --- a/API/ocn/src/main/java/tc/oc/api/ocn/OCNServerService.java +++ b/API/ocn/src/main/java/tc/oc/api/ocn/OCNServerService.java @@ -10,8 +10,12 @@ import tc.oc.api.docs.virtual.ServerDoc; import tc.oc.api.http.HttpOption; import tc.oc.api.message.types.FindMultiResponse; import tc.oc.api.message.types.FindRequest; +import tc.oc.api.message.types.UseServerRequest; +import tc.oc.api.message.types.UseServerResponse; import tc.oc.api.model.HttpModelService; import tc.oc.api.queue.QueueQueryService; +import tc.oc.api.queue.Transaction; +import tc.oc.api.queue.Transaction.Factory; import tc.oc.api.servers.BungeeMetricRequest; import tc.oc.api.servers.ServerService; @@ -19,9 +23,11 @@ import tc.oc.api.servers.ServerService; class OCNServerService extends HttpModelService implements ServerService { private final QueueQueryService queryService; + private final Transaction.Factory transactionFactory; - @Inject OCNServerService(QueueQueryService queryService) { + @Inject public OCNServerService(QueueQueryService queryService, Factory transactionFactory) { this.queryService = queryService; + this.transactionFactory = transactionFactory; } @Override @@ -29,6 +35,10 @@ class OCNServerService extends HttpModelService imple return this.client().post("/servers/metric", request, HttpOption.INFINITE_RETRY); } + @Override public ListenableFuture requestServer(UseServerRequest request) { + return transactionFactory.request(request, UseServerResponse.class); + } + @Override public ListenableFuture> all() { return queryService.all(); diff --git a/Commons/bungee/src/main/java/tc/oc/commons/bungee/commands/ServerCommands.java b/Commons/bungee/src/main/java/tc/oc/commons/bungee/commands/ServerCommands.java index 377a445..7288cd5 100644 --- a/Commons/bungee/src/main/java/tc/oc/commons/bungee/commands/ServerCommands.java +++ b/Commons/bungee/src/main/java/tc/oc/commons/bungee/commands/ServerCommands.java @@ -1,6 +1,7 @@ package tc.oc.commons.bungee.commands; import java.util.concurrent.ExecutorService; +import javax.annotation.Nonnull; import javax.inject.Inject; import com.google.common.util.concurrent.Futures; @@ -16,12 +17,19 @@ import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.plugin.CommandBypassException; +import tc.oc.api.bungee.users.BungeeUserStore; import tc.oc.api.docs.Server; import tc.oc.api.docs.virtual.ServerDoc; +import tc.oc.api.message.types.UseServerRequest; +import tc.oc.api.message.types.UseServerResponse; +import tc.oc.api.minecraft.users.UserStore; import tc.oc.api.model.ModelSync; +import tc.oc.api.servers.ServerService; import tc.oc.commons.bungee.servers.ServerTracker; import tc.oc.commons.core.commands.Commands; +import tc.oc.commons.core.concurrent.Flexecutor; import tc.oc.commons.core.restart.RestartManager; +import tc.oc.minecraft.scheduler.Sync; public class ServerCommands implements Commands { @@ -29,12 +37,20 @@ public class ServerCommands implements Commands { private final ServerTracker serverTracker; private final ProxyServer proxy; private final ExecutorService executor; + private final ServerService serverService; + private final BungeeUserStore userStore; + private final Flexecutor commandExecutor; - @Inject ServerCommands(RestartManager restartManager, ServerTracker serverTracker, ProxyServer proxy, @ModelSync ExecutorService executor) { + @Inject ServerCommands(RestartManager restartManager, ServerTracker serverTracker, ProxyServer proxy, + @ModelSync ExecutorService executor, ServerService serverService, + BungeeUserStore userStore, @Sync Flexecutor commandExecutor) { this.restartManager = restartManager; this.serverTracker = serverTracker; this.proxy = proxy; this.executor = executor; + this.serverService = serverService; + this.userStore = userStore; + this.commandExecutor = commandExecutor; } @Command( @@ -57,6 +73,33 @@ public class ServerCommands implements Commands { } } + @Command( + aliases = {"requestserver", "re"}, + desc = "Request a server for yourself" + ) + @CommandPermissions("ocn.requestserver") + public void request(final CommandContext args, CommandSender sender) throws CommandException { + if(sender instanceof ProxiedPlayer) { + final ProxiedPlayer player = (ProxiedPlayer) sender; + commandExecutor.callback( + serverService.requestServer(new UseServerRequest() { + @Nonnull @Override public String user_id() { + return userStore.getUser(player)._id(); + } + }), (response) -> { + if (response.now()) { + player.connect(proxy.getServerInfo(response.server_name())); + player.sendMessage(new ComponentBuilder("Your server is already online! Connecting...").color(ChatColor.GREEN).create()); + } else { + player.sendMessage(new ComponentBuilder("Server requested! Please wait up to two minutes before trying to connect to /server " + + response.server_name()).color(ChatColor.GOLD).create()); + } + }); + } else { + sender.sendMessage(new ComponentBuilder("Only players may use this command").color(ChatColor.RED).create()); + } + } + @Command( aliases = {"gserver"}, desc = "Global server teleport", diff --git a/PGM/src/main/java/tc/oc/pgm/rotation/AbstractRotationProvider.java b/PGM/src/main/java/tc/oc/pgm/rotation/AbstractRotationProvider.java index dc23048..1a98855 100644 --- a/PGM/src/main/java/tc/oc/pgm/rotation/AbstractRotationProvider.java +++ b/PGM/src/main/java/tc/oc/pgm/rotation/AbstractRotationProvider.java @@ -27,7 +27,7 @@ public abstract class AbstractRotationProvider implements RotationProvider { Preconditions.checkNotNull(name, "rotation name"); synchronized(this) { RotationState state = this.rotations.get(name); - if (state != null) return state + if (state != null) return state; for (String key : this.rotations.keySet()) { if (key.equalsIgnoreCase(name)) {