This commit is contained in:
kento2 2026-07-05 03:06:15 +02:00
parent ea6ae529cc
commit 7040a6ce1e
20 changed files with 135 additions and 83 deletions

View file

@ -2,33 +2,30 @@ package de.kentoj.scrow.bukkit;
import de.kentoj.scrow.bukkit.economy.command.CoinsCommand;
import de.kentoj.scrow.bukkit.friends.command.FriendCommand;
import de.kentoj.scrow.bukkit.instancemanager.cache.InstanceCache;
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;
import de.kentoj.scrow.bukkit.server.PlayCommand;
import de.kentoj.scrow.bukkit.instancemanager.command.LobbyCommand;
import de.kentoj.scrow.bukkit.instancemanager.command.PlayCommand;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class CoreImplPlugin extends JavaPlugin {
public static boolean ENABLE_DATABASE = false;
@Override
public void onEnable() {
ScrowAPISurface.initScrowAPI(this, ENABLE_DATABASE);
ScrowAPISurface.initScrowAPI(this, true);
{
ScrowAPI.getCommandApi().register(new CoinsCommand().getRootNode());
ScrowAPI.getCommandApi().register(FriendCommand.create());
ScrowAPI.getCommandApi().register(InstanceCommand.create());
var instanceCache = new InstanceCache();
ScrowAPI.getCommandApi().register(InstanceCommand.create(instanceCache));
ScrowAPI.getCommandApi().register(new PlayCommand().getRootNode());
ScrowAPI.getCommandApi().register(new LobbyCommand().getRootNode());
}

View file

@ -17,9 +17,13 @@ import io.nats.client.Options;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.bukkit.plugin.Plugin;
import org.jdbi.v3.core.ConnectionFactory;
import org.jdbi.v3.core.Jdbi;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
@NoArgsConstructor(access = AccessLevel.NONE)
public class ScrowAPISurface {
@ -39,7 +43,14 @@ public class ScrowAPISurface {
}
if (enableDatabase) {
ScrowAPI.setJdbi(Jdbi.create(EnvUtils.envOrThrow("HOST_POSTGRES")));
try {
Class.forName("org.postgresql.Driver", true, ScrowAPISurface.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
var props = new Properties();
props.setProperty("user", "postgres");
ScrowAPI.setJdbi(Jdbi.create(EnvUtils.envOrThrow("HOST_POSTGRES"), props));
}
ScrowAPI.setPlayerManager(new PlayerManagerImpl());

View file

@ -45,12 +45,12 @@ public class FriendAddLiteral implements CommandExecutor<CommandSender> {
var self = (Player) ctx.getSender();
var other = ctx.getArg(playerArg);
return Tasks.supplyAsync(() -> findAction(self, other)
.mapSuccess(action -> {
if (action == AddAction.SEND_REQUEST) sendRequest(self, other);
else if (action == AddAction.ACCEPT_REQUEST) acceptRequest(self, other);
return new Object();
})
).toFuture();
.mapSuccess(action -> {
if (action == AddAction.SEND_REQUEST) sendRequest(self, other);
else if (action == AddAction.ACCEPT_REQUEST) acceptRequest(self, other);
return new Object();
}))
.toFuture();
}
private void sendRequest(Player self, OfflinePlayer other) {

View file

@ -27,9 +27,9 @@ public class PostgresFriendshipService implements FriendshipService {
jdbi = ScrowAPI.getJdbi();
jdbi.useHandle(h -> h.execute("""
CREATE TABLE IF NOT EXISTS friendships (
first_uuid UUID NOT NULL,
second_uuid UUID NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
first_uuid UUID NOT NULL,
second_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)

View file

@ -25,13 +25,13 @@ public class PostgresFriendRequestService implements FriendRequestService {
jdbi = ScrowAPI.getJdbi();
jdbi.useHandle(h -> h.execute("""
CREATE TABLE IF NOT EXISTS friend-requests (
CREATE TABLE IF NOT EXISTS friendrequests (
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)
created_at TIMESTAMPTZ NOT NULL,
PRIMARY KEY (from_uuid, to_uuid),
CONSTRAINT friendship_no_self_request
CHECK (from_uuid <> to_uuid)
)
"""));
}
@ -40,7 +40,7 @@ public class PostgresFriendRequestService implements FriendRequestService {
public @Nullable FriendRequest getFriendRequest(UUID from, UUID to) {
return jdbi.withHandle(h -> h.createQuery("""
SELECT *
FROM friend-requests
FROM friendrequests
WHERE from_uuid = :from AND to_uuid = :to
""")
.bind("from", from)
@ -53,11 +53,12 @@ public class PostgresFriendRequestService implements FriendRequestService {
@Override
public boolean saveFriendRequest(FriendRequest friendRequest) {
return jdbi.withHandle(h -> h.createUpdate("""
INSERT INTO friend-requests (from_uuid, to_uuid, created_at)
VALUES (:from, :to, :created_at)
INSERT INTO friendrequests (from_uuid, to_uuid, created_at)
VALUES (:from, :to, :createdAt)
""")
.bind("from", friendRequest.getFrom())
.bind("to", friendRequest.getTo())
.bind("createdAt", friendRequest.getCreatedAt())
.execute() > 0);
}
@ -65,7 +66,7 @@ public class PostgresFriendRequestService implements FriendRequestService {
public List<FriendRequest> getFriendRequestsTo(UUID playerId) {
return jdbi.withHandle(h -> h.createQuery("""
SELECT *
FROM friend-requests
FROM friendrequests
WHERE to_uuid = :to
""")
.bind("to", playerId)
@ -77,7 +78,7 @@ public class PostgresFriendRequestService implements FriendRequestService {
public List<FriendRequest> getFriendRequestsFrom(UUID playerId) {
return jdbi.withHandle(h -> h.createQuery("""
SELECT *
FROM friend-requests
FROM friendrequests
WHERE from_uuid = :from
""")
.bind("from", playerId)
@ -89,7 +90,7 @@ public class PostgresFriendRequestService implements FriendRequestService {
public boolean deleteFriendRequest(UUID from, UUID to) {
return jdbi.withHandle(h -> h.createUpdate("""
DELETE
FROM friend-requests
FROM friendrequests
WHERE from_uuid = :from AND to_uuid = :to
""")
.bind("from", from)

View file

@ -0,0 +1,44 @@
package de.kentoj.scrow.bukkit.instancemanager.cache;
import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrowlib.instancemanager.ServerInstance;
import de.kentoj.scrowlib.messaging.MessageBroker;
import org.bson.Document;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class InstanceCache {
private final MessageBroker messageBroker = ScrowAPI.getMessageBroker();
private final ConcurrentMap<String, ServerInstance> cache = new ConcurrentHashMap<>();
public InstanceCache() {
messageBroker.subscribe("event.instance.up", doc -> {
var inst = toInstance(doc);
cache.put(inst.getHandle(), inst);
});
messageBroker.subscribe("event.instance.down", doc -> {
cache.remove(doc.getString("handle"));
});
}
public Collection<ServerInstance> getInstances() {
return cache.values();
}
public @Nullable ServerInstance getInstance(String handle) {
return cache.get(handle);
}
private ServerInstance toInstance(Document doc) {
return new ServerInstance(
doc.getString("handle"),
doc.getString("template"),
doc.getInteger("port")
);
}
}

View file

@ -2,6 +2,7 @@ package de.kentoj.scrow.bukkit.instancemanager.command;
import de.kentoj.kencommandapi.api.node.CommandNode;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import de.kentoj.scrow.bukkit.instancemanager.cache.InstanceCache;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@ -10,12 +11,12 @@ import org.bukkit.command.CommandSender;
@NoArgsConstructor(access = AccessLevel.NONE)
public class InstanceCommand {
public static RootCommandNode<CommandSender> create() {
public static RootCommandNode<CommandSender> create(InstanceCache instanceCache) {
var style = new ScrowMessageStyle("server-manager", NamedTextColor.RED);
RootCommandNode<CommandSender> 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());
rootNode.addLiteral(new InstanceDestroyLiteral(instanceCache, style).getLiteral());
return rootNode;
}
}

View file

@ -8,6 +8,7 @@ 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.instancemanager.cache.InstanceCache;
import de.kentoj.scrow.bukkit.scheduler.Tasks;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.scrowlib.instancemanager.ServerInstance;
@ -23,16 +24,13 @@ public class InstanceDestroyLiteral implements CommandExecutor<CommandSender> {
private final CommandArgument<CommandSender, String> handleArg;
private final ScrowMessageStyle style;
public InstanceDestroyLiteral(ScrowMessageStyle style) {
public InstanceDestroyLiteral(InstanceCache cache, 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());
handleArg.setSuggestionProvider(ctx -> cache.getInstances().stream()
.map(ServerInstance::getHandle)
.toList());
literal = CommandNode.node("destroy");
literal.addArgument(handleArg);
literal.setExecutor(this);

View file

@ -1,4 +1,4 @@
package de.kentoj.scrow.bukkit.server;
package de.kentoj.scrow.bukkit.instancemanager.command;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;

View file

@ -1,4 +1,4 @@
package de.kentoj.scrow.bukkit.server;
package de.kentoj.scrow.bukkit.instancemanager.command;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;