diff --git a/build.gradle.kts b/build.gradle.kts index a97d3e2..0870213 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { library(libs.hikari) compileOnly(libs.paperApi) implementation(libs.bundles.bstats) { isTransitive = false } + library(libs.mariadb.java.client) annotationProcessor(libs.lombok) } @@ -52,6 +53,7 @@ paper { name = "Medina" version = project.version.toString() main = "dev.plex.medina.Medina" + loader = "dev.plex.medina.MedinaLibraryManager" apiVersion = "1.20" foliaSupported = true authors = listOf("Telesphoreo") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f625a7c..f555fda 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,13 +3,15 @@ paper = "1.20.4-R0.1-SNAPSHOT" bstats = "3.0.2" lombok = "1.18.32" hikari = "5.1.0" +mariadb-java-client = "3.4.0" [libraries] paperApi = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" } -bstatsBase = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" } -bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" } +bstats-base = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" } +bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" } lombok = { group = "org.projectlombok", name = "lombok", version.ref = "lombok" } hikari = { group = "com.zaxxer", name = "HikariCP", version.ref = "hikari" } +mariadb-java-client = { group = "org.mariadb.jdbc", name = "mariadb-java-client", version.ref = "mariadb-java-client"} [bundles] -bstats = ["bstatsBase", "bstatsBukkit"] \ No newline at end of file +bstats = ["bstats-base", "bstats-bukkit"] \ No newline at end of file diff --git a/src/main/java/dev/plex/medina/Medina.java b/src/main/java/dev/plex/medina/Medina.java index 342fd45..45798bf 100644 --- a/src/main/java/dev/plex/medina/Medina.java +++ b/src/main/java/dev/plex/medina/Medina.java @@ -3,6 +3,7 @@ package dev.plex.medina; import dev.plex.medina.config.Config; import dev.plex.medina.registration.CommandRegistration; import dev.plex.medina.storage.SQLConnection; +import dev.plex.medina.storage.SQLReports; import dev.plex.medina.util.MedinaUtils; import lombok.Getter; import org.bstats.bukkit.Metrics; @@ -20,6 +21,9 @@ public class Medina extends JavaPlugin @Getter private SQLConnection sqlConnection; + @Getter + private SQLReports sqlReports; + @Override public void onLoad() { @@ -40,6 +44,8 @@ public class Medina extends JavaPlugin sqlConnection = new SQLConnection(); MedinaUtils.testConnection(); + sqlReports = new SQLReports(); + new CommandRegistration(); } } diff --git a/src/main/java/dev/plex/medina/MedinaLibraryManager.java b/src/main/java/dev/plex/medina/MedinaLibraryManager.java new file mode 100644 index 0000000..1bd69f8 --- /dev/null +++ b/src/main/java/dev/plex/medina/MedinaLibraryManager.java @@ -0,0 +1,57 @@ +package dev.plex.medina; + +import com.google.gson.Gson; +import io.papermc.paper.plugin.loader.PluginClasspathBuilder; +import io.papermc.paper.plugin.loader.PluginLoader; +import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.repository.RemoteRepository; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +public class MedinaLibraryManager implements PluginLoader +{ + @Override + public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) + { + MavenLibraryResolver resolver = new MavenLibraryResolver(); + PluginLibraries pluginLibraries = load(); + pluginLibraries.asDependencies().forEach(resolver::addDependency); + pluginLibraries.asRepositories().forEach(resolver::addRepository); + classpathBuilder.addLibrary(resolver); + } + + public PluginLibraries load() + { + try (var in = getClass().getResourceAsStream("/paper-libraries.json")) + { + return new Gson().fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), PluginLibraries.class); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + private record PluginLibraries(Map repositories, List dependencies) + { + public Stream asDependencies() + { + return dependencies.stream() + .map(d -> new Dependency(new DefaultArtifact(d), null)); + } + + public Stream asRepositories() + { + return repositories.entrySet().stream() + .map(e -> new RemoteRepository.Builder(e.getKey(), "default", e.getValue()).build()); + } + } +} diff --git a/src/main/java/dev/plex/medina/command/MedinaCommand.java b/src/main/java/dev/plex/medina/command/MedinaCommand.java index a0f56c3..4bbed07 100644 --- a/src/main/java/dev/plex/medina/command/MedinaCommand.java +++ b/src/main/java/dev/plex/medina/command/MedinaCommand.java @@ -2,10 +2,12 @@ package dev.plex.medina.command; import java.util.Arrays; import java.util.List; +import java.util.UUID; import com.google.common.collect.Lists; import dev.plex.medina.Medina; import dev.plex.medina.command.annotation.CommandParameters; +import dev.plex.medina.command.exception.PlayerNotFoundException; import dev.plex.medina.command.source.RequiredCommandSource; import dev.plex.medina.util.MedinaUtils; import net.kyori.adventure.audience.Audience; @@ -148,7 +150,7 @@ public abstract class MedinaCommand extends Command implements PluginIdentifiabl send(sender, component); } } - catch (NumberFormatException ex) + catch (PlayerNotFoundException | NumberFormatException ex) { send(sender, MedinaUtils.mmDeserialize(ex.getMessage())); } @@ -224,6 +226,25 @@ public abstract class MedinaCommand extends Command implements PluginIdentifiabl return !(sender instanceof Player); } + protected Player getNonNullPlayer(String name) + { + try + { + UUID uuid = UUID.fromString(name); + return Bukkit.getPlayer(uuid); + } + catch (IllegalArgumentException ignored) + { + } + + Player player = Bukkit.getPlayer(name); + if (player == null) + { + throw new PlayerNotFoundException(); + } + return player; + } + /** * Converts a message entry from the "messages.yml" to a Component * @@ -304,6 +325,19 @@ public abstract class MedinaCommand extends Command implements PluginIdentifiabl return MedinaUtils.mmDeserialize(s); } + protected Integer parseInt(CommandSender sender, String string) + { + try + { + return Integer.parseInt(string); + } + catch (NumberFormatException ex) + { + sender.sendMessage(mmString("Not a valid number.")); + } + return null; + } + public CommandMap getMap() { return Medina.getPlugin().getServer().getCommandMap(); diff --git a/src/main/java/dev/plex/medina/command/exception/PlayerNotFoundException.java b/src/main/java/dev/plex/medina/command/exception/PlayerNotFoundException.java new file mode 100644 index 0000000..df1573f --- /dev/null +++ b/src/main/java/dev/plex/medina/command/exception/PlayerNotFoundException.java @@ -0,0 +1,11 @@ +package dev.plex.medina.command.exception; + +import static dev.plex.medina.util.MedinaUtils.messageString; + +public class PlayerNotFoundException extends RuntimeException +{ + public PlayerNotFoundException() + { + super(messageString("playerNotFound")); + } +} diff --git a/src/main/java/dev/plex/medina/command/impl/AnyCommand.java b/src/main/java/dev/plex/medina/command/impl/AnyCommand.java deleted file mode 100644 index cea9f92..0000000 --- a/src/main/java/dev/plex/medina/command/impl/AnyCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package dev.plex.medina.command.impl; - -import dev.plex.medina.command.MedinaCommand; -import dev.plex.medina.command.annotation.CommandParameters; -import dev.plex.medina.command.source.RequiredCommandSource; -import net.kyori.adventure.text.Component; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -@CommandParameters(name = "anycommand", usage = "/", description = "Tests the command system with a command", permission = "medina.anycommand", source = RequiredCommandSource.ANY) -public class AnyCommand extends MedinaCommand -{ - @Override - protected Component execute(@NotNull CommandSender sender, @Nullable Player playerSender, @NotNull String[] args) - { - return mmString("AnyCommand registered."); - } - - @Override - public @NotNull List smartTabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException - { - return List.of(); - } -} diff --git a/src/main/java/dev/plex/medina/command/impl/ConsoleOnlyCommand.java b/src/main/java/dev/plex/medina/command/impl/ConsoleOnlyCommand.java deleted file mode 100644 index 141fc8e..0000000 --- a/src/main/java/dev/plex/medina/command/impl/ConsoleOnlyCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package dev.plex.medina.command.impl; - -import dev.plex.medina.command.MedinaCommand; -import dev.plex.medina.command.annotation.CommandParameters; -import dev.plex.medina.command.source.RequiredCommandSource; -import net.kyori.adventure.text.Component; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -@CommandParameters(name = "consoleonly", usage = "/", description = "Tests the command system with a console only command", permission = "medina.consoleonly", source = RequiredCommandSource.CONSOLE) -public class ConsoleOnlyCommand extends MedinaCommand -{ - @Override - protected Component execute(@NotNull CommandSender sender, @Nullable Player playerSender, @NotNull String[] args) - { - return mmString("ConsoleOnlyCommand registered."); - } - - @Override - public @NotNull List smartTabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException - { - return List.of(); - } -} diff --git a/src/main/java/dev/plex/medina/command/impl/ReportCommand.java b/src/main/java/dev/plex/medina/command/impl/ReportCommand.java index fa473c9..5ee9352 100644 --- a/src/main/java/dev/plex/medina/command/impl/ReportCommand.java +++ b/src/main/java/dev/plex/medina/command/impl/ReportCommand.java @@ -3,12 +3,18 @@ package dev.plex.medina.command.impl; import dev.plex.medina.command.MedinaCommand; import dev.plex.medina.command.annotation.CommandParameters; import dev.plex.medina.command.source.RequiredCommandSource; +import dev.plex.medina.data.Report; +import dev.plex.medina.util.MedinaUtils; import net.kyori.adventure.text.Component; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.time.ZonedDateTime; +import java.util.Collections; import java.util.List; @CommandParameters(name = "report", usage = "/ ", description = "Reports a player", permission = "medina.report", source = RequiredCommandSource.IN_GAME) @@ -17,12 +23,36 @@ public class ReportCommand extends MedinaCommand @Override protected Component execute(@NotNull CommandSender sender, @Nullable Player playerSender, @NotNull String[] args) { - return mmString("Report command registered."); + if (args.length < 2) + { + return usage(); + } + + Player player = getNonNullPlayer(args[0]); + + String reason = StringUtils.join(args, " ", 1, args.length); + + Report report = new Report( + 0, + Bukkit.getPlayer(sender.getName()).getUniqueId(), + sender.getName(), + player.getUniqueId(), + player.getName(), + ZonedDateTime.now(), + reason, + false); + + plugin.getSqlReports().addReport(report); + return messageComponent("reportSubmitted", player.getName()); } @Override public @NotNull List smartTabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { - return List.of(); + if (args.length == 1 && sender.hasPermission("medina.report")) + { + return MedinaUtils.getPlayerNameList(); + } + return Collections.emptyList(); } } diff --git a/src/main/java/dev/plex/medina/command/impl/ReportsCommand.java b/src/main/java/dev/plex/medina/command/impl/ReportsCommand.java new file mode 100644 index 0000000..42577cb --- /dev/null +++ b/src/main/java/dev/plex/medina/command/impl/ReportsCommand.java @@ -0,0 +1,110 @@ +package dev.plex.medina.command.impl; + +import dev.plex.medina.command.MedinaCommand; +import dev.plex.medina.command.annotation.CommandParameters; +import dev.plex.medina.command.source.RequiredCommandSource; +import dev.plex.medina.data.Report; +import dev.plex.medina.util.MedinaLog; +import dev.plex.medina.util.MedinaUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.time.ZoneId; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +@CommandParameters(name = "reports", usage = "/ | delete >", description = "View existing reports on a player", permission = "medina.reports", source = RequiredCommandSource.ANY) +public class ReportsCommand extends MedinaCommand +{ + @Override + protected Component execute(@NotNull CommandSender sender, @Nullable Player playerSender, @NotNull String[] args) + { + if (args.length == 0) + { + return usage(); + } + + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayerIfCached(args[0]); + if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore()) + { + return messageComponent("playerNotFound"); + } + + switch (args[1].toLowerCase()) + { + case "list": + { + plugin.getSqlReports().getReports(offlinePlayer.getUniqueId()).whenComplete((reports, ex) -> + { + // we don't want to include deleted reports in the logic + long count = reports.stream() + .filter(report -> !report.isDeleted()) + .count(); + if (count <= 0) + { + send(sender, messageComponent("noReports", offlinePlayer.getName())); + return; + } + readReports(sender, offlinePlayer, reports); + }); + + return null; + } + case "delete": + { + int id = parseInt(sender, args[2]); + plugin.getSqlReports().getReports(id).whenComplete(((report, ex) -> + { + if (report.isDeleted()) + { + send(sender, messageComponent("reportDoesntExist")); + return; + } + else + { + plugin.getSqlReports().deleteReport(id, offlinePlayer.getUniqueId()).whenComplete((report1, ex1) -> + { + send(sender, messageComponent("deletedReport", id)); + }); + } + })); + + return null; + } + } + return null; + } + + private void readReports(@NotNull CommandSender sender, OfflinePlayer player, List reports) + { + AtomicReference reportList = new AtomicReference<>(messageComponent("reportHeader", player.getName())); + for (Report report : reports) + { + Component reportLine = messageComponent("reportPrefix", report.getReportId(), player.getName(), MedinaUtils.useTimezone(report.getTimestamp())); + reportLine = reportLine.append(messageComponent("reportLine", report.getReason())); + reportList.set(reportList.get().append(Component.newline())); + reportList.set(reportList.get().append(reportLine)); + } + send(sender, reportList.get()); + } + + @Override + public @NotNull List smartTabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException + { + if (args.length == 1 && sender.hasPermission("medina.reports")) + { + return MedinaUtils.getPlayerNameList(); + } + if (args.length == 2 && sender.hasPermission("medina.reports")) + { + return List.of("list", "delete"); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/dev/plex/medina/data/Report.java b/src/main/java/dev/plex/medina/data/Report.java index 7853bfe..a05bd50 100644 --- a/src/main/java/dev/plex/medina/data/Report.java +++ b/src/main/java/dev/plex/medina/data/Report.java @@ -3,10 +3,10 @@ package dev.plex.medina.data; import com.google.gson.GsonBuilder; import dev.plex.medina.storage.annotation.PrimaryKey; import dev.plex.medina.storage.annotation.TableName; +import dev.plex.medina.storage.annotation.VarcharLimit; import dev.plex.medina.util.adapter.ZonedDateTimeAdapter; import lombok.Data; import lombok.Getter; -import lombok.Setter; import java.time.ZonedDateTime; import java.util.UUID; @@ -16,19 +16,24 @@ import java.util.UUID; public class Report { @PrimaryKey - private int reportId; // This will be automatically set from addReport + private final int reportId; // This will be automatically set from addReport @Getter private final UUID reporterUUID; private final String reporterName; + @Getter private final UUID reportedUUID; private final String reportedName; + @Getter private final ZonedDateTime timestamp; + @VarcharLimit(2000) + @Getter private final String reason; + @Getter private final boolean deleted; public String toJSON() diff --git a/src/main/java/dev/plex/medina/storage/SQLConnection.java b/src/main/java/dev/plex/medina/storage/SQLConnection.java index 0bc4b37..bee28c1 100644 --- a/src/main/java/dev/plex/medina/storage/SQLConnection.java +++ b/src/main/java/dev/plex/medina/storage/SQLConnection.java @@ -49,7 +49,7 @@ public class SQLConnection implements MedinaBase try (Connection con = getCon()) { con.prepareStatement("CREATE TABLE IF NOT EXISTS `reports` (" + - "`reportId` INT NOT NULL AUTOINCREMENT, " + + "`reportId` INT NOT NULL AUTO_INCREMENT, " + "`reporterUUID` VARCHAR(46) NOT NULL, " + "`reporterName` VARCHAR(18), " + "`reportedUUID` VARCHAR(46) NOT NULL, " + diff --git a/src/main/java/dev/plex/medina/storage/SQLReports.java b/src/main/java/dev/plex/medina/storage/SQLReports.java index eb8dfc2..2165501 100644 --- a/src/main/java/dev/plex/medina/storage/SQLReports.java +++ b/src/main/java/dev/plex/medina/storage/SQLReports.java @@ -1,15 +1,13 @@ package dev.plex.medina.storage; import com.google.common.collect.Lists; -import dev.plex.medina.Medina; import dev.plex.medina.MedinaBase; import dev.plex.medina.data.Report; -import dev.plex.medina.util.MedinaUtils; +import dev.plex.medina.util.MedinaLog; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.SQLException; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -20,33 +18,80 @@ import java.util.concurrent.CompletableFuture; public class SQLReports implements MedinaBase { private static final String SELECT = "SELECT * FROM `reports` WHERE reportedUUID=?"; + private static final String SELECT_ID = "SELECT * FROM `reports` WHERE reportId=?"; private static final String INSERT = "INSERT INTO `reports` (`reportId`, `reporterUUID`, `reporterName`, `reportedUUID`, `reportedName`, `timestamp`, `reason`, `deleted`) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"; - private static final String DELETE = "DELETE FROM `reports` WHERE reportId=? AND reportedUUID=?"; + private static final String DELETE = "UPDATE `reports` SET `deleted`=true WHERE reportId=? AND reportedUUID=?"; + + public CompletableFuture getReports(int reportedId) + { + MedinaLog.log("getting reports for: " + reportedId); + return CompletableFuture.supplyAsync(() -> + { + Report report; + MedinaLog.log("initialized List"); + try (Connection con = plugin.getSqlConnection().getCon()) + { + MedinaLog.log("opened connection"); + PreparedStatement statement = con.prepareStatement(SELECT_ID); + MedinaLog.log("prepared select statement"); + statement.setInt(1, reportedId); + MedinaLog.log("set reportedUUID to " + reportedId); + ResultSet set = statement.executeQuery(); + MedinaLog.log("executing query"); + MedinaLog.log("adding a report..."); + report = new Report( + reportedId, + UUID.fromString(set.getString("reporterUUID")), + set.getString("reporterName"), + UUID.fromString(set.getString("reportedUUID")), + set.getString("reportedName"), + ZonedDateTime.ofInstant(Instant.ofEpochMilli(set.getLong("timestamp")), ZoneId.systemDefault()), + set.getString("reason"), + set.getBoolean("deleted")); + MedinaLog.log("added a report, id is " + report.getReportId()); + return report; + } + catch (Throwable e) + { + e.printStackTrace(); + return null; + } + }); + } public CompletableFuture> getReports(UUID reportedUUID) { + MedinaLog.log("getting reports for: " + reportedUUID); return CompletableFuture.supplyAsync(() -> { List reports = Lists.newArrayList(); + MedinaLog.log("initialized List"); try (Connection con = plugin.getSqlConnection().getCon()) { + MedinaLog.log("opened connection"); PreparedStatement statement = con.prepareStatement(SELECT); + MedinaLog.log("prepared select statement"); statement.setString(1, reportedUUID.toString()); + MedinaLog.log("set reportedUUID to " + reportedUUID); ResultSet set = statement.executeQuery(); + MedinaLog.log("executing query"); while (set.next()) { + MedinaLog.log("adding a report..."); Report report = new Report( + set.getInt("reportId"), UUID.fromString(set.getString("reporterUUID")), set.getString("reporterName"), reportedUUID, set.getString("reportedName"), - ZonedDateTime.ofInstant(Instant.ofEpochMilli(set.getLong("timestamp")), ZoneId.of(MedinaUtils.TIMEZONE)), + ZonedDateTime.ofInstant(Instant.ofEpochMilli(set.getLong("timestamp")), ZoneId.systemDefault()), set.getString("reason"), set.getBoolean("deleted")); reports.add(report); + MedinaLog.log("added a report, id is " + report.getReportId()); } } - catch (SQLException e) + catch (Throwable e) { e.printStackTrace(); return reports; @@ -57,16 +102,20 @@ public class SQLReports implements MedinaBase public CompletableFuture deleteReport(int reportId, UUID reportedUUID) { + MedinaLog.log("deleting report"); return CompletableFuture.runAsync(() -> { + MedinaLog.log("running async"); try (Connection con = plugin.getSqlConnection().getCon()) { + MedinaLog.log("established connection"); PreparedStatement statement = con.prepareStatement(DELETE); statement.setInt(1, reportId); statement.setString(2, reportedUUID.toString()); statement.execute(); + MedinaLog.log("deleted report"); } - catch (SQLException e) + catch (Throwable e) { e.printStackTrace(); } @@ -82,16 +131,17 @@ public class SQLReports implements MedinaBase try (Connection con = plugin.getSqlConnection().getCon()) { PreparedStatement statement = con.prepareStatement(INSERT); - statement.setString(1, report.getReporterUUID().toString()); - statement.setString(2, report.getReporterName()); - statement.setString(3, report.getReportedUUID().toString()); - statement.setString(4, report.getReportedName()); - statement.setLong(5, report.getTimestamp().toInstant().toEpochMilli()); - statement.setString(6, report.getReason()); - statement.setBoolean(7, report.isDeleted()); + statement.setInt(1, reports.size() + 1); + statement.setString(2, report.getReporterUUID().toString()); + statement.setString(3, report.getReporterName()); + statement.setString(4, report.getReportedUUID().toString()); + statement.setString(5, report.getReportedName()); + statement.setLong(6, report.getTimestamp().toInstant().toEpochMilli()); + statement.setString(7, report.getReason()); + statement.setBoolean(8, report.isDeleted()); statement.execute(); } - catch (SQLException e) + catch (Throwable e) { e.printStackTrace(); } diff --git a/src/main/java/dev/plex/medina/storage/annotation/VarcharLimit.java b/src/main/java/dev/plex/medina/storage/annotation/VarcharLimit.java new file mode 100644 index 0000000..11755a2 --- /dev/null +++ b/src/main/java/dev/plex/medina/storage/annotation/VarcharLimit.java @@ -0,0 +1,13 @@ +package dev.plex.medina.storage.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface VarcharLimit +{ + int value(); +} diff --git a/src/main/java/dev/plex/medina/util/MedinaUtils.java b/src/main/java/dev/plex/medina/util/MedinaUtils.java index c6796e7..1725e98 100644 --- a/src/main/java/dev/plex/medina/util/MedinaUtils.java +++ b/src/main/java/dev/plex/medina/util/MedinaUtils.java @@ -1,19 +1,26 @@ package dev.plex.medina.util; -import dev.plex.medina.Medina; import dev.plex.medina.MedinaBase; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import java.sql.Connection; import java.sql.SQLException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import java.time.format.DateTimeFormatter; + public class MedinaUtils implements MedinaBase { private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); - public static String TIMEZONE = plugin.config.getString("timezone"); + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("MM/dd/yyyy 'at' hh:mm:ss a z"); public static Component mmDeserialize(String input) { @@ -60,6 +67,16 @@ public class MedinaUtils implements MedinaBase return f; } + public static List getPlayerNameList() + { + return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + } + + public static String useTimezone(ZonedDateTime date) + { + return DATE_FORMAT.withZone(ZoneId.systemDefault()).format(date); + } + public static void testConnection() { MedinaLog.log("Attempting to connect to DB: {0}", plugin.config.getString("database.name")); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 10a18a9..474e001 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -6,7 +6,4 @@ database: hostname: 127.0.0.1 port: 3306 username: minecraft - password: medina - -# The timezone the reports will show up as -timezone: Etc/UTC \ No newline at end of file + password: medina \ No newline at end of file diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 077ed08..a47e4f0 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -16,4 +16,25 @@ specifyPlayer: "You must specify a player!" noPermissionNode: "You must have the permission: {0} to use this command!" noPermissionInGame: "You must be in console to use this command!" noPermissionConsole: "You must be in-game to use this command!" -consoleOnly: "This command can only be executed by the console." \ No newline at end of file +consoleOnly: "This command can only be executed by the console." + +# 0 - the reported player's username +reportSubmitted: "Your report against {0} was submitted." + +noReports: "This player has no existing reports." + +# 0 - Player who is having their reports fetched +reportHeader: "Player reports for: {0}" + +# 0 - Report ID +# 1 - Author of the note +# 2 - Timestamp +reportPrefix: "{0} - Written by: {1} on {2}" + +# 0 - The content of the report +reportLine: "# {0}" + +# 0 - the Report ID +deletedReport: "Report ID: {0} deleted" + +reportDoesntExist: "There is no report with this ID belonging to that player." \ No newline at end of file