This commit is contained in:
okx-code
2026-05-13 04:50:36 +01:00
parent 896b8ec8ca
commit 6f95833481
6 changed files with 232 additions and 2 deletions

View File

@@ -30,7 +30,7 @@ dependencies {
paperPlugin(project(path = ":plugins:simpleadminhacks-paper"))
paperPlugin(project(path = ":plugins:heliodor-paper"))
paperPlugin(project(path = ":plugins:secureboot-paper"))
paperPlugin(project(path = ":plugins:zorweth-paper"))
paperPlugin(project(path = ":plugins:zorweth-paper", configuration = "shadow"))
zorwethPlugin(project(path = ":plugins:banstick-paper", configuration = "shadow"))
zorwethPlugin(project(path = ":plugins:bastion-paper"))
@@ -57,7 +57,7 @@ dependencies {
zorwethPlugin(project(path = ":plugins:simpleadminhacks-paper"))
zorwethPlugin(project(path = ":plugins:heliodor-paper"))
zorwethPlugin(project(path = ":plugins:secureboot-paper"))
zorwethPlugin(project(path = ":plugins:zorweth-paper"))
zorwethPlugin(project(path = ":plugins:zorweth-paper", configuration = "shadow"))
gammaPlugin(project(path = ":plugins:banstick-paper", configuration = "shadow"))
gammaPlugin(project(path = ":plugins:bastion-paper"))

View File

@@ -1,7 +1,12 @@
plugins {
alias(libs.plugins.shadow)
}
version = "1.0.0"
dependencies {
compileOnly(libs.paper.api)
compileOnly(project(":plugins:civmodcore-paper"))
api(project(":libraries:name-api"))
compileOnly(libs.worldedit)
}

View File

@@ -0,0 +1,16 @@
package net.civmc.zorweth;
import org.bukkit.NamespacedKey;
public final class RocketTransferKeys {
public static final NamespacedKey SOURCE_TRANSFER_ID = new NamespacedKey("zorweth", "source_transfer_id");
public static final NamespacedKey SOURCE_CLEARED = new NamespacedKey("zorweth", "source_cleared");
public static final NamespacedKey DESTINATION_TRANSFER_ID = new NamespacedKey("zorweth", "destination_transfer_id");
public static final NamespacedKey DESTINATION_APPLIED_LOCAL = new NamespacedKey("zorweth", "destination_applied_local");
public static final NamespacedKey SCHEMATIC_PASTED_LOCAL = new NamespacedKey("zorweth", "schematic_pasted_local");
public static final NamespacedKey CHESTS_APPLIED_LOCAL = new NamespacedKey("zorweth", "chests_applied_local");
private RocketTransferKeys() {
}
}

View File

@@ -1,19 +1,34 @@
package net.civmc.zorweth;
import com.google.common.base.Strings;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import javax.sql.DataSource;
import net.civmc.zorweth.database.ZorwethDatabase;
import org.bukkit.plugin.java.JavaPlugin;
import vg.civcraft.mc.civmodcore.dao.DatabaseCredentials;
public final class ZorwethPlugin extends JavaPlugin {
private static ZorwethPlugin instance;
private Clipboard rocketClipboard;
private HikariDataSource dataSource;
private String serverName;
private String destinationServer;
private String destinationWorld;
private String transferFailureMessage;
public static ZorwethPlugin getInstance() {
return instance;
@@ -22,14 +37,96 @@ public final class ZorwethPlugin extends JavaPlugin {
@Override
public void onEnable() {
instance = this;
saveDefaultConfig();
loadConfiguration();
if (!initDatabase()) {
getServer().getPluginManager().disablePlugin(this);
return;
}
this.rocketClipboard = loadRocketClipboard();
getServer().getPluginManager().registerEvents(new FlightComputer(this), this);
}
@Override
public void onDisable() {
if (this.dataSource != null) {
this.dataSource.close();
this.dataSource = null;
}
}
public Clipboard getRocketClipboard() {
return this.rocketClipboard;
}
public DataSource getDataSource() {
return this.dataSource;
}
public String getServerName() {
return this.serverName;
}
public String getDestinationServer() {
return this.destinationServer;
}
public String getDestinationWorld() {
return this.destinationWorld;
}
public String getTransferFailureMessage() {
return this.transferFailureMessage;
}
private void loadConfiguration() {
this.serverName = getConfig().getString("server-name", "zorweth");
this.destinationServer = getConfig().getString("destination-server", this.serverName);
this.destinationWorld = getConfig().getString("destination-world", "world");
this.transferFailureMessage = getConfig().getString("transfer-failure-message",
"Unable to complete rocket transfer. Please reconnect and try again.");
}
private boolean initDatabase() {
final DatabaseCredentials credentials = (DatabaseCredentials) getConfig().get("database");
if (credentials == null) {
getLogger().severe("Database credentials are missing from config.yml");
return false;
}
this.dataSource = createDataSource(credentials);
try (Connection connection = this.dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.executeQuery("SELECT 1");
} catch (final SQLException exception) {
getLogger().log(Level.SEVERE, "Unable to connect to the Zorweth database", exception);
return false;
}
try {
ZorwethDatabase.migrate(this.dataSource);
return true;
} catch (final SQLException exception) {
getLogger().log(Level.SEVERE, "Unable to migrate the Zorweth database", exception);
return false;
}
}
private HikariDataSource createDataSource(final DatabaseCredentials credentials) {
final HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:" + credentials.driver() + "://" + credentials.host() + ":" +
credentials.port() + "/" + credentials.database());
config.setConnectionTimeout(credentials.connectionTimeout());
config.setIdleTimeout(credentials.idleTimeout());
config.setMaxLifetime(credentials.maxLifetime());
config.setMaximumPoolSize(credentials.poolSize());
config.setUsername(credentials.username());
if (!Strings.isNullOrEmpty(credentials.password())) {
config.setPassword(credentials.password());
}
return new HikariDataSource(config);
}
private Clipboard loadRocketClipboard() {
final File file = new File(getDataFolder(), "rocket.schem");
final ClipboardFormat format = ClipboardFormats.findByFile(file);

View File

@@ -0,0 +1,95 @@
package net.civmc.zorweth.database;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import net.civmc.nameapi.Migrator;
public final class ZorwethDatabase {
private ZorwethDatabase() {
}
public static void migrate(final DataSource dataSource) throws SQLException {
final Migrator migrator = new Migrator();
migrator.registerMigration("zorweth", 0,
"""
CREATE TABLE IF NOT EXISTS rocket_transfers (
transfer_id VARCHAR(36) NOT NULL,
state VARCHAR(32) NOT NULL,
source_server VARCHAR(64) NOT NULL,
destination_server VARCHAR(64) NOT NULL,
source_world VARCHAR(64) NOT NULL,
destination_world VARCHAR(64) NOT NULL,
source_origin_x INT NOT NULL,
source_origin_y INT NOT NULL,
source_origin_z INT NOT NULL,
destination_origin_x INT NOT NULL,
destination_origin_y INT NOT NULL,
destination_origin_z INT NOT NULL,
destination_requested_x INT NOT NULL,
destination_requested_z INT NOT NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (transfer_id),
INDEX idx_rocket_transfers_state (state),
INDEX idx_rocket_transfers_destination (destination_server, state)
)
""",
"""
CREATE TABLE IF NOT EXISTS rocket_transfer_players (
transfer_id VARCHAR(36) NOT NULL,
player_uuid VARCHAR(36) NOT NULL,
relative_x DOUBLE NOT NULL,
relative_y DOUBLE NOT NULL,
relative_z DOUBLE NOT NULL,
yaw FLOAT NOT NULL,
pitch FLOAT NOT NULL,
inventory LONGBLOB NOT NULL,
health DOUBLE NOT NULL,
xp_level INT NOT NULL,
xp_progress FLOAT NOT NULL,
food_level INT NOT NULL,
saturation FLOAT NOT NULL,
exhaustion FLOAT NOT NULL,
held_slot INT NOT NULL,
game_mode VARCHAR(32) NOT NULL,
state VARCHAR(32) NOT NULL DEFAULT 'PENDING',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (transfer_id, player_uuid),
INDEX idx_rocket_transfer_players_player (player_uuid, state),
CONSTRAINT fk_rocket_transfer_players_transfer FOREIGN KEY (transfer_id)
REFERENCES rocket_transfers (transfer_id) ON DELETE CASCADE
)
""",
"""
CREATE TABLE IF NOT EXISTS rocket_transfer_chests (
transfer_id VARCHAR(36) NOT NULL,
relative_x INT NOT NULL,
relative_y INT NOT NULL,
relative_z INT NOT NULL,
inventory LONGBLOB NOT NULL,
state VARCHAR(32) NOT NULL DEFAULT 'PENDING',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (transfer_id, relative_x, relative_y, relative_z),
CONSTRAINT fk_rocket_transfer_chests_transfer FOREIGN KEY (transfer_id)
REFERENCES rocket_transfers (transfer_id) ON DELETE CASCADE
)
""",
"""
CREATE TABLE IF NOT EXISTS player_server_state (
player_uuid VARCHAR(36) NOT NULL,
last_server VARCHAR(64) NOT NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (player_uuid),
INDEX idx_player_server_state_last_server (last_server)
)
""");
try (Connection connection = dataSource.getConnection()) {
migrator.migrate(connection);
}
}
}

View File

@@ -0,0 +1,17 @@
server-name: zorweth
destination-server: zorweth
destination-world: world
transfer-failure-message: Unable to complete rocket transfer. Please reconnect and try again.
database:
==: vg.civcraft.mc.civmodcore.dao.DatabaseCredentials
user: root
password: root
host: localhost
port: 3306
driver: mariadb
database: database
poolsize: 5
connection_timeout: 10000
idle_timeout: 600000
max_lifetime: 7200000