mirror of
https://github.com/CivMC/Civ.git
synced 2026-07-15 15:18:04 +00:00
phase 5
This commit is contained in:
@@ -102,6 +102,7 @@ dependencies {
|
||||
proxyPlugin(project(path = ":plugins:announcements-velocity", configuration = "shadow"))
|
||||
proxyPlugin(project(path = ":plugins:kiragateway-velocity", configuration = "shadow"))
|
||||
proxyPlugin(project(path = ":plugins:namelayer-velocity", configuration = "shadow"))
|
||||
proxyPlugin(project(path = ":plugins:zorweth-velocity", configuration = "shadow"))
|
||||
}
|
||||
|
||||
val copyPaperPlugins = tasks.register<Copy>("copyPaperPlugins") {
|
||||
|
||||
@@ -584,7 +584,7 @@ public final class FlightComputer implements Listener {
|
||||
for (final RocketManifestPassenger passenger : manifest.passengers()) {
|
||||
if (Bukkit.getPlayer(passenger.playerUuid()) == null) {
|
||||
markPreparedTransferCancelled(manifest);
|
||||
clicker.sendMessage(Component.text("Passenger disconnected before launch commit completed.", NamedTextColor.RED));
|
||||
clicker.sendMessage(Component.text("Passenger disconnected before launch completed.", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
14
plugins/zorweth-velocity/build.gradle.kts
Normal file
14
plugins/zorweth-velocity/build.gradle.kts
Normal file
@@ -0,0 +1,14 @@
|
||||
plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
version = "1.0.0"
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.velocity.api)
|
||||
annotationProcessor(libs.velocity.api)
|
||||
|
||||
api(libs.configurate.yaml)
|
||||
api(libs.hikaricp)
|
||||
api(libs.mariadb.client)
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package net.civmc.zorweth.velocity;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.player.ServerPostConnectEvent;
|
||||
import com.velocitypowered.api.event.player.ServerPreConnectEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.configurate.CommentedConfigurationNode;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
@Plugin(id = "zorweth", name = "Zorweth", version = "1.0.0", authors = {"Okx"})
|
||||
public final class ZorwethVelocityPlugin {
|
||||
|
||||
private static final String TRANSFER_SOURCE_CLEARED = "SOURCE_CLEARED";
|
||||
private static final String TRANSFER_CLAIMED = "CLAIMED";
|
||||
private static final String TRANSFER_PREPARED = "PREPARED";
|
||||
|
||||
private final ProxyServer server;
|
||||
private final Logger logger;
|
||||
private final Path dataDirectory;
|
||||
private CommentedConfigurationNode config;
|
||||
private HikariDataSource dataSource;
|
||||
private RocketTransferRouter router;
|
||||
|
||||
@Inject
|
||||
public ZorwethVelocityPlugin(final ProxyServer server, final Logger logger,
|
||||
@DataDirectory final Path dataDirectory) {
|
||||
this.server = server;
|
||||
this.logger = logger;
|
||||
this.dataDirectory = dataDirectory;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProxyInitialization(final ProxyInitializeEvent event) {
|
||||
loadConfig();
|
||||
this.dataSource = createDataSource();
|
||||
this.router = new RocketTransferRouter(this.dataSource);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProxyShutdown(final ProxyShutdownEvent event) {
|
||||
if (this.dataSource != null) {
|
||||
this.dataSource.close();
|
||||
this.dataSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(priority = -1)
|
||||
public void onServerPreConnect(final ServerPreConnectEvent event) {
|
||||
final PendingTransfer transfer;
|
||||
try {
|
||||
transfer = this.router.getPendingTransfer(event.getPlayer().getUniqueId());
|
||||
} catch (final SQLException exception) {
|
||||
this.logger.error("Failed to look up pending rocket transfer", exception);
|
||||
routeToHoldingOrDisconnect(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (transfer == null || TRANSFER_PREPARED.equals(transfer.state())) {
|
||||
return;
|
||||
}
|
||||
if (!TRANSFER_SOURCE_CLEARED.equals(transfer.state()) && !TRANSFER_CLAIMED.equals(transfer.state())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Optional<RegisteredServer> destination = this.server.getServer(transfer.destinationServer());
|
||||
if (destination.isEmpty()) {
|
||||
routeToHoldingOrDisconnect(event);
|
||||
return;
|
||||
}
|
||||
event.setResult(ServerPreConnectEvent.ServerResult.allowed(destination.get()));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onServerPostConnect(final ServerPostConnectEvent event) {
|
||||
final Optional<ServerConnection> currentServer = event.getPlayer().getCurrentServer();
|
||||
if (currentServer.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.router.updateLastServer(
|
||||
event.getPlayer().getUniqueId(),
|
||||
currentServer.get().getServerInfo().getName()
|
||||
);
|
||||
} catch (final SQLException exception) {
|
||||
this.logger.error("Failed to update player last server", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void routeToHoldingOrDisconnect(final ServerPreConnectEvent event) {
|
||||
final String holdingServer = this.config.node("holding-server").getString("").trim();
|
||||
if (!holdingServer.isEmpty()) {
|
||||
final Optional<RegisteredServer> server = this.server.getServer(holdingServer);
|
||||
if (server.isPresent()) {
|
||||
event.setResult(ServerPreConnectEvent.ServerResult.allowed(server.get()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
event.getPlayer().disconnect(Component.text(
|
||||
this.config.node("failure-message").getString("Unable to verify your rocket transfer. Please reconnect and try again."),
|
||||
NamedTextColor.RED
|
||||
));
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
try {
|
||||
if (!Files.exists(this.dataDirectory)) {
|
||||
Files.createDirectories(this.dataDirectory);
|
||||
}
|
||||
final Path configFile = this.dataDirectory.resolve("config.yml");
|
||||
if (!Files.exists(configFile)) {
|
||||
try (InputStream input = getClass().getResourceAsStream("/config.yml")) {
|
||||
if (input == null) {
|
||||
throw new IllegalStateException("Default config.yml is missing");
|
||||
}
|
||||
Files.copy(input, configFile);
|
||||
}
|
||||
}
|
||||
this.config = YamlConfigurationLoader.builder().path(configFile).build().load();
|
||||
} catch (final IOException exception) {
|
||||
throw new RuntimeException("Could not load Zorweth Velocity config", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private HikariDataSource createDataSource() {
|
||||
final CommentedConfigurationNode database = this.config.node("database");
|
||||
final HikariConfig hikariConfig = new HikariConfig();
|
||||
hikariConfig.setJdbcUrl("jdbc:" + database.node("driver").getString("mariadb") + "://"
|
||||
+ database.node("host").getString("localhost") + ":"
|
||||
+ database.node("port").getInt(3306) + "/"
|
||||
+ database.node("database").getString("database"));
|
||||
hikariConfig.setConnectionTimeout(database.node("connection_timeout").getLong(10_000L));
|
||||
hikariConfig.setIdleTimeout(database.node("idle_timeout").getLong(600_000L));
|
||||
hikariConfig.setMaxLifetime(database.node("max_lifetime").getLong(7_200_000L));
|
||||
hikariConfig.setMaximumPoolSize(database.node("poolsize").getInt(5));
|
||||
hikariConfig.setUsername(database.node("user").getString("root"));
|
||||
final String password = database.node("password").getString("");
|
||||
if (!password.isBlank()) {
|
||||
hikariConfig.setPassword(password);
|
||||
}
|
||||
return new HikariDataSource(hikariConfig);
|
||||
}
|
||||
|
||||
private record PendingTransfer(String state, String destinationServer) {
|
||||
}
|
||||
|
||||
private static final class RocketTransferRouter {
|
||||
|
||||
private final HikariDataSource dataSource;
|
||||
|
||||
private RocketTransferRouter(final HikariDataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
private PendingTransfer getPendingTransfer(final UUID playerUuid) throws SQLException {
|
||||
try (Connection connection = this.dataSource.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("""
|
||||
SELECT rt.state, rt.destination_server
|
||||
FROM rocket_transfer_players rtp
|
||||
JOIN rocket_transfers rt ON rt.transfer_id = rtp.transfer_id
|
||||
WHERE rtp.player_uuid = ?
|
||||
AND rt.state IN ('PREPARED', 'SOURCE_CLEARED', 'CLAIMED')
|
||||
AND rtp.state IN ('PENDING', 'CLAIMED')
|
||||
ORDER BY rt.created_at DESC
|
||||
LIMIT 1
|
||||
""")) {
|
||||
statement.setString(1, playerUuid.toString());
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
if (!resultSet.next()) {
|
||||
return null;
|
||||
}
|
||||
return new PendingTransfer(
|
||||
resultSet.getString("state"),
|
||||
resultSet.getString("destination_server")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLastServer(final UUID playerUuid, final String serverName) throws SQLException {
|
||||
try (Connection connection = this.dataSource.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("""
|
||||
INSERT INTO player_server_state (player_uuid, last_server)
|
||||
VALUES (?, ?)
|
||||
ON DUPLICATE KEY UPDATE last_server = VALUES(last_server)
|
||||
""")) {
|
||||
statement.setString(1, playerUuid.toString());
|
||||
statement.setString(2, serverName);
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
plugins/zorweth-velocity/src/main/resources/config.yml
Normal file
14
plugins/zorweth-velocity/src/main/resources/config.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
database:
|
||||
driver: mariadb
|
||||
user: root
|
||||
password: root
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: database
|
||||
poolsize: 5
|
||||
connection_timeout: 10000
|
||||
idle_timeout: 600000
|
||||
max_lifetime: 7200000
|
||||
|
||||
holding-server: ""
|
||||
failure-message: "Unable to verify your rocket transfer. Please reconnect and try again."
|
||||
@@ -47,6 +47,7 @@ include(":plugins:kitpvp-paper")
|
||||
include(":plugins:voidworld-paper")
|
||||
include(":plugins:heliodor-paper")
|
||||
include(":plugins:zorweth-paper")
|
||||
include(":plugins:zorweth-velocity")
|
||||
include(":plugins:civproxy-velocity")
|
||||
include(":plugins:secureboot-paper")
|
||||
include(":plugins:kiragateway-velocity")
|
||||
|
||||
Reference in New Issue
Block a user