Migrate database to LuckPerms meta
This commit is contained in:
parent
870b495deb
commit
69099b2cec
11 changed files with 181 additions and 288 deletions
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright 2024 project-connecticut
|
Copyright 2024 ReconnectedCC
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ dependencies {
|
||||||
annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}")
|
annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}")
|
||||||
include "io.wispforest:owo-sentinel:${project.owo_version}"
|
include "io.wispforest:owo-sentinel:${project.owo_version}"
|
||||||
|
|
||||||
include implementation("org.postgresql:postgresql:${project.postgresql_version}")
|
compileOnly "net.luckperms:api:${project.luckpermsapi_version}"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ org.gradle.parallel=true
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.20.1
|
minecraft_version=1.20.1
|
||||||
yarn_mappings=1.20.1+build.10
|
yarn_mappings=1.20.1+build.10
|
||||||
loader_version=0.16.3
|
loader_version=0.16.5
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.7.0
|
mod_version=1.8.4
|
||||||
maven_group=cc.reconnected
|
maven_group=cc.reconnected
|
||||||
archives_base_name=rcc-server
|
archives_base_name=rcc-server
|
||||||
|
|
||||||
|
@ -18,4 +18,4 @@ fabric_version=0.92.2+1.20.1
|
||||||
|
|
||||||
owo_version=0.11.2+1.20
|
owo_version=0.11.2+1.20
|
||||||
|
|
||||||
postgresql_version=42.7.3
|
luckpermsapi_version=5.4
|
|
@ -1,10 +1,9 @@
|
||||||
package cc.reconnected.server;
|
package cc.reconnected.server;
|
||||||
|
|
||||||
import cc.reconnected.server.commands.RccCommand;
|
import cc.reconnected.server.commands.RccCommand;
|
||||||
import cc.reconnected.server.database.DatabaseClient;
|
|
||||||
import cc.reconnected.server.database.PlayerData;
|
import cc.reconnected.server.database.PlayerData;
|
||||||
import cc.reconnected.server.database.PlayerTable;
|
|
||||||
import cc.reconnected.server.events.PlayerWelcome;
|
import cc.reconnected.server.events.PlayerWelcome;
|
||||||
|
import cc.reconnected.server.events.Ready;
|
||||||
import cc.reconnected.server.http.ServiceServer;
|
import cc.reconnected.server.http.ServiceServer;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
@ -12,15 +11,15 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
|
import net.luckperms.api.LuckPerms;
|
||||||
|
import net.luckperms.api.LuckPermsProvider;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,14 +43,9 @@ public class RccServer implements ModInitializer {
|
||||||
return serviceServer;
|
return serviceServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DatabaseClient database = new DatabaseClient();
|
private LuckPerms luckPerms;
|
||||||
public DatabaseClient database() {
|
public LuckPerms luckPerms() {
|
||||||
return database;
|
return luckPerms;
|
||||||
}
|
|
||||||
|
|
||||||
private final PlayerTable playerTable = new PlayerTable();
|
|
||||||
public PlayerTable playerTable() {
|
|
||||||
return playerTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getTPS() {
|
public static float getTPS() {
|
||||||
|
@ -77,20 +71,17 @@ public class RccServer implements ModInitializer {
|
||||||
|
|
||||||
CommandRegistrationCallback.EVENT.register(RccCommand::register);
|
CommandRegistrationCallback.EVENT.register(RccCommand::register);
|
||||||
|
|
||||||
try {
|
|
||||||
// Jumpstart connection
|
|
||||||
database.connection();
|
|
||||||
playerTable.ensureDatabaseCreated();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error("Database error", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serviceServer = new ServiceServer();
|
serviceServer = new ServiceServer();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.error("Unable to start HTTP server", e);
|
LOGGER.error("Unable to start HTTP server", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
|
||||||
|
luckPerms = LuckPermsProvider.get();
|
||||||
|
Ready.READY.invoker().ready(server, luckPerms);
|
||||||
|
});
|
||||||
|
|
||||||
ServerTickEvents.END_SERVER_TICK.register(server -> {
|
ServerTickEvents.END_SERVER_TICK.register(server -> {
|
||||||
currentMspt = server.getTickTime();
|
currentMspt = server.getTickTime();
|
||||||
if (currentMspt != 0) {
|
if (currentMspt != 0) {
|
||||||
|
@ -106,23 +97,17 @@ public class RccServer implements ModInitializer {
|
||||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
currentPlayerCount = server.getCurrentPlayerCount() + 1;
|
currentPlayerCount = server.getCurrentPlayerCount() + 1;
|
||||||
var player = handler.getPlayer();
|
var player = handler.getPlayer();
|
||||||
var playerData = playerTable.getPlayerData(player.getUuid());
|
var playerData = PlayerData.getPlayer(player.getUuid());
|
||||||
if(playerData == null) {
|
playerData.set(PlayerData.KEYS.username, player.getName().getString());
|
||||||
// new player!
|
var firstJoinedDate = playerData.getDate(PlayerData.KEYS.firstJoinedDate);
|
||||||
playerData = new PlayerData(handler.getPlayer().getUuid());
|
boolean isNewPlayer = false;
|
||||||
playerData.firstJoinedDate(new Date());
|
if (firstJoinedDate == null) {
|
||||||
playerData.name(player.getName().getString());
|
playerData.setDate(PlayerData.KEYS.firstJoinedDate, new Date());
|
||||||
playerTable.updatePlayerData(playerData);
|
isNewPlayer = true;
|
||||||
|
}
|
||||||
|
if(isNewPlayer) {
|
||||||
PlayerWelcome.PLAYER_WELCOME.invoker().playerWelcome(player, playerData, server);
|
PlayerWelcome.PLAYER_WELCOME.invoker().playerWelcome(player, playerData, server);
|
||||||
|
LOGGER.info("Player {} joined for the first time!", player.getName().getString());
|
||||||
// TODO: make it customizable via config
|
|
||||||
broadcastMessage(server, Text.literal("Welcome " + player.getName().getString() + " to the server!").formatted(Formatting.LIGHT_PURPLE));
|
|
||||||
} else {
|
|
||||||
if (!playerData.name().equals(player.getName().getString())) {
|
|
||||||
playerData.name(player.getName().getString());
|
|
||||||
playerTable.updatePlayerData(playerData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,4 @@ import io.wispforest.owo.config.annotation.Config;
|
||||||
@Config(name = "rcc-server-config", wrapperName = "RccServerConfig")
|
@Config(name = "rcc-server-config", wrapperName = "RccServerConfig")
|
||||||
public class RccServerConfigModel {
|
public class RccServerConfigModel {
|
||||||
public short httpPort = 25581;
|
public short httpPort = 25581;
|
||||||
public String databaseUrl = "jdbc:postgresql://127.0.0.1:5432/rcc?user=myuser&password=mypassword";
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,7 @@ import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
import static net.minecraft.server.command.CommandManager.argument;
|
|
||||||
import static net.minecraft.server.command.CommandManager.*;
|
|
||||||
|
|
||||||
public class RccCommand {
|
public class RccCommand {
|
||||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) {
|
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) {
|
||||||
|
@ -21,13 +17,6 @@ public class RccCommand {
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
return 1;
|
return 1;
|
||||||
})
|
})
|
||||||
.then(literal("clearcache")
|
|
||||||
.executes(context -> {
|
|
||||||
RccServer.getInstance().playerTable().clearCache();
|
|
||||||
context.getSource().sendFeedback(() -> Text.literal("RCC PlayerTable cache cleared!"), false);
|
|
||||||
return 1;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package cc.reconnected.server.database;
|
|
||||||
|
|
||||||
import cc.reconnected.server.RccServer;
|
|
||||||
|
|
||||||
import java.sql.*;
|
|
||||||
|
|
||||||
public class DatabaseClient {
|
|
||||||
private Connection connection;
|
|
||||||
public Connection connection() throws SQLException {
|
|
||||||
if (connection == null || connection.isClosed()) {
|
|
||||||
connection = DriverManager.getConnection(RccServer.CONFIG.databaseUrl());
|
|
||||||
}
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +1,165 @@
|
||||||
package cc.reconnected.server.database;
|
package cc.reconnected.server.database;
|
||||||
|
|
||||||
|
import cc.reconnected.server.RccServer;
|
||||||
|
import net.luckperms.api.LuckPerms;
|
||||||
|
import net.luckperms.api.model.user.User;
|
||||||
|
import net.luckperms.api.node.Node;
|
||||||
|
import net.luckperms.api.node.NodeBuilder;
|
||||||
|
import net.luckperms.api.node.NodeType;
|
||||||
|
import net.luckperms.api.node.types.MetaNode;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.time.Instant;
|
||||||
import java.util.UUID;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class PlayerData {
|
public class PlayerData {
|
||||||
|
public static final String nodePrefix = "rcc";
|
||||||
|
|
||||||
|
private static LuckPerms luckPerms() {
|
||||||
|
return RccServer.getInstance().luckPerms();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KEYS {
|
||||||
|
public static final String username = "username";
|
||||||
|
public static final String discordId = "discord_id";
|
||||||
|
public static final String isBot = "is_bot";
|
||||||
|
public static final String isAlt = "is_alt";
|
||||||
|
public static final String pronouns = "pronouns";
|
||||||
|
public static final String firstJoinedDate = "first_joined_date";
|
||||||
|
public static final String supporterLevel = "supporter_level";
|
||||||
|
}
|
||||||
|
|
||||||
|
private final User lpUser;
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String name;
|
private String name;
|
||||||
private Date firstJoinedDate;
|
|
||||||
@Nullable
|
|
||||||
private String discordId;
|
|
||||||
|
|
||||||
private boolean isBot = false;
|
private Set<MetaNode> rawNodes;
|
||||||
private boolean isAlt = false;
|
private Map<String, String> nodes;
|
||||||
|
|
||||||
@Nullable
|
private PlayerData(UUID uuid, User lpUser) {
|
||||||
private String pronouns = null;
|
|
||||||
|
|
||||||
public PlayerData(UUID uuid) {
|
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
|
this.lpUser = lpUser;
|
||||||
|
|
||||||
|
refreshNodes();
|
||||||
|
|
||||||
|
RccServer.LOGGER.info("Player {} has the following RCC nodes", this.uuid);
|
||||||
|
nodes.forEach((key, value) -> {
|
||||||
|
RccServer.LOGGER.info("{}: {}", key, value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID uuid() {
|
public UUID getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public @Nullable String getUsername() {
|
||||||
if (name == null) {
|
var username = get(KEYS.username);
|
||||||
return uuid.toString();
|
if (username == null) {
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
return name;
|
return username;
|
||||||
}
|
|
||||||
public void name(@Nullable String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date firstJoinedDate() {
|
public String getEffectiveName() {
|
||||||
return firstJoinedDate;
|
var effName = getUsername();
|
||||||
}
|
if (effName == null)
|
||||||
public void firstJoinedDate(Date firstJoinedDate) {
|
return uuid.toString();
|
||||||
this.firstJoinedDate = firstJoinedDate;
|
return effName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable String discordId() {
|
public void refreshNodes() {
|
||||||
return discordId;
|
rawNodes = lpUser.getNodes(NodeType.META)
|
||||||
}
|
.parallelStream()
|
||||||
public void discordId(@Nullable String discordId) {
|
.filter(node -> node.getMetaKey().startsWith(nodePrefix + "."))
|
||||||
this.discordId = discordId;
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
nodes = rawNodes.stream().collect(Collectors.toMap(MetaNode::getMetaKey, MetaNode::getMetaValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBot() {
|
public void set(String key, @Nullable String value) {
|
||||||
return isBot;
|
var node = meta(key, value).build();
|
||||||
}
|
luckPerms().getUserManager().modifyUser(uuid, user -> {
|
||||||
public void isBot(boolean isBot) {
|
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals(key)));
|
||||||
this.isBot = isBot;
|
user.data().add(node);
|
||||||
|
refreshNodes();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAlt() {
|
public @Nullable String get(String key) {
|
||||||
return isAlt;
|
if (!nodes.containsKey(nodePrefix + "." + key))
|
||||||
}
|
return null;
|
||||||
public void isAlt(boolean isAlt) {
|
return nodes.get(nodePrefix + "." + key);
|
||||||
this.isAlt = isAlt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String pronouns() {
|
public @Nullable MetaNode getNode(String key) {
|
||||||
return pronouns;
|
return rawNodes.stream().filter(rawNode -> rawNode.getMetaKey().equals(key)).findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
public void pronouns(@Nullable String pronouns) {
|
|
||||||
this.pronouns = pronouns;
|
public void setBoolean(String key, boolean value) {
|
||||||
|
set(key, Boolean.toString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String key) {
|
||||||
|
if (!nodes.containsKey(nodePrefix + "." + key))
|
||||||
|
return false;
|
||||||
|
return Boolean.parseBoolean(nodes.get(nodePrefix + "." + key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String key, boolean defaultValue) {
|
||||||
|
if (!nodes.containsKey(nodePrefix + "." + key))
|
||||||
|
return defaultValue;
|
||||||
|
return Boolean.parseBoolean(nodes.get(nodePrefix + "." + key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(String key, Date date) {
|
||||||
|
var dateString = DateTimeFormatter.ISO_INSTANT.format(date.toInstant());
|
||||||
|
set(key, dateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate(String key) {
|
||||||
|
if (!nodes.containsKey(nodePrefix + "." + key))
|
||||||
|
return null;
|
||||||
|
var dateString = nodes.get(nodePrefix + "." + key);
|
||||||
|
var ta = DateTimeFormatter.ISO_INSTANT.parse(dateString);
|
||||||
|
return Date.from(Instant.from(ta));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(String key) {
|
||||||
|
luckPerms().getUserManager().modifyUser(uuid, user -> {
|
||||||
|
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals(nodePrefix + "." + key)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerData getPlayer(UUID uuid) {
|
||||||
|
var lp = luckPerms();
|
||||||
|
var userManager = lp.getUserManager();
|
||||||
|
|
||||||
|
var userFuture = userManager.loadUser(uuid);
|
||||||
|
// TODO: ouch, not good...
|
||||||
|
var lpUser = userFuture.join();
|
||||||
|
|
||||||
|
var playerData = new PlayerData(uuid, lpUser);
|
||||||
|
playerData.name = lpUser.getUsername();
|
||||||
|
return playerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerData getPlayer(ServerPlayerEntity player) {
|
||||||
|
var user = luckPerms().getPlayerAdapter(ServerPlayerEntity.class).getUser(player);
|
||||||
|
var playerData = new PlayerData(player.getUuid(), user);
|
||||||
|
playerData.name = player.getEntityName();
|
||||||
|
return playerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NodeBuilder<?, ?> node(String key) {
|
||||||
|
return Node.builder(nodePrefix + "." + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NodeBuilder<?, ?> meta(String key, String value) {
|
||||||
|
return MetaNode.builder(nodePrefix + "." + key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
package cc.reconnected.server.database;
|
|
||||||
|
|
||||||
import cc.reconnected.server.RccServer;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class PlayerTable {
|
|
||||||
private final HashMap<UUID, PlayerData> cache = new HashMap<>();
|
|
||||||
|
|
||||||
private DatabaseClient database() {
|
|
||||||
return RccServer.getInstance().database();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ensureDatabaseCreated() {
|
|
||||||
try {
|
|
||||||
var conn = database().connection();
|
|
||||||
|
|
||||||
var stmt = conn.prepareStatement(
|
|
||||||
"CREATE TABLE IF NOT EXISTS players (" +
|
|
||||||
"uuid UUID NOT NULL PRIMARY KEY," +
|
|
||||||
"firstJoined TIMESTAMP DEFAULT CURRENT_TIMESTAMP," +
|
|
||||||
"lastKnownName VARCHAR(16)," +
|
|
||||||
"discordId VARCHAR," +
|
|
||||||
"isBot BOOL DEFAULT FALSE," +
|
|
||||||
"isAlt BOOL DEFAULT FALSE," +
|
|
||||||
"pronouns VARCHAR DEFAULT NULL" +
|
|
||||||
");");
|
|
||||||
|
|
||||||
stmt.executeUpdate();
|
|
||||||
stmt.close();
|
|
||||||
|
|
||||||
} catch (SQLException e) {
|
|
||||||
RccServer.LOGGER.error("Could not create players data tables", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshPlayerData(UUID uuid) {
|
|
||||||
cache.remove(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearCache() {
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean exists(UUID uuid) {
|
|
||||||
try {
|
|
||||||
var conn = database().connection();
|
|
||||||
|
|
||||||
var stmt = conn.prepareStatement("SELECT uuid FROM players WHERE uuid = ?;");
|
|
||||||
stmt.setObject(1, uuid);
|
|
||||||
var set = stmt.executeQuery();
|
|
||||||
var exists = set.next();
|
|
||||||
stmt.close();
|
|
||||||
|
|
||||||
return exists;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
RccServer.LOGGER.error("Could not get player data from database", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public PlayerData getPlayerData(UUID uuid) {
|
|
||||||
if (cache.containsKey(uuid)) {
|
|
||||||
return cache.get(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var conn = database().connection();
|
|
||||||
|
|
||||||
var stmt = conn.prepareStatement("SELECT * FROM players WHERE uuid = ?;");
|
|
||||||
stmt.setObject(1, uuid);
|
|
||||||
var set = stmt.executeQuery();
|
|
||||||
if (!set.next()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var playerData = new PlayerData(set.getObject("uuid", UUID.class));
|
|
||||||
var firstJoinTimestamp = set.getObject("firstJoined", Timestamp.class);
|
|
||||||
playerData.firstJoinedDate(new Date(firstJoinTimestamp.getTime()));
|
|
||||||
playerData.name(set.getString("lastKnownName"));
|
|
||||||
playerData.discordId(set.getString("discordId"));
|
|
||||||
playerData.isBot(set.getBoolean("isBot"));
|
|
||||||
playerData.isAlt(set.getBoolean("isAlt"));
|
|
||||||
playerData.pronouns(set.getString("pronouns"));
|
|
||||||
|
|
||||||
stmt.close();
|
|
||||||
|
|
||||||
cache.put(uuid, playerData);
|
|
||||||
return playerData;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
RccServer.LOGGER.error("Could not get player data from database", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean deletePlayerData(UUID uuid) {
|
|
||||||
cache.remove(uuid);
|
|
||||||
try {
|
|
||||||
var conn = database().connection();
|
|
||||||
|
|
||||||
var stmt = conn.prepareStatement("DELETE FROM players WHERE uuid = ?;");
|
|
||||||
stmt.setObject(1, uuid);
|
|
||||||
stmt.execute();
|
|
||||||
stmt.close();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch(SQLException e) {
|
|
||||||
RccServer.LOGGER.error("Could not delete player data from database", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean createPlayerData(PlayerData playerData) {
|
|
||||||
if(exists(playerData.uuid())) {
|
|
||||||
return updatePlayerData(playerData);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.put(playerData.uuid(), playerData);
|
|
||||||
|
|
||||||
try {
|
|
||||||
var conn = database().connection();
|
|
||||||
|
|
||||||
var stmt = conn.prepareStatement("INSERT INTO players(uuid, firstJoined, lastKnownName, discordId, isBot, isAlt, pronouns) VALUES (?,?,?,?,?,?,?);");
|
|
||||||
stmt.setObject(1, playerData.uuid());
|
|
||||||
var timestamp = new Timestamp(playerData.firstJoinedDate().getTime());
|
|
||||||
stmt.setTimestamp(2, timestamp);
|
|
||||||
stmt.setString(3, playerData.name());
|
|
||||||
stmt.setString(4, playerData.discordId());
|
|
||||||
stmt.setBoolean(5, playerData.isBot());
|
|
||||||
stmt.setBoolean(6, playerData.isAlt());
|
|
||||||
stmt.setString(7, playerData.pronouns());
|
|
||||||
stmt.execute();
|
|
||||||
stmt.close();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch(SQLException e) {
|
|
||||||
RccServer.LOGGER.error("Could not create player data from database", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean updatePlayerData(PlayerData playerData) {
|
|
||||||
if(!exists(playerData.uuid())) {
|
|
||||||
return createPlayerData(playerData);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.put(playerData.uuid(), playerData);
|
|
||||||
|
|
||||||
try {
|
|
||||||
var conn = database().connection();
|
|
||||||
|
|
||||||
var stmt = conn.prepareStatement("UPDATE players SET lastknownname = ?, discordid = ?, isBot = ?, isAlt = ?, pronouns = ? WHERE uuid = ?");
|
|
||||||
//var stmt = conn.prepareStatement("INSERT INTO players(uuid, firstJoined, lastKnownName, discordId, isBot, isAlt, pronouns) VALUES (?,?,?,?,?,?,?);");
|
|
||||||
stmt.setString(1, playerData.name());
|
|
||||||
stmt.setString(2, playerData.discordId());
|
|
||||||
stmt.setBoolean(3, playerData.isBot());
|
|
||||||
stmt.setBoolean(4, playerData.isAlt());
|
|
||||||
stmt.setString(5, playerData.pronouns());
|
|
||||||
stmt.setObject(6, playerData.uuid());
|
|
||||||
stmt.execute();
|
|
||||||
stmt.close();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
RccServer.LOGGER.error("Could not update player data on database", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
src/main/java/cc/reconnected/server/events/Ready.java
Normal file
17
src/main/java/cc/reconnected/server/events/Ready.java
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package cc.reconnected.server.events;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.luckperms.api.LuckPerms;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
|
public interface Ready {
|
||||||
|
Event<Ready> READY = EventFactory.createArrayBacked(Ready.class,
|
||||||
|
(listeners) -> (server, luckPerms) -> {
|
||||||
|
for (Ready listener : listeners) {
|
||||||
|
listener.ready(server, luckPerms);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
void ready(MinecraftServer server, LuckPerms luckPerms);
|
||||||
|
}
|
|
@ -6,7 +6,8 @@
|
||||||
"description": "Server mod for the ReconnectedCC Minecraft server",
|
"description": "Server mod for the ReconnectedCC Minecraft server",
|
||||||
"authors": [
|
"authors": [
|
||||||
"AlexDevs",
|
"AlexDevs",
|
||||||
"EmmaKnijn"
|
"EmmaKnijn",
|
||||||
|
"ReconnectedCC"
|
||||||
],
|
],
|
||||||
"contact": {
|
"contact": {
|
||||||
"sources": "https://github.com/ReconnectedCC/rcc-server"
|
"sources": "https://github.com/ReconnectedCC/rcc-server"
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
"fabricloader": ">=0.16.0",
|
"fabricloader": ">=0.16.0",
|
||||||
"minecraft": "~1.20.1",
|
"minecraft": "~1.20.1",
|
||||||
"java": ">=17",
|
"java": ">=17",
|
||||||
"fabric-api": "*"
|
"fabric-api": "*",
|
||||||
|
"luckperms": ">=5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue