This commit is contained in:
kento2 2026-05-31 10:49:33 +02:00
parent 0b0b650f83
commit e4fd6a8c5f
12 changed files with 236 additions and 46 deletions

View file

@ -1,10 +1,8 @@
package de.kentoj.scrow.bukkit;
import de.kentoj.scrow.bukkit.crown.command.CrownCommand;
import de.kentoj.scrow.bukkit.economy.CoinsCommand;
import de.kentoj.scrow.bukkit.friends.command.FriendCommand;
import io.nats.client.Message;
import io.nats.client.Nats;
import org.bson.Document;
import org.bukkit.plugin.java.JavaPlugin;
import reactor.core.publisher.Mono;
@ -21,33 +19,14 @@ public class CoreImplPlugin extends JavaPlugin {
{
ScrowAPI.getCommandManager().register(new FriendCommand().getRootNode());
ScrowAPI.getCommandManager().register(new CoinsCommand().getRootNode());
ScrowAPI.getCommandManager().register(new CrownCommand().getRootNode());
}
{
var playerId = UUID.randomUUID();
var economyService = ScrowAPI.getEconomyService();
Mono.when(
economyService.setCoins(playerId, 120),
economyService.depositCoins(playerId, 100)
)
.then(economyService.tryWithdrawCoins(playerId, 300))
.doOnNext(a -> System.out.println("withdraw 1 success " + a))
.then(economyService.tryWithdrawCoins(playerId, 50))
.doOnNext(a -> System.out.println("withdraw 2 success " + a))
.then(economyService.getCoins(playerId))
.doOnNext(a -> System.out.println("coins: " + a))
.block();
}
registerServer();
}
private void registerServer() {
ScrowAPI.getNatsRepository().publish("crown.status", new Document()
.append("state", "up"));
ScrowAPI.getNatsRepository().subscribe("crown.status", doc -> {
doc.
});
ScrowAPI.getNats().reqpublish("crown.status", new Document()
.append("state", "up").toJson());
ScrowAPI.getServerManager().updateState(System.getenv("SERVER_HANDLE"), "UP");
}
@Override

View file

@ -5,6 +5,7 @@ import com.mongodb.MongoClientSettings;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import de.kentoj.kencommandapi.BukkitKenCommandApi;
import de.kentoj.scrow.bukkit.crown.CrownServerManager;
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
import de.kentoj.scrow.bukkit.friends.friendship.InMemoryFriendshipService;
@ -12,6 +13,7 @@ import de.kentoj.scrow.bukkit.friends.friendship.MongoFriendshipService;
import de.kentoj.scrow.bukkit.friends.request.InMemoryFriendRequestService;
import de.kentoj.scrow.bukkit.friends.request.MongoFriendRequestService;
import io.nats.client.Nats;
import io.nats.client.Options;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.bson.UuidRepresentation;
@ -35,7 +37,12 @@ public class ScrowAPISurface {
}));
try {
ScrowAPI.setMessageBroker(Nats.connect());
String natsHost = System.getenv("HOST_NATS");
var options = Options.builder()
.server(natsHost)
.pedantic()
.build();
ScrowAPI.setNats(Nats.connect(options));
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
@ -46,18 +53,21 @@ public class ScrowAPISurface {
MongoClientSettings.getDefaultCodecRegistry(),
CodecRegistries.fromProviders(pojoCodecProvider)
);
String mongoHost = System.getenv("HOST_MONGO");
var settings = MongoClientSettings.builder()
.codecRegistry(codecRegistry)
.uuidRepresentation(UuidRepresentation.STANDARD)
.applyConnectionString(new ConnectionString("mongodb://localhost:27017/scrow"))
.applyConnectionString(new ConnectionString(mongoHost))
.build();
mongoClient = MongoClients.create(settings);
ScrowAPI.setDatabase(mongoClient.getDatabase("scrow"));
}
ScrowAPI.setServerManager(new CrownServerManager(ScrowAPI.getNats()));
ScrowAPI.setEconomyService(ScrowAPI.getDatabase() != null ?
new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService());
new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService());
ScrowAPI.setFriendRequestService(ScrowAPI.getDatabase() != null ?
new MongoFriendRequestService(ScrowAPI.getDatabase()) : new InMemoryFriendRequestService());

View file

@ -0,0 +1,47 @@
package de.kentoj.scrow.bukkit.crown;
import com.google.common.base.Preconditions;
import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.ServerManager;
import io.nats.client.Connection;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Arrays;
@RequiredArgsConstructor
public class CrownServerManager implements ServerManager {
private final Connection nats;
@Override
public Mono<@NotNull String> deployServer(String template) {
return Mono.fromFuture(nats.request("crown.deploy-server", template.getBytes()))
.map(msg -> new String(msg.getData()));
}
@Override
public Flux<@NotNull String> getRunningServers() {
return Mono.fromFuture(nats.request("crown.deploy-server", new byte[0]))
.flatMapMany(msg -> {
var ids = new String(msg.getData()).split("\u001F");
return Flux.fromStream(Arrays.stream(ids));
});
}
@Override
public Mono<@NotNull Void> destroyServer(String handle) {
return Mono.fromFuture(nats.request("crown.destroy-server",handle.getBytes()))
.then();
}
@Override
public Mono<@NotNull Void> updateState(String handle, String state) {
Preconditions.checkArgument(!state.contains(" "), "state may not contain spaces");
var payload = (handle + " " + state).getBytes();
return Mono.fromFuture(nats.request("crown.update-state", payload))
.then();
}
}

