diff --git a/.classpath b/.classpath
index 58ad8b1..720c4f0 100644
--- a/.classpath
+++ b/.classpath
@@ -12,6 +12,12 @@
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index 5cede7c..9108392 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ test_server/
.gradle
build/
server/
+bin/
diff --git a/.project b/.project
index 765ab9b..28c5951 100644
--- a/.project
+++ b/.project
@@ -1,6 +1,6 @@
- civil-core-civilcore
+ CivilCore
Project civilcore created by Buildship.
diff --git a/bin/main/paper-plugin.yml b/bin/main/paper-plugin.yml
index 3f63ddd..5db0a58 100644
--- a/bin/main/paper-plugin.yml
+++ b/bin/main/paper-plugin.yml
@@ -1,5 +1,5 @@
api-version: "1.21"
-name: civil-core
+name: CivilCore
version: 0.1.0
main: rip.iwakura.civil.Core
authors:
diff --git a/bin/main/rip/iwakura/civil/Core.class b/bin/main/rip/iwakura/civil/Core.class
index 98b6222..4c18cb3 100644
Binary files a/bin/main/rip/iwakura/civil/Core.class and b/bin/main/rip/iwakura/civil/Core.class differ
diff --git a/build.gradle.kts b/build.gradle.kts
index 59ec723..e1607bc 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -3,7 +3,7 @@ version = "0.1.0"
plugins {
java
- id("com.github.johnrengelman.shadow") version "7.1.2"
+ id("com.gradleup.shadow") version "8.3.6"
id("de.eldoria.plugin-yml.paper") version "0.7.1"
}
@@ -21,15 +21,20 @@ paper {
apiVersion = "1.21"
}
-tasks.withType {
- val isDebug = providers.gradleProperty("isDebug")
- if (isDebug.isPresent()) {
- destinationDirectory.set(file(isDebug))
+tasks {
+ register("copyToServer") {
+ from(shadowJar)
+ destinationDir = File("server/plugins")
+ }
+ build {
+ dependsOn(shadowJar)
}
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT")
+ implementation("com.j256.ormlite", "ormlite-jdbc", "6.1")
+ implementation("org.postgresql", "postgresql", "42.7.5")
library("com.google.code.gson", "gson", "2.10.1") // All platform plugins
}
diff --git a/build.sh b/build.sh
index 5e2b430..1404b4f 100644
--- a/build.sh
+++ b/build.sh
@@ -5,6 +5,6 @@ catch () {
exit 1
}
-./gradlew build -PisDebug=./server/plugins || catch
+./gradlew clean build copyToServer || catch
cd server && java -jar server.jar -nogui && cd ..
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b790ed4..82d9ae2 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -10,4 +10,4 @@ plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
-rootProject.name = "civil-core"
+rootProject.name = "CivilCore"
diff --git a/src/main/java/rip/iwakura/civil/Core.java b/src/main/java/rip/iwakura/civil/Core.java
index b5cdd84..c04addb 100644
--- a/src/main/java/rip/iwakura/civil/Core.java
+++ b/src/main/java/rip/iwakura/civil/Core.java
@@ -1,10 +1,41 @@
package rip.iwakura.civil;
+import java.sql.SQLException;
+import java.util.logging.Level;
+
+import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
+import rip.iwakura.civil.events.ChatHandler;
+import rip.iwakura.civil.commands.Team;
+import rip.iwakura.civil.events.JoinHandler;
+
public class Core extends JavaPlugin {
+ public Database database;
+
@Override
public void onEnable() {
getLogger().info("Hello world! We are booting up...");
+
+ saveDefaultConfig();
+
+ try {
+ this.database = new Database(getConfig().getString("database.url"));
+ } catch (SQLException e) {
+ getLogger().log(Level.SEVERE, e.getMessage());
+ Bukkit.getPluginManager().disablePlugin(this);
+
+ return;
+ }
+
+ Team teamCommand = new Team(database);
+
+ this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
+ commands.registrar().register(teamCommand.getCommand());
+ });
+
+ getServer().getPluginManager().registerEvents(new JoinHandler(database), this);
+ getServer().getPluginManager().registerEvents(new ChatHandler(this), this);
}
}
diff --git a/src/main/java/rip/iwakura/civil/Database.java b/src/main/java/rip/iwakura/civil/Database.java
new file mode 100644
index 0000000..6cabcb0
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/Database.java
@@ -0,0 +1,83 @@
+package rip.iwakura.civil;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.logging.log4j.LogManager;
+import org.bukkit.entity.Player;
+
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.jdbc.JdbcConnectionSource;
+import com.j256.ormlite.logger.LoggerFactory;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.TableUtils;
+
+import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
+import rip.iwakura.civil.types.CivilPlayer;
+import rip.iwakura.civil.types.CivilTeam;
+
+public class Database {
+ private final Dao playerDao;
+ private final Dao teamDao;
+ private ConnectionSource connectionSource;
+
+ public Database(String uri) throws SQLException {
+ connectionSource = new JdbcConnectionSource(uri);
+
+
+ TableUtils.createTableIfNotExists(connectionSource, CivilPlayer.class);
+ TableUtils.createTableIfNotExists(connectionSource, CivilTeam.class);
+
+ playerDao = DaoManager.createDao(connectionSource, CivilPlayer.class);
+ teamDao = DaoManager.createDao(connectionSource, CivilTeam.class);
+ }
+
+ public void createPlayer(Player p) throws SQLException {
+ playerDao.create(
+ new CivilPlayer(p.getUniqueId(), p.getName())
+ );
+ }
+
+ public void createTeam(String name, String prefix) throws SQLException {
+ teamDao.create(
+ new CivilTeam(name, prefix)
+ );
+ }
+
+ public void joinTeam(Player p, CivilTeam team) throws SQLException {
+ CivilPlayer civilPlayer = playerDao.queryForId(p.getUniqueId());
+ civilPlayer.setTeam(team);
+ playerDao.update(civilPlayer);
+ }
+
+ public void joinTeam(CivilPlayer p, CivilTeam team) throws SQLException {
+ p.setTeam(team);
+ playerDao.update(p);
+ }
+
+ public CivilTeam getTeam(String team) throws SQLException {
+ return teamDao.queryForId(team);
+ }
+
+ public List getAllTeams() throws SQLException {
+ return teamDao.queryForAll();
+ }
+
+ public CivilPlayer getPlayer(String name) throws SQLException {
+ return playerDao.queryBuilder().where().eq("name", name).queryForFirst();
+ }
+
+ public CivilPlayer getPlayer(UUID uuid) throws SQLException {
+ return playerDao.queryForId(uuid);
+ }
+
+ public CivilPlayer getPlayer(Player p) throws SQLException {
+ return playerDao.queryForId(p.getUniqueId());
+ }
+
+ public List getAllPlayers() throws SQLException {
+ return playerDao.queryForAll();
+ }
+}
diff --git a/src/main/java/rip/iwakura/civil/commands/PlayerArgument.java b/src/main/java/rip/iwakura/civil/commands/PlayerArgument.java
new file mode 100644
index 0000000..0979be7
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/commands/PlayerArgument.java
@@ -0,0 +1,77 @@
+package rip.iwakura.civil.commands;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import org.bukkit.entity.Player;
+
+import com.mojang.brigadier.Message;
+import com.mojang.brigadier.arguments.ArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
+import com.mojang.brigadier.suggestion.Suggestions;
+import com.mojang.brigadier.suggestion.SuggestionsBuilder;
+
+import io.papermc.paper.command.brigadier.MessageComponentSerializer;
+import io.papermc.paper.command.brigadier.argument.CustomArgumentType;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import rip.iwakura.civil.types.CivilPlayer;
+import rip.iwakura.civil.Database;
+
+/**
+ * PlayerArgument
+ */
+public class PlayerArgument implements CustomArgumentType.Converted {
+ private Database database;
+
+ public PlayerArgument(Database database) {
+ this.database = database;
+ }
+
+ @Override
+ public CivilPlayer convert(String playerName) throws CommandSyntaxException {
+ try {
+ CivilPlayer civilPlayer = database.getPlayer(playerName);
+
+ if (civilPlayer == null) {
+ final Message message = MessageComponentSerializer.message()
+ .serialize(Component.text(playerName + " doesn't exist!", NamedTextColor.RED));
+ throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
+ }
+
+ return civilPlayer;
+
+ } catch (SQLException e) {
+ final Message message = MessageComponentSerializer.message()
+ .serialize(Component.text("Uh oh, an error occured!", NamedTextColor.RED));
+ throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
+ }
+ }
+
+ @Override
+ public CompletableFuture listSuggestions(CommandContext ctx, SuggestionsBuilder builder) {
+ try {
+ List players = database.getAllPlayers();
+
+ for (CivilPlayer player : players) {
+ String name = player.getName();
+
+ if (name.toLowerCase().startsWith(builder.getRemainingLowerCase())) {
+ builder.suggest(name);
+ }
+ }
+ } catch (SQLException e) {
+ }
+
+ return builder.buildFuture();
+ }
+
+ @Override
+ public ArgumentType getNativeType() {
+ return StringArgumentType.word();
+ }
+}
diff --git a/src/main/java/rip/iwakura/civil/commands/Team.java b/src/main/java/rip/iwakura/civil/commands/Team.java
new file mode 100644
index 0000000..3bfb7c8
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/commands/Team.java
@@ -0,0 +1,79 @@
+package rip.iwakura.civil.commands;
+
+import java.sql.SQLException;
+
+import javax.xml.crypto.Data;
+
+import org.bukkit.entity.Player;
+
+import com.mojang.brigadier.Command;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.tree.LiteralCommandNode;
+
+import io.papermc.paper.command.brigadier.CommandSourceStack;
+import io.papermc.paper.command.brigadier.Commands;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import rip.iwakura.civil.Database;
+import rip.iwakura.civil.types.*;
+
+public class Team {
+ private Database database;
+
+ public Team(Database database) {
+ this.database = database;
+ }
+
+ private LiteralArgumentBuilder createTeam() {
+ return Commands.literal("create")
+ .then(
+ Commands.argument("name", StringArgumentType.string())
+ .then(
+ Commands.argument("prefix", StringArgumentType.string())
+ .executes(ctx -> {
+ String name = StringArgumentType.getString(ctx, "name");
+ String prefix = StringArgumentType.getString(ctx, "prefix");
+
+ try {
+ database.createTeam(name, prefix);
+ return Command.SINGLE_SUCCESS;
+ } catch (SQLException e) {
+ ctx.getSource().getSender().sendMessage(
+ Component.text(e.getMessage(), NamedTextColor.RED));
+ return 0;
+ }
+ })));
+ }
+
+ // Add a player to a team.
+ private LiteralArgumentBuilder joinTeam() {
+ return Commands.literal("add")
+ .then(
+ Commands.argument("player", new PlayerArgument(database))
+ .then(
+ Commands.argument("team", new TeamArgument(database))
+ .executes(ctx -> {
+ CivilTeam civilTeam = ctx.getArgument("team", CivilTeam.class);
+ CivilPlayer civilPlayer = ctx.getArgument("player",
+ CivilPlayer.class);
+
+ try {
+ database.joinTeam(civilPlayer, civilTeam);
+ return Command.SINGLE_SUCCESS;
+ } catch (SQLException e) {
+ ctx.getSource().getSender().sendMessage(
+ Component.text(e.getMessage(), NamedTextColor.RED));
+ return 0;
+ }
+ })));
+ };
+
+ public LiteralCommandNode getCommand() {
+ return Commands.literal("team")
+ .then(createTeam())
+ .then(joinTeam()).build();
+ }
+
+}
diff --git a/src/main/java/rip/iwakura/civil/commands/TeamArgument.java b/src/main/java/rip/iwakura/civil/commands/TeamArgument.java
new file mode 100644
index 0000000..3a9988a
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/commands/TeamArgument.java
@@ -0,0 +1,75 @@
+package rip.iwakura.civil.commands;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import com.mojang.brigadier.Message;
+import com.mojang.brigadier.arguments.ArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
+import com.mojang.brigadier.suggestion.Suggestions;
+import com.mojang.brigadier.suggestion.SuggestionsBuilder;
+
+import io.papermc.paper.command.brigadier.MessageComponentSerializer;
+import io.papermc.paper.command.brigadier.argument.CustomArgumentType;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import rip.iwakura.civil.types.CivilTeam;
+import rip.iwakura.civil.Database;
+
+/**
+ * TeamArgument
+ */
+public class TeamArgument implements CustomArgumentType.Converted {
+ private Database database;
+
+ public TeamArgument(Database database) {
+ this.database = database;
+ }
+
+ @Override
+ public CivilTeam convert(String teamName) throws CommandSyntaxException {
+ try {
+ CivilTeam civilTeam = database.getTeam(teamName);
+
+ if (civilTeam == null) {
+ final Message message = MessageComponentSerializer.message()
+ .serialize(Component.text(teamName + " doesn't exist!", NamedTextColor.RED));
+ throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
+ }
+
+ return civilTeam;
+
+ } catch (SQLException e) {
+ final Message message = MessageComponentSerializer.message()
+ .serialize(Component.text("Uh oh, an error occured!", NamedTextColor.RED));
+ throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
+ }
+ }
+
+ @Override
+ public CompletableFuture listSuggestions(CommandContext ctx, SuggestionsBuilder builder) {
+ try {
+ List teams = database.getAllTeams();
+
+ for (CivilTeam team : teams) {
+ String name = team.getName();
+
+ if (name.toLowerCase().startsWith(builder.getRemainingLowerCase())) {
+ builder.suggest(name);
+ }
+ }
+ } catch (SQLException e) {
+ }
+
+ return builder.buildFuture();
+ }
+
+ @Override
+ public ArgumentType getNativeType() {
+ return StringArgumentType.string();
+ }
+}
diff --git a/src/main/java/rip/iwakura/civil/events/ChatHandler.java b/src/main/java/rip/iwakura/civil/events/ChatHandler.java
new file mode 100644
index 0000000..2a6bda1
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/events/ChatHandler.java
@@ -0,0 +1,51 @@
+package rip.iwakura.civil.events;
+
+import java.sql.SQLException;
+import java.util.logging.Level;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+
+import io.papermc.paper.chat.ChatRenderer;
+import io.papermc.paper.event.player.AsyncChatEvent;
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+import rip.iwakura.civil.Core;
+import rip.iwakura.civil.Database;
+
+public class ChatHandler implements Listener, ChatRenderer {
+ private Core core;
+ private Database database;
+
+ public ChatHandler(Core core) {
+ this.core = core;
+ this.database = core.database;
+ }
+
+ @EventHandler
+ public void chatHandler(AsyncChatEvent event) {
+ event.renderer(this);
+ }
+
+ @Override
+ public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
+ String prefix = null;
+
+ try {
+ prefix = database.getPlayer(source).getTeam().getPrefix();
+ } catch (SQLException e) {
+ core.getLogger().log(Level.WARNING, e.getMessage());;
+ } catch (NullPointerException e) {
+ }
+
+ if (prefix == null) prefix = "";
+
+ return MiniMessage.miniMessage()
+ .deserialize(prefix)
+ .append(sourceDisplayName)
+ .append(Component.text(": "))
+ .append(message);
+ }
+}
diff --git a/src/main/java/rip/iwakura/civil/events/JoinHandler.java b/src/main/java/rip/iwakura/civil/events/JoinHandler.java
new file mode 100644
index 0000000..77f8082
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/events/JoinHandler.java
@@ -0,0 +1,25 @@
+package rip.iwakura.civil.events;
+
+import java.sql.SQLException;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+import rip.iwakura.civil.Database;
+
+public class JoinHandler implements Listener {
+ private Database database;
+
+ public JoinHandler(Database database) {
+ this.database = database;
+ }
+
+ @EventHandler
+ public void chatHandler(PlayerJoinEvent event) throws SQLException {
+ Player p = event.getPlayer();
+
+ if (database.getPlayer(p) == null) database.createPlayer(p);
+ }
+}
diff --git a/src/main/java/rip/iwakura/civil/types/CivilPlayer.java b/src/main/java/rip/iwakura/civil/types/CivilPlayer.java
new file mode 100644
index 0000000..2ca4014
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/types/CivilPlayer.java
@@ -0,0 +1,38 @@
+package rip.iwakura.civil.types;
+
+import java.util.UUID;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "players")
+public class CivilPlayer {
+ @DatabaseField(id = true, canBeNull = false, generatedId = false, columnName = "uuid")
+ private UUID uuid;
+
+ @DatabaseField(canBeNull = false, columnName = "name")
+ private String name;
+
+ @DatabaseField(canBeNull = true, foreign = true, foreignAutoRefresh = true)
+ private CivilTeam team;
+
+ public CivilPlayer() {
+ }
+
+ public CivilPlayer(UUID uuid, String name) {
+ this.uuid = uuid;
+ this.name = name;
+ }
+
+ public void setTeam(CivilTeam team) {
+ this.team = team;
+ }
+
+ public CivilTeam getTeam() {
+ return team;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/src/main/java/rip/iwakura/civil/types/CivilTeam.java b/src/main/java/rip/iwakura/civil/types/CivilTeam.java
new file mode 100644
index 0000000..c6fb73e
--- /dev/null
+++ b/src/main/java/rip/iwakura/civil/types/CivilTeam.java
@@ -0,0 +1,43 @@
+package rip.iwakura.civil.types;
+
+import org.bukkit.Location;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "teams")
+public class CivilTeam {
+ @DatabaseField(id = true)
+ private String name;
+
+ @DatabaseField(canBeNull = false)
+ private String prefix;
+
+ /*@DatabaseField(canBeNull = true)
+ private Location home;*/
+
+ public CivilTeam() {
+ }
+
+ public CivilTeam(String name, String prefix) {
+ this.name = name;
+ this.prefix = prefix;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+/*
+ public void setHome(Location home) {
+ this.home = home;
+ }
+
+ public Location getHome() {
+ return home;
+ }
+ */
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..40ac02b
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,2 @@
+database:
+ url: ""
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
new file mode 100644
index 0000000..ccf1f99
--- /dev/null
+++ b/src/main/resources/log4j.properties
@@ -0,0 +1,16 @@
+log4j.rootLogger=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+
+# print the date in ISO 8601 format
+log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%p] %c{1} %m%n
+
+# be more verbose with our code
+log4j.logger.com.j256.ormlite=DEBUG
+
+# to enable logging of arguments to all of the SQL calls
+# uncomment the following lines
+log4j.logger.com.j256.ormlite.stmt.mapped.BaseMappedStatement=TRACE
+log4j.logger.com.j256.ormlite.stmt.mapped.MappedCreate=TRACE
+log4j.logger.com.j256.ormlite.stmt.StatementExecutor=TRACE