From b0d4a7d061eca699c043f4be541b3e2a0e80616c Mon Sep 17 00:00:00 2001 From: kento2 Date: Sat, 27 Jun 2026 16:46:30 +0200 Subject: [PATCH] gradle sucks etc --- README.md | 1 + build.gradle.kts | 12 +- core-bukkit-api/build.gradle.kts | 1 - .../java/de/kentoj/scrow/bukkit/ScrowAPI.java | 14 +-- .../scrow/bukkit/minigame/MinigameInfo.java | 12 ++ core-bukkit-impl/build.gradle.kts | 14 ++- .../kentoj/scrow/bukkit/ScrowAPISurface.java | 58 ++++------ .../economy/PostgresEconomyService.java | 86 +++++++++++++++ .../friends/command/FriendAddLiteral.java | 9 +- .../friendship/PostgresFriendshipService.java | 96 ++++++++++++++++ .../request/PostgresFriendRequestService.java | 104 ++++++++++++++++++ .../src/main/resources/plugin.yml | 4 +- core-lib/build.gradle.kts | 1 - .../connection/DatabaseConnectionFactory.java | 8 ++ .../DatabaseConnectionFactoryImpl.java | 31 ++++++ .../scrowlib/messaging/NatsRepository.java | 7 +- .../messaging/SubscriptionContext.java | 3 +- .../messaging/respose/SafeResult.java | 7 ++ core-velocity-api/build.gradle.kts | 1 - .../de/kentoj/scrow/velocity/ScrowAPI.java | 14 +-- core-velocity-impl/build.gradle.kts | 24 +++- .../corevelocity/CoreVelocityPlugin.java | 5 +- .../scrow/corevelocity/ScrowAPISurface.java | 35 ++---- .../{ => server}/SendPlayerWatchdog.java | 8 +- .../{ => server}/ServerRegisterWatchdog.java | 31 +++--- 25 files changed, 463 insertions(+), 123 deletions(-) create mode 100644 core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameInfo.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/PostgresEconomyService.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/friendship/PostgresFriendshipService.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/request/PostgresFriendRequestService.java create mode 100644 core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactory.java create mode 100644 core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactoryImpl.java rename core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/{ => server}/SendPlayerWatchdog.java (79%) rename core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/{ => server}/ServerRegisterWatchdog.java (56%) diff --git a/README.md b/README.md index ebae924..7127db9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ TODO +- cleanup nats - timeout/error handling with reactive - djb's multilogd for logging(?) diff --git a/build.gradle.kts b/build.gradle.kts index 0574e8a..eff1891 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } group = "de.kentoj.scrow" -version = "1.0-SNAPSHOT" +version = "1.0.0" repositories { mavenCentral() @@ -18,6 +18,8 @@ subprojects { apply(plugin = "java") apply(plugin = "io.freefair.lombok") + version = rootProject.version + java { withSourcesJar() withJavadocJar() @@ -49,6 +51,14 @@ subprojects { // https://www.mongodb.com/docs/languages/java/reactive-streams-driver/current/get-started/download-and-install/ implementation(platform("org.mongodb:mongodb-driver-bom:5.6.1")) implementation("org.mongodb:mongodb-driver-reactivestreams") + + // https://mvnrepository.com/artifact/org.postgresql/r2dbc-postgresql + // TODO remove or fully switch to postgres + implementation("org.postgresql:r2dbc-postgresql:1.1.1.RELEASE") + // https://mvnrepository.com/artifact/org.springframework.data/spring-data-r2dbc + implementation("org.springframework.data:spring-data-r2dbc:4.1.0-RC1") + // https://mvnrepository.com/artifact/io.r2dbc/r2dbc-pool + implementation("io.r2dbc:r2dbc-pool:1.0.2.RELEASE") } } diff --git a/core-bukkit-api/build.gradle.kts b/core-bukkit-api/build.gradle.kts index 601d24e..2c6df38 100644 --- a/core-bukkit-api/build.gradle.kts +++ b/core-bukkit-api/build.gradle.kts @@ -5,7 +5,6 @@ plugins { } group = "de.kentoj.scrow" -version = "1.0-SNAPSHOT" repositories { mavenCentral() 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 c794f68..c733445 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 @@ -1,9 +1,9 @@ package de.kentoj.scrow.bukkit; -import com.mongodb.reactivestreams.client.MongoDatabase; import de.kentoj.kencommandapi.BukkitKenCommandApi; import de.kentoj.scrow.bukkit.friends.FriendRequestService; import de.kentoj.scrow.bukkit.friends.FriendshipService; +import de.kentoj.scrowlib.connection.DatabaseConnectionFactory; import de.kentoj.scrowlib.servermanager.ServerManager; import io.nats.client.Connection; import lombok.AccessLevel; @@ -17,7 +17,7 @@ import reactor.core.scheduler.Scheduler; public class ScrowAPI { @Getter - private static @Nullable MongoDatabase database; + private static DatabaseConnectionFactory dbConFactory; @Getter private static BukkitKenCommandApi commandApi; @Getter @@ -33,11 +33,6 @@ public class ScrowAPI { @Getter private static ServerManager serverManager; - @ApiStatus.Internal - public static void setDatabase(@Nullable MongoDatabase database) { - ScrowAPI.database = database; - } - @ApiStatus.Internal public static void setEconomyService(EconomyService economyService) { ScrowAPI.economyService = economyService; @@ -72,5 +67,10 @@ public class ScrowAPI { public static void setServerManager(ServerManager serverManager) { ScrowAPI.serverManager = serverManager; } + + @ApiStatus.Internal + public static void setDbConFactory(@Nullable DatabaseConnectionFactory dbConFactory) { + ScrowAPI.dbConFactory = dbConFactory; + } } 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 new file mode 100644 index 0000000..5cefd7c --- /dev/null +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameInfo.java @@ -0,0 +1,12 @@ +package de.kentoj.scrow.bukkit.minigame; + +import de.kentoj.scrowlib.servermanager.ServerInstance; + +public interface MinigameInfo { + + String getName(); + + int getPlayerCount(); + + ServerInstance getServerInstance(); +} diff --git a/core-bukkit-impl/build.gradle.kts b/core-bukkit-impl/build.gradle.kts index 8b8fdee..089ef74 100644 --- a/core-bukkit-impl/build.gradle.kts +++ b/core-bukkit-impl/build.gradle.kts @@ -6,7 +6,6 @@ plugins { } group = "de.kentoj.scrow" -version = "1.0-SNAPSHOT" repositories { mavenCentral() @@ -16,9 +15,6 @@ dependencies { implementation(project(":core-bukkit-api")) implementation(kotlin("stdlib-jdk8")) - - //implementation("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT") - //implementation("de.kentoj.scrow:kencommandapi-bukkit:0.8") } tasks { @@ -31,6 +27,14 @@ tasks { } } +tasks.processResources { + filesMatching("plugin.yml") { + expand(mapOf( + "version" to project.version.toString() + )) + } +} + tasks.build { dependsOn("shadowJar") -} +} \ No newline at end of file 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 6771c0b..d0ff9e5 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 @@ -1,27 +1,23 @@ package de.kentoj.scrow.bukkit; -import com.mongodb.ConnectionString; -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.economy.InMemoryEconomyService; -import de.kentoj.scrow.bukkit.economy.MongoEconomyService; +import de.kentoj.scrow.bukkit.economy.PostgresEconomyService; import de.kentoj.scrow.bukkit.friends.friendship.InMemoryFriendshipService; -import de.kentoj.scrow.bukkit.friends.friendship.MongoFriendshipService; +import de.kentoj.scrow.bukkit.friends.friendship.PostgresFriendshipService; import de.kentoj.scrow.bukkit.friends.request.InMemoryFriendRequestService; -import de.kentoj.scrow.bukkit.friends.request.MongoFriendRequestService; +import de.kentoj.scrow.bukkit.friends.request.PostgresFriendRequestService; +import de.kentoj.scrowlib.connection.DatabaseConnectionFactoryImpl; import de.kentoj.scrowlib.servermanager.ServerManagerImpl; 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.bson.UuidRepresentation; -import org.bson.codecs.configuration.CodecRegistries; -import org.bson.codecs.pojo.PojoCodecProvider; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.Nullable; +import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import java.io.IOException; @@ -29,8 +25,6 @@ import java.io.IOException; @NoArgsConstructor(access = AccessLevel.NONE) public class ScrowAPISurface { - private static @Nullable MongoClient mongoClient; - public static void initScrowAPI(Plugin plugin, boolean enableDatabase) { ScrowAPI.setMinecraftScheduler(Schedulers.fromExecutor(cmd -> { Bukkit.getScheduler().runTask(plugin, cmd); @@ -48,39 +42,25 @@ public class ScrowAPISurface { } if (enableDatabase) { - var pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build(); - var codecRegistry = CodecRegistries.fromRegistries( - MongoClientSettings.getDefaultCodecRegistry(), - CodecRegistries.fromProviders(pojoCodecProvider) - ); - String mongoHost = System.getenv("HOST_MONGO"); - var settings = MongoClientSettings.builder() - .codecRegistry(codecRegistry) - .uuidRepresentation(UuidRepresentation.STANDARD) - .applyConnectionString(new ConnectionString(mongoHost)) - .build(); - - mongoClient = MongoClients.create(settings); - ScrowAPI.setDatabase(mongoClient.getDatabase("scrow")); + ConnectionFactory factory = ConnectionFactories.get(System.getenv("HOST_POSTGRES")); + ScrowAPI.setDbConFactory(new DatabaseConnectionFactoryImpl(factory)); } ScrowAPI.setServerManager(new ServerManagerImpl(ScrowAPI.getNats())); - - ScrowAPI.setEconomyService(ScrowAPI.getDatabase() != null ? - new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService()); - - ScrowAPI.setFriendRequestService(ScrowAPI.getDatabase() != null ? - new MongoFriendRequestService(ScrowAPI.getDatabase()) : new InMemoryFriendRequestService()); - - ScrowAPI.setFriendshipService(ScrowAPI.getDatabase() != null ? - new MongoFriendshipService(ScrowAPI.getDatabase()) : new InMemoryFriendshipService()); - + ScrowAPI.setEconomyService(ScrowAPI.getDbConFactory() != null ? + new PostgresEconomyService(ScrowAPI.getDbConFactory()) : new InMemoryEconomyService()); + ScrowAPI.setFriendRequestService(ScrowAPI.getDbConFactory() != null ? + new PostgresFriendRequestService(ScrowAPI.getDbConFactory()) : new InMemoryFriendRequestService()); + ScrowAPI.setFriendshipService(ScrowAPI.getDbConFactory() != null ? + new PostgresFriendshipService(ScrowAPI.getDbConFactory()) : new InMemoryFriendshipService()); ScrowAPI.setCommandApi(new BukkitKenCommandApi()); } public static void destroyScrowAPI() { - if (mongoClient != null) { - mongoClient.close(); + try { + ScrowAPI.getDbConFactory().close(); + } catch (Exception e) { + throw new RuntimeException(e); } } } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/PostgresEconomyService.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/PostgresEconomyService.java new file mode 100644 index 0000000..a39a145 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/economy/PostgresEconomyService.java @@ -0,0 +1,86 @@ +package de.kentoj.scrow.bukkit.economy; + +import com.google.common.base.Preconditions; +import de.kentoj.scrow.bukkit.EconomyService; +import de.kentoj.scrowlib.connection.DatabaseConnectionFactory; +import org.jetbrains.annotations.NotNull; +import reactor.core.publisher.Mono; + +import java.util.UUID; + +// TODO log operations to separate table +public class PostgresEconomyService implements EconomyService { + + private final DatabaseConnectionFactory conFactory; + + public PostgresEconomyService(DatabaseConnectionFactory conFactory) { + this.conFactory = conFactory; + conFactory.create().sql(""" + CREATE TABLE IF NOT EXISTS economy ( + playerId UUID NOT NULL, + balance INTEGER NOT NULL DEFAULT 0, + PRIMARY KEY(playerId) + ) + """).then().block(); + } + + @Override + public Mono<@NotNull Integer> getCoins(UUID playerId) { + return conFactory.create() + .sql(""" + SELECT balance + FROM economy + WHERE playerId = :playerId + """) + .bind("playerId", playerId) + .map(row -> row.get("balance", Integer.class)) + .one(); + } + + @Override + public Mono<@NotNull Void> setCoins(UUID playerId, int amount) { + Preconditions.checkArgument(amount >= 0, "amount can not be negative"); + return conFactory.create().sql(""" + INSERT INTO economy (playerId, balance) + VALUES (:playerId, :amount) + ON CONFLICT (playerId) + DO UPDATE + SET balance = :amount + WHERE economy.playerId = :playerId + """) + .bind("playerId", playerId) + .bind("amount", amount) + .then(); + } + + @Override + public Mono<@NotNull Void> depositCoins(UUID playerId, int amount) { + Preconditions.checkArgument(amount >= 0, "amount can not be negative"); + return conFactory.create().sql(""" + INSERT INTO economy (playerId, balance) + VALUES (:playerId, :amount) + ON CONFLICT (playerId) + DO UPDATE + SET balance = economy.balance + EXCLUDED.balance + WHERE economy.playerId = :playerId + """) + .bind("playerId", playerId) + .bind("amount", amount) + .then(); + } + + @Override + public Mono<@NotNull Boolean> tryWithdrawCoins(UUID playerId, int amount) { + Preconditions.checkArgument(amount >= 0, "amount can not be negative"); + return conFactory.create().sql(""" + UPDATE economy + SET balance = balance - :amount + WHERE playerId = :playerId + """) + .bind("playerId", playerId) + .bind("amount", amount) + .fetch() + .rowsUpdated() + .map(updated -> updated > 0); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendAddLiteral.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendAddLiteral.java index 3afa2ac..d28a752 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendAddLiteral.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/command/FriendAddLiteral.java @@ -19,11 +19,10 @@ public class FriendAddLiteral implements CommandExecutor second_uuid) + ) + """).then().block(); + } + + @Override + public Mono<@NotNull Friendship> getFriendship(UUID uuid1, UUID uuid2) { + var uuids = new OrderedUUIDPair(uuid1, uuid2); + + return dbConFactory.create().sql(""" + SELECT first_uuid, second_uuid, created_at + FROM friendships + WHERE first_uuid = :first AND second_uuid = :second + """) + .bind("first", uuids.getFirst()) + .bind("second", uuids.getSecond()) + .map(row -> (Friendship) new FriendshipImpl( + row.get("first_uuid", UUID.class), + row.get("second_uuid", UUID.class), + row.get("created_at", Instant.class) + )) + .one(); + } + + @Override + public Flux<@NotNull Friendship> getFriendships(UUID playerId) { + return dbConFactory.create().sql(""" + SELECT first_uuid, second_uuid, created_at + FROM friendships + WHERE first_uuid = :playerId OR second_uuid = :playerId + """) + .bind("playerId", playerId) + .map((row, meta) -> (Friendship) new FriendshipImpl( + row.get("first_uuid", UUID.class), + row.get("second_uuid", UUID.class), + row.get("created_at", Instant.class) + )) + .all(); + } + + @Override + public Mono<@NotNull Boolean> saveFriendship(Friendship friendship) { + return dbConFactory.create().sql(""" + INSERT INTO friendships (first_uuid, second_uuid, created_at) + VALUES (:first, :second, :createdAt) + ON CONFLICT (first_uuid, second_uuid) DO NOTHING + """) + .bind("first", friendship.getUuids().getFirst()) + .bind("second", friendship.getUuids().getSecond()) + .bind("createdAt", friendship.getCreatedAt()) + .fetch() + .rowsUpdated() + .map(rows -> rows > 0); + } + + @Override + public Mono<@NotNull Boolean> deleteFriendship(UUID uuid1, UUID uuid2) { + var uuids = new OrderedUUIDPair(uuid1, uuid2); + + return dbConFactory.create().sql(""" + DELETE FROM friendships + WHERE first_uuid = :first AND second_uuid = :second + """) + .bind("first", uuids.getFirst()) + .bind("second", uuids.getSecond()) + .fetch() + .rowsUpdated() + .map(rows -> rows > 0); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/request/PostgresFriendRequestService.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/request/PostgresFriendRequestService.java new file mode 100644 index 0000000..17ea7c9 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/friends/request/PostgresFriendRequestService.java @@ -0,0 +1,104 @@ +package de.kentoj.scrow.bukkit.friends.request; + +import de.kentoj.scrow.bukkit.friends.FriendRequest; +import de.kentoj.scrow.bukkit.friends.FriendRequestService; +import de.kentoj.scrowlib.connection.DatabaseConnectionFactory; +import io.r2dbc.spi.Readable; +import org.jetbrains.annotations.NotNull; +import org.springframework.r2dbc.core.DatabaseClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.Instant; +import java.util.UUID; + +public class PostgresFriendRequestService implements FriendRequestService { + + private final DatabaseConnectionFactory conFactory; + + public PostgresFriendRequestService(DatabaseConnectionFactory conFactory) { + this.conFactory = conFactory; + conFactory.create().sql(""" + CREATE TABLE IF NOT EXISTS friend-requests ( + from_uuid UUID NOT NULL, + to_uuid UUID NOT NULL, + created_at TIMESTAMPTZ NOT NULL, + PRIMARY KEY (first_uuid, second_uuid), + CONSTRAINT friendship_no_self_friendship + CHECK (first_uuid <> second_uuid) + ) + """).then().block(); + } + + @Override + public Mono<@NotNull FriendRequest> getFriendRequest(UUID from, UUID to) { + return conFactory.create().sql(""" + SELECT * + FROM friend-requests + WHERE from_uuid = :from AND to_uuid = :to + """) + .bind("from", from) + .bind("to", to) + .map(this::parseFriendRequest) + .one(); + } + + @Override + public Mono<@NotNull Boolean> saveFriendRequest(FriendRequest friendRequest) { + return conFactory.create().sql(""" + INSERT INTO friend-requests (from_uuid, to_uuid, created_at) + VALUES (:from, :to, :created_at) + """) + .bind("from", friendRequest.getFrom()) + .bind("to", friendRequest.getTo()) + .fetch() + .rowsUpdated() + .map(cnt -> cnt > 0); + } + + @Override + public Flux<@NotNull FriendRequest> getFriendRequestsTo(UUID playerId) { + return conFactory.create().sql(""" + SELECT * + FROM friend-requests + WHERE to_uuid = :to + """) + .bind("to", playerId) + .map(this::parseFriendRequest) + .all(); + } + + @Override + public Flux<@NotNull FriendRequest> getFriendRequestsFrom(UUID playerId) { + return conFactory.create().sql(""" + SELECT * + FROM friend-requests + WHERE from_uuid = :from + """) + .bind("from", playerId) + .map(this::parseFriendRequest) + .all(); + } + + @Override + public Mono<@NotNull Boolean> deleteFriendRequest(UUID from, UUID to) { + return conFactory.create().sql(""" + DELETE + FROM friend-requests + WHERE from_uuid = :from AND to_uuid = :to + """) + .bind("from", from) + .bind("to", to) + .fetch() + .rowsUpdated() + .map(deleted -> deleted > 0); + } + + private FriendRequest parseFriendRequest(Readable row) { + return new FriendRequestImpl( + row.get("from_uuid", UUID.class), + row.get("to_uuid", UUID.class), + row.get("created_at", Instant.class) + ); + } +} \ No newline at end of file diff --git a/core-bukkit-impl/src/main/resources/plugin.yml b/core-bukkit-impl/src/main/resources/plugin.yml index d405e8f..8e79abd 100644 --- a/core-bukkit-impl/src/main/resources/plugin.yml +++ b/core-bukkit-impl/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: "CoreBukkit" -version: "1.0" +version: "${version}" main: "de.kentoj.scrow.bukkit.CoreImplPlugin" api-version: "1.21" -author: "Kento2 " \ No newline at end of file +author: "Kento2" \ No newline at end of file diff --git a/core-lib/build.gradle.kts b/core-lib/build.gradle.kts index c1b9e43..d27736c 100644 --- a/core-lib/build.gradle.kts +++ b/core-lib/build.gradle.kts @@ -8,7 +8,6 @@ plugins { } group = "de.kentoj.scrow" -version = "0.4" repositories { mavenCentral() 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 new file mode 100644 index 0000000..611e734 --- /dev/null +++ b/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactory.java @@ -0,0 +1,8 @@ +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 new file mode 100644 index 0000000..7853190 --- /dev/null +++ b/core-lib/src/main/java/de/kentoj/scrowlib/connection/DatabaseConnectionFactoryImpl.java @@ -0,0 +1,31 @@ +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/messaging/NatsRepository.java b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/NatsRepository.java index 359374c..8e8ba0b 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/NatsRepository.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/NatsRepository.java @@ -6,9 +6,12 @@ import io.nats.client.Dispatcher; import io.nats.client.Message; import org.bson.Document; import org.jetbrains.annotations.NotNull; +import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.concurrent.atomic.AtomicBoolean; + public class NatsRepository { private final Connection nats; @@ -34,15 +37,13 @@ public class NatsRepository { public Flux<@NotNull SubscriptionContext> subscribe(String subject) { return Flux.create(sink -> { - var handler = dispatcher.subscribe(subject, msg -> { + dispatcher.subscribe(subject, msg -> { try { sink.next(new SubscriptionContext(msg)); } catch (Throwable e) { sink.error(e); } }); - sink.onCancel(handler::unsubscribe); - sink.onDispose(handler::unsubscribe); }); } diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SubscriptionContext.java b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SubscriptionContext.java index 5382e93..7d00f05 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SubscriptionContext.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/SubscriptionContext.java @@ -1,6 +1,5 @@ package de.kentoj.scrowlib.messaging; -import de.kentoj.scrowlib.messaging.respose.SafeResult; import io.nats.client.Message; import lombok.AllArgsConstructor; import lombok.Value; @@ -13,6 +12,6 @@ public class SubscriptionContext { Document document; public SubscriptionContext(Message msg) { - this(msg, SafeResult.fromMessage(msg).unwrap()); + this(msg, DocumentRepository.fromMessage(msg)); } } diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/respose/SafeResult.java b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/respose/SafeResult.java index 6988f62..75a7504 100644 --- a/core-lib/src/main/java/de/kentoj/scrowlib/messaging/respose/SafeResult.java +++ b/core-lib/src/main/java/de/kentoj/scrowlib/messaging/respose/SafeResult.java @@ -3,6 +3,8 @@ package de.kentoj.scrowlib.messaging.respose; import de.kentoj.scrowlib.messaging.DocumentRepository; import io.nats.client.Message; import org.bson.Document; +import org.jetbrains.annotations.NotNull; +import reactor.core.publisher.Mono; public abstract sealed class SafeResult permits SafeErrorResult, SafeSuccessResult { @@ -61,4 +63,9 @@ public abstract sealed class SafeResult permits SafeErrorResult, SafeSuccessResu } throw new IllegalArgumentException("document does not conform to SafeDocument format"); } + + public static Mono<@NotNull SafeResult> mono(Mono<@NotNull Document> mono) { + return mono.map(SafeResult::wrap) + .onErrorResume(err -> Mono.just(SafeResult.wrap(err))); + } } diff --git a/core-velocity-api/build.gradle.kts b/core-velocity-api/build.gradle.kts index 5dc4e6d..e3ea402 100644 --- a/core-velocity-api/build.gradle.kts +++ b/core-velocity-api/build.gradle.kts @@ -5,7 +5,6 @@ plugins { } group = "de.kentoj.scrow" -version = "0.1" repositories { mavenCentral() 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 2d1e666..b93f81d 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,7 +1,7 @@ package de.kentoj.scrow.velocity; -import com.mongodb.reactivestreams.client.MongoDatabase; import de.kentoj.kencommandapi.VelocityKenCommandApi; +import de.kentoj.scrowlib.connection.DatabaseConnectionFactory; import de.kentoj.scrowlib.servermanager.ServerManager; import io.nats.client.Connection; import lombok.AccessLevel; @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; public class ScrowAPI { @Getter - private static @Nullable MongoDatabase database; + private static DatabaseConnectionFactory dbConFactory; @Getter private static VelocityKenCommandApi commandApi; @Getter @@ -22,11 +22,6 @@ public class ScrowAPI { @Getter private static ServerManager serverManager; - @ApiStatus.Internal - public static void setDatabase(@Nullable MongoDatabase database) { - ScrowAPI.database = database; - } - @ApiStatus.Internal public static void setCommandApi(VelocityKenCommandApi commandApi) { ScrowAPI.commandApi = commandApi; @@ -41,5 +36,10 @@ public class ScrowAPI { public static void setServerManager(ServerManager serverManager) { ScrowAPI.serverManager = serverManager; } + + @ApiStatus.Internal + public static void setDbConFactory(@Nullable DatabaseConnectionFactory dbConFactory) { + ScrowAPI.dbConFactory = dbConFactory; + } } diff --git a/core-velocity-impl/build.gradle.kts b/core-velocity-impl/build.gradle.kts index e255c74..330600a 100644 --- a/core-velocity-impl/build.gradle.kts +++ b/core-velocity-impl/build.gradle.kts @@ -4,7 +4,6 @@ plugins { } group = "de.kentoj.scrow" -version = "0.1" repositories { mavenCentral() @@ -25,4 +24,27 @@ dependencies { // http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-velocity implementation("de.kentoj.scrow:kencommandapi-velocity") +} + +val generateBuildInfo by tasks.registering { + val outputDir = layout.buildDirectory.dir("generated/sources/buildInfo") + outputs.dir(outputDir) + doLast { + val file = outputDir.get() + .file("de/kentoj/scrow/generated/BuildInfo.java") + .asFile + file.parentFile.mkdirs() + file.writeText( + """ + package de.kentoj.scrow.generated; + public final class BuildInfo { + private BuildInfo() {} + public static final String VERSION = "${project.version}"; + } + """.trimIndent() + ) + } +} +sourceSets.main { + java.srcDir(generateBuildInfo) } \ No newline at end of file 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 d12b002..74c5ec3 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 @@ -7,13 +7,16 @@ 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.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.velocity.ScrowAPI; import lombok.extern.java.Log; @Plugin( id = "corevelocity", name = "CoreVelocity", - version = "0.1" + version = BuildInfo.VERSION // may not resolve until building for the first time ) @Log public class CoreVelocityPlugin { 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 38e7fa0..a33d453 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 @@ -1,29 +1,22 @@ package de.kentoj.scrow.corevelocity; -import com.mongodb.ConnectionString; -import com.mongodb.MongoClientSettings; -import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; import com.velocitypowered.api.proxy.ProxyServer; import de.kentoj.kencommandapi.VelocityKenCommandApi; import de.kentoj.scrow.velocity.ScrowAPI; +import de.kentoj.scrowlib.connection.DatabaseConnectionFactoryImpl; import de.kentoj.scrowlib.servermanager.ServerManagerImpl; 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.bson.UuidRepresentation; -import org.bson.codecs.configuration.CodecRegistries; -import org.bson.codecs.pojo.PojoCodecProvider; -import org.jetbrains.annotations.Nullable; import java.io.IOException; @NoArgsConstructor(access = AccessLevel.NONE) public class ScrowAPISurface { - private static @Nullable MongoClient mongoClient; - public static void initScrowAPI(ProxyServer server, boolean enableDatabase) { try { String natsHost = System.getenv("HOST_NATS"); @@ -37,20 +30,8 @@ public class ScrowAPISurface { } if (enableDatabase) { - var pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build(); - var codecRegistry = CodecRegistries.fromRegistries( - MongoClientSettings.getDefaultCodecRegistry(), - CodecRegistries.fromProviders(pojoCodecProvider) - ); - String mongoHost = System.getenv("HOST_MONGO"); - var settings = MongoClientSettings.builder() - .codecRegistry(codecRegistry) - .uuidRepresentation(UuidRepresentation.STANDARD) - .applyConnectionString(new ConnectionString(mongoHost)) - .build(); - - mongoClient = MongoClients.create(settings); - ScrowAPI.setDatabase(mongoClient.getDatabase("scrow")); + ConnectionFactory factory = ConnectionFactories.get(System.getenv("HOST_POSTGRES")); + ScrowAPI.setDbConFactory(new DatabaseConnectionFactoryImpl(factory)); } ScrowAPI.setServerManager(new ServerManagerImpl(ScrowAPI.getNats())); @@ -59,8 +40,10 @@ public class ScrowAPISurface { } public static void destroyScrowAPI() { - if (mongoClient != null) { - mongoClient.close(); + try { + ScrowAPI.getDbConFactory().close(); + } catch (Exception e) { + throw new RuntimeException(e); } } } diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/SendPlayerWatchdog.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/SendPlayerWatchdog.java similarity index 79% rename from core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/SendPlayerWatchdog.java rename to core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/SendPlayerWatchdog.java index 88ca3f4..e85601c 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/SendPlayerWatchdog.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/SendPlayerWatchdog.java @@ -1,4 +1,4 @@ -package de.kentoj.scrow.corevelocity; +package de.kentoj.scrow.corevelocity.server; import com.velocitypowered.api.proxy.ProxyServer; import de.kentoj.scrowlib.messaging.NatsRepository; @@ -22,10 +22,8 @@ public class SendPlayerWatchdog { public void listen() { natsRepo.subscribe("proxy.send-player") - .flatMap(msg -> - handleSendPlayer(SafeResult.unwrap(msg)) - .flatMap(result -> natsRepo.publishSafeResult(msg.getReplyTo(), SafeResult.wrap(result))) - .onErrorResume(err -> natsRepo.publishSafeResult(msg.getReplyTo(), SafeResult.wrap(err))) + .flatMap(ctx -> + SafeResult.mono(handleSendPlayer(ctx.getDocument())) ) .subscribe(); } diff --git a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ServerRegisterWatchdog.java b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java similarity index 56% rename from core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ServerRegisterWatchdog.java rename to core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java index 576332a..7f5af50 100644 --- a/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/ServerRegisterWatchdog.java +++ b/core-velocity-impl/src/main/java/de/kentoj/scrow/corevelocity/server/ServerRegisterWatchdog.java @@ -1,13 +1,14 @@ -package de.kentoj.scrow.corevelocity; +package de.kentoj.scrow.corevelocity.server; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.server.ServerInfo; -import de.kentoj.scrowlib.messaging.DocumentRepository; import de.kentoj.scrowlib.messaging.NatsRepository; +import de.kentoj.scrowlib.messaging.SubscriptionContext; import de.kentoj.scrowlib.messaging.respose.SafeResult; import de.kentoj.scrowlib.servermanager.ServerManager; import io.nats.client.Connection; import lombok.extern.java.Log; +import org.bson.Document; import org.jetbrains.annotations.NotNull; import reactor.core.publisher.Mono; @@ -28,28 +29,26 @@ public class ServerRegisterWatchdog { public void listen() { natsRepo.subscribe("crown.set-state") - .map(SafeResult::unwrap) - .concatMap(doc -> { - var state = doc.getString("state"); - var handle = doc.getString("handle"); - return handleStateChange(state, handle); + .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)); } - private @NotNull Mono<@NotNull Void> handleStateChange(String state, String handle) { + private @NotNull Mono<@NotNull Void> handleStateChange(SubscriptionContext ctx, String state, String handle) { return switch (state) { case "UP" -> serverManager.getInfo(handle) - .doOnNext(instance -> { - log.info("registering " + handle); - server.registerServer(new ServerInfo(handle, new InetSocketAddress(instance.getPort()))); - }) + .doOnNext(instance -> + server.registerServer(new ServerInfo(handle, new InetSocketAddress(instance.getPort())))) .then(); case "DOWN" -> serverManager.getInfo(handle) - .doOnNext(instance -> { - log.info("unregistering " + handle); - server.unregisterServer(new ServerInfo(handle, new InetSocketAddress(instance.getPort()))); - }) + .doOnNext(instance -> + server.unregisterServer(new ServerInfo(handle, new InetSocketAddress(instance.getPort())))) .then(); default -> Mono.empty(); };