View file

@ -0,0 +1,20 @@
package de.kentoj.scrow.bukkit.crown.command;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.scrow.bukkit.ScrowAPI;
import lombok.Getter;
import org.bukkit.command.CommandSender;
public class CrownCommand {
@Getter
private final CommandNode<CommandSender, BukkitCommandContext> rootNode;
public CrownCommand() {
this.rootNode = ScrowAPI.getCommandManager().createNode("crown", "server-manager");
this.rootNode.addLiteral(new CrownListServersLiteral().getNode());
this.rootNode.addLiteral(new CrownDeployServerLiteral().getNode());
this.rootNode.addLiteral(new CrownDestroyServerLiteral().getNode());
}
}

View file

@ -0,0 +1,35 @@
package de.kentoj.scrow.bukkit.crown.command;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.structure.argument.types.StringArgumentType;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.scrow.bukkit.ScrowAPI;
import lombok.Getter;
import org.bukkit.command.CommandSender;
public class CrownDeployServerLiteral implements CommandExecutor<CommandSender, BukkitCommandContext> {
@Getter
private final CommandNode<CommandSender, BukkitCommandContext> node;
private final CommandArgument<CommandSender, BukkitCommandContext, String> templateArg;
public CrownDeployServerLiteral() {
this.node = ScrowAPI.getCommandManager().createNode("deploy-server");
this.node.setExecutor(this);
{
this.templateArg = ScrowAPI.getCommandManager().createArgument("template", new StringArgumentType<>());
this.node.addArgument(templateArg);
}
}
@Override
public void execute(BukkitCommandContext ctx) {
var template = ctx.getArg(templateArg);
ScrowAPI.getServerManager().deployServer(template)
.subscribe(handle -> {
ctx.getSender().sendMessage("Deployed instance of " + template + " with handle " + handle);
});
}
}

View file

@ -0,0 +1,41 @@
package de.kentoj.scrow.bukkit.crown.command;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.structure.argument.types.StringArgumentType;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.scrow.bukkit.ScrowAPI;
import lombok.Getter;
import org.bukkit.command.CommandSender;
import java.util.stream.Collectors;
public class CrownDestroyServerLiteral implements CommandExecutor<CommandSender, BukkitCommandContext> {
@Getter
private final CommandNode<CommandSender, BukkitCommandContext> node;
private final CommandArgument<CommandSender, BukkitCommandContext, String> handleArg;
public CrownDestroyServerLiteral() {
this.node = ScrowAPI.getCommandManager().createNode("destroy-server");
this.node.setExecutor(this);
{
this.handleArg = ScrowAPI.getCommandManager().createArgument("template", new StringArgumentType<>());
this.handleArg.setSuggestionProvider(ctx -> {
//noinspection CodeBlock2Expr
return ScrowAPI.getServerManager().getRunningServers().collect(Collectors.toSet()).toFuture();
});
this.node.addArgument(handleArg);
}
}
@Override
public void execute(BukkitCommandContext ctx) {
var handle = ctx.getArg(handleArg);
ScrowAPI.getServerManager().destroyServer(handle)
.subscribe(__ -> {
ctx.getSender().sendMessage("Destroyed server with handle " + handle);
});
}
}

View file

@ -0,0 +1,31 @@
package de.kentoj.scrow.bukkit.crown.command;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.scrow.bukkit.ScrowAPI;
import lombok.Getter;
import org.bukkit.command.CommandSender;
public class CrownListServersLiteral implements CommandExecutor<CommandSender, BukkitCommandContext> {
@Getter
private final CommandNode<CommandSender, BukkitCommandContext> node;
public CrownListServersLiteral() {
this.node = ScrowAPI.getCommandManager().createNode("list-servers");
this.node.setExecutor(this);
}
@Override
public void execute(BukkitCommandContext ctx) {
ScrowAPI.getServerManager().getRunningServers()
.collectList()
.subscribe(uids -> {
var msg = new StringBuilder().append('\n');
uids.forEach(uid -> msg.append(" > ").append(uid));
msg.append('\n');
ctx.getPlayerSender().sendMessage(msg.toString());
});
}
}

View file

@ -23,7 +23,7 @@ public class CoinsCommand {
private final CommandArgument<CommandSender, BukkitCommandContext, Integer> amountArg;
public CoinsCommand() {
this.rootNode = ScrowAPI.getCommandManager().createNode("coins");
this.rootNode = ScrowAPI.getCommandManager().createNode("coins", "eco");
this.playerArg = ScrowAPI.getCommandManager().createArgument("player", OfflinePlayerArgumentType.getInstance());
this.amountArg = ScrowAPI.getCommandManager().createArgument("amount", new IntegerArgumentType<>());