diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 0c8cf8e..44f08f3 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,26 +5,47 @@ - + + + + + + + - - - + + + + + + + + + + - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + diff --git a/core-bukkit-api/build.gradle.kts b/core-bukkit-api/build.gradle.kts index a9219c5..1057536 100644 --- a/core-bukkit-api/build.gradle.kts +++ b/core-bukkit-api/build.gradle.kts @@ -24,9 +24,9 @@ dependencies { api("io.nats:jnats:2.25.2") // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-core - api("de.kentoj.scrow:kencommandapi-core:0.22") + api("de.kentoj.scrow:kencommandapi-core:0.23") // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-bukkit - api("de.kentoj.scrow:kencommandapi-bukkit:0.22") + api("de.kentoj.scrow:kencommandapi-bukkit:0.23") } publishing { diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java index 127756b..cca3405 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java @@ -6,7 +6,7 @@ import de.kentoj.scrow.bukkit.friends.FriendshipService; import de.kentoj.scrow.bukkit.misc.EconomyService; import de.kentoj.scrow.bukkit.misc.PlayerManager; import de.kentoj.scrow.bukkit.region.RegionManager; -import de.kentoj.scrowlib.servermanager.InstanceManager; +import de.kentoj.scrowlib.instancemanager.InstanceManager; import io.nats.client.Connection; import lombok.AccessLevel; import lombok.Getter; diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameInfo.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameInfo.java index 5cefd7c..170da7d 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameInfo.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameInfo.java @@ -1,6 +1,6 @@ package de.kentoj.scrow.bukkit.minigame; -import de.kentoj.scrowlib.servermanager.ServerInstance; +import de.kentoj.scrowlib.instancemanager.ServerInstance; public interface MinigameInfo { diff --git a/core-bukkit-impl/build.gradle.kts b/core-bukkit-impl/build.gradle.kts index c936191..ee8669b 100644 --- a/core-bukkit-impl/build.gradle.kts +++ b/core-bukkit-impl/build.gradle.kts @@ -5,7 +5,6 @@ plugins { id("de.kentoj.scrow.scrow-repository") id("de.kentoj.scrow.base-dependencies") id("de.kentoj.scrow.database") - id("de.kentoj.scrow.reactor") } group = "de.kentoj.scrow" @@ -22,7 +21,7 @@ dependencies { implementation(project(":core-bukkit-api")) // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-core - implementation("de.kentoj.scrow:kencommandapi-core:0.22") + implementation("de.kentoj.scrow:kencommandapi-core:0.23") } tasks { diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java index 5eaa390..4c465c1 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java @@ -1,9 +1,8 @@ package de.kentoj.scrow.bukkit; -import de.kentoj.scrow.bukkit.crown.CrownCommand; import de.kentoj.scrow.bukkit.economy.command.CoinsCommand; -import de.kentoj.scrow.bukkit.economy.command.CoinsSetLiteral; import de.kentoj.scrow.bukkit.friends.command.FriendCommand; +import de.kentoj.scrow.bukkit.instancemanager.command.InstanceCommand; import de.kentoj.scrow.bukkit.region.RegionPlayerTracker; import de.kentoj.scrow.bukkit.region.RegionTask; import de.kentoj.scrow.bukkit.server.LobbyCommand; @@ -27,8 +26,8 @@ public class CoreImplPlugin extends JavaPlugin { { ScrowAPI.getCommandApi().register(new CoinsCommand().getRootNode()); - ScrowAPI.getCommandApi().register(new FriendCommand().getRootNode()); - ScrowAPI.getCommandApi().register(new CrownCommand().getRootNode()); + ScrowAPI.getCommandApi().register(FriendCommand.create()); + ScrowAPI.getCommandApi().register(InstanceCommand.create()); ScrowAPI.getCommandApi().register(new PlayCommand().getRootNode()); ScrowAPI.getCommandApi().register(new LobbyCommand().getRootNode()); } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java index c2b1eea..bc94557 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java @@ -8,18 +8,14 @@ import de.kentoj.scrow.bukkit.friends.friendship.PostgresFriendshipService; import de.kentoj.scrow.bukkit.friends.request.InMemoryFriendRequestService; import de.kentoj.scrow.bukkit.friends.request.PostgresFriendRequestService; import de.kentoj.scrow.bukkit.region.RegionManagerImpl; -import de.kentoj.scrowlib.connection.DatabaseConnectionFactoryImpl; -import de.kentoj.scrowlib.servermanager.InstanceManagerImpl; +import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl; import de.kentoj.scrowlib.utils.EnvUtils; import io.nats.client.Nats; import io.nats.client.Options; -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; -import reactor.core.scheduler.Schedulers; +import org.jdbi.v3.core.Jdbi; import java.io.IOException; @@ -41,26 +37,20 @@ public class ScrowAPISurface { } if (enableDatabase) { - ConnectionFactory factory = ConnectionFactories.get(EnvUtils.envOrThrow("HOST_POSTGRES")); - ScrowAPI.setJdbi(new DatabaseConnectionFactoryImpl(factory)); + ScrowAPI.setJdbi(Jdbi.create(EnvUtils.envOrThrow("HOST_POSTGRES"))); } ScrowAPI.setRegionManager(new RegionManagerImpl()); ScrowAPI.setCommandApi(new CommandAPI(plugin)); ScrowAPI.setInstanceManager(new InstanceManagerImpl(ScrowAPI.getNats())); ScrowAPI.setEconomyService(ScrowAPI.getJdbi() != null ? - new PostgresEconomyService(ScrowAPI.getJdbi()) : new InMemoryEconomyService()); + new PostgresEconomyService() : new InMemoryEconomyService()); ScrowAPI.setFriendRequestService(ScrowAPI.getJdbi() != null ? - new PostgresFriendRequestService(ScrowAPI.getJdbi()) : new InMemoryFriendRequestService()); + new PostgresFriendRequestService() : new InMemoryFriendRequestService()); ScrowAPI.setFriendshipService(ScrowAPI.getJdbi() != null ? - new PostgresFriendshipService(ScrowAPI.getJdbi()) : new InMemoryFriendshipService()); + new PostgresFriendshipService() : new InMemoryFriendshipService()); } public static void destroyScrowAPI() { - try { - ScrowAPI.getJdbi().close(); - } catch (Exception e) { - throw new RuntimeException(e); - } } } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownCommand.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownCommand.java deleted file mode 100644 index f94001f..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.kentoj.scrow.bukkit.crown; - -import de.kentoj.kencommandapi.api.node.CommandNode; -import de.kentoj.scrowlib.convention.ScrowMessageStyle; -import lombok.Getter; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.command.CommandSender; - -public class CrownCommand { - - @Getter - private final CommandNode rootNode; - - public CrownCommand() { - this.rootNode = CommandNode.node("crown", "server-manager"); - var style = new ScrowMessageStyle(Component.text("crown") - .color(NamedTextColor.GOLD)); - this.rootNode.addLiteral(new CrownListServersLiteral(style).getNode()); - this.rootNode.addLiteral(new CrownDeployServerLiteral(style).getRootNode()); - this.rootNode.addLiteral(new CrownDestroyServerLiteral(style).getRootNode()); - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownDeployServerLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownDeployServerLiteral.java deleted file mode 100644 index 22f1054..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownDeployServerLiteral.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.kentoj.scrow.bukkit.crown; - -import de.kentoj.kencommandapi.api.node.CommandNode; -import de.kentoj.kencommandapi.api.argument.CommandArgument; -import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; -import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; -import com.leakyabstractions.result.api.Result; -import de.kentoj.scrow.bukkit.ScrowAPI; -import lombok.Getter; -import org.bukkit.command.CommandSender; - -import java.util.concurrent.CompletableFuture; - -public class CrownDeployServerLiteral implements CommandExecutor { - - @Getter - private final CommandNode rootNode; - private final CommandArgument templateArg; - - public CrownDeployServerLiteral() { - this.rootNode = CommandNode.node("deploy-server"); - this.rootNode.setExecutor(this); - { - this.templateArg = CommandArgument.arg("template", new StringArgumentType<>()); - this.rootNode.addArgument(templateArg); - } - } - - @Override - public CompletableFuture> execute(CommandContext ctx) { - var template = ctx.getArg(templateArg); - return ScrowAPI.getInstanceManager().deployInstance(template) - .map(server -> { - ctx.getSender().sendMessage("Deployed instance of " + template + " with handle " + server.getHandle()); - // FIXME handle unknown server - return Result.success(); - }).toFuture(); - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownDestroyServerLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownDestroyServerLiteral.java deleted file mode 100644 index 06fe639..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownDestroyServerLiteral.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.kentoj.scrow.bukkit.crown; - -import de.kentoj.kencommandapi.api.node.CommandNode; -import de.kentoj.kencommandapi.api.argument.CommandArgument; -import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; -import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; -import com.leakyabstractions.result.api.Result; -import com.leakyabstractions.result.api.Results; -import de.kentoj.scrow.bukkit.ScrowAPI; -import de.kentoj.scrowlib.servermanager.ServerInstance; -import lombok.Getter; -import org.bukkit.command.CommandSender; - -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -public class CrownDestroyServerLiteral implements CommandExecutor { - - @Getter - private final CommandNode rootNode; - private final CommandArgument handleArg; - - public CrownDestroyServerLiteral() { - this.rootNode = CommandNode.node("destroy-server"); - this.rootNode.setExecutor(this); - { - this.handleArg = CommandArgument.arg("template", new StringArgumentType<>()); - this.handleArg.setSuggestionProvider(ctx -> { - //noinspection CodeBlock2Expr - return ScrowAPI.getInstanceManager().getInstances() - .map(ServerInstance::getHandle) - .collect(Collectors.toSet()) - .toFuture(); - }); - this.rootNode.addArgument(handleArg); - } - } - - @Override - public CompletableFuture> execute(CommandContext ctx) { - var handle = ctx.getArg(handleArg); - return ScrowAPI.getInstanceManager().destroyInstance(handle) - .map(__ -> { - ctx.getSender().sendMessage("Destroyed server with handle " + handle); - return Result.success(); - }).toFuture(); - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownListServersLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownListServersLiteral.java deleted file mode 100644 index 17753e9..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/crown/CrownListServersLiteral.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.kentoj.scrow.bukkit.crown; - -import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; -import com.leakyabstractions.result.api.Result; -import de.kentoj.kencommandapi.api.node.CommandNode; -import de.kentoj.scrow.bukkit.ScrowAPI; -import de.kentoj.scrowlib.convention.ScrowMessageStyle; -import lombok.Getter; -import net.kyori.adventure.text.Component; -import org.bukkit.command.CommandSender; - -import java.util.concurrent.CompletableFuture; - -public class CrownListServersLiteral implements CommandExecutor { - - @Getter - private final CommandNode node; - private final ScrowMessageStyle style; - - public CrownListServersLiteral(ScrowMessageStyle style) { - this.style = style; - this.node = CommandNode.node("list-servers"); - this.node.setExecutor(this); - } - - @Override - public CompletableFuture> execute(CommandContext ctx) { - return ScrowAPI.getInstanceManager().getInstances() - .collectList() - .map(list -> style.list(Component.text("Running instances:"), - list.stream() - .map(inst -> - Component.text(inst.getHandle() + " on port " + inst.getPort() + ": " + inst.getState()) - ) - .toList()) - ) - .doOnNext(ctx.getSender()::sendMessage) - .thenReturn(Result.success()).toFuture(); - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/command/CoinsCommand.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/command/CoinsCommand.java index faf9952..2711cce 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/command/CoinsCommand.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/command/CoinsCommand.java @@ -26,7 +26,7 @@ public class CoinsCommand implements CommandExecutor { private final MessageStyle style; public CoinsCommand() { - style = new ScrowMessageStyle("Coins", NamedTextColor.GOLD); + style = ScrowMessageStyle.GENERIC; rootNode = CommandNode.rootNode(style, "coins", "bal", "balance"); rootNode.setPermission("command.coins.get.self"); @@ -44,7 +44,7 @@ public class CoinsCommand implements CommandExecutor { public CompletableFuture> execute(CommandContext ctx) { var player = ((Player) ctx.getSender()); return Tasks.supplyAsync(() -> - ScrowAPI.getEconomyService().getCoins(player.getUniqueId())) + ScrowAPI.getEconomyService().getCoins(player.getUniqueId())) .>mapSync(amount -> { player.sendMessage(style.ok("You have " + amount + "$")); return Results.success(new Object()); diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendCommand.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendCommand.java index ffca644..4e07f50 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendCommand.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendCommand.java @@ -17,5 +17,6 @@ public class FriendCommand { rootNode.addLiteral(new FriendAddLiteral(style).getLiteral()); rootNode.addLiteral(new FriendRemoveLiteral(style).getRootNode()); rootNode.addLiteral(new FriendRequestsLiteral(style).getLiteral()); + return rootNode; } } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceCommand.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceCommand.java new file mode 100644 index 0000000..31d83f1 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceCommand.java @@ -0,0 +1,21 @@ +package de.kentoj.scrow.bukkit.instancemanager.command; + +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.kencommandapi.api.node.RootCommandNode; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.CommandSender; + +@NoArgsConstructor(access = AccessLevel.NONE) +public class InstanceCommand { + public static RootCommandNode create() { + var style = new ScrowMessageStyle("server-manager", NamedTextColor.RED); + RootCommandNode rootNode = CommandNode.rootNode(style, "instance", "server-manager"); + rootNode.addLiteral(new InstanceListLiteral(style).getNode()); + rootNode.addLiteral(new InstanceDeployLiteral(style).getLiteral()); + rootNode.addLiteral(new InstanceDestroyLiteral(style).getLiteral()); + return rootNode; + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceDeployLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceDeployLiteral.java new file mode 100644 index 0000000..06c46ab --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceDeployLiteral.java @@ -0,0 +1,47 @@ +package de.kentoj.scrow.bukkit.instancemanager.command; + +import com.leakyabstractions.result.api.Result; +import com.leakyabstractions.result.core.Results; +import de.kentoj.kencommandapi.api.argument.CommandArgument; +import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; +import de.kentoj.kencommandapi.api.invocation.CommandContext; +import de.kentoj.kencommandapi.api.invocation.CommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.scrow.bukkit.ScrowAPI; +import de.kentoj.scrow.bukkit.scheduler.Tasks; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; +import lombok.Getter; +import org.bukkit.command.CommandSender; + +import java.util.concurrent.CompletableFuture; + +public class InstanceDeployLiteral implements CommandExecutor { + + @Getter + private final CommandNode literal; + private final CommandArgument templateArg; + private final ScrowMessageStyle style; + + public InstanceDeployLiteral(ScrowMessageStyle style) { + this.style = style; + + templateArg = CommandArgument.arg("template", new StringArgumentType<>()); + + literal = CommandNode.node("deploy"); + literal.addArgument(templateArg); + literal.setExecutor(this); + } + + @Override + public CompletableFuture> execute(CommandContext ctx) { + var template = ctx.getArg(templateArg); + ctx.getSender().sendMessage(style.ok("Deploying instance... this may take a while")); + return Tasks.supplyAsync(() -> + ScrowAPI.getInstanceManager().deployInstance(template)) + .>mapSync(instance -> { + ctx.getSender().sendMessage(style.ok("Deployed instance of " + template + " with handle " + instance.getHandle())); + // FIXME handle unknown server + return Results.success(new Object()); + }).toFuture(); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceDestroyLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceDestroyLiteral.java new file mode 100644 index 0000000..fc2063c --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceDestroyLiteral.java @@ -0,0 +1,52 @@ +package de.kentoj.scrow.bukkit.instancemanager.command; + +import com.leakyabstractions.result.api.Result; +import com.leakyabstractions.result.core.Results; +import de.kentoj.kencommandapi.api.argument.CommandArgument; +import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; +import de.kentoj.kencommandapi.api.invocation.CommandContext; +import de.kentoj.kencommandapi.api.invocation.CommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.scrow.bukkit.ScrowAPI; +import de.kentoj.scrow.bukkit.scheduler.Tasks; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; +import de.kentoj.scrowlib.instancemanager.ServerInstance; +import lombok.Getter; +import org.bukkit.command.CommandSender; + +import java.util.concurrent.CompletableFuture; + +public class InstanceDestroyLiteral implements CommandExecutor { + + @Getter + private final CommandNode literal; + private final CommandArgument handleArg; + private final ScrowMessageStyle style; + + public InstanceDestroyLiteral(ScrowMessageStyle style) { + this.style = style; + + handleArg = CommandArgument.arg("handle", new StringArgumentType<>()); + handleArg.setSuggestionProvider(ctx -> + Tasks.supplyAsync(() -> ScrowAPI.getInstanceManager().getInstances().stream() + .map(ServerInstance::getHandle) + .toList()) + .toFuture()); + + literal = CommandNode.node("destroy"); + literal.addArgument(handleArg); + literal.setExecutor(this); + } + + @Override + public CompletableFuture> execute(CommandContext ctx) { + var handle = ctx.getArg(handleArg); + return Tasks.supplyAsync(() -> ScrowAPI.getInstanceManager().destroyInstance(handle)) + .>mapSync(found -> { + if (!found) + return Results.failure("No instance with that handle found"); + ctx.getSender().sendMessage(style.ok("Destroyed server with handle " + handle)); + return Results.success(new Object()); + }).toFuture(); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceListLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceListLiteral.java new file mode 100644 index 0000000..3be7901 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/instancemanager/command/InstanceListLiteral.java @@ -0,0 +1,43 @@ +package de.kentoj.scrow.bukkit.instancemanager.command; + +import com.leakyabstractions.result.api.Result; +import com.leakyabstractions.result.core.Results; +import de.kentoj.kencommandapi.api.invocation.CommandContext; +import de.kentoj.kencommandapi.api.invocation.CommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.scrow.bukkit.ScrowAPI; +import de.kentoj.scrow.bukkit.scheduler.Tasks; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; +import lombok.Getter; +import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; + +import java.util.concurrent.CompletableFuture; + +public class InstanceListLiteral implements CommandExecutor { + + @Getter + private final CommandNode node; + private final ScrowMessageStyle style; + + public InstanceListLiteral(ScrowMessageStyle style) { + this.style = style; + this.node = CommandNode.node("list"); + this.node.setExecutor(this); + } + + @Override + public CompletableFuture> execute(CommandContext ctx) { + return Tasks.supplyAsync(() -> + ScrowAPI.getInstanceManager().getInstances()) + .>mapSync(instances -> { + var msg = Component.text("Running instances:"); + for (var inst : instances) { + msg = msg.appendNewline() + .append(Component.text(" - " + inst.getHandle() + " on port " + inst.getPort())); + } + ctx.getSender().sendMessage(style.ok(msg)); + return Results.success(new Object()); + }).toFuture(); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/playermanager/PlayerManagerImpl.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/playermanager/PlayerManagerImpl.java index 7e35110..27434a5 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/playermanager/PlayerManagerImpl.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/playermanager/PlayerManagerImpl.java @@ -1,8 +1,8 @@ package de.kentoj.scrow.bukkit.playermanager; -import com.leakyabstractions.result.api.Result; import de.kentoj.scrow.bukkit.misc.PlayerManager; import de.kentoj.scrowlib.messaging.MessageBroker; +import de.kentoj.scrowlib.utils.ResultUtils; import lombok.RequiredArgsConstructor; import org.bson.Document; @@ -14,10 +14,10 @@ public class PlayerManagerImpl implements PlayerManager { private final MessageBroker messageBroker; @Override - public Result sendPlayer(UUID playerId, String instanceHandle) { - return messageBroker.request("players.send", new Document() - .append("playerId", playerId) - .append("handle", instanceHandle)) - .mapSuccess(__ -> null); + public void sendPlayer(UUID playerId, String instanceHandle) { + var result = messageBroker.request("players.send", new Document() + .append("playerId", playerId) + .append("handle", instanceHandle)); + ResultUtils.unwrap(result, "failed to send player to " + instanceHandle); } } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/LobbyCommand.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/LobbyCommand.java index b3fb32d..0b6be99 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/LobbyCommand.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/LobbyCommand.java @@ -2,28 +2,28 @@ package de.kentoj.scrow.bukkit.server; import com.leakyabstractions.result.api.Result; import com.leakyabstractions.result.core.Results; -import de.kentoj.kencommandapi.api.node.CommandNode; import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; +import de.kentoj.kencommandapi.api.invocation.SyncCommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.kencommandapi.api.node.RootCommandNode; +import de.kentoj.kencommandapi.api.platform.MessageStyle; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import java.util.concurrent.CompletableFuture; - -public class LobbyCommand implements CommandExecutor { +public class LobbyCommand implements SyncCommandExecutor { @Getter - private final CommandNode rootNode; + private final RootCommandNode rootNode; public LobbyCommand() { - this.rootNode = CommandNode.node("lobby", "l", "hub"); + this.rootNode = CommandNode.rootNode(MessageStyle.PLAIN, "lobby", "l", "hub"); this.rootNode.setExecutor(this); } @Override - public CompletableFuture> execute(CommandContext ctx) { + public Result executeSync(CommandContext ctx) { Bukkit.dispatchCommand(ctx.getSender(), "play lobby"); - return CompletableFuture.completedFuture(Results.success(new Object())); + return Results.success(new Object()); } } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/PlayCommand.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/PlayCommand.java index 4e3e40a..fd217a1 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/PlayCommand.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/server/PlayCommand.java @@ -7,8 +7,10 @@ import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.kencommandapi.api.invocation.CommandExecutor; import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.kencommandapi.api.node.RootCommandNode; import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.scheduler.Tasks; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; import lombok.Getter; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -18,28 +20,36 @@ import java.util.concurrent.CompletableFuture; public class PlayCommand implements CommandExecutor { @Getter - private final CommandNode rootNode; + private final RootCommandNode rootNode; private final CommandArgument gamemodeArg; public PlayCommand() { - this.rootNode = CommandNode.node("play", "queue"); - this.gamemodeArg = CommandArgument.arg("gamemode", new StringArgumentType<>()); - this.rootNode.addArgument(this.gamemodeArg); - this.rootNode.setExecutor(this); + var style = ScrowMessageStyle.GENERIC; + + gamemodeArg = CommandArgument.arg("gamemode", new StringArgumentType<>()); + + rootNode = CommandNode.rootNode(style, "play", "queue"); + rootNode.addArgument(this.gamemodeArg); + rootNode.setExecutor(this); } @Override public CompletableFuture> execute(CommandContext ctx) { var gamemode = ctx.getArg(gamemodeArg); var player = (Player) ctx.getSender(); - return Tasks.supplyAsync(() -> ScrowAPI.getInstanceManager().getInstances() - .mapSuccess(instances -> { + return Tasks.supplyAsync(() -> ScrowAPI.getInstanceManager().getInstances()) + .mapAsync(instances -> { var instance = instances.stream() .filter(inst -> inst.getTemplate().equals(gamemode)) .findFirst() .orElse(null); - if (instance == null) return Results.failure("No instance available"); - return ScrowAPI.getPlayerManager().sendPlayer(player.getUniqueId(), instance.getHandle()); - })); + if (instance == null) + return Results.failure("No instance for " + gamemode + " found"); + + return Results.ofCallable(() -> { + ScrowAPI.getPlayerManager().sendPlayer(player.getUniqueId(), instance.getHandle()); + return new Object(); + }).mapFailure(Exception::getMessage); + }).toFuture(); } } diff --git a/core-lib/build.gradle.kts b/core-lib/build.gradle.kts index 8139e4c..29e0c68 100644 --- a/core-lib/build.gradle.kts +++ b/core-lib/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { api("org.mongodb:bson:5.8.0") // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-core - api("de.kentoj.scrow:kencommandapi-core:0.22") + api("de.kentoj.scrow:kencommandapi-core:0.23") } publishing { diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactory.java b/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactory.java deleted file mode 100644 index 611e734..0000000 --- a/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.kentoj.scrowlib.connection; - -import org.springframework.r2dbc.core.DatabaseClient; - -public interface DatabaseConnectionFactory extends AutoCloseable { - - DatabaseClient create(); -} diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactoryImpl.java b/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactoryImpl.java deleted file mode 100644 index 7853190..0000000 --- a/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactoryImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package de.kentoj.scrowlib.connection; - -import io.r2dbc.pool.ConnectionPool; -import io.r2dbc.pool.ConnectionPoolConfiguration; -import io.r2dbc.spi.ConnectionFactory; -import lombok.RequiredArgsConstructor; -import org.springframework.r2dbc.core.DatabaseClient; - -@RequiredArgsConstructor -public class DatabaseConnectionFactoryImpl implements DatabaseConnectionFactory { - - private final ConnectionPool backingFactory; - - public DatabaseConnectionFactoryImpl(ConnectionFactory connectionFactory) { - this(new ConnectionPool(ConnectionPoolConfiguration.builder() - .connectionFactory(connectionFactory) - .build())); - } - - // FIXME - // its been a while and i no longer remember what had to be fixed - @Override - public DatabaseClient create() { - return DatabaseClient.create(backingFactory); - } - - @Override - public void close() { - backingFactory.close(); - } -} diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/convention/ScrowMessageStyle.java b/core-lib/src/main/java/de/kentoj/scrowlib/convention/ScrowMessageStyle.java index 31a5261..3776bb7 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/convention/ScrowMessageStyle.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/convention/ScrowMessageStyle.java @@ -11,6 +11,8 @@ import java.util.List; public class ScrowMessageStyle implements MessageStyle { + public static ScrowMessageStyle GENERIC = new ScrowMessageStyle("Scrow", NamedTextColor.WHITE); + @Getter private final Component prefix; @Getter @@ -32,16 +34,6 @@ public class ScrowMessageStyle implements MessageStyle { .append(msg.colorIfAbsent(NamedTextColor.GRAY)); } - public Component list(Component header, List list) { - var res = ok(header); - for (Component component : list) { - res = res.appendNewline() - .append(Component.text(" - ").color(NamedTextColor.GRAY)) - .append(component.colorIfAbsent(NamedTextColor.GRAY)); - } - return res; - } - @Override public Component err(Component msg) { return ok(msg.color(NamedTextColor.RED)); diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/InstanceManager.java b/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/InstanceManager.java similarity index 90% rename from core-lib/src/main/java/de/kentoj/scrowlib/servermanager/InstanceManager.java rename to core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/InstanceManager.java index 551b461..613221d 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/InstanceManager.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/InstanceManager.java @@ -1,4 +1,4 @@ -package de.kentoj.scrowlib.servermanager; +package de.kentoj.scrowlib.instancemanager; import org.jspecify.annotations.Nullable; diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/InstanceManagerImpl.java b/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/InstanceManagerImpl.java new file mode 100644 index 0000000..67608c6 --- /dev/null +++ b/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/InstanceManagerImpl.java @@ -0,0 +1,52 @@ +package de.kentoj.scrowlib.instancemanager; + +import de.kentoj.scrowlib.messaging.MessageBroker; +import io.nats.client.Connection; +import org.bson.Document; +import org.jspecify.annotations.Nullable; + +import java.util.List; + +import static de.kentoj.scrowlib.utils.ResultUtils.unwrap; + +public class InstanceManagerImpl implements InstanceManager { + + private final MessageBroker messageBroker; + + public InstanceManagerImpl(Connection natsCon) { + messageBroker = new MessageBroker(natsCon); + } + + @Override + public ServerInstance deployInstance(String template) { + var result = messageBroker.request("instance.deploy", new Document("template", template)); + var document = unwrap(result, "failed to deploy instance of " + template); + return ServerInstance.fromDocument(document); + } + + @Override + public boolean destroyInstance(String handle) { + var result = messageBroker.request("instance.destroy", new Document("handle", handle)); + return unwrap(result.mapSuccess(__ -> true) + .recover(this::wasNotFound, __ -> false), "failed to destroy instance " + handle); + } + + @Override + public List getInstances() { + var result = messageBroker.request("instance.list", new Document()); + return unwrap(result.mapSuccess(doc -> doc.getList("instances", Document.class) + .stream().map(ServerInstance::fromDocument).toList()), + "failed to get instances"); + } + + @Override + public @Nullable ServerInstance getInstance(String handle) { + var result = messageBroker.request("instance.get", new Document("handle", handle)); + return unwrap(result.mapSuccess(ServerInstance::fromDocument) + .recover(this::wasNotFound, __ -> null), "failed to get instance " + handle); + } + + private boolean wasNotFound(String failure) { + return "no instance found".equals(failure); + } +} diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/ServerInstance.java b/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/ServerInstance.java similarity index 94% rename from core-lib/src/main/java/de/kentoj/scrowlib/servermanager/ServerInstance.java rename to core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/ServerInstance.java index 853226d..8df7729 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/ServerInstance.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/instancemanager/ServerInstance.java @@ -1,4 +1,4 @@ -package de.kentoj.scrowlib.servermanager; +package de.kentoj.scrowlib.instancemanager; import com.google.common.base.Preconditions; import lombok.Value; diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/RequestHandler.java b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/RequestHandler.java index 2efef74..2a2b896 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/RequestHandler.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/RequestHandler.java @@ -12,5 +12,5 @@ public interface RequestHandler { * * @return result to send back to the requesting client. */ - CompletionStage> handle(Document request); + CompletionStage> handle(Document doc); } diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SyncRequestHandler.java b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SyncRequestHandler.java new file mode 100644 index 0000000..bece2d0 --- /dev/null +++ b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SyncRequestHandler.java @@ -0,0 +1,17 @@ +package de.kentoj.scrowlib.messaging; + +import com.leakyabstractions.result.api.Result; +import org.bson.Document; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +@FunctionalInterface +public interface SyncRequestHandler extends RequestHandler{ + Result handleSync(Document doc); + + @Override + default CompletionStage> handle(Document doc) { + return CompletableFuture.completedFuture(handleSync(doc)); + } +} diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/InstanceManagerImpl.java b/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/InstanceManagerImpl.java deleted file mode 100644 index 5afb601..0000000 --- a/core-lib/src/main/java/de/kentoj/scrowlib/servermanager/InstanceManagerImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.kentoj.scrowlib.servermanager; - -import com.leakyabstractions.result.api.Result; -import de.kentoj.scrowlib.messaging.MessageBroker; -import io.nats.client.Connection; -import org.bson.Document; -import org.jspecify.annotations.Nullable; - -import java.util.List; - -public class InstanceManagerImpl implements InstanceManager { - - private final MessageBroker messageBroker; - - public InstanceManagerImpl(Connection natsCon) { - messageBroker = new MessageBroker(natsCon); - } - - @Override - public Result deployInstance(String template) { - var result = messageBroker.request("instance.deploy", new Document("template", template)); - return result.mapSuccess(ServerInstance::fromDocument); - } - - @Override - public Result destroyInstance(String handle) { - var result = messageBroker.request("instance.destroy", new Document("handle", handle)); - return result.mapSuccess(__ -> null); - } - - @Override - public Result, String> getInstances() { - var result = messageBroker.request("instance.list", new Document()); - return result.mapSuccess(doc -> doc.getList("instances", Document.class) - .stream() - .map(ServerInstance::fromDocument) - .toList()); - } - - @Override - public Result<@Nullable ServerInstance, String> getInstance(String handle) { - var result = messageBroker.request("instance.get", new Document("handle", handle)); - return result.mapSuccess(ServerInstance::fromDocument); - } -} diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/utils/ResultUtils.java b/core-lib/src/main/java/de/kentoj/scrowlib/utils/ResultUtils.java new file mode 100644 index 0000000..4d1c491 --- /dev/null +++ b/core-lib/src/main/java/de/kentoj/scrowlib/utils/ResultUtils.java @@ -0,0 +1,17 @@ +package de.kentoj.scrowlib.utils; + +import com.leakyabstractions.result.api.Result; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.Optional; + +@NoArgsConstructor(access = AccessLevel.NONE) +public class ResultUtils { + public static S unwrap(Result result, String message) { + Optional err = result.getFailure(); + if (err.isPresent()) + throw new RuntimeException(message + ": " + err.orElseThrow()); + return result.getSuccess().orElseThrow(); + } +} diff --git a/core-velocity-api/build.gradle.kts b/core-velocity-api/build.gradle.kts index e760250..3f20c57 100644 --- a/core-velocity-api/build.gradle.kts +++ b/core-velocity-api/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("de.kentoj.scrow.scrow-repository") id("de.kentoj.scrow.base-dependencies") id("de.kentoj.scrow.java-library") - id("de.kentoj.scrow.reactor") + id("de.kentoj.scrow.database") } group = "de.kentoj.scrow" @@ -24,9 +24,9 @@ dependencies { api("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT") // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-core - api("de.kentoj.scrow:kencommandapi-core:0.22") + api("de.kentoj.scrow:kencommandapi-core:0.23") // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-velocity - api("de.kentoj.scrow:kencommandapi-velocity:0.22") + api("de.kentoj.scrow:kencommandapi-velocity:0.23") } publishing { diff --git a/core-velocity-api/src/main/java/de/kentoj/scrow/velocity/ScrowAPI.java b/core-velocity-api/src/main/java/de/kentoj/scrow/velocity/ScrowAPI.java index f682c83..c59ae8e 100644 --- a/core-velocity-api/src/main/java/de/kentoj/scrow/velocity/ScrowAPI.java +++ b/core-velocity-api/src/main/java/de/kentoj/scrow/velocity/ScrowAPI.java @@ -1,20 +1,19 @@ package de.kentoj.scrow.velocity; import de.kentoj.kencommandapi.CommandAPI; -import de.kentoj.scrowlib.connection.DatabaseConnectionFactory; -import de.kentoj.scrowlib.servermanager.InstanceManager; +import de.kentoj.scrowlib.instancemanager.InstanceManager; import io.nats.client.Connection; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.jdbi.v3.core.Jdbi; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class ScrowAPI { @Getter - private static DatabaseConnectionFactory dbConFactory; + private static Jdbi jdbi; @Getter private static CommandAPI commandApi; @Getter @@ -38,8 +37,8 @@ public class ScrowAPI { } @ApiStatus.Internal - public static void setDbConFactory(@Nullable DatabaseConnectionFactory dbConFactory) { - ScrowAPI.dbConFactory = dbConFactory; + public static void setJdbi(Jdbi jdbi) { + ScrowAPI.jdbi = jdbi; } } diff --git a/core-velocity-impl/build.gradle.kts b/core-velocity-impl/build.gradle.kts index 1821ec9..7744f3a 100644 --- a/core-velocity-impl/build.gradle.kts +++ b/core-velocity-impl/build.gradle.kts @@ -4,7 +4,6 @@ plugins { id("de.kentoj.scrow.scrow-repository") id("de.kentoj.scrow.base-dependencies") id("de.kentoj.scrow.database") - id("de.kentoj.scrow.reactor") } group = "de.kentoj.scrow" diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/CoreVelocityPlugin.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/CoreVelocityPlugin.java index 5f1c66b..5ad2d34 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/CoreVelocityPlugin.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/CoreVelocityPlugin.java @@ -6,12 +6,15 @@ import com.velocitypowered.api.proxy.ProxyServer; import de.kentoj.scrow.corevelocity.command.OnlineCommand; import de.kentoj.scrow.corevelocity.privmsg.LastTargetCache; import de.kentoj.scrow.corevelocity.privmsg.MsgCommand; +import de.kentoj.scrow.corevelocity.privmsg.PrivMsgHandler; import de.kentoj.scrow.corevelocity.privmsg.ReplyCommand; import de.kentoj.scrow.corevelocity.server.SendPlayerWatchdog; import de.kentoj.scrow.corevelocity.server.ServerRegisterWatchdog; -import de.kentoj.scrow.generated.BuildInfo; // may not resolve until building for the first time +import de.kentoj.scrow.generated.BuildInfo; import de.kentoj.scrow.velocity.ScrowAPI; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; import lombok.extern.java.Log; +import net.kyori.adventure.text.format.NamedTextColor; @Plugin( id = "corevelocity", @@ -28,12 +31,14 @@ public class CoreVelocityPlugin { var cmds = ScrowAPI.getCommandApi(); { var lastTargetCache = new LastTargetCache(); - cmds.register(new ReplyCommand(server, lastTargetCache).getRootNode()); - cmds.register(new MsgCommand(server, lastTargetCache).getRootNode()); + var style = new ScrowMessageStyle("MSG", NamedTextColor.LIGHT_PURPLE); + var privmsgHelper = new PrivMsgHandler(style); + cmds.register(new ReplyCommand(server, lastTargetCache, privmsgHelper, style).getRootNode()); + cmds.register(new MsgCommand(server, lastTargetCache, privmsgHelper, style).getRootNode()); cmds.register(new OnlineCommand(server).getRootNode()); } - var registerWatchdog = new ServerRegisterWatchdog(ScrowAPI.getNats(), ScrowAPI.getInstanceManager(), server); + var registerWatchdog = new ServerRegisterWatchdog(ScrowAPI.getNats(), server); var sendPlayerWatchdog = new SendPlayerWatchdog(ScrowAPI.getNats(), server); registerWatchdog.listen(); sendPlayerWatchdog.listen(); diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ScrowAPISurface.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ScrowAPISurface.java index f0a4934..17209f2 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ScrowAPISurface.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ScrowAPISurface.java @@ -3,14 +3,13 @@ package de.kentoj.scrow.corevelocity; import com.velocitypowered.api.proxy.ProxyServer; import de.kentoj.kencommandapi.CommandAPI; import de.kentoj.scrow.velocity.ScrowAPI; -import de.kentoj.scrowlib.connection.DatabaseConnectionFactoryImpl; +import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl; import de.kentoj.scrowlib.utils.EnvUtils; import io.nats.client.Nats; import io.nats.client.Options; -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.jdbi.v3.core.Jdbi; import java.io.IOException; @@ -30,20 +29,14 @@ public class ScrowAPISurface { } if (enableDatabase) { - ConnectionFactory factory = ConnectionFactories.get(EnvUtils.envOrThrow("HOST_POSTGRES")); - ScrowAPI.setDbConFactory(new DatabaseConnectionFactoryImpl(factory)); + ScrowAPI.setJdbi(Jdbi.create(EnvUtils.envOrThrow("HOST_POSTGRES"))); } - ScrowAPI.setInstanceManager(new ServerManagerImpl(ScrowAPI.getNats())); + ScrowAPI.setInstanceManager(new InstanceManagerImpl(ScrowAPI.getNats())); ScrowAPI.setCommandApi(new CommandAPI(server)); } public static void destroyScrowAPI() { - try { - ScrowAPI.getDbConFactory().close(); - } catch (Exception e) { - throw new RuntimeException(e); - } } } diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/command/OnlineCommand.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/command/OnlineCommand.java index 9216215..9cf0050 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/command/OnlineCommand.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/command/OnlineCommand.java @@ -1,39 +1,40 @@ package de.kentoj.scrow.corevelocity.command; +import com.leakyabstractions.result.api.Result; +import com.leakyabstractions.result.core.Results; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.ProxyServer; -import de.kentoj.kencommandapi.api.node.CommandNode; import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; -import com.leakyabstractions.result.api.Result; -import com.leakyabstractions.result.api.Results; +import de.kentoj.kencommandapi.api.invocation.SyncCommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.kencommandapi.api.node.RootCommandNode; +import de.kentoj.kencommandapi.api.platform.MessageStyle; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; import lombok.Getter; import lombok.RequiredArgsConstructor; import net.kyori.adventure.text.Component; -import java.util.concurrent.CompletableFuture; - @RequiredArgsConstructor -public class OnlineCommand implements CommandExecutor { +public class OnlineCommand implements SyncCommandExecutor { @Getter - private final CommandNode rootNode; + private final RootCommandNode rootNode; private final ProxyServer server; public OnlineCommand(ProxyServer server) { this.server = server; - rootNode = CommandNode.node("online"); + rootNode = CommandNode.rootNode(ScrowMessageStyle.GENERIC, "online"); rootNode.setExecutor(this); } @Override - public CompletableFuture> execute(CommandContext ctx) { + public Result executeSync(CommandContext ctx) { int cnt = server.getPlayerCount(); var msg = cnt != 1 ? "There are currently " + cnt + " players online" : "There is currently 1 player online"; ctx.getSender().sendMessage(Component.text(msg)); - return Result.success().toFuture(); + return Results.success(new Object()); } } diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/MsgCommand.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/MsgCommand.java index 18d4a04..4520902 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/MsgCommand.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/MsgCommand.java @@ -1,52 +1,54 @@ package de.kentoj.scrow.corevelocity.privmsg; +import com.leakyabstractions.result.api.Result; +import com.leakyabstractions.result.core.Results; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; -import de.kentoj.kencommandapi.api.node.CommandNode; import de.kentoj.kencommandapi.api.argument.CommandArgument; import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; -import com.leakyabstractions.result.api.Result; -import com.leakyabstractions.result.api.Results; +import de.kentoj.kencommandapi.api.invocation.SyncCommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.kencommandapi.api.node.RootCommandNode; +import de.kentoj.kencommandapi.api.platform.MessageStyle; import de.kentoj.kencommandapi.type.PlayerArgumentType; -import de.kentoj.scrow.velocity.ScrowAPI; import lombok.Getter; -import java.util.concurrent.CompletableFuture; - -public class MsgCommand implements CommandExecutor { +public class MsgCommand implements SyncCommandExecutor { @Getter - private final CommandNode rootNode; + private final RootCommandNode rootNode; private final CommandArgument targetArg; private final CommandArgument msgArg; private final LastTargetCache cache; + private final PrivMsgHandler privMsgHandler; - public MsgCommand(ProxyServer server, LastTargetCache cache) { + public MsgCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler helper, MessageStyle style) { this.cache = cache; + this.privMsgHandler = helper; targetArg = CommandArgument.arg("target", new PlayerArgumentType(server)); msgArg = CommandArgument.arg("msg", new StringArgumentType<>(true)); - rootNode = CommandNode.node("msg", "w", "privmsg"); + + rootNode = CommandNode.rootNode(style, "msg", "w", "privmsg"); rootNode.setExecutor(this); rootNode.addArgument(targetArg); rootNode.addArgument(msgArg); } @Override - public CompletableFuture> execute(CommandContext ctx) { + public Result executeSync(CommandContext ctx) { var target = ctx.getArg(targetArg); var msg = ctx.getArg(msgArg); - var sender = (Player)ctx.getSender(); + var sender = (Player) ctx.getSender(); var isMessagingSelf = target.getUniqueId().equals(sender.getUniqueId()); - if (isMessagingSelf) return Result.error("You can't message yourself").toFuture(); + if (isMessagingSelf) return Results.failure("You can't message yourself"); cache.setLastTarget(sender.getUniqueId(), target.getUniqueId()); - PrivmsgHelper.handle(sender, target, msg); - return Result.success().toFuture(); + privMsgHandler.handle(sender, target, msg); + return Results.success(new Object()); } } diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/PrivMsgHandler.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/PrivMsgHandler.java new file mode 100644 index 0000000..4c73baa --- /dev/null +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/PrivMsgHandler.java @@ -0,0 +1,19 @@ +package de.kentoj.scrow.corevelocity.privmsg; + +import com.velocitypowered.api.proxy.Player; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; +import lombok.RequiredArgsConstructor; +import net.kyori.adventure.text.Component; + +import static net.kyori.adventure.text.Component.text; + +@RequiredArgsConstructor +public class PrivMsgHandler { + + private final ScrowMessageStyle style; + + public void handle(Player player, Player target, String msg) { + target.sendMessage(style.ok(text(player.getUsername() + " -> You:").append(Component.text(msg)))); + player.sendMessage(style.ok(text("You -> " + player.getUsername()).append(Component.text(msg)))); + } +} diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/PrivmsgHelper.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/PrivmsgHelper.java deleted file mode 100644 index 7c60151..0000000 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/PrivmsgHelper.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.kentoj.scrow.corevelocity.privmsg; - -import com.velocitypowered.api.proxy.Player; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import net.kyori.adventure.text.Component; - -@NoArgsConstructor(access = AccessLevel.NONE) -public class PrivmsgHelper { - - public static void handle(Player player, Player target, String msg) { - target.sendMessage(Component.text("[PRIVMSG] " + player.getUsername() + " -> You: " + msg)); - player.sendMessage(Component.text("[PRIVMSG] " + "you -> " + player.getUsername() + ": " + msg)); - } -} diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/ReplyCommand.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/ReplyCommand.java index d9d0c3e..bd169f1 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/ReplyCommand.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/privmsg/ReplyCommand.java @@ -1,48 +1,51 @@ package de.kentoj.scrow.corevelocity.privmsg; +import com.leakyabstractions.result.api.Result; +import com.leakyabstractions.result.core.Results; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; -import de.kentoj.kencommandapi.api.node.CommandNode; import de.kentoj.kencommandapi.api.argument.CommandArgument; import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; import de.kentoj.kencommandapi.api.invocation.CommandContext; -import de.kentoj.kencommandapi.api.invocation.CommandExecutor; -import com.leakyabstractions.result.api.Result; -import com.leakyabstractions.result.api.Results; +import de.kentoj.kencommandapi.api.invocation.SyncCommandExecutor; +import de.kentoj.kencommandapi.api.node.CommandNode; +import de.kentoj.kencommandapi.api.node.RootCommandNode; +import de.kentoj.kencommandapi.api.platform.MessageStyle; import lombok.Getter; -import java.util.concurrent.CompletableFuture; - -public class ReplyCommand implements CommandExecutor { +public class ReplyCommand implements SyncCommandExecutor { @Getter - private final CommandNode rootNode; + private final RootCommandNode rootNode; private final CommandArgument msgArg; private final LastTargetCache cache; private final ProxyServer server; + private final PrivMsgHandler privMsgHandler; - public ReplyCommand(ProxyServer server, LastTargetCache cache) { + public ReplyCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler privMsgHandler, MessageStyle style) { this.cache = cache; this.server = server; + this.privMsgHandler = privMsgHandler; msgArg = CommandArgument.arg("msg", new StringArgumentType<>(true)); - rootNode = CommandNode.node("reply", "r"); + rootNode = CommandNode.rootNode(style, "reply", "r"); rootNode.setExecutor(this); rootNode.addArgument(msgArg); } @Override - public CompletableFuture> execute(CommandContext ctx) { - var sender = (Player)ctx.getSender(); + public Result executeSync(CommandContext ctx) { + var sender = (Player) ctx.getSender(); var targetId = cache.getLastTarget(sender.getUniqueId()); var target = server.getPlayer(targetId).orElse(null); - if (target == null) return Result.error("The player you last messaged is no longer online").toFuture(); - var msg = ctx.getArg(msgArg); + + if (target == null) + return Results.failure("The player you last messaged is no longer online"); cache.setLastTarget(sender.getUniqueId(), target.getUniqueId()); - PrivmsgHelper.handle(sender, target, msg); - return Result.success().toFuture(); + privMsgHandler.handle(sender, target, msg); + return Results.success(new Object()); } } diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java index 47e0477..14a2685 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java @@ -1,15 +1,13 @@ package de.kentoj.scrow.corevelocity.server; +import com.leakyabstractions.result.core.Results; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.server.ServerInfo; import de.kentoj.scrowlib.messaging.MessageBroker; -import de.kentoj.scrowlib.messaging.respose.SafeResult; -import de.kentoj.scrowlib.servermanager.InstanceManager; +import de.kentoj.scrowlib.messaging.SyncRequestHandler; import io.nats.client.Connection; import lombok.extern.java.Log; import org.bson.Document; -import org.jetbrains.annotations.NotNull; -import reactor.core.publisher.Mono; import java.net.InetSocketAddress; @@ -17,39 +15,30 @@ import java.net.InetSocketAddress; public class ServerRegisterWatchdog { private final MessageBroker natsRepo; - private final InstanceManager instanceManager; private final ProxyServer server; - public ServerRegisterWatchdog(Connection nats, InstanceManager instanceManager, ProxyServer server) { + public ServerRegisterWatchdog(Connection nats, ProxyServer server) { this.natsRepo = new MessageBroker(nats); - this.instanceManager = instanceManager; this.server = server; } public void listen() { - natsRepo.subscribe("crown.set-state") - .flatMap(ctx -> { - var state = ctx.getDocument().getString("state"); - var handle = ctx.getDocument().getString("handle"); - return handleStateChange(ctx, state, handle) - .then(Mono.fromRunnable(() -> { - natsRepo.publishSafeResult(ctx.getMsg().getReplyTo(), SafeResult.wrap(new Document())); - })); - }) - .subscribe(null, e -> log.throwing(getClass().getName(), "listen", e)); - } + natsRepo.handle("event.instance.up", (SyncRequestHandler) doc -> { + var handle = doc.getString("handle"); + var port = doc.getInteger("port"); + return Results.ofCallable(() -> { + server.registerServer(new ServerInfo(handle, new InetSocketAddress(port))); + return new Document(); + }).mapFailure(Throwable::getMessage); + }); - private @NotNull Result handleStateChange(SubscriptionContext ctx, String state, String handle) { - return switch (state) { - case "UP" -> instanceManager.getInfo(handle) - .doOnNext(instance -> - server.registerServer(new ServerInfo(handle, new InetSocketAddress(instance.getPort())))) - .then(); - case "DOWN" -> instanceManager.getInfo(handle) - .doOnNext(instance -> - server.unregisterServer(new ServerInfo(handle, new InetSocketAddress(instance.getPort())))) - .then(); - default -> Mono.empty(); - }; + natsRepo.handle("event.instance.down", (SyncRequestHandler) doc -> { + var handle = doc.getString("handle"); + var port = doc.getInteger("port"); + return Results.ofCallable(() -> { + server.unregisterServer(new ServerInfo(handle, new InetSocketAddress(port))); + return new Document(); + }).mapFailure(Throwable::getMessage); + }); } }