diff --git a/server/build.gradle b/server/build.gradle index 3688f9b..e101ceb 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -11,6 +11,7 @@ dependencies { library "org.mariadb.jdbc:mariadb-java-client:3.1.4" library "com.zaxxer:HikariCP:5.0.1" library "org.apache.maven.resolver:maven-resolver-transport-http:1.9.15" + library "org.jetbrains:annotations:24.0.1" compileOnly "dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT" compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") { exclude group: "org.bukkit", module: "bukkit" @@ -58,6 +59,10 @@ paper { required = false load = 'BEFORE' } + 'SlimeWorldManager' { + required = false + load = 'AFTER' + } } } diff --git a/server/src/main/java/dev/plex/Plex.java b/server/src/main/java/dev/plex/Plex.java index ce1805d..be55b16 100644 --- a/server/src/main/java/dev/plex/Plex.java +++ b/server/src/main/java/dev/plex/Plex.java @@ -1,5 +1,6 @@ package dev.plex; +import com.google.common.collect.Lists; import dev.plex.cache.DataUtils; import dev.plex.cache.PlayerCache; import dev.plex.config.Config; @@ -17,11 +18,13 @@ import dev.plex.storage.punishment.SQLNotes; import dev.plex.storage.punishment.SQLPunishment; import dev.plex.util.*; import dev.plex.util.redis.MessageUtil; +import dev.plex.util.sql.SQLUtil; import dev.plex.world.CustomWorld; import lombok.Getter; import lombok.Setter; import net.milkbowl.vault.chat.Chat; import net.milkbowl.vault.permission.Permission; +import org.apache.commons.lang3.StringUtils; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.plugin.RegisteredServiceProvider; diff --git a/server/src/main/java/dev/plex/command/impl/SetLoginMessageCMD.java b/server/src/main/java/dev/plex/command/impl/SetLoginMessageCMD.java index d2b28d5..27df005 100644 --- a/server/src/main/java/dev/plex/command/impl/SetLoginMessageCMD.java +++ b/server/src/main/java/dev/plex/command/impl/SetLoginMessageCMD.java @@ -8,6 +8,7 @@ import dev.plex.command.exception.CommandFailException; import dev.plex.command.source.RequiredCommandSource; import dev.plex.player.PlexPlayer; import dev.plex.util.PlexLog; +import dev.plex.util.PlexUtils; import net.kyori.adventure.text.Component; import org.apache.commons.lang3.StringUtils; import org.bukkit.command.CommandSender; @@ -53,8 +54,7 @@ public class SetLoginMessageCMD extends PlexCommand validateMessage(message); plexPlayer.setLoginMessage(message); return messageComponent("setOtherPlayersLoginMessage", plexPlayer.getName(), - message.replace("%player%", plexPlayer.getName()) - .replace("%rank%", plexPlayer.getRank())); + message.replace("%player%", plexPlayer.getName())); } if (isConsole(sender)) { @@ -63,11 +63,11 @@ public class SetLoginMessageCMD extends PlexCommand PlexPlayer plexPlayer = plugin.getPlayerCache().getPlexPlayer(playerSender.getUniqueId()); String message = StringUtils.join(args, " ", 0, args.length); message = message.replace(plexPlayer.getName(), "%player%"); + message = PlexUtils.legacyToMiniString(message); validateMessage(message); plexPlayer.setLoginMessage(message); return messageComponent("setOwnLoginMessage", - message.replace("%player%", plexPlayer.getName()) - .replace("%rank%", plexPlayer.getRank())); + message.replace("%player%", plexPlayer.getName())); } return null; } diff --git a/server/src/main/java/dev/plex/command/impl/TagCMD.java b/server/src/main/java/dev/plex/command/impl/TagCMD.java index ce9f654..33499fb 100644 --- a/server/src/main/java/dev/plex/command/impl/TagCMD.java +++ b/server/src/main/java/dev/plex/command/impl/TagCMD.java @@ -47,7 +47,7 @@ public class TagCMD extends PlexCommand { return usage("/tag set "); } - String prefix = PlexUtils.cleanString(StringUtils.join(args, " ", 1, args.length)); + String prefix = PlexUtils.legacyToMiniString(StringUtils.join(args, " ", 1, args.length)); Component convertedComponent = SafeMiniMessage.mmDeserializeWithoutEvents(prefix); diff --git a/server/src/main/java/dev/plex/listener/impl/ChatListener.java b/server/src/main/java/dev/plex/listener/impl/ChatListener.java index 21af2e7..323db76 100644 --- a/server/src/main/java/dev/plex/listener/impl/ChatListener.java +++ b/server/src/main/java/dev/plex/listener/impl/ChatListener.java @@ -101,7 +101,7 @@ public class ChatListener extends PlexListener private static void defaultChatProcessing(AsyncChatEvent event, PlexPlayer plexPlayer) { - String text = PlexUtils.cleanString(PlexUtils.getTextFromComponent(event.message())); + String text = PlexUtils.legacyToMiniString(PlexUtils.getTextFromComponent(event.message())); event.message(SafeMiniMessage.mmDeserializeWithoutEvents(text)); } } diff --git a/server/src/main/java/dev/plex/meta/PlayerMeta.java b/server/src/main/java/dev/plex/meta/PlayerMeta.java index 7c0f2ba..d2ee7af 100644 --- a/server/src/main/java/dev/plex/meta/PlayerMeta.java +++ b/server/src/main/java/dev/plex/meta/PlayerMeta.java @@ -37,8 +37,7 @@ public class PlayerMeta if (!plexPlayer.getLoginMessage().isEmpty()) { return plexPlayer.getLoginMessage() - .replace("%player%", plexPlayer.getName()) - .replace("%rank%", plexPlayer.getRank()); + .replace("%player%", plexPlayer.getName()); } else { diff --git a/server/src/main/java/dev/plex/player/PlexPlayer.java b/server/src/main/java/dev/plex/player/PlexPlayer.java index 7495cbc..68c684d 100644 --- a/server/src/main/java/dev/plex/player/PlexPlayer.java +++ b/server/src/main/java/dev/plex/player/PlexPlayer.java @@ -5,7 +5,10 @@ import com.google.gson.GsonBuilder; import dev.plex.Plex; import dev.plex.punishment.Punishment; import dev.plex.punishment.extra.Note; +import dev.plex.storage.annotation.MapObjectList; import dev.plex.storage.annotation.PrimaryKey; +import dev.plex.storage.annotation.SQLTable; +import dev.plex.storage.annotation.VarcharLimit; import dev.plex.util.adapter.ZonedDateTimeAdapter; import lombok.AccessLevel; import lombok.Getter; @@ -14,6 +17,7 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionAttachment; +import org.jetbrains.annotations.NotNull; import java.time.ZonedDateTime; import java.util.List; @@ -21,11 +25,16 @@ import java.util.UUID; @Getter @Setter +@SQLTable("players") public class PlexPlayer { @Setter(AccessLevel.NONE) @PrimaryKey + @NotNull private UUID uuid; + + @VarcharLimit(16) + @NotNull private String name; private String loginMessage; @@ -44,13 +53,13 @@ public class PlexPlayer private long coins; - private String rank; - private List ips = Lists.newArrayList(); - private List punishments = Lists.newArrayList(); - private List notes = Lists.newArrayList(); - private transient PermissionAttachment permissionAttachment; + @MapObjectList + private List punishments = Lists.newArrayList(); + + @MapObjectList + private List notes = Lists.newArrayList(); public PlexPlayer() { @@ -69,7 +78,6 @@ public class PlexPlayer this.coins = 0; - this.rank = ""; if (loadExtraData) { this.loadPunishments(); diff --git a/server/src/main/java/dev/plex/punishment/Punishment.java b/server/src/main/java/dev/plex/punishment/Punishment.java index 075035a..bd0d56d 100644 --- a/server/src/main/java/dev/plex/punishment/Punishment.java +++ b/server/src/main/java/dev/plex/punishment/Punishment.java @@ -3,6 +3,7 @@ package dev.plex.punishment; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import dev.plex.Plex; +import dev.plex.storage.annotation.SQLTable; import dev.plex.util.MojangUtils; import dev.plex.util.PlexUtils; import dev.plex.util.TimeUtils; @@ -10,16 +11,19 @@ import dev.plex.util.adapter.ZonedDateTimeAdapter; import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.NotNull; import java.time.ZonedDateTime; import java.util.UUID; @Getter @Setter +@SQLTable("punishments") public class Punishment { private static final Gson gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeAdapter()).create(); private static final String banUrl = Plex.get().config.getString("banning.ban_url"); + @NotNull private final UUID punished; private final UUID punisher; private String ip; diff --git a/server/src/main/java/dev/plex/punishment/extra/Note.java b/server/src/main/java/dev/plex/punishment/extra/Note.java index 0b67339..846502f 100644 --- a/server/src/main/java/dev/plex/punishment/extra/Note.java +++ b/server/src/main/java/dev/plex/punishment/extra/Note.java @@ -1,6 +1,8 @@ package dev.plex.punishment.extra; import com.google.gson.GsonBuilder; +import dev.plex.storage.annotation.NoLimit; +import dev.plex.storage.annotation.SQLTable; import dev.plex.util.adapter.ZonedDateTimeAdapter; import lombok.Data; @@ -8,9 +10,12 @@ import java.time.ZonedDateTime; import java.util.UUID; @Data +@SQLTable("notes") public class Note { private final UUID uuid; + + @NoLimit private final String note; private final UUID writtenBy; private final ZonedDateTime timestamp; diff --git a/server/src/main/java/dev/plex/storage/annotation/MapObjectList.java b/server/src/main/java/dev/plex/storage/annotation/MapObjectList.java new file mode 100644 index 0000000..154e1c8 --- /dev/null +++ b/server/src/main/java/dev/plex/storage/annotation/MapObjectList.java @@ -0,0 +1,17 @@ +package dev.plex.storage.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Taah + * @since 1:42 AM [25-08-2023] + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface MapObjectList +{ +} diff --git a/server/src/main/java/dev/plex/storage/annotation/NoLimit.java b/server/src/main/java/dev/plex/storage/annotation/NoLimit.java new file mode 100644 index 0000000..381837f --- /dev/null +++ b/server/src/main/java/dev/plex/storage/annotation/NoLimit.java @@ -0,0 +1,17 @@ +package dev.plex.storage.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Taah + * @since 1:42 AM [25-08-2023] + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface NoLimit +{ +} diff --git a/server/src/main/java/dev/plex/storage/annotation/PrimaryKey.java b/server/src/main/java/dev/plex/storage/annotation/PrimaryKey.java index 6c425bf..f18659c 100644 --- a/server/src/main/java/dev/plex/storage/annotation/PrimaryKey.java +++ b/server/src/main/java/dev/plex/storage/annotation/PrimaryKey.java @@ -14,4 +14,5 @@ import java.lang.annotation.Target; @Target(ElementType.FIELD) public @interface PrimaryKey { + boolean dontSet() default false; } diff --git a/server/src/main/java/dev/plex/storage/annotation/SQLTable.java b/server/src/main/java/dev/plex/storage/annotation/SQLTable.java new file mode 100644 index 0000000..458a1dc --- /dev/null +++ b/server/src/main/java/dev/plex/storage/annotation/SQLTable.java @@ -0,0 +1,18 @@ +package dev.plex.storage.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Taah + * @since 4:27 AM [25-08-2023] + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SQLTable +{ + String value(); +} diff --git a/server/src/main/java/dev/plex/storage/annotation/VarcharLimit.java b/server/src/main/java/dev/plex/storage/annotation/VarcharLimit.java new file mode 100644 index 0000000..52117b6 --- /dev/null +++ b/server/src/main/java/dev/plex/storage/annotation/VarcharLimit.java @@ -0,0 +1,18 @@ +package dev.plex.storage.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Taah + * @since 1:42 AM [25-08-2023] + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface VarcharLimit +{ + int value(); +} diff --git a/server/src/main/java/dev/plex/storage/player/SQLPlayerData.java b/server/src/main/java/dev/plex/storage/player/SQLPlayerData.java index 63a4d92..8f4817a 100644 --- a/server/src/main/java/dev/plex/storage/player/SQLPlayerData.java +++ b/server/src/main/java/dev/plex/storage/player/SQLPlayerData.java @@ -86,7 +86,6 @@ public class SQLPlayerData String name = set.getString("name"); String loginMSG = set.getString("login_msg"); String prefix = set.getString("prefix"); - String rankName = set.getString("rank").toUpperCase(); boolean adminActive = set.getBoolean("adminActive"); long coins = set.getLong("coins"); boolean vanished = set.getBoolean("vanished"); @@ -97,7 +96,6 @@ public class SQLPlayerData plexPlayer.setName(name); plexPlayer.setLoginMessage(loginMSG); plexPlayer.setPrefix(prefix); - plexPlayer.setRank(rankName); plexPlayer.setAdminActive(adminActive); plexPlayer.setIps(ips); plexPlayer.setCoins(coins); @@ -135,7 +133,6 @@ public class SQLPlayerData PlexPlayer plexPlayer = new PlexPlayer(UUID.fromString(set.getString("uuid")), loadExtraData); String loginMSG = set.getString("login_msg"); String prefix = set.getString("prefix"); - String rankName = set.getString("rank").toUpperCase(); boolean adminActive = set.getBoolean("adminActive"); long coins = set.getLong("coins"); boolean vanished = set.getBoolean("vanished"); @@ -146,7 +143,6 @@ public class SQLPlayerData plexPlayer.setName(username); plexPlayer.setLoginMessage(loginMSG); plexPlayer.setPrefix(prefix); - plexPlayer.setRank(rankName); plexPlayer.setAdminActive(adminActive); plexPlayer.setIps(ips); plexPlayer.setCoins(coins); @@ -211,7 +207,6 @@ public class SQLPlayerData plexPlayer.setName(name); plexPlayer.setLoginMessage(loginMSG); plexPlayer.setPrefix(prefix); - plexPlayer.setRank(rankName); plexPlayer.setAdminActive(adminActive); plexPlayer.setIps(ips); plexPlayer.setCoins(coins); @@ -257,7 +252,6 @@ public class SQLPlayerData plexPlayer.setName(name); plexPlayer.setLoginMessage(loginMSG); plexPlayer.setPrefix(prefix); - plexPlayer.setRank(rankName); plexPlayer.setAdminActive(adminActive); plexPlayer.setIps(ips); plexPlayer.setCoins(coins); @@ -288,7 +282,7 @@ public class SQLPlayerData statement.setString(1, player.getName()); statement.setString(2, player.getLoginMessage()); statement.setString(3, player.getPrefix()); - statement.setString(4, player.getRank().toLowerCase()); + statement.setString(4, null); // rank statement.setBoolean(5, player.isAdminActive()); statement.setString(6, new Gson().toJson(player.getIps())); statement.setLong(7, player.getCoins()); @@ -318,7 +312,7 @@ public class SQLPlayerData statement.setString(2, player.getName()); statement.setString(3, player.getLoginMessage()); statement.setString(4, player.getPrefix()); - statement.setString(5, player.getRank().toLowerCase()); + statement.setString(5, null); //rank statement.setBoolean(6, player.isAdminActive()); statement.setString(7, new Gson().toJson(player.getIps())); statement.setLong(8, player.getCoins()); diff --git a/server/src/main/java/dev/plex/util/PlexLog.java b/server/src/main/java/dev/plex/util/PlexLog.java index 6a867bb..8097e85 100644 --- a/server/src/main/java/dev/plex/util/PlexLog.java +++ b/server/src/main/java/dev/plex/util/PlexLog.java @@ -13,6 +13,7 @@ public class PlexLog { for (int i = 0; i < strings.length; i++) { + if (strings[i] == null) continue; if (message.contains("{" + i + "}")) { message = message.replace("{" + i + "}", strings[i].toString()); @@ -30,6 +31,7 @@ public class PlexLog { for (int i = 0; i < strings.length; i++) { + if (strings[i] == null) continue; if (message.contains("{" + i + "}")) { message = message.replace("{" + i + "}", strings[i].toString()); @@ -42,6 +44,7 @@ public class PlexLog { for (int i = 0; i < strings.length; i++) { + if (strings[i] == null) continue; if (message.contains("{" + i + "}")) { message = message.replace("{" + i + "}", strings[i].toString()); @@ -56,6 +59,7 @@ public class PlexLog { for (int i = 0; i < strings.length; i++) { + if (strings[i] == null) continue; if (message.contains("{" + i + "}")) { message = message.replace("{" + i + "}", strings[i].toString()); diff --git a/server/src/main/java/dev/plex/util/PlexUtils.java b/server/src/main/java/dev/plex/util/PlexUtils.java index 944a5cd..1df6f08 100644 --- a/server/src/main/java/dev/plex/util/PlexUtils.java +++ b/server/src/main/java/dev/plex/util/PlexUtils.java @@ -5,7 +5,6 @@ import com.google.common.collect.Lists; import dev.plex.Plex; import dev.plex.PlexBase; import dev.plex.listener.impl.ChatListener; -import dev.plex.player.PlexPlayer; import dev.plex.storage.StorageType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; @@ -27,6 +26,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Arrays; import java.util.List; +import java.util.Stack; import java.util.UUID; import java.util.stream.Collectors; @@ -98,11 +98,14 @@ public class PlexUtils implements PlexBase } } - public static boolean isFolia() { - try { + public static boolean isFolia() + { + try + { Class.forName("io.papermc.paper.threadedregions.ThreadedRegionizer"); } - catch (Exception e) { + catch (Exception e) + { return false; } @@ -129,6 +132,45 @@ public class PlexUtils implements PlexBase return false; } + public static Component removeHoverAndClick(Component component) + { + Stack components = new Stack<>(); + components.push(component); + while (!components.isEmpty()) + { + Component curr = components.pop(); + curr.clickEvent(null).hoverEvent(null); + curr.children().forEach(components::push); + } + return component; + } + + public static String legacyToMiniString(String input) + { + return cleanString(input.replace("&a", "") + .replace("&b", "") + .replace("&c", "") + .replace("&d", "") + .replace("&e", "") + .replace("&f", "") + .replace("&1", "") + .replace("&2", "") + .replace("&3", "") + .replace("&4", "") + .replace("&5", "") + .replace("&6", "") + .replace("&7", "") + .replace("&8", "") + .replace("&9", "") + .replace("&0", "") + .replace("&r", "") + .replace("&l", "") + .replace("&o", "") + .replace("&n", "") + .replace("&m", "") + .replace("&k", "")); + } + public static String mmStripColor(String input) { return PlainTextComponentSerializer.plainText().serialize(mmDeserialize(input)); diff --git a/server/src/main/java/dev/plex/util/ReflectionsUtil.java b/server/src/main/java/dev/plex/util/ReflectionsUtil.java index fc7198a..8f0583f 100644 --- a/server/src/main/java/dev/plex/util/ReflectionsUtil.java +++ b/server/src/main/java/dev/plex/util/ReflectionsUtil.java @@ -2,9 +2,13 @@ package dev.plex.util; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.ClassPath; +import com.google.common.reflect.TypeToken; import dev.plex.Plex; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -54,4 +58,14 @@ public class ReflectionsUtil }); return Collections.unmodifiableSet(classes); } + + public static Class getGenericField(Field field) + { + Type type = field.getGenericType(); + if (type instanceof ParameterizedType parameterizedType) + { + return TypeToken.of(parameterizedType.getActualTypeArguments()[0]).getRawType(); + } + return field.getType(); + } } diff --git a/server/src/main/java/dev/plex/util/sql/SQLUtil.java b/server/src/main/java/dev/plex/util/sql/SQLUtil.java new file mode 100644 index 0000000..aa50fac --- /dev/null +++ b/server/src/main/java/dev/plex/util/sql/SQLUtil.java @@ -0,0 +1,186 @@ +package dev.plex.util.sql; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import dev.plex.punishment.PunishmentType; +import dev.plex.storage.annotation.*; +import dev.plex.util.PlexLog; +import dev.plex.util.ReflectionsUtil; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author Taah + * @since 4:28 AM [25-08-2023] + */ +public class SQLUtil +{ + public static final List TABLES = Lists.newArrayList(); + + public static List createTable(List result, Class clazz) + { + if (!clazz.isAnnotationPresent(SQLTable.class)) + { + PlexLog.error("Unable to map {0} to a table, it is missing the SQLTable's annotation", clazz.getName()); + return null; + } + final List collectionFields = Lists.newArrayList(); + + final Table table = new Table(clazz.getAnnotation(SQLTable.class).value()); + + final StringBuilder mainResult = new StringBuilder("CREATE TABLE IF NOT EXISTS `" + table.name() + "` ("); + final List declaredFields = Arrays.stream(clazz.getDeclaredFields()).filter(field -> !Modifier.isTransient(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())).collect(Collectors.toList()); + final List iterating = declaredFields.stream().toList(); + for (Field value : iterating) + { + if (Collection.class.isAssignableFrom(value.getType())) + { + collectionFields.add(value); + declaredFields.remove(value); + } + } + Field primaryKey = null; + + for (int i = 0; i < declaredFields.size(); i++) + { + Field declaredField = declaredFields.get(i); + final Mapper mapped = Mapper.getByClass(declaredField.getType()); + if (mapped == null) + { + PlexLog.warn("Could not map field {0} for class {1}", declaredField.getName(), clazz.getName()); + continue; + } + if (declaredField.isAnnotationPresent(PrimaryKey.class)) + { + if (primaryKey != null) + { + PlexLog.error("You can only have one primary key for a table! The class {0} has more than one!", clazz.getName()); + return ImmutableList.of(); + } + primaryKey = declaredField; + } + + writeFieldToSQL(table, mainResult, mapped, declaredField); + if (i < declaredFields.size() - 1) + { + mainResult.append(", "); + } + } + if (primaryKey != null && !primaryKey.getAnnotation(PrimaryKey.class).dontSet()) + { + mainResult.append(", PRIMARY KEY (`").append(primaryKey.getName()).append("`)"); + } + mainResult.append(");"); + result.add(mainResult.toString()); + + TABLES.add(table); + + if (primaryKey == null && !collectionFields.isEmpty()) + { + PlexLog.error("You must define a primary key to point to if you wish to have a list saved. You can use @PrimaryKey(dontSet = true) to make sure that SQL does not save it as a primary key."); + return ImmutableList.of(); + } + + Field finalPrimaryKey = primaryKey; + collectionFields.forEach(field -> + { + final String tableName = field.getName() + "To" + StringUtils.capitalize(clazz.getSimpleName()); + StringBuilder sql = new StringBuilder("CREATE TABLE IF NOT EXISTS `" + tableName + "` ("); + if (field.isAnnotationPresent(MapObjectList.class)) + { + createTable(result, ReflectionsUtil.getGenericField(field)); + return; + } + final Mapper mapped = Mapper.getByClass(ReflectionsUtil.getGenericField(field)); + if (mapped == null) + { + PlexLog.warn("Could not map collection field {0} for class {1}", field.getName(), clazz.getName()); + return; + } + final Table listTable = new Table(tableName); + writeFieldToSQL(listTable, sql, mapped, field); + sql.append(", "); + writeFieldToSQL(listTable, sql, Mapper.getByClass(finalPrimaryKey.getType()), finalPrimaryKey); + sql.append(");"); + result.add(sql.toString()); + table.mappedTables().add(listTable); + }); + return result; + } + + private static void writeFieldToSQL(Table table, StringBuilder sb, Mapper mapped, Field field) + { + + sb.append("`").append(field.getName()).append("` "); + if (mapped == Mapper.VARCHAR) + { + if (field.isAnnotationPresent(NoLimit.class)) + { + sb.append("TEXT"); + table.columns().put(field.getName(), Mapper.TEXT); + } + else + { + sb.append(mapped.name()); + table.columns().put(field.getName(), mapped); + } + } + else + { + sb.append(mapped.name()); + table.columns().put(field.getName(), mapped); + } + if (mapped == Mapper.VARCHAR && !field.isAnnotationPresent(NoLimit.class)) + { + if (UUID.class.isAssignableFrom(field.getType())) + { + sb.append(" (").append(36).append(")"); + } + else if (field.isAnnotationPresent(VarcharLimit.class)) + { + int limit = field.getAnnotation(VarcharLimit.class).value(); + sb.append(" (").append(limit).append(")"); + } + else + { + sb.append("(65535)"); + } + } + if (field.isAnnotationPresent(NotNull.class)) + { + sb.append(" NOT NULL"); + } + } + + @Accessors(fluent = true) + public enum Mapper + { + VARCHAR(String.class, UUID.class, PunishmentType.class), + BOOLEAN(Boolean.class, boolean.class), + BIGINT(Long.class, long.class, ZonedDateTime.class), + INT(Integer.class, int.class), + TEXT; + + private final Class[] clazz; + + Mapper(Class... clazz) + { + this.clazz = clazz; + } + + public static Mapper getByClass(Class clazz) + { + return Arrays.stream(values()).filter(mapper -> mapper.clazz != null && Arrays.asList(mapper.clazz).contains(clazz)).findFirst().orElse(null); + } + } +} diff --git a/server/src/main/java/dev/plex/util/sql/Table.java b/server/src/main/java/dev/plex/util/sql/Table.java new file mode 100644 index 0000000..a1534bd --- /dev/null +++ b/server/src/main/java/dev/plex/util/sql/Table.java @@ -0,0 +1,23 @@ +package dev.plex.util.sql; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.Map; + +/** + * @author Taah + * @since 5:30 AM [26-08-2023] + */ + +@Data +@Accessors(fluent = true) +public class Table +{ + private final String name; + private final Map columns = Maps.newHashMap(); + private final List
mappedTables = Lists.newArrayList(); +}