Skip to content

Commit

Permalink
feat: database & progress on merge command
Browse files Browse the repository at this point in the history
  • Loading branch information
MatzHilven committed Jun 21, 2024
1 parent 089d01a commit 3f449be
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ build/
### NixOS ###
*.nix
.envrc

.env
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@
<version>0.10.2</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
11 changes: 6 additions & 5 deletions src/main/java/com/slampvp/factory/FactoryServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.slampvp.factory.command.FactoryCommand;
import com.slampvp.factory.common.Constants;
import com.slampvp.factory.database.DatabaseManager;
import com.slampvp.factory.plot.PlotGenerator;
import com.slampvp.factory.plot.PlotManager;
import net.minestom.server.MinecraftServer;
Expand Down Expand Up @@ -30,9 +31,12 @@ public final class FactoryServer {

public static void main(String[] args) {
MinecraftServer minecraftServer = MinecraftServer.init();

MojangAuth.init();

MinecraftServer.getSchedulerManager().buildShutdownTask(() -> {
DatabaseManager.getInstance().close();
});

InstanceManager instanceManager = MinecraftServer.getInstanceManager();
InstanceContainer instanceContainer = instanceManager.createInstanceContainer();

Expand All @@ -51,11 +55,8 @@ public static void main(String[] args) {
player.setGameMode(GameMode.CREATIVE);
});

// MinecraftServer.getSchedulerManager().buildShutdownTask(() -> {
// instanceContainer.saveChunksToStorage().thenAccept(t -> LOGGER.info("Saved world."));
// });

PlotManager.getInstance().init();
DatabaseManager.getInstance().init();

streamPackage("com.slampvp.factory.command", FactoryCommand.class).forEach(c ->
MinecraftServer.getCommandManager().register(c)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.slampvp.factory.command.plot.sub;

import com.slampvp.factory.command.Command;
import com.slampvp.factory.command.FactoryCommand;
import com.slampvp.factory.common.Locale;
import com.slampvp.factory.player.Rank;
import com.slampvp.factory.plot.Plot;
import com.slampvp.factory.plot.PlotFlag;
import com.slampvp.factory.plot.PlotManager;
import net.kyori.adventure.text.TextReplacementConfig;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentEntity;
import net.minestom.server.entity.Player;

import java.util.Optional;

@Command(
description = "Get info of a plot.",
usage = "/plot info",
minimumRank = Rank.ADMIN,
playerOnly = true
)
public class InfoCommand extends FactoryCommand {
public InfoCommand() {
super("info");
}

@Override
public void init() {

addSyntax((sender, context) -> {
Player player = (Player) sender;
Optional<Plot> optionalPlot = PlotManager.getInstance().getPlot(player.getPosition());

if (optionalPlot.isEmpty()) {
sender.sendMessage(Locale.Plot.NOT_IN_PLOT);
return;
}

Plot plot = optionalPlot.get();

player.sendMessage("ID: " + plot.getId());
player.sendMessage("Owner: " + plot.getOwner());
player.sendMessage("Start: " + plot.getStart());
player.sendMessage("End: " + plot.getEnd());
player.sendMessage("");
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.slampvp.factory.command.plot.sub;

import com.slampvp.factory.FactoryServer;
import com.slampvp.factory.command.Command;
import com.slampvp.factory.command.FactoryCommand;
import com.slampvp.factory.common.Locale;
import com.slampvp.factory.player.Rank;
import com.slampvp.factory.plot.ClaimResult;
import com.slampvp.factory.plot.MergeResult;
import com.slampvp.factory.plot.PlotManager;
import net.minestom.server.entity.Player;

@Command(description = "Merge two plots together into one large plot.", usage = "/plot merge", minimumRank = Rank.DEFAULT, playerOnly = true)
public class MergeCommand extends FactoryCommand {
public MergeCommand() {
super("merge");
}

@Override
public void init() {
addSyntax((sender, context) -> {
Player player = (Player) sender;
MergeResult mergeResult = PlotManager.getInstance().mergePlot(player);

switch (mergeResult) {
case NOT_IN_PLOT -> sender.sendMessage(Locale.Plot.NOT_IN_PLOT);
case NO_MERGE_CANDIDATE -> sender.sendMessage(Locale.Plot.NO_MERGE_CANDIDATE);
case SUCCESS -> {
PlotManager.getInstance().getPlot(player.getPosition()).ifPresent(plot -> player.teleport(plot.getSpawn()));
sender.sendMessage(Locale.Plot.MERGED);
}
case FAILURE -> {
FactoryServer.LOGGER.error("Plot merging failed.");
}
}
});
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/slampvp/factory/common/Locale.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public static final class Plot {
public static final TextComponent ALREADY_TRUSTED = PREFIX.append(
Component.text("This player is already a trusted player of your plot!").color(NamedTextColor.RED)
);
public static final TextComponent NO_MERGE_CANDIDATE = PREFIX.append(
Component.text("Cannot find a merge candidate!").color(NamedTextColor.RED)
);

public static final TextComponent CLAIMED = PREFIX.append(
Component.text("You've successfully claimed this plot!").color(NamedTextColor.GREEN)
Expand Down Expand Up @@ -119,5 +122,8 @@ public static final class Plot {
public static final TextComponent REMOVED_TARGET = PREFIX.append(
Component.text("You've been removed from <player>'s plot!").color(NamedTextColor.GREEN)
);
public static final TextComponent MERGED = PREFIX.append(
Component.text("You've successfully merged your plots!").color(NamedTextColor.GREEN)
);
}
}
85 changes: 85 additions & 0 deletions src/main/java/com/slampvp/factory/database/DatabaseManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.slampvp.factory.database;

import com.slampvp.factory.FactoryServer;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.function.Consumer;

public class DatabaseManager {
private static DatabaseManager instance;
private final HikariDataSource dataSource;

private DatabaseManager() {
HikariConfig config = new HikariConfig();
config.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");

config.addDataSourceProperty("serverName", "localhost");
config.addDataSourceProperty("portNumber", "5432");
config.addDataSourceProperty("databaseName", "factory");
config.addDataSourceProperty("user", "postgres");
config.addDataSourceProperty("password", "password");

config.setMaximumPoolSize(5);
config.setMinimumIdle(2);
config.setConnectionTimeout(30000);

dataSource = new HikariDataSource(config);
}

public static synchronized DatabaseManager getInstance() {
if (instance == null) {
instance = new DatabaseManager();
}
return instance;
}

public void init() {
FactoryServer.LOGGER.info("Creating database tables...");
executeUpdate(DatabaseTables.TABLES_QUERY);
}

public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}

public void close() {
if (dataSource != null && !dataSource.isClosed()) {
dataSource.close();
}
}

public void executeUpdate(String query) {
executeUpdate(query, statement -> {
});
}

public void executeUpdate(String query, Consumer<PreparedStatement> statementConsumer) {
try (Connection connection = getConnection(); PreparedStatement pstmt = connection.prepareStatement(query)) {
statementConsumer.accept(pstmt);
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}

public void executeQuery(String query, Consumer<ResultSet> resultSetConsumer) {
executeQuery(query, statement -> {
}, resultSetConsumer);
}

public void executeQuery(String query, Consumer<PreparedStatement> statementConsumer, Consumer<ResultSet> resultSetConsumer) {
try (Connection connection = getConnection(); PreparedStatement pstmt = connection.prepareStatement(query)) {
statementConsumer.accept(pstmt);
try (ResultSet rs = pstmt.executeQuery()) {
resultSetConsumer.accept(rs);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
97 changes: 97 additions & 0 deletions src/main/java/com/slampvp/factory/database/DatabaseTables.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.slampvp.factory.database;

final class DatabaseTables {
static final String TABLES_QUERY = """
DO
$$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'plot_id') THEN
CREATE TYPE PLOT_ID AS
(
x INT,
z INT
);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'vec') THEN
CREATE TYPE VEC AS
(
x FLOAT,
y FLOAT,
z FLOAT
);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'pos') THEN
CREATE TYPE POS AS
(
x FLOAT,
y FLOAT,
z FLOAT,
yaw FLOAT,
pitch FLOAT
);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'plot_target') THEN
CREATE TYPE PLOT_TARGET AS ENUM ('TRUSTED', 'MEMBER', 'PUBLIC');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'plot_member') THEN
CREATE TYPE PLOT_MEMBER AS ENUM ('TRUSTED', 'MEMBER');
END IF;
END
$$;
DO
$$
BEGIN
CREATE TABLE IF NOT EXISTS plots
(
id BIGINT GENERATED ALWAYS AS IDENTITY,
plot_id PLOT_ID NOT NULL,
owner VARCHAR(36) NOT NULL,
start VEC NOT NULL,
"end" VEC NOT NULL,
spawn POS NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX IF NOT EXISTS index_plots_on_owner ON plots (owner);
CREATE TABLE IF NOT EXISTS plot_banned_players
(
plot_id BIGINT NOT NULL,
uuid VARCHAR(36) NOT NULL,
PRIMARY KEY (plot_id, uuid),
CONSTRAINT fk_plot FOREIGN KEY (plot_id) REFERENCES plots (id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS index_plot_banned_players_on_both ON plot_banned_players (plot_id, uuid);
CREATE INDEX IF NOT EXISTS index_plot_banned_players_on_plot_id ON plot_banned_players (plot_id);
CREATE TABLE IF NOT EXISTS plot_warps
(
plot_id BIGINT NOT NULL,
name TEXT NOT NULL,
pos POS NOT NULL,
PRIMARY KEY (plot_id, name, pos),
CONSTRAINT fk_plot FOREIGN KEY (plot_id) REFERENCES plots (id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS index_plot_warps_on_all ON plot_warps (plot_id, name, pos);
CREATE INDEX IF NOT EXISTS index_plot_warps_on_plot_id ON plot_warps (plot_id);
CREATE TABLE IF NOT EXISTS plot_members
(
plot_id BIGINT NOT NULL,
uuid VARCHAR(36) NOT NULL,
type PLOT_MEMBER NOT NULL,
PRIMARY KEY (plot_id, uuid, type),
CONSTRAINT fk_plot FOREIGN KEY (plot_id) REFERENCES plots (id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS index_plot_members_on_all ON plot_members (plot_id, uuid, type);
CREATE INDEX IF NOT EXISTS index_plot_members_on_plot_id ON plot_members (plot_id);
CREATE TABLE IF NOT EXISTS plot_flags
(
plot_id BIGINT NOT NULL,
target PLOT_TARGET NOT NULL,
flags INT NOT NULL,
PRIMARY KEY (plot_id, target, flags),
CONSTRAINT fk_plot FOREIGN KEY (plot_id) REFERENCES plots (id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS index_plot_flags_on_all ON plot_flags (plot_id, target, flags);
CREATE INDEX IF NOT EXISTS index_plot_flags_on_plot_id ON plot_flags (plot_id);
END
$$;
""";
}
8 changes: 8 additions & 0 deletions src/main/java/com/slampvp/factory/plot/MergeResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.slampvp.factory.plot;

public enum MergeResult {
NOT_IN_PLOT,
NO_MERGE_CANDIDATE,
SUCCESS,
FAILURE;
}
Loading

0 comments on commit 3f449be

Please sign in to comment.