From e6bbb76a0b07758f5eb90f9134eeb2adc714ad13 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 27 Oct 2025 18:34:30 +0100 Subject: [PATCH 01/32] Rename .java to .kt --- CommonCore/SQL/src/de/steamwar/sql/{AuditLog.java => AuditLog.kt} | 0 .../src/de/steamwar/sql/{BannedUserIPs.java => BannedUserIPs.kt} | 0 .../src/de/steamwar/sql/{BauweltMember.java => BauweltMember.kt} | 0 .../src/de/steamwar/sql/{SteamwarUser.java => SteamwarUser.kt} | 0 CommonCore/SQL/src/de/steamwar/sql/{UserPerm.java => UserPerm.kt} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename CommonCore/SQL/src/de/steamwar/sql/{AuditLog.java => AuditLog.kt} (100%) rename CommonCore/SQL/src/de/steamwar/sql/{BannedUserIPs.java => BannedUserIPs.kt} (100%) rename CommonCore/SQL/src/de/steamwar/sql/{BauweltMember.java => BauweltMember.kt} (100%) rename CommonCore/SQL/src/de/steamwar/sql/{SteamwarUser.java => SteamwarUser.kt} (100%) rename CommonCore/SQL/src/de/steamwar/sql/{UserPerm.java => UserPerm.kt} (100%) diff --git a/CommonCore/SQL/src/de/steamwar/sql/AuditLog.java b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/AuditLog.java rename to CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.java b/CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.java rename to CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/BauweltMember.java b/CommonCore/SQL/src/de/steamwar/sql/BauweltMember.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/BauweltMember.java rename to CommonCore/SQL/src/de/steamwar/sql/BauweltMember.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java rename to CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserPerm.java b/CommonCore/SQL/src/de/steamwar/sql/UserPerm.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/UserPerm.java rename to CommonCore/SQL/src/de/steamwar/sql/UserPerm.kt From a462231babd494bd818e7790657e1cdee6258a4b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 27 Oct 2025 18:34:31 +0100 Subject: [PATCH 02/32] Starting... --- .../steamwar/bausystem/config/BauServer.java | 2 +- .../bausystem/features/bau/InfoCommand.java | 4 +- .../features/region/TestblockCommand.java | 5 +- .../features/script/ScriptHelper.java | 2 +- .../features/script/lua/libs/StorageLib.java | 2 +- .../storage/YAPIONFormatSimulatorLoader.java | 2 +- .../features/world/AntiBauAddMemberFix.java | 2 +- CommonCore/SQL/build.gradle.kts | 41 ++ .../SQL/src/de/steamwar/sql/AuditLog.kt | 176 +++-- .../SQL/src/de/steamwar/sql/BannedUserIPs.kt | 99 +-- .../SQL/src/de/steamwar/sql/BauweltMember.kt | 202 +++--- CommonCore/SQL/src/de/steamwar/sql/Fight.java | 4 +- .../src/de/steamwar/sql/GameModeConfig.java | 12 +- .../src/de/steamwar/sql/SchematicNode.java | 8 +- .../SQL/src/de/steamwar/sql/SteamwarUser.kt | 634 ++++++++---------- CommonCore/SQL/src/de/steamwar/sql/Token.java | 2 +- .../SQL/src/de/steamwar/sql/UserPerm.kt | 105 ++- .../steamwar/sql/internal/KotlinDatabase.kt | 58 ++ .../fightsystem/commands/InfoCommand.java | 2 +- .../fightsystem/fight/FightPlayer.java | 2 +- .../fightsystem/record/PacketProcessor.java | 2 +- .../src/de/steamwar/bausystem/BauSystem.java | 2 +- .../src/de/steamwar/bausystem/Mapper.java | 4 +- .../bausystem/commands/CommandInfo.java | 4 +- .../bausystem/commands/CommandLockschem.java | 2 +- .../de/steamwar/lobby/LobbyPacketHandler.java | 2 +- .../lobby/particle/ParticleRequirement.java | 4 +- .../lobby/portal/FightserverPortal.java | 2 +- .../de/steamwar/lobby/util/Leaderboard.java | 2 +- .../commands/schematiccommand/GUI.java | 4 +- .../SchematicCommandUtils.java | 12 +- .../schematiccommand/SchematicMapper.java | 6 +- .../schematiccommand/parts/MemberPart.java | 6 +- .../schematiccommand/parts/SavePart.java | 2 +- .../schematiccommand/parts/SearchPart.java | 2 +- .../schematiccommand/parts/ViewPart.java | 2 +- .../src/de/steamwar/command/TypeUtils.java | 4 +- .../steamwar/inventory/SchematicSelector.java | 12 +- .../steamwar/network/CoreNetworkHandler.java | 4 +- .../network/handlers/InventoryHandler.java | 5 +- .../de/steamwar/providers/BauServerInfo.java | 2 +- .../steamwar/tntleague/game/TNTLeagueGame.kt | 12 +- .../src/de/steamwar/messages/Chatter.java | 2 +- .../velocitycore/commands/BauCommand.java | 3 +- .../velocitycore/commands/CheckCommand.java | 12 +- .../commands/PunishmentCommand.java | 2 +- .../velocitycore/commands/TeamCommand.java | 4 +- .../velocitycore/commands/WhoisCommand.java | 4 +- .../discord/channels/ChecklistChannel.java | 3 +- .../discord/channels/DiscordChannel.java | 4 +- .../velocitycore/listeners/BanListener.java | 4 +- .../velocitycore/listeners/ChatListener.java | 4 +- .../steamwar/velocitycore/mods/ModUtils.java | 2 +- .../network/handlers/EloPlayerHandler.java | 6 +- .../handlers/ExecuteCommandHandler.java | 2 +- .../handlers/InventoryCallbackHandler.java | 2 +- .../network/handlers/PrepareSchemHandler.java | 2 +- .../velocitycore/tablist/TablistServer.java | 2 +- .../src/de/steamwar/plugins/Auth.kt | 2 +- WebsiteBackend/src/de/steamwar/routes/Data.kt | 6 +- .../src/de/steamwar/routes/EventReferees.kt | 11 +- .../src/de/steamwar/routes/Events.kt | 6 +- .../src/de/steamwar/routes/Schematic.kt | 4 +- .../src/de/steamwar/routes/Stats.kt | 2 +- settings.gradle.kts | 6 + 65 files changed, 784 insertions(+), 772 deletions(-) create mode 100644 CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/config/BauServer.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/config/BauServer.java index fea634a2..67fd9e52 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/config/BauServer.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/config/BauServer.java @@ -36,7 +36,7 @@ public class BauServer { private Integer owner; public UUID getOwner() { - return SteamwarUser.get(getOwnerID()).getUUID(); + return SteamwarUser.byId(getOwnerID()).getUUID(); } public int getOwnerID() { diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java index adeb4c45..e5bce542 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java @@ -47,7 +47,7 @@ public class InfoCommand extends SWCommand { @Register(description = "BAU_INFO_COMMAND_HELP") public void genericCommand(Player p) { - BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.get(bauServer.getOwnerID()).getUserName()); + BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.byId(bauServer.getOwnerID()).getUserName()); Region region = Region.getRegion(p.getLocation()); for (Flag flag : Flag.getFlags()) { if (!region.getFlags().has(flag).isApplicable()) continue; @@ -97,7 +97,7 @@ public class InfoCommand extends SWCommand { st.append("§8, "); } st.append("§7"); - st.append(SteamwarUser.get(bauweltMembers.get(i).getMemberID()).getUserName()); + st.append(SteamwarUser.byId(bauweltMembers.get(i).getMemberID()).getUserName()); } return st.toString(); } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java index d09c06a0..e8815dee 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java @@ -31,7 +31,6 @@ import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; import de.steamwar.linkage.Linked; import de.steamwar.linkage.LinkedInstance; -import de.steamwar.sql.BauweltMember; import de.steamwar.sql.Punishment; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; @@ -198,7 +197,7 @@ public class TestblockCommand extends SWCommand { @Override public List tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) { List stringList = new ArrayList<>(SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s)); - stringList.addAll(SchematicNode.getNodeTabcomplete(SteamwarUser.get(0), s)); + stringList.addAll(SchematicNode.getNodeTabcomplete(SteamwarUser.byId(0), s)); return stringList; } @@ -206,7 +205,7 @@ public class TestblockCommand extends SWCommand { public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) { SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); if (node == null) { - node = SchematicNode.getNodeFromPath(SteamwarUser.get(0), s); + node = SchematicNode.getNodeFromPath(SteamwarUser.byId(0), s); } return node; } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptHelper.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptHelper.java index fd4bc826..bb486680 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptHelper.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptHelper.java @@ -38,7 +38,7 @@ public class ScriptHelper { BookMeta meta = (BookMeta) itemStack.getItemMeta(); if(!writeable) { meta.setTitle(script.getName()); - meta.setAuthor(SteamwarUser.get(script.getUserId()).getUserName()); + meta.setAuthor(SteamwarUser.byId(script.getUserId()).getUserName()); } meta.setPages(getScriptPages(script)); itemStack.setItemMeta(meta); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/StorageLib.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/StorageLib.java index c1646d41..04cde3f0 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/StorageLib.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/StorageLib.java @@ -89,7 +89,7 @@ public class StorageLib implements LuaLib, Enable, Disable { jsonObject.keySet().forEach(key -> { map.put(key, fromJson(jsonObject.get(key))); }); - SteamwarUser steamwarUser = SteamwarUser.get(Integer.parseInt(playerStorage.getName().substring(0, playerStorage.getName().length() - ".json".length()))); + SteamwarUser steamwarUser = SteamwarUser.byId(Integer.parseInt(playerStorage.getName().substring(0, playerStorage.getName().length() - ".json".length()))); PLAYER_STORAGE.put(steamwarUser.getUUID(), map); } catch (Exception e) {} } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/YAPIONFormatSimulatorLoader.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/YAPIONFormatSimulatorLoader.java index c138ecb1..6111eb32 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/YAPIONFormatSimulatorLoader.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/YAPIONFormatSimulatorLoader.java @@ -54,7 +54,7 @@ public class YAPIONFormatSimulatorLoader implements SimulatorLoader { } String name = file.getName().substring(0, file.getName().length() - 7); - SteamwarUser steamwarUser = SteamwarUser.get(Integer.parseInt(name)); + SteamwarUser steamwarUser = SteamwarUser.byId(Integer.parseInt(name)); List simulators = new ArrayList<>(); for (String s : yapionObject.getKeys()) { diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/AntiBauAddMemberFix.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/AntiBauAddMemberFix.java index c8c40cba..da75fe7c 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/AntiBauAddMemberFix.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/AntiBauAddMemberFix.java @@ -41,7 +41,7 @@ public class AntiBauAddMemberFix implements Listener { } if (BauweltMember.getBauMember(BauServer.getInstance().getOwner(), event.getPlayer().getUniqueId()) == null) { event.getPlayer().kickPlayer(""); - throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.get(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!"); + throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.byId(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!"); } } diff --git a/CommonCore/SQL/build.gradle.kts b/CommonCore/SQL/build.gradle.kts index dc171dde..b6831f70 100644 --- a/CommonCore/SQL/build.gradle.kts +++ b/CommonCore/SQL/build.gradle.kts @@ -19,10 +19,51 @@ plugins { steamwar.java + kotlin("jvm") +} + +kotlin { + jvmToolchain(8) +} + +sourceSets { + main { + java { + srcDirs("src/") + exclude("**/*.kt") + } + kotlin { + srcDirs("src/") + exclude("**/*.java") + } + resources { + srcDirs("src/") + exclude("**/*.java", "**/*.kt") + } + } + test { + java { + srcDirs("testsrc/") + exclude("**/*.kt") + } + kotlin { + srcDirs("testsrc/") + exclude("**/*.java") + } + resources { + srcDirs("testsrc/") + exclude("**/*.java", "**/*.kt") + } + } } dependencies { compileOnly(libs.sqlite) implementation("org.yaml:snakeyaml:2.2") + + api(libs.exposedCore) + api(libs.exposedDao) + api(libs.exposedJdbc) + api(libs.exposedTime) } \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt index 04f87d9d..6d48857b 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt @@ -17,109 +17,105 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SqlTypeMapper; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NonNull; +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import java.time.Instant -import java.sql.Timestamp; -import java.time.Instant; +object AuditLogTable: IntIdTable("AuditLog", "AuditLogId") { + val time = timestamp("Time") + val server = varchar("ServerName", 255) + val serverOwner = integer("ServerOwner").nullable() + val actor = integer("Actor") + val action = enumerationByName("ActionType", 255, AuditLog.Type::class) + val actionText = text("ActionText") +} -@AllArgsConstructor -public class AuditLog { +class AuditLog(id: EntityID): IntEntity(id) { + companion object: IntEntityClass(AuditLogTable) { + const val SERVER_NAME_VELOCITY: String = "Velocity" - static { - SqlTypeMapper.nameEnumMapper(AuditLog.Type.class); + private fun create( + serverName: String, + serverOwner: SteamwarUser?, + actor: SteamwarUser, + actionType: Type, + text: String = "" + ) = useDb { + new { + this.time = Instant.now() + this.server = serverName + this.serverOwner = serverOwner?.id?.value + this.actor = actor.id.value + this.action = actionType + this.actionText = text + } + } + + @JvmStatic + fun createJoin(jointServerName: String, serverOwner: SteamwarUser?, joinedPlayer: SteamwarUser) = create(jointServerName, serverOwner, joinedPlayer, Type.JOIN) + + @JvmStatic + fun createLeave(leftServerName: String, serverOwner: SteamwarUser?, joinedPlayer: SteamwarUser) = create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE) + + @JvmStatic + fun createCommand(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser?, command: String) = player?.let { create(serverName, serverOwner, it, Type.COMMAND, command) } + + @JvmStatic + fun createSensitiveCommand( + serverName: String, + serverOwner: SteamwarUser?, + player: SteamwarUser?, + command: String + ) = player?.let { create(serverName, serverOwner, it, Type.SENSITIVE_COMMAND, command) } + + @JvmStatic + fun createChat(serverName: String, serverOwner: SteamwarUser?, chatter: SteamwarUser, chat: String) = create(serverName, serverOwner, chatter, Type.CHAT, chat) + + @JvmStatic + fun createGuiOpen(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser, guiName: String) = create(serverName, serverOwner, player, Type.GUI_OPEN, guiName) + + @JvmStatic + fun createGuiClick( + serverName: String, + serverOwner: SteamwarUser?, + player: SteamwarUser, + guiName: String, + clickType: String, + slot: Int, + itemName: String + ) = create( + serverName, + serverOwner, + player, + Type.GUI_CLICK, + "Gui: $guiName\nSlot: $slot\nClickType: $clickType\nItemName: $itemName" + ) + + @JvmStatic + fun createGuiClose(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser, guiName: String) = create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName) } - public static final String SERVER_NAME_VELOCITY = "Velocity"; + var time by AuditLogTable.time + var server by AuditLogTable.server + var serverOwner by AuditLogTable.serverOwner + var actor by AuditLogTable.actor + var action by AuditLogTable.action + var actionText by AuditLogTable.actionText - private static final Table table = new Table<>(AuditLog.class); - - private static final Statement create = table.insertFields(true, "time", "serverName", "serverOwner", "actor", "actionType", "actionText"); - - @Getter - @Field - private final Timestamp time; - - @Getter - @Field - private final String serverName; - - @Field(nullable = true) - private final int serverOwner; - - @Field - private final int actor; - - @Getter - @Field - private final Type actionType; - - @Getter - @Field - private final String actionText; - - public enum Type { + enum class Type { JOIN, LEAVE, COMMAND, SENSITIVE_COMMAND, - CHAT, GUI_OPEN, GUI_CLOSE, GUI_CLICK, } - - private static void create(String serverName, SteamwarUser serverOwner, SteamwarUser actor, Type actionType, String text) { - create.insertGetKey(Timestamp.from(Instant.now()), serverName, serverOwner, actor, actionType, text); - } - - public static void createJoin(@NonNull String jointServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) { - create(jointServerName, serverOwner, joinedPlayer, Type.JOIN, ""); - } - - public static void createLeave(@NonNull String leftServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) { - create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE, ""); - } - - public static void createCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) { - if (player == null) return; - create(serverName, serverOwner, player, Type.COMMAND, command); - } - - public static void createSensitiveCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) { - if (player == null) return; - create(serverName, serverOwner, player, Type.SENSITIVE_COMMAND, command); - } - - public static void createChat(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser chatter, @NonNull String chat) { - create(serverName, serverOwner, chatter, Type.CHAT, chat); - } - - public static void createGuiOpen(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) { - create(serverName, serverOwner, player, Type.GUI_OPEN, guiName); - } - - public static void createGuiClick(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName, @NonNull String clickType, int slot, @NonNull String itemName) { - create(serverName, serverOwner, player, Type.GUI_CLICK, "Gui: " + guiName + "\nSlot: " + slot + "\nClickType: " + clickType + "\nItemName: " + itemName); - } - - public static void createGuiClose(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) { - create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName); - } - - public SteamwarUser getServerOwner() { - return SteamwarUser.get(serverOwner); - } - - public SteamwarUser getActor() { - return SteamwarUser.get(actor); - } -} +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt b/CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt index f16e0343..495238ad 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt @@ -17,51 +17,62 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.deleteWhere +import org.jetbrains.exposed.v1.jdbc.insertIgnore +import java.sql.Timestamp +import java.time.Instant -import java.sql.Timestamp; -import java.time.Instant; -import java.util.List; +object BannedUserIPsTable: CompositeIdTable("BannedUserIPs") { + val userId = reference("UserID", SteamwarUserTable) + val timestamp = timestamp("Timestamp") + val ip = varchar("IP", 45) -@AllArgsConstructor -public class BannedUserIPs { - - private static final Table table = new Table<>(BannedUserIPs.class); - - private static final SelectStatement getByID = table.selectFields("UserID"); - private static final SelectStatement getByIP = new SelectStatement<>(table, "SELECT * FROM BannedUserIPs WHERE IP = ? ORDER BY Timestamp DESC"); - private static final Statement banIP = table.insertAll(); - private static final Statement unbanIPs = table.deleteFields("UserID"); - - @Getter - @Field(keys = {Table.PRIMARY}) - private final int userID; - @Getter - @Field(def = "CURRENT_TIMESTAMP") - private final Timestamp timestamp; - @Field(keys = {Table.PRIMARY}) - private final String ip; - - public static List get(int userID) { - return getByID.listSelect(userID); - } - - public static List get(String ip) { - return getByIP.listSelect(ip); - } - - public static void banIP(int userID, String ip){ - banIP.update(userID, Timestamp.from(Instant.now()), ip); - } - - public static void unbanIPs(int userID) { - unbanIPs.update(userID); - } + override val primaryKey = PrimaryKey(userId, ip) } + +class BannedUserIPs(id: EntityID): CompositeEntity(id) { + companion object: CompositeEntityClass(BannedUserIPsTable) { + + @JvmStatic + fun get(userId: Int) = useDb { + find { BannedUserIPsTable.userId eq userId }.toList() + } + + @JvmStatic + fun get(ip: String) = useDb { + find { BannedUserIPsTable.ip eq ip }.toList() + } + + @JvmStatic + fun banIP(userId: Int, ip: String) = useDb { + BannedUserIPsTable.insertIgnore { + it[BannedUserIPsTable.userId] = userId + it[BannedUserIPsTable.ip] = ip + it[BannedUserIPsTable.timestamp] = Instant.now() + } + } + + @JvmStatic + fun unbanIPs(userId: Int) = useDb { + BannedUserIPsTable.deleteWhere { BannedUserIPsTable.userId eq userId } + } + } + + val userID by BannedUserIPsTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + val timestamp: Timestamp by BannedUserIPsTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) }) + val ip by BannedUserIPsTable.ip + + fun remove() = useDb { + delete() + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/BauweltMember.kt b/CommonCore/SQL/src/de/steamwar/sql/BauweltMember.kt index 71fa3a46..a314d793 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/BauweltMember.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/BauweltMember.kt @@ -17,107 +17,109 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.Getter; +import de.steamwar.sql.BauweltMemberTable.bauweltId +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.jdbc.insertIgnore +import java.util.UUID -import java.util.*; +object BauweltMemberTable: CompositeIdTable("BauweltMember") { + val bauweltId = reference("BauweltID", SteamwarUserTable) + val memberId = reference("MemberID", SteamwarUserTable) + val build = bool("Build") + val worldEdit = bool("WorldEdit") + val world = bool("World") -public class BauweltMember { - private static final Map memberCache = new HashMap<>(); - - public static void clear() { - memberCache.clear(); - } - - private static final Table table = new Table<>(BauweltMember.class); - private static final SelectStatement getMember = table.select(Table.PRIMARY); - private static final SelectStatement getMembers = table.selectFields("BauweltID"); - private static final Statement update = table.insertAll(); - private static final Statement delete = table.delete(Table.PRIMARY); - - public static void addMember(UUID ownerID, UUID memberID) { - new BauweltMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId(), false, false).updateDB(); - } - - public static BauweltMember getBauMember(UUID ownerID, UUID memberID){ - return getBauMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId()); - } - - public static BauweltMember getBauMember(int ownerID, int memberID){ - BauweltMember member = memberCache.get(memberID); - if(member != null && member.bauweltID == ownerID) - return member; - return getMember.select(ownerID, memberID); - } - - public static List getMembers(UUID bauweltID){ - return getMembers(SteamwarUser.get(bauweltID).getId()); - } - - public static List getMembers(int bauweltID){ - return getMembers.listSelect(bauweltID); - } - - @Getter - @Field(keys = {Table.PRIMARY}) - private final int bauweltID; - @Getter - @Field(keys = {Table.PRIMARY}) - private final int memberID; - @Getter - @Field(def = "0") - private boolean worldEdit; - @Getter - @Field(def = "0") - private boolean world; - - public BauweltMember(int bauweltID, int memberID, boolean worldEdit, boolean world) { - this.bauweltID = bauweltID; - this.memberID = memberID; - this.worldEdit = worldEdit; - this.world = world; - memberCache.put(memberID, this); - } - - public void setWorldEdit(boolean worldEdit) { - this.worldEdit = worldEdit; - updateDB(); - } - - public void setWorld(boolean world) { - this.world = world; - updateDB(); - } - - private void updateDB(){ - update.update(bauweltID, memberID, worldEdit, world); - } - - public void remove(){ - delete.update(bauweltID, memberID); - memberCache.remove(memberID); - } - - public boolean isBuild() { - return worldEdit; - } - - public boolean isSupervisor() { - return world; - } - - public void setBuild(boolean build) { - this.worldEdit = build; - updateDB(); - } - - public void setSupervisor(boolean supervisor) { - this.world = supervisor; - updateDB(); - } + override val primaryKey = PrimaryKey(bauweltId, memberId) } + +class BauweltMember(id: EntityID): CompositeEntity(id) { + companion object: CompositeEntityClass(BauweltMemberTable) { + private val cache = mutableMapOf() + + private fun cache(member: BauweltMember) = cache.put(member.memberID, member) + + @JvmStatic + fun clear() = cache.clear() + + @JvmStatic + @Deprecated("Use addMember(ownerId: Int, newMemberId: Int)") + fun addMember(ownerId: UUID, newMemberId: UUID) = addMember(SteamwarUser.get(ownerId)!!.id, SteamwarUser.get(newMemberId)!!.id) + + @JvmStatic + fun addMember(ownerId: Int, newMemberId: Int) = addMember(EntityID(ownerId, SteamwarUserTable), EntityID(newMemberId, SteamwarUserTable)) + + fun addMember(ownerId: EntityID, newMemberId: EntityID) = useDb { + BauweltMemberTable.insertIgnore { + it[bauweltId] = ownerId + it[memberId] = newMemberId + it[build] = false + it[worldEdit] = false + it[world] = false + } + } + + @JvmStatic + @Deprecated("Use getBauMember(bauwelt: Int, member: Int)") + fun getBauMember(bauwelt: UUID, member: UUID) = useDb { + find { (bauweltId eq SteamwarUser.get(bauwelt)!!.id) and (BauweltMemberTable.memberId eq SteamwarUser.get(member)!!.id) }.firstOrNull()?.also { cache(it) } + } + + @JvmStatic + fun getBauMember(bauwelt: Int, member: Int) = useDb { + find { (bauweltId eq bauwelt) and (BauweltMemberTable.memberId eq member) }.firstOrNull()?.also { cache(it) } + } + + @JvmStatic + @Deprecated("Use getMembers(bauwelt: Int)") + fun getMembers(bauwelt: UUID) = getMembers(SteamwarUser.get(bauwelt)!!.id.value) + + @JvmStatic + fun getMembers(bauwelt: Int) = useDb { + find { bauweltId eq bauwelt }.toList().also { it.forEach { cache(it) } } + } + } + + val bauweltID by BauweltMemberTable.bauweltId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + val memberID by BauweltMemberTable.memberId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + private var worldEditInternal by BauweltMemberTable.worldEdit + var worldEdit: Boolean + get() = worldEditInternal + set(value) = useDb { + worldEditInternal = value + } + private var buildInternal by BauweltMemberTable.build + var build: Boolean + get() = buildInternal + set(value) = useDb { + buildInternal = value + } + private var worldInternal by BauweltMemberTable.world + var world: Boolean + get() = worldInternal + set(value) = useDb { + worldInternal = value + } + var supervisor: Boolean + get() = world + set(value) = useDb { + world = value + } + + fun isBuild() = worldEdit + fun isSupervisor() = world + fun isWorldEdit() = build + fun isWorld() = world + + fun remove() = useDb { + delete() + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/Fight.java b/CommonCore/SQL/src/de/steamwar/sql/Fight.java index b1f122b2..8b589aaf 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/Fight.java +++ b/CommonCore/SQL/src/de/steamwar/sql/Fight.java @@ -105,11 +105,11 @@ public class Fight { } public SteamwarUser getBlueLeader() { - return SteamwarUser.get(blueLeader); + return SteamwarUser.byId(blueLeader); } public SteamwarUser getRedLeader() { - return SteamwarUser.get(redLeader); + return SteamwarUser.byId(redLeader); } public boolean replayAllowed() { diff --git a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java index 18941b19..87abc1c2 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java +++ b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java @@ -35,11 +35,19 @@ import java.util.stream.Collectors; public final class GameModeConfig { public static final Function ToString = Function.identity(); - public static final Function ToStaticWarGear = __ -> "WarGear"; - public static final Function ToInternalName = file -> file.getName().replace(".yml", ""); + public static final Function ToStaticWarGear = GameModeConfig::constWarGear; + public static final Function ToInternalName = GameModeConfig::internalName; public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm"); private static final Random random = new Random(); + private static String constWarGear(File f) { + return "WarGear"; + } + + private static String internalName(File f) { + return f.getName().replace(".yml", ""); + } + private static final Map> byFileName; private static final Map> byGameName; private static final Map> bySchematicType; diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java index bac7929f..38fab77f 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java @@ -242,11 +242,11 @@ public class SchematicNode { public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { - return accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent); + return accessibleByUserTypeParent(SteamwarUser.byId(owner), SchematicType.fromDB(schemType), parent); } public static List getAllAccessibleSchematicsOfType(int user, String schemType) { - return accessibleByUserType(SteamwarUser.get(user), SchematicType.fromDB(schemType)); + return accessibleByUserType(SteamwarUser.byId(user), SchematicType.fromDB(schemType)); } public static List getAllSchematicsOfType(int owner, String schemType) { @@ -278,12 +278,12 @@ public class SchematicNode { @Deprecated public static List getSchematicsAccessibleByUser(int user, Integer parent) { - return list(SteamwarUser.get(user), parent); + return list(SteamwarUser.byId(user), parent); } @Deprecated public static List getAllSchematicsAccessibleByUser(int user) { - return getAll(SteamwarUser.get(user)); + return getAll(SteamwarUser.byId(user)); } public static List getAllParentsOfNode(SchematicNode node) { diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt index 719deb68..c48351bc 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt @@ -17,373 +17,273 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.*; -import lombok.Getter; +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.JoinType +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.inList +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.jdbc.insert +import org.jetbrains.exposed.v1.jdbc.select +import java.security.SecureRandom +import java.sql.Timestamp +import java.util.* +import java.util.function.Consumer +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.PBEKeySpec -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.sql.Timestamp; -import java.util.*; -import java.util.function.Consumer; -import java.util.logging.Level; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class SteamwarUser { - private static final SecureRandom random = new SecureRandom(); - private static final SecretKeyFactory factory; - - static { - try { - factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException(e); - } - - new SqlTypeMapper<>(UUID.class, "CHAR(36)", (rs, identifier) -> UUID.fromString(rs.getString(identifier)), (st, index, value) -> st.setString(index, value.toString())); - new SqlTypeMapper<>(Locale.class, "VARCHAR(32)", (rs, identifier) -> { - String l = rs.getString(identifier); - return l != null ? Locale.forLanguageTag(l) : null; - }, (st, index, value) -> st.setString(index, value.toLanguageTag())); - new SqlTypeMapper<>(SteamwarUser.class, null, (rs, identifier) -> { throw new SecurityException("SteamwarUser cannot be used as type (recursive select)"); }, (st, index, value) -> st.setInt(index, value.id)); - } - - private static final Table table = new Table<>(SteamwarUser.class, "UserData"); - private static final Statement insert = table.insertFields("UUID", "UserName"); - private static final SelectStatement byID = table.selectFields("id"); - private static final SelectStatement byUUID = table.selectFields("UUID"); - private static final SelectStatement byName = table.selectFields("UserName"); - private static final SelectStatement byDiscord = table.selectFields("DiscordId"); - private static final SelectStatement byTeam = table.selectFields("Team"); - private static final SelectStatement getUsersWithPerm = new SelectStatement<>(table, "SELECT S.* FROM UserData S JOIN UserPerm P ON S.id = P.User WHERE P.Perm = ?"); - private static final SelectStatement getAll = new SelectStatement(table, "SELECT * FROM UserData"); - - private static final Statement updateName = table.update(Table.PRIMARY, "UserName"); - private static final Statement updatePassword = table.update(Table.PRIMARY, "Password"); - private static final Statement updateLocale = table.update(Table.PRIMARY, "Locale", "ManualLocale"); - private static final Statement updateTeam = table.update(Table.PRIMARY, "Team"); - private static final Statement updateLeader = table.update(Table.PRIMARY, "Leader"); - private static final Statement updateDiscord = table.update(Table.PRIMARY, "DiscordId"); - - private static final Statement getPlaytime = new Statement("SELECT SUM(UNIX_TIMESTAMP(EndTime) - UNIX_TIMESTAMP(StartTime)) as Playtime FROM Session WHERE UserID = ?"); - private static final Statement getFirstjoin = new Statement("SELECT MIN(StartTime) AS FirstJoin FROM Session WHERE UserID = ?"); - private static final Statement getLastonline = new Statement("SELECT MAX(EndTime) AS LastOnline FROM Session WHERE UserID = ?"); - - private static final Map usersById = new HashMap<>(); - private static final Map usersByUUID = new HashMap<>(); - private static final Map usersByName = new HashMap<>(); - private static final Map usersByDiscord = new HashMap<>(); - public static void clear() { - usersById.clear(); - usersByName.clear(); - usersByUUID.clear(); - usersByDiscord.clear(); - } - - public static void invalidate(int userId) { - SteamwarUser user = usersById.remove(userId); - if (user == null) - return; - usersByName.remove(user.getUserName()); - usersByUUID.remove(user.getUUID()); - usersByDiscord.remove(user.getDiscordId()); - } - - public static SteamwarUser get(String userName){ - SteamwarUser user = usersByName.get(userName.toLowerCase()); - if(user != null) - return user; - return byName.select(userName); - } - - public static SteamwarUser get(UUID uuid){ - SteamwarUser user = usersByUUID.get(uuid); - if(user != null) - return user; - return byUUID.select(uuid); - } - - public static SteamwarUser get(int id) { - SteamwarUser user = usersById.get(id); - if(user != null) - return user; - return byID.select(id); - } - - public static SteamwarUser get(Long discordId) { - if(usersByDiscord.containsKey(discordId)) - return usersByDiscord.get(discordId); - return byDiscord.select(discordId); - } - - public static SteamwarUser getOrCreate(UUID uuid, String name, Consumer newPlayer) { - SteamwarUser user = get(uuid); - - if (user != null) { - if (!user.userName.equals(name)) { - updateName.update(name, user.id); - user.userName = name; - } - - return user; - } else { - insert.update(uuid, name); - newPlayer.accept(uuid); - return get(uuid); - } - } - - public static List getUsersWithPerm(UserPerm userPerm) { - return getUsersWithPerm.listSelect(userPerm); - } - - public static List getServerTeam() { - return Stream.of(getUsersWithPerm(UserPerm.PREFIX_ADMIN), - getUsersWithPerm(UserPerm.PREFIX_DEVELOPER), - getUsersWithPerm(UserPerm.PREFIX_MODERATOR), - getUsersWithPerm(UserPerm.PREFIX_SUPPORTER), - getUsersWithPerm(UserPerm.PREFIX_BUILDER) - ) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - } - - public static List getTeam(int teamId) { - return byTeam.listSelect(teamId); - } - - public static void batchCache(Set ids) { - ids.removeIf(usersById::containsKey); - if(ids.isEmpty()) - return; - - try (SelectStatement batch = new SelectStatement<>(table, "SELECT * FROM UserData WHERE id IN (" + ids.stream().map(Object::toString).collect(Collectors.joining(", ")) + ")")) { - batch.listSelect(); - } - } - - @Getter - @Field(keys = {Table.PRIMARY}, autoincrement = true) - private final int id; - @Field(keys = {"uuid"}) - private final UUID uuid; - @Getter - @Field - private String userName; - @Field(nullable = true) - private String password; - @Getter - @Field(def = "0") - private int team; - @Getter - @Field(def = "0") - private boolean leader; - @Field(nullable = true) - private Locale locale; - @Field(def = "0") - private boolean manualLocale; - @Getter - @Field(keys = {"discordId"}, nullable = true) - private Long discordId; - - private Map punishments = null; - private Set permissions = null; - private UserPerm.Prefix prefix = null; - - public SteamwarUser(int id, UUID uuid, String userName, String password, int team, boolean leader, Locale locale, boolean manualLocale, Long discordId) { - this.id = id; - this.uuid = uuid; - this.userName = userName; - this.password = password; - this.team = team; - this.leader = leader; - this.locale = locale; - this.manualLocale = manualLocale; - this.discordId = discordId != null && discordId != 0 ? discordId : null; - - usersById.put(id, this); - usersByName.put(userName.toLowerCase(), this); - usersByUUID.put(uuid, this); - if (this.discordId != null) { - usersByDiscord.put(discordId, this); - } - } - - public UUID getUUID() { - return uuid; - } - - public Locale getLocale() { - if(locale != null) - return locale; - return Locale.getDefault(); - } - - public Punishment getPunishment(Punishment.PunishmentType type) { - initPunishments(); - return punishments.getOrDefault(type, null); - } - - public boolean isPunished(Punishment.PunishmentType punishment) { - initPunishments(); - if (!punishments.containsKey(punishment)) { - return false; - } - if (!punishments.get(punishment).isCurrent()) { - if (punishment == Punishment.PunishmentType.Ban) { - BannedUserIPs.unbanIPs(id); - } - punishments.remove(punishment); - return false; - } - return true; - } - - public boolean hasPerm(UserPerm perm) { - initPerms(); - return permissions.contains(perm); - } - - public Set perms() { - initPerms(); - return permissions; - } - - public UserPerm.Prefix prefix() { - initPerms(); - return prefix; - } - - public double getOnlinetime() { - return getPlaytime.select(rs -> { - if (rs.next() && rs.getBigDecimal("Playtime") != null) - return rs.getBigDecimal("Playtime").doubleValue(); - return 0.0; - }, id); - } - - public Timestamp getFirstjoin() { - return getFirstjoin.select(rs -> { - if (rs.next()) - return rs.getTimestamp("FirstJoin"); - return null; - }, id); - } - - public Timestamp getLastOnline() { - return getLastonline.select(rs -> { - if (rs.next()) - return rs.getTimestamp("LastOnline"); - return null; - }, id); - } - - public void punish(Punishment.PunishmentType punishment, Timestamp time, String banReason, int from, boolean perma) { - initPunishments(); - punishments.remove(punishment); - punishments.put(punishment, Punishment.createPunishment(id, from, punishment, banReason, time, perma)); - } - - public void setTeam(int team) { - this.team = team; - updateTeam.update(team, id); - setLeader(false); - } - - public void setLeader(boolean leader) { - this.leader = leader; - updateLeader.update(leader, id); - } - - public void setLocale(Locale locale, boolean manualLocale) { - if (locale == null || (this.manualLocale && !manualLocale)) - return; - - this.locale = locale; - this.manualLocale = manualLocale; - updateLocale.update(locale.toLanguageTag(), manualLocale, id); - } - - public void setDiscordId(Long discordId) { - usersByDiscord.remove(this.discordId); - this.discordId = discordId; - updateDiscord.update(discordId, id); - if (discordId != null) { - usersByDiscord.put(discordId, this); - } - } - - public void setPassword(String password) { - try { - byte[] salt = new byte[16]; - random.nextBytes(salt); - String saltString = Base64.getEncoder().encodeToString(salt); - - byte[] hash = generateHash(password, salt); - String hashString = Base64.getEncoder().encodeToString(hash); - this.password = hashString + ":" + saltString; - updatePassword.update(this.password, id); - } catch (Exception e) { - throw new SecurityException(e); - } - } - - public boolean verifyPassword(String password) { - try { - if (!hasPassword()) { - return false; - } - - String[] parts = this.password.split(":"); - if (parts.length != 2) { - SQLConfig.impl.getLogger().log(Level.SEVERE ,"Invalid password hash for user {0} ({1})", new Object[]{userName, id}); - return false; - } - - String hashString = parts[0]; - byte[] realHash = Base64.getDecoder().decode(hashString); - String saltString = parts[1]; - byte[] salt = Base64.getDecoder().decode(saltString); - byte[] hash = generateHash(password, salt); - return Arrays.equals(realHash, hash); - } catch (Exception e) { - SQLConfig.impl.getLogger().log(Level.SEVERE, "Error while verifying password for user " + userName + " (" + id + ")", e); - return false; - } - } - - public boolean hasPassword() { - return this.password != null; - } - - private byte[] generateHash(String password, byte[] salt) - throws InvalidKeySpecException { - PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 512); - return factory.generateSecret(spec).getEncoded(); - - } - - private void initPunishments() { - if(punishments != null) - return; - - punishments = Punishment.getPunishmentsOfPlayer(id); - } - - private void initPerms() { - if(permissions != null) - return; - - permissions = UserPerm.getPerms(id); - prefix = permissions.stream().filter(UserPerm.prefixes::containsKey).findAny().map(UserPerm.prefixes::get).orElse(UserPerm.emptyPrefix); - } - - public static List getAll() { - return getAll.listSelect(); - } +object SteamwarUserTable : IntIdTable("UserData", "id") { + val uuid = varchar("UUID", 36) + val username = varchar("UserName", 32) + val team = integer("Team") + val leader = bool("Leader") + val locale = varchar("Locale", 16).nullable() + val manualeLocale = bool("ManualeLocale") + val bedrock = bool("Bedrock") + val password = text("Password").nullable() + val discordId = long("DiscordId").nullable() } + +class SteamwarUser(id: EntityID): IntEntity(id) { + companion object: IntEntityClass(SteamwarUserTable) { + private val random = SecureRandom() + private val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512") + + private val byId = mutableMapOf() + private val byUUID = mutableMapOf() + private val byDiscordId = mutableMapOf() + private val byUsername = mutableMapOf() + + @JvmStatic + fun clear() { + byId.clear() + byUUID.clear() + byDiscordId.clear() + byUsername.clear() + } + + @JvmStatic + fun invalidate(userId: Int) { + val user = byId.remove(userId) + if(user != null) { + byUUID.remove(user.getUUID()) + byDiscordId.remove(user.discordId) + byUsername.remove(user.userName) + } + } + + @JvmStatic + fun byId(id: Int) = byId[id] ?: useDb { findById(id)?.also { cache(it) } } + + @JvmStatic + fun get(uuid: UUID) = byUUID[uuid] ?: useDb { find { SteamwarUserTable.uuid eq uuid.toString() }.firstOrNull()?.also { cache(it) } } + + @JvmStatic + fun get(discordId: Long) = byDiscordId[discordId] ?: useDb { find { SteamwarUserTable.discordId eq discordId }.firstOrNull()?.also { cache(it) } } + + @JvmStatic + fun get(username: String) = byUsername[username] ?: useDb { find { SteamwarUserTable.username eq username }.firstOrNull()?.also { cache(it) } } + + private fun cache(user: SteamwarUser) { + byId[user.getId()] = user + byUUID[user.getUUID()] = user + user.discordId?.let { byDiscordId[it] = user } + byUsername[user.userName] = user + } + + @JvmStatic + fun getOrCreate(uuid: UUID, name: String, newPlayer: Consumer): SteamwarUser { + val user = get(uuid) + + return if (user != null) { + if (user.userName != name) { + useDb { + user.userName = name + } + } + + user + } else { + useDb { + SteamwarUserTable.insert { + it[SteamwarUserTable.uuid] = uuid.toString() + it[username] = name + } + } + + newPlayer.accept(uuid) + get(uuid) ?: error("User $uuid not found after creation!") + } + } + + @JvmStatic + fun getUsersWithPerm(perm: UserPerm) = useDb { + UserPermTable.join(SteamwarUserTable, JoinType.INNER, UserPermTable.user, SteamwarUserTable.id) + .select(SteamwarUserTable.fields).where { UserPermTable.perm eq perm }.map { wrapRow(it) } + } + + @JvmStatic + fun getServerTeam() = useDb { listOf( + getUsersWithPerm(UserPerm.PREFIX_ADMIN), + getUsersWithPerm(UserPerm.PREFIX_DEVELOPER), + getUsersWithPerm(UserPerm.PREFIX_MODERATOR), + getUsersWithPerm(UserPerm.PREFIX_SUPPORTER), + getUsersWithPerm(UserPerm.PREFIX_BUILDER), + ).flatten() } + + @JvmStatic + fun getTeam(teamId: Int) = useDb { + find { SteamwarUserTable.team eq teamId }.toList() + } + + @JvmStatic + fun batchCache(ids: MutableSet) { + ids.removeIf(byId::containsKey) + if(ids.isEmpty()) return + + useDb { + find { SteamwarUserTable.id inList ids }.forEach { cache(it) } + } + } + } + + val uuid: UUID by SteamwarUserTable.uuid.transform({ it.toString() }, { UUID.fromString(it) }) + var userName by SteamwarUserTable.username + private var teamInternal by SteamwarUserTable.team + var team: Int + get() = teamInternal + set(value) = useDb { + teamInternal = value + leaderInternal = false + } + + private var leaderInternal by SteamwarUserTable.leader + var leader: Boolean + get() = leaderInternal + set(value) = useDb { + leaderInternal = value + } + fun isLeader() = leader + + var locale: Locale by SteamwarUserTable.locale + .transform({ it.toLanguageTag() }, { it?.let { Locale.forLanguageTag(it) } ?: Locale.getDefault()}) + var manualLocale by SteamwarUserTable.manualeLocale + var bedrock by SteamwarUserTable.bedrock + private var passwordInternal by SteamwarUserTable.password + var password: String? + get() = passwordInternal + set(value) { + if(value == null) { + useDb { + passwordInternal = null + } + return + } + + val salt = ByteArray(16) + random.nextBytes(salt) + val saltString = Base64.getEncoder().encode(salt) + + val hash = generateHash(value, salt) + val hashString = Base64.getEncoder().encode(hash) + + useDb { + passwordInternal = "$hashString:$saltString" + } + } + + var discordId by SteamwarUserTable.discordId + + private val punishments by lazy { Punishment.getPunishmentsOfPlayer(id.value) } + private val perms by lazy { UserPerm.getPerms(id.value) } + private val prefix by lazy { perms.firstOrNull { UserPerm.prefixes.containsKey(it) }?.let { UserPerm.prefixes[it]} ?: UserPerm.emptyPrefix } + + fun getUUID(): UUID = uuid + fun getId() = id.value + + fun getPunishment(punishment: Punishment.PunishmentType) = punishments[punishment] + fun isPunished(punishment: Punishment.PunishmentType) = getPunishment(punishment) + ?.let { + if (!it.isCurrent) { + if (punishment == Punishment.PunishmentType.Ban) { + BannedUserIPs.unbanIPs(id.value) + } + punishments.remove(punishment) + return@let false + } + + return@let true + } ?: false + + fun hasPerm(perm: UserPerm) = perms.contains(perm) + fun perms() = perms + fun prefix() = prefix + + fun getOnlinetime() = useDb { + exec("SELECT SUM(UNIX_TIMESTAMP(EndTime) - UNIX_TIMESTAMP(StartTime)) as Playtime FROM Session WHERE UserID = ${this@SteamwarUser.id.value}") { rs -> + return@exec if (rs.next()) { + rs.getBigDecimal("Playtime").toDouble() + } else { + 0.0 + } + } ?: 0.0 + } + + fun getFirstjoin() = useDb { + exec("SELECT MIN(StartTime) AS FirstJoin FROM Session WHERE UserID = ${this@SteamwarUser.id.value}") { rs -> + return@exec if (rs.next()) { + rs.getTimestamp("FirstJoin") + } else { null } + } + } + + fun getLastOnline() = useDb { + exec("SELECT MAX(EndTime) AS LastOnline FROM Session WHERE UserID = ${this@SteamwarUser.id.value}") { rs -> + return@exec if (rs.next()) { + rs.getTimestamp("LastOnline") + } else { null } + } + } + + fun punish(punishment: Punishment.PunishmentType, time: Timestamp, reason: String, from: Int, perma: Boolean) = useDb { + punishments.remove(punishment) + punishments[punishment] = Punishment.createPunishment(this@SteamwarUser.id.value, from, punishment, reason, time, perma) + } + + fun setLocale(locale: Locale?, manualeLocale: Boolean) { + if (locale == null || (this.manualLocale && !manualLocale)) return + + useDb { + this@SteamwarUser.locale = locale + this@SteamwarUser.manualLocale = manualeLocale + } + } + + fun setDiscordId(discordId: Long) { + byDiscordId.remove(this.discordId) + useDb { + this@SteamwarUser.discordId = discordId + } + byDiscordId[discordId] = this + } + + fun verifyPassword(password: String): Boolean { + if (!hasPassword()) return false + + val (hashString, saltString) = this.password!!.split(':') + + val hash = Base64.getDecoder().decode(hashString) + val salt = Base64.getDecoder().decode(saltString) + + return hash.contentEquals(generateHash(password, salt)) + } + + fun hasPassword() = password != null + + fun generateHash(password: String, salt: ByteArray): ByteArray = + PBEKeySpec(password.toCharArray(), salt, 65536, 128).let { factory.generateSecret(it).encoded } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/Token.java b/CommonCore/SQL/src/de/steamwar/sql/Token.java index ca32c0fa..01fd56fa 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/Token.java +++ b/CommonCore/SQL/src/de/steamwar/sql/Token.java @@ -105,6 +105,6 @@ public class Token { } public SteamwarUser getOwner() { - return SteamwarUser.get(owner); + return SteamwarUser.byId(owner); } } diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserPerm.kt b/CommonCore/SQL/src/de/steamwar/sql/UserPerm.kt index 7a575d82..a49b141a 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/UserPerm.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/UserPerm.kt @@ -17,16 +17,24 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.Table +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.jdbc.deleteWhere +import org.jetbrains.exposed.v1.jdbc.insert +import org.jetbrains.exposed.v1.jdbc.selectAll -import java.util.*; -import java.util.stream.Collectors; +object UserPermTable: Table("UserPerm") { + val user = reference("User", SteamwarUserTable.id) + val perm = enumerationByName("Perm", 32, UserPerm::class) -public enum UserPerm { + override val primaryKey = PrimaryKey(user, perm) +} + +enum class UserPerm { PREFIX_NONE, // special value, not stored in database PREFIX_YOUTUBER, PREFIX_GUIDE, @@ -45,54 +53,41 @@ public enum UserPerm { MODERATION, ADMINISTRATION; - public static final Map prefixes; - public static final Prefix emptyPrefix; - static { - // https://www.digminecraft.com/lists/color_list_pc.php - SqlTypeMapper.nameEnumMapper(UserPerm.class); - Map p = new EnumMap<>(UserPerm.class); - emptyPrefix = new Prefix("§7", ""); - p.put(PREFIX_NONE, emptyPrefix); - p.put(PREFIX_YOUTUBER, new Prefix("§7", "YT")); - p.put(PREFIX_GUIDE, new Prefix("§x§e§7§6§2§e§d", "Guide")); // E762ED + companion object { + @JvmField + val emptyPrefix = Prefix("§7", "") + @JvmField + val prefixes = mapOf( + PREFIX_NONE to emptyPrefix, + PREFIX_YOUTUBER to Prefix("§7", "YT"), + PREFIX_GUIDE to Prefix("§x§e§7§6§2§e§d", "Guide"), // E762ED + PREFIX_SUPPORTER to Prefix("§x§6§0§9§5§F§B", "Sup"), // 6095FB + PREFIX_MODERATOR to Prefix("§x§F§F§A§2§5§C", "Mod"), // FFA25C + PREFIX_BUILDER to Prefix("§x§6§0§F§F§6§A", "Arch"), // 60FF6A + PREFIX_DEVELOPER to Prefix("§x§0§B§B§C§B§3", "Dev"), // 0BBCB3 + PREFIX_ADMIN to Prefix("§x§F§F§2§B§2§4", "Admin"), // FF2B24 + ) - p.put(PREFIX_SUPPORTER, new Prefix("§x§6§0§9§5§F§B", "Sup")); // 6095FB - p.put(PREFIX_MODERATOR, new Prefix("§x§F§F§A§2§5§C", "Mod")); // FFA25C - p.put(PREFIX_BUILDER, new Prefix("§x§6§0§F§F§6§A", "Arch")); // 60FF6A - p.put(PREFIX_DEVELOPER, new Prefix("§x§0§B§B§C§B§3", "Dev")); // 0BBCB3 - p.put(PREFIX_ADMIN, new Prefix("§x§F§F§2§B§2§4", "Admin")); // FF2B24 - prefixes = Collections.unmodifiableMap(p); + @JvmStatic + fun getPerms(id: Int) = useDb { + UserPermTable.selectAll().where { UserPermTable.user eq id }.map { it[UserPermTable.perm] }.toSet() + } + + @JvmStatic + fun addPerm(user: SteamwarUser, perm: UserPerm) = useDb { + UserPermTable.insert { + it[UserPermTable.user] = user.getId() + it[UserPermTable.perm] = perm + } + } + + @JvmStatic + fun removePerm(user: SteamwarUser, perm: UserPerm) = useDb { + UserPermTable.deleteWhere { + (UserPermTable.user eq user.getId()) and (UserPermTable.perm eq perm) + } + } } - private static final Table table = new Table<>(UserPermTable.class, "UserPerm"); - private static final SelectStatement getPerms = table.selectFields("user"); - private static final Statement addPerm = table.insertAll(); - private static final Statement removePerm = table.delete(Table.PRIMARY); - - public static Set getPerms(int user) { - return getPerms.listSelect(user).stream().map(up -> up.perm).collect(Collectors.toSet()); - } - - public static void addPerm(SteamwarUser user, UserPerm perm) { - addPerm.update(user, perm); - } - - public static void removePerm(SteamwarUser user, UserPerm perm) { - removePerm.update(user, perm); - } - - @Getter - @AllArgsConstructor - public static class Prefix { - private final String colorCode; - private final String chatPrefix; - } - - @AllArgsConstructor - public static class UserPermTable { - @Field(keys = {Table.PRIMARY}) - private final int user; - @Field(keys = {Table.PRIMARY}) - private final UserPerm perm; - } -} + data class Prefix(val colorCode: String, val chatPrefix: String) +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt new file mode 100644 index 00000000..d4869623 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt @@ -0,0 +1,58 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql.internal + +import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.JdbcTransaction +import org.jetbrains.exposed.v1.jdbc.transactions.TransactionManager +import org.jetbrains.exposed.v1.jdbc.transactions.transaction +import java.io.File +import java.util.Properties + +object KotlinDatabase { + lateinit var db: Database + + fun ensureConnected() { + if(KotlinDatabase::db.isInitialized) return + + val file = File(System.getProperty("user.home"), "mysql.properties") + + val properties = Properties() + properties.load(file.inputStream()) + + val host = properties.getProperty("host") + val port = properties.getProperty("port") + val database = properties.getProperty("database") + val username = properties.getProperty("user") + val password = properties.getProperty("password") + + db = Database.connect( + "jdbc:mysql://$host:$port/$database", + driver = "com.mysql.cj.jdbc.Driver", + user = username, + password = password + ) + } +} + +fun useDb(statement: JdbcTransaction.() -> T): T { + KotlinDatabase.ensureConnected() + return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db, statement) +} \ No newline at end of file diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/InfoCommand.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/InfoCommand.java index 306a4fc5..9cf59ca0 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/InfoCommand.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/InfoCommand.java @@ -58,7 +58,7 @@ public class InfoCommand implements CommandExecutor { if(team.getSchematic() != 0) { SchematicNode schematic = SchematicNode.getSchematicNode(team.getSchematic()); - FightSystem.getMessage().send("INFO_SCHEMATIC", player, team.getColoredName(), schematic.getName(), SteamwarUser.get(schematic.getOwner()).getUserName(), schematic.getRank()); + FightSystem.getMessage().send("INFO_SCHEMATIC", player, team.getColoredName(), schematic.getName(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getRank()); } } return false; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightPlayer.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightPlayer.java index a5d605aa..70ecb318 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightPlayer.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightPlayer.java @@ -94,7 +94,7 @@ public class FightPlayer { } public SteamwarUser getUser() { - return SteamwarUser.get(id); + return SteamwarUser.byId(id); } public void ifAI(Consumer function) { diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java index 8628d3fb..26ea3d58 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java @@ -243,7 +243,7 @@ public class PacketProcessor implements Listener { int userId = source.readInt(); execSync(() -> { - SteamwarUser user = SteamwarUser.get(userId); + SteamwarUser user = SteamwarUser.byId(userId); addREntity(entityId, new RPlayer(entityServer, user.getUUID(), user.getUserName(), Config.SpecSpawn)); team.addEntry(user.getUserName()); diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java b/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java index 2b6f816b..5c6fcf1b 100644 --- a/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java +++ b/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java @@ -116,7 +116,7 @@ public class BauSystem extends JavaPlugin implements Listener { } public static UUID getOwner() { - return SteamwarUser.get(getOwnerID()).getUUID(); + return SteamwarUser.byId(getOwnerID()).getUUID(); } public static int getOwnerID() { diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java b/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java index 9079cabe..f22a8332 100644 --- a/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java +++ b/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java @@ -78,10 +78,10 @@ public class Mapper { private static TypeMapper bauweltMemberTypeMapper() { return SWCommandUtils.createMapper(s -> BauweltMember.getMembers(BauSystem.getOwnerID()) .stream() - .filter(m -> SteamwarUser.get(m.getMemberID()).getUserName().equals(s)).findFirst().orElse(null), + .filter(m -> SteamwarUser.byId(m.getMemberID()).getUserName().equals(s)).findFirst().orElse(null), s -> BauweltMember.getMembers(BauSystem.getOwnerID()) .stream() - .map(m -> SteamwarUser.get(m.getMemberID()).getUserName()) + .map(m -> SteamwarUser.byId(m.getMemberID()).getUserName()) .collect(Collectors.toList())); } } diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java index 0e2f5dcd..269e0638 100644 --- a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java @@ -49,7 +49,7 @@ public class CommandInfo extends SWCommand { } public static void sendBauInfo(Player p) { - p.sendMessage(BauSystem.PREFIX + "Besitzer: §e" + SteamwarUser.get(BauSystem.getOwnerID()).getUserName()); + p.sendMessage(BauSystem.PREFIX + "Besitzer: §e" + SteamwarUser.byId(BauSystem.getOwnerID()).getUserName()); Region region = Region.getRegion(p.getLocation()); p.sendMessage(BauSystem.PREFIX + "§eTNT§8: " + region.getTntMode().getName() + " §eFire§8: " + (region.isFire() ? "§aAUS" : "§cAN") + " §eFreeze§8: " + (region.isFreeze() ? "§aAN" : "§cAUS")); if (region.hasProtection()) { @@ -60,7 +60,7 @@ public class CommandInfo extends SWCommand { StringBuilder membermessage = new StringBuilder().append(BauSystem.PREFIX).append("Mitglieder: "); for (BauweltMember member : members) { - membermessage.append("§e").append(SteamwarUser.get(member.getMemberID()).getUserName()).append("§8["); + membermessage.append("§e").append(SteamwarUser.byId(member.getMemberID()).getUserName()).append("§8["); membermessage.append(member.isWorldEdit() ? "§a" : "§c").append("WE").append("§8,"); membermessage.append(member.isWorld() ? "§a" : "§c").append("W").append("§8]").append(" "); } diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java index b1a0a071..2d45f7d9 100644 --- a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java @@ -56,7 +56,7 @@ public class CommandLockschem extends SWCommand { return; } p.sendMessage(BauSystem.PREFIX + "Schematic " + node .getName() + " von " + - SteamwarUser.get(node.getOwner()).getUserName() + " von " + node.getSchemtype().toString() + + SteamwarUser.byId(node.getOwner()).getUserName() + " von " + node.getSchemtype().toString() + " auf NORMAL zurückgesetzt!"); node.setSchemtype(SchematicType.Normal); } diff --git a/LobbySystem/src/de/steamwar/lobby/LobbyPacketHandler.java b/LobbySystem/src/de/steamwar/lobby/LobbyPacketHandler.java index 37284085..fcc27177 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbyPacketHandler.java +++ b/LobbySystem/src/de/steamwar/lobby/LobbyPacketHandler.java @@ -41,7 +41,7 @@ public class LobbyPacketHandler extends PacketHandler { @Handler public void serverStarting(StartingServerPacket packet) { - Player player = Objects.requireNonNull(Bukkit.getPlayer(SteamwarUser.get(packet.getUser()).getUUID())); + Player player = Objects.requireNonNull(Bukkit.getPlayer(SteamwarUser.byId(packet.getUser()).getUUID())); player.teleport(LobbySystem.config().getWaitingHallSpawn(), PlayerTeleportEvent.TeleportCause.PLUGIN); if (JumpAndRun.isPlayerInJumpAndRun(player)) { JumpAndRun.reset(player); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java index bc5ba669..1ac5679a 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java @@ -185,7 +185,7 @@ public interface ParticleRequirement { } static ParticleRequirement specificPlayer(int userId) { - String userName = SteamwarUser.get(userId).getUserName(); + String userName = SteamwarUser.byId(userId).getUserName(); return new ParticleRequirement() { @Override public String getRequirementName(Player player) { @@ -200,7 +200,7 @@ public interface ParticleRequirement { } static ParticleRequirement easterEventSpecificPlayer(int userId) { - String userName = SteamwarUser.get(userId).getUserName(); + String userName = SteamwarUser.byId(userId).getUserName(); return new ParticleRequirement() { @Override public String getRequirementName(Player player) { diff --git a/LobbySystem/src/de/steamwar/lobby/portal/FightserverPortal.java b/LobbySystem/src/de/steamwar/lobby/portal/FightserverPortal.java index 85fd0d1c..98f9343c 100644 --- a/LobbySystem/src/de/steamwar/lobby/portal/FightserverPortal.java +++ b/LobbySystem/src/de/steamwar/lobby/portal/FightserverPortal.java @@ -122,7 +122,7 @@ public class FightserverPortal implements PortalHandler, Comparable locations, List npcs, List players) { - List remainingPlayers = players.stream().map(SteamwarUser::get).collect(Collectors.toList()); + List remainingPlayers = players.stream().map(SteamwarUser::byId).collect(Collectors.toList()); List remainingLocations = new ArrayList<>(locations); npcs.removeIf(npc -> { SteamwarUser user = SteamwarUser.get(npc.getUuid()); diff --git a/LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java b/LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java index 68c9766a..f0a33a4a 100644 --- a/LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java +++ b/LobbySystem/src/de/steamwar/lobby/util/Leaderboard.java @@ -71,7 +71,7 @@ public class Leaderboard implements Listener { for (int i = 0; i < leaderboard.size(); i++) { LeaderboardEntry entry = leaderboard.get(i); RArmorStand entity = new RArmorStand(server, location.clone().add(0, (leaderboard.size() - i - 1) * 0.32, 0), RArmorStand.Size.MARKER); - SteamwarUser user = SteamwarUser.get(entry.user); + SteamwarUser user = SteamwarUser.byId(entry.user); String color = "§7"; if (i == 0) { color = "§6§l"; diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java index d5428118..51e3589e 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java @@ -197,7 +197,7 @@ public class GUI { inv.setItem(4, SWItem.getMaterial("CAULDRON_ITEM"), SchematicSystem.MESSAGE.parse("GUI_INFO_TYPE", player, node.getSchemtype().name()), Collections.emptyList(), node.getSchemtype().fightType(), click -> {}); } - SteamwarUser owneruser = SteamwarUser.get(node.getOwner()); + SteamwarUser owneruser = SteamwarUser.byId(node.getOwner()); SWItem skull = SWItem.getPlayerSkull(owneruser.getUserName()); skull.setName(SchematicSystem.MESSAGE.parse("GUI_INFO_MEMBER_FROM", player, owneruser.getUserName())); inv.setItem(8, skull.getItemStack(), clickType -> {}); @@ -316,7 +316,7 @@ public class GUI { static void delmembers(Player p, SchematicNode schem){ List> members = new LinkedList<>(); for(NodeMember member : schem.getMembers()){ - SteamwarUser user = SteamwarUser.get(member.getMember()); + SteamwarUser user = SteamwarUser.byId(member.getMember()); members.add(new SWListInv.SWListEntry<>(SWItem.getPlayerSkull(user.getUserName()), member)); } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java index cea1122c..e872562b 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java @@ -141,7 +141,7 @@ public class SchematicCommandUtils { } if (node.getOwner() != user.getId()) { - nodeString.append(" ").append(SchematicSystem.MESSAGE.parse("UTIL_LIST_FROM", player, SteamwarUser.get(node.getOwner()).getUserName())); + nodeString.append(" ").append(SchematicSystem.MESSAGE.parse("UTIL_LIST_FROM", player, SteamwarUser.byId(node.getOwner()).getUserName())); } TextComponent schematics = new TextComponent(nodeString.toString()); @@ -213,7 +213,7 @@ public class SchematicCommandUtils { } else { SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_NAME", player, node.getName()); } - SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_OWNER", player, node.getOwner() == user.getId() ? user.getUserName() : SteamwarUser.get(node.getOwner()).getUserName()); + SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_OWNER", player, node.getOwner() == user.getId() ? user.getUserName() : SteamwarUser.byId(node.getOwner()).getUserName()); if(node.getOwner() == user.getId()) { player.spigot().sendMessage( new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_PARENT", false, player, node.getParent() == null ? "/" : node.getParentNode().generateBreadcrumbs())) @@ -261,7 +261,7 @@ public class SchematicCommandUtils { if(node.getOwner() == user.getId()) { ComponentBuilder memberBuilder = new ComponentBuilder(SchematicSystem.MESSAGE.parse("UTIL_INFO_MEMBER_STRING", player) + " ").color(ChatColor.GRAY); NodeMember.getNodeMembers(node.getId()).forEach(nodeMember -> { - SteamwarUser member = SteamwarUser.get(nodeMember.getMember()); + SteamwarUser member = SteamwarUser.byId(nodeMember.getMember()); memberBuilder.append(member.getUserName()) .color(ChatColor.YELLOW) .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem delmember " + node.generateBreadcrumbs() + " " + member.getUserName())) @@ -275,7 +275,7 @@ public class SchematicCommandUtils { player.spigot().sendMessage(memberBuilder.create()); } else { List schematicMembers = new ArrayList<>(); - NodeMember.getNodeMembers(node.getId()).forEach(nodeMember -> schematicMembers.add(SteamwarUser.get(nodeMember.getMember()).getUserName())); + NodeMember.getNodeMembers(node.getId()).forEach(nodeMember -> schematicMembers.add(SteamwarUser.byId(nodeMember.getMember()).getUserName())); if(!schematicMembers.isEmpty()) { SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_MEMBER", player, schematicMembers.stream().reduce((s, s2) -> s + ", " + s2).orElse("")); } @@ -343,7 +343,7 @@ public class SchematicCommandUtils { public static SteamwarUser getUser(Player player) { if (PUBLIC_TOGGLED.contains(player)) { - return SteamwarUser.get(0); + return SteamwarUser.byId(0); } else { return SteamwarUser.get(player.getUniqueId()); } @@ -368,7 +368,7 @@ public class SchematicCommandUtils { if(BauServerInfo.isBauServer() && BauServerInfo.getOwnerId() != user.getId() && (Punishment.isPunished(user, Punishment.PunishmentType.NoSchemSharing, punishment -> SchematicSystem.MESSAGE.send("UTIL_LOAD_NOT_HERE", player)) || - Punishment.isPunished(SteamwarUser.get(BauServerInfo.getOwnerId()), Punishment.PunishmentType.NoSchemReceiving, punishment -> + Punishment.isPunished(SteamwarUser.byId(BauServerInfo.getOwnerId()), Punishment.PunishmentType.NoSchemReceiving, punishment -> SchematicSystem.MESSAGE.send("UTIL_LOAD_NOT_HERE_ALL", player)))) { return; } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicMapper.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicMapper.java index 157e8d2d..73564422 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicMapper.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicMapper.java @@ -46,12 +46,12 @@ public class SchematicMapper { return new TypeMapper() { @Override public List tabCompletes(CommandSender commandSender, String[] strings, String s) { - return SchematicNode.getNodeTabcomplete(SteamwarUser.get(0), s); + return SchematicNode.getNodeTabcomplete(SteamwarUser.byId(0), s); } @Override public SchematicNode map(CommandSender commandSender, String[] previousArguments, String s) { - return SchematicNode.getNodeFromPath(SteamwarUser.get(0), s); + return SchematicNode.getNodeFromPath(SteamwarUser.byId(0), s); } }; } @@ -69,7 +69,7 @@ public class SchematicMapper { public List tabCompletes(CommandSender commandSender, String[] strings, String s) { return Optional.ofNullable(SchematicNode.getNodeFromPath(getUser((Player) commandSender), strings[strings.length - 1])) .map(SchematicNode::getMembers) - .map(nodeMembers -> nodeMembers.stream().map(NodeMember::getMember).map(SteamwarUser::get).map(SteamwarUser::getUserName).collect(Collectors.toList())) + .map(nodeMembers -> nodeMembers.stream().map(NodeMember::getMember).map(SteamwarUser::byId).map(SteamwarUser::getUserName).collect(Collectors.toList())) .orElse(Collections.emptyList()); } }; diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java index 8ffa543b..8e42ef86 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java @@ -92,7 +92,7 @@ public class MemberPart extends SWCommand { @Register("delmember") public void delMember(Player player, @Validator("isOwnerValidator") SchematicNode node, @Mapper("memberMapper") NodeMember member) { SteamwarUser user = getUser(player); - SteamwarUser target = SteamwarUser.get(member.getMember()); + SteamwarUser target = SteamwarUser.byId(member.getMember()); List nodes = SchematicNode.deepGet(node.getId(), node1 -> node1.getOwner() != user.getId()); if (!nodes.isEmpty()) { @@ -123,7 +123,7 @@ public class MemberPart extends SWCommand { return; } - addMember(player, node, team.getMembers().stream().map(SteamwarUser::get).filter(steamwarUser -> steamwarUser.getId() != user.getId()).toArray(SteamwarUser[]::new)); + addMember(player, node, team.getMembers().stream().map(SteamwarUser::byId).filter(steamwarUser -> steamwarUser.getId() != user.getId()).toArray(SteamwarUser[]::new)); } @Register("delteam") @@ -141,7 +141,7 @@ public class MemberPart extends SWCommand { NodeMember nodeMember = NodeMember.getNodeMember(node.getId(), member); if (nodeMember != null) { nodeMember.delete(); - removed.add(SteamwarUser.get(member).getUserName()); + removed.add(SteamwarUser.byId(member).getUserName()); } } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java index 7aa98ed0..32178e1a 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java @@ -66,7 +66,7 @@ public class SavePart extends SWCommand { if(BauServerInfo.isBauServer() && BauServerInfo.getOwnerId() != user.getId() && (Punishment.isPunished(user, Punishment.PunishmentType.NoSchemReceiving, punishment -> SchematicSystem.MESSAGE.send("COMMAND_PUNISHMENT_NO_SAVE_EXTERNAL", player)) || - Punishment.isPunished(SteamwarUser.get(BauServerInfo.getOwnerId()), Punishment.PunishmentType.NoSchemSharing, punishment -> + Punishment.isPunished(SteamwarUser.byId(BauServerInfo.getOwnerId()), Punishment.PunishmentType.NoSchemSharing, punishment -> SchematicSystem.MESSAGE.send("COMMAND_PUNISHMENT_NO_SAVE", player)))) { return; } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SearchPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SearchPart.java index d6834468..607bcbbc 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SearchPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SearchPart.java @@ -135,7 +135,7 @@ public class SearchPart extends SWCommand { i++; } - List nodes = SchematicNode.getAll(SteamwarUser.get(userId)).stream().filter(node -> { + List nodes = SchematicNode.getAll(SteamwarUser.byId(userId)).stream().filter(node -> { for (Predicate predicate : predicates) { if (!predicate.test(node)) { return false; diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java index 35544a4f..b4421fa9 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java @@ -60,7 +60,7 @@ public class ViewPart extends SWCommand { @Register({"list", "public"}) @Register({"list", "public", "/"}) public void schemListPublic(Player player, @OptionalValue(value = "1", onlyUINIG = true) int page) { - createCachedSchemList(player, SchematicNode.list(SteamwarUser.get(0), null), Math.max(page - 1, 0), null, SchematicCommandUtils.SchematicListBehavior.builder().setPublics(true).setPageCommandGen(integer -> "/schem list public " + integer).build()); + createCachedSchemList(player, SchematicNode.list(SteamwarUser.byId(0), null), Math.max(page - 1, 0), null, SchematicCommandUtils.SchematicListBehavior.builder().setPublics(true).setPageCommandGen(integer -> "/schem list public " + integer).build()); } @Register("list") diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java index 30deed6e..43e3df0c 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java @@ -67,7 +67,7 @@ public class TypeUtils { Player player = (Player) commandSender; return BauweltMember.getMembers(player.getUniqueId()) .stream() - .filter(member -> SteamwarUser.get(member.getMemberID()).getUserName().equalsIgnoreCase(s)) + .filter(member -> SteamwarUser.byId(member.getMemberID()).getUserName().equalsIgnoreCase(s)) .findAny() .orElse(null); } @@ -80,7 +80,7 @@ public class TypeUtils { Player player = (Player) sender; return BauweltMember.getMembers(player.getUniqueId()) .stream() - .map(m -> SteamwarUser.get(m.getMemberID()).getUserName()) + .map(m -> SteamwarUser.byId(m.getMemberID()).getUserName()) .collect(Collectors.toList()); } }); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java index f5975063..5cfbc78e 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java @@ -84,7 +84,7 @@ public class SchematicSelector { public void open() { injectable.onSelectorCreate(this); if(publicMode == PublicMode.PUBLIC_ONLY) { - this.user = SteamwarUser.get(0); + this.user = SteamwarUser.byId(0); } openList(null); injectable.onSelectorOpen(this, SchematicSelectorInjectable.OpenFrom.FRESH); @@ -131,7 +131,7 @@ public class SchematicSelector { }).setCustomModelData(CMDs.Schematic.OWN_SCHEMS)); } else { inv.setItem(48, new SWItem(Material.GLASS, Core.MESSAGE.parse("SCHEM_SELECTOR_PUB", player), clickType -> { - this.user = SteamwarUser.get(0); + this.user = SteamwarUser.byId(0); openList(null); }).setCustomModelData(CMDs.Schematic.PUBLIC_SCHEMS)); } @@ -326,7 +326,7 @@ public class SchematicSelector { if(filter.getOwner() == null) { inv.setItem(1, SWItem.getMaterial("SKULL_ITEM"), (byte) 3, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER", player), ownerCallback); } else { - SteamwarUser tUser = SteamwarUser.get(filter.getOwner()); + SteamwarUser tUser = SteamwarUser.byId(filter.getOwner()); SWItem item = SWItem.getPlayerSkull(tUser.getUserName()); item.setName(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER", player)); item.setEnchanted(true); @@ -485,7 +485,7 @@ public class SchematicSelector { } private static Optional getParent(SchematicNode node) { - return node.getOptionalParent().map(integer -> SchematicNode.byIdAndUser(SteamwarUser.get(node.getEffectiveOwner()), integer)); + return node.getOptionalParent().map(integer -> SchematicNode.byIdAndUser(SteamwarUser.byId(node.getEffectiveOwner()), integer)); } public static SelectorTarget selectSchematic() { @@ -585,7 +585,7 @@ public class SchematicSelector { lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME_SEARCH", player, name)); } if(owner != null) { - lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER_SEARCH", player, SteamwarUser.get(owner).getUserName())); + lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER_SEARCH", player, SteamwarUser.byId(owner).getUserName())); } if(type != null) { lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE_SEARCH", player, type.name())); @@ -606,7 +606,7 @@ public class SchematicSelector { if (name != null) { return new SWItem(Material.NAME_TAG, itemName, lore, false, click -> {}); } else if (owner != null) { - SWItem playerSkull = SWItem.getPlayerSkull(SteamwarUser.get(owner).getUserName()); + SWItem playerSkull = SWItem.getPlayerSkull(SteamwarUser.byId(owner).getUserName()); playerSkull.setName(itemName); playerSkull.setLore(lore); return playerSkull; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/network/CoreNetworkHandler.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/network/CoreNetworkHandler.java index 10adeac0..5215776d 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/network/CoreNetworkHandler.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/network/CoreNetworkHandler.java @@ -48,7 +48,7 @@ public class CoreNetworkHandler extends PacketHandler { @Handler public void handleCloseInventoryPacket(CloseInventoryPacket packet) { - Player player = Bukkit.getPlayer(SteamwarUser.get(packet.getPlayerId()).getUUID()); + Player player = Bukkit.getPlayer(SteamwarUser.byId(packet.getPlayerId()).getUUID()); if (player != null) { player.closeInventory(); } @@ -66,7 +66,7 @@ public class CoreNetworkHandler extends PacketHandler { @Handler public void handlePingPacket(PingPacket packet) { - UUID uuid = SteamwarUser.get(packet.getId()).getUUID(); + UUID uuid = SteamwarUser.byId(packet.getId()).getUUID(); if(Bukkit.getPlayer(uuid) != null) { Player player = Bukkit.getPlayer(uuid); BountifulWrapper.impl.playPling(player); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/network/handlers/InventoryHandler.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/network/handlers/InventoryHandler.java index d2e8e73b..d05d4dae 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/network/handlers/InventoryHandler.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/network/handlers/InventoryHandler.java @@ -24,7 +24,6 @@ import de.steamwar.inventory.SWAnvilInv; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.network.NetworkSender; -import de.steamwar.network.packets.NetworkPacket; import de.steamwar.network.packets.PacketHandler; import de.steamwar.network.packets.client.AnvilAnswerPacket; import de.steamwar.network.packets.client.InventoryCallbackPacket; @@ -42,7 +41,7 @@ public class InventoryHandler extends PacketHandler { @Handler public static void handleInventoryPacket(InventoryPacket packet) { - Player player = Bukkit.getPlayer(SteamwarUser.get(packet.getPlayer()).getUUID()); + Player player = Bukkit.getPlayer(SteamwarUser.byId(packet.getPlayer()).getUUID()); Map items = new HashMap<>(); packet.getItems().forEach((i, item) -> { @SuppressWarnings("deprecation") SWItem it = SWItem.getItemFromJson(new JsonParser().parse(item).getAsJsonObject()); @@ -60,7 +59,7 @@ public class InventoryHandler extends PacketHandler { @Handler public static void handleAnvilInventoryPacket(AnvilInventoryPacket packet) { - Player player = Bukkit.getPlayer(SteamwarUser.get(packet.getPlayerId()).getUUID()); + Player player = Bukkit.getPlayer(SteamwarUser.byId(packet.getPlayerId()).getUUID()); SWAnvilInv inv = new SWAnvilInv(player, packet.getTitle(), packet.getDefaultText()); if (packet.getMaterial() != null && !packet.getMaterial().isEmpty()) { diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java index 8f937e3a..51c8c73f 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java @@ -41,6 +41,6 @@ public class BauServerInfo { public static SteamwarUser getOwnerUser() { if (bauOwner == null) return null; - return SteamwarUser.get(bauOwner); + return SteamwarUser.byId(bauOwner); } } diff --git a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt index 3d4471af..c408db98 100644 --- a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt +++ b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt @@ -166,7 +166,7 @@ object TNTLeagueGame { else if (redTeam.leader == null && TNTLeagueConfig.config.redLeader == null || player.uniqueId == TNTLeagueConfig.config.redLeader) redTeam else null - private fun getEventFreeTeam(player: Player) = SteamwarUser.get(player.uniqueId).let { user -> + private fun getEventFreeTeam(player: Player) = SteamwarUser.get(player.uniqueId)!!.let { user -> if (user.team == TNTLeagueConfig.config.eventTeamBlue.teamId && blueTeam.members.size < TNTLeagueConfig.config.event.maximumTeamMembers) blueTeam else if (user.team == TNTLeagueConfig.config.eventTeamRed.teamId && redTeam.members.size < TNTLeagueConfig.config.event.maximumTeamMembers) redTeam else null @@ -259,13 +259,13 @@ object TNTLeagueGame { redTeam.name.message.colorByTeam(redTeam), state.lobbyName, TNTLeagueConfig.config.gameTime - gameTimeRemaining, - blueTeam.leader?.let { SteamwarUser.get(it.uniqueId).id } ?: 0, - redTeam.leader?.let { SteamwarUser.get(it.uniqueId).id } ?: 0, + blueTeam.leader?.let { SteamwarUser.get(it.uniqueId)!!.getId() } ?: 0, + redTeam.leader?.let { SteamwarUser.get(it.uniqueId)!!.getId() } ?: 0, 0, 0, - blueTeam.members.map { SteamwarUser.get(it.uniqueId).id }, - redTeam.members.map { SteamwarUser.get(it.uniqueId).id }, - plugin.server.onlinePlayers.filter {! blueTeam.members.contains(it) && !redTeam.members.contains(it) }.map { SteamwarUser.get(it.uniqueId).id } + blueTeam.members.map { SteamwarUser.get(it.uniqueId)!!.getId() }, + redTeam.members.map { SteamwarUser.get(it.uniqueId)!!.getId() }, + plugin.server.onlinePlayers.filter {! blueTeam.members.contains(it) && !redTeam.members.contains(it) }.map { SteamwarUser.get(it.uniqueId)!!.getId() } )) } diff --git a/VelocityCore/src/de/steamwar/messages/Chatter.java b/VelocityCore/src/de/steamwar/messages/Chatter.java index 2494287a..2fd9e997 100644 --- a/VelocityCore/src/de/steamwar/messages/Chatter.java +++ b/VelocityCore/src/de/steamwar/messages/Chatter.java @@ -201,7 +201,7 @@ public interface Chatter { return new PlayerlessChatter() { @Override public SteamwarUser user() { - return SteamwarUser.get(-1); + return SteamwarUser.byId(-1); } @Override diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java index 0d679ca9..c146e1d8 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java @@ -33,7 +33,6 @@ import de.steamwar.messages.PlayerChatter; import de.steamwar.network.packets.server.BaumemberUpdatePacket; import de.steamwar.persistent.Bauserver; import de.steamwar.sql.BauweltMember; -import de.steamwar.sql.SchematicType; import de.steamwar.sql.SteamwarUser; import de.steamwar.velocitycore.*; import de.steamwar.velocitycore.inventory.SWInventory; @@ -198,7 +197,7 @@ public class BauCommand extends SWCommand { @Override public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { return BauweltMember.getMembers(sender.user().getId()).stream() - .map(bauweltMember -> SteamwarUser.get(bauweltMember.getMemberID()).getUserName()) + .map(bauweltMember -> SteamwarUser.byId(bauweltMember.getMemberID()).getUserName()) .toList(); } }; diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java index 722a1193..4a7b8d38 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java @@ -106,13 +106,13 @@ public class CheckCommand extends SWCommand { new Message("CHECK_LIST_TO_CHECK_HOVER"), ClickEvent.runCommand("/check schematic " + schematic.getId()), getWaitTime(schematic), - schematic.getSchemtype().getKuerzel(), SteamwarUser.get(schematic.getOwner()).getUserName(), schematic.getName()); + schematic.getSchemtype().getKuerzel(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getName()); } else { sender.prefixless("CHECK_LIST_CHECKING", new Message("CHECK_LIST_CHECKING_HOVER"), ClickEvent.runCommand("/join " + current.checker.user().getUserName()), getWaitTime(schematic), - schematic.getSchemtype().getKuerzel(), SteamwarUser.get(schematic.getOwner()).getUserName(), schematic.getName(), current.checker.user().getUserName()); + schematic.getSchemtype().getKuerzel(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getName(), current.checker.user().getUserName()); } } } @@ -135,7 +135,7 @@ public class CheckCommand extends SWCommand { int playerTeam = sender.user().hasPerm(UserPerm.MODERATION) ? 0 : sender.user().getTeam(); // Ignore 795 SteamWar Team - if (playerTeam != 0 && playerTeam != 795 && SteamwarUser.get(schem.getOwner()).getTeam() == playerTeam) { + if (playerTeam != 0 && playerTeam != 795 && SteamwarUser.byId(schem.getOwner()).getTeam() == playerTeam) { sender.system("CHECK_SCHEMATIC_OWN_TEAM"); return; } @@ -228,7 +228,7 @@ public class CheckCommand extends SWCommand { currentSchems.put(schematic.getId(), this); for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic)) - checker.prefixless("CHECK_SCHEMATIC_PREVIOUS", previous.getEndTime(), SteamwarUser.get(previous.getValidator()).getUserName(), previous.getDeclineReason()); + checker.prefixless("CHECK_SCHEMATIC_PREVIOUS", previous.getEndTime(), SteamwarUser.byId(previous.getValidator()).getUserName(), previous.getDeclineReason()); next(); }).start(); } @@ -277,7 +277,7 @@ public class CheckCommand extends SWCommand { private void accept(){ concludeCheckSession("freigegeben", fightTypes.get(schematic.getSchemtype()), () -> { - Chatter owner = Chatter.of(SteamwarUser.get(schematic.getOwner()).getUUID()); + Chatter owner = Chatter.of(SteamwarUser.byId(schematic.getOwner()).getUUID()); owner.withPlayerOrOffline( player -> owner.system("CHECK_ACCEPTED", schematic.getSchemtype().name(), schematic.getName()), () -> DiscordAlert.send(owner, Color.GREEN, new Message("DC_TITLE_SCHEMINFO"), new Message("DC_SCHEM_ACCEPT", schematic.getName()), true) @@ -290,7 +290,7 @@ public class CheckCommand extends SWCommand { private void decline(String reason){ concludeCheckSession(reason, SchematicType.Normal, () -> { - Chatter owner = Chatter.of(SteamwarUser.get(schematic.getOwner()).getUUID()); + Chatter owner = Chatter.of(SteamwarUser.byId(schematic.getOwner()).getUUID()); owner.withPlayerOrOffline( player -> owner.system("CHECK_DECLINED", schematic.getSchemtype().name(), schematic.getName(), reason), () -> DiscordAlert.send(owner, Color.RED, new Message("DC_TITLE_SCHEMINFO"), new Message("DC_SCHEM_DECLINE", schematic.getName(), reason), false) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java index c209c210..667b4b15 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java @@ -92,7 +92,7 @@ public class PunishmentCommand { String ip = IPSanitizer.getTrueAddress(player).getHostAddress(); Chatter.disconnect(player).system(punishmentMessage(user, Punishment.PunishmentType.Ban)); for (BannedUserIPs banned : BannedUserIPs.get(ip)) { - SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID()); + SteamwarUser bannedUser = SteamwarUser.byId(banned.getUserID()); if (bannedUser.isPunished(Punishment.PunishmentType.Ban) && bannedUser.getPunishment(Punishment.PunishmentType.Ban).getEndTime().before(time)) { bannedUser.punish(Punishment.PunishmentType.Ban, time, banReason, punisher.getId(), perma); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java index 59ba800d..3606348b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java @@ -240,7 +240,7 @@ public class TeamCommand extends SWCommand { @Override public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { return Team.get(sender.user().getTeam()).getMembers().stream() - .map(SteamwarUser::get) + .map(SteamwarUser::byId) .map(SteamwarUser::getUserName) .toList(); } @@ -296,7 +296,7 @@ public class TeamCommand extends SWCommand { @Register(value = "info", description = "TEAM_INFO_USAGE") public void info(Chatter sender, @ErrorMessage("UNKNOWN_TEAM") Team team){ - List users = team.getMembers().stream().map(SteamwarUser::get).toList(); + List users = team.getMembers().stream().map(SteamwarUser::byId).toList(); sender.system("TEAM_INFO_TEAM", team.getTeamName(), team.getTeamColor(), team.getTeamKuerzel()); sender.prefixless("TEAM_INFO_LEADER", users.stream().filter(SteamwarUser::isLeader).count(), getMemberList(users, true)); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java index 24b7fd12..1abb69d2 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java @@ -56,7 +56,7 @@ public class WhoisCommand extends SWCommand { } // SW ID or Discord ID - whois(sender, id < Integer.MAX_VALUE ? SteamwarUser.get((int) id) : SteamwarUser.get(id), parameters); + whois(sender, id < Integer.MAX_VALUE ? SteamwarUser.byId((int) id) : SteamwarUser.get(id), parameters); } @Register(description = "WHOIS_USAGE") @@ -128,7 +128,7 @@ public class WhoisCommand extends SWCommand { if (!all && !punishment.isCurrent()) { continue; } - sender.prefixless("WHOIS_PUNISHMENT", SteamwarUser.get(punishment.getPunisher()), punishment.getType().name(), duration(sender, punishment.getStartTime(), false), duration(sender, punishment.getEndTime(), punishment.isPerma()), punishment.getReason()); + sender.prefixless("WHOIS_PUNISHMENT", SteamwarUser.byId(punishment.getPunisher()), punishment.getType().name(), duration(sender, punishment.getStartTime(), false), duration(sender, punishment.getEndTime(), punishment.isPerma()), punishment.getReason()); isPunished = true; } if (!isPunished) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java index ead8845c..d0b853db 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java @@ -23,7 +23,6 @@ import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; import de.steamwar.velocitycore.commands.CheckCommand; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -43,7 +42,7 @@ public class ChecklistChannel extends DiscordChannel { for(SchematicNode schem : schems) { String waitTime = ""; - system("CHECK_LIST_TO_CHECK", waitTime, schem.getSchemtype().getKuerzel(), SteamwarUser.get(schem.getOwner()).getUserName(), schem.getName()); + system("CHECK_LIST_TO_CHECK", waitTime, schem.getSchemtype().getKuerzel(), SteamwarUser.byId(schem.getOwner()).getUserName(), schem.getName()); lastSchematics.add(schem.getId()); } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java index f5c25f2a..4922d69b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java @@ -47,7 +47,7 @@ public class DiscordChannel extends Chatter.PlayerlessChatter { public static SteamwarUser userOrPublic(User dcUser) { SteamwarUser user = SteamwarUser.get(dcUser.getIdLong()); - return user != null ? user : SteamwarUser.get(0); + return user != null ? user : SteamwarUser.byId(0); } private final Queue webhooks = new ArrayDeque<>(); @@ -67,7 +67,7 @@ public class DiscordChannel extends Chatter.PlayerlessChatter { } public DiscordChannel(MessageChannel channel, int maxNumberOfWebhooks) { - this(SteamwarUser.get(-1), channel, maxNumberOfWebhooks); + this(SteamwarUser.byId(-1), channel, maxNumberOfWebhooks); ChannelListener.getChannels().put(this.channel, this); if (channel instanceof TextChannel) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java index b1207a0f..53e4639e 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java @@ -56,7 +56,7 @@ public class BanListener extends BasicListener { Timestamp highestBan = ips.get(0).getTimestamp(); boolean perma = false; for(BannedUserIPs banned : ips) { - SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID()); + SteamwarUser bannedUser = SteamwarUser.byId(banned.getUserID()); if (bannedUser.isPunished(Punishment.PunishmentType.Ban)) { Punishment ban = bannedUser.getPunishment(Punishment.PunishmentType.Ban); if(ban.isPerma()) { @@ -77,7 +77,7 @@ public class BanListener extends BasicListener { clickEvent, user.getUserName(), (Function) ((Chatter sender) -> ips.stream().map(banned -> { - SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID()); + SteamwarUser bannedUser = SteamwarUser.byId(banned.getUserID()); return sender.parseToLegacy("BAN_AVOIDING_LIST", bannedUser.getUserName(), banned.getTimestamp().toLocalDateTime().format(DateTimeFormatter.ofPattern(sender.parseToPlain("TIMEFORMAT")))); }).collect(Collectors.joining(" "))) diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java index 6b0c7059..02e5cc3d 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java @@ -90,7 +90,7 @@ public class ChatListener extends BasicListener { user = SteamwarUser.get(player.getUniqueId()); name = player.getUsername(); } else if (source instanceof ConsoleCommandSource) { - user = SteamwarUser.get(-1); + user = SteamwarUser.byId(-1); name = "«CONSOLE»"; } else { name = source.toString(); @@ -128,7 +128,7 @@ public class ChatListener extends BasicListener { SteamwarUser user = SteamwarUser.get(player.getUniqueId()); if (message.contains("jndi:ldap")) { - PunishmentCommand.ban(user, Punishment.PERMA_TIME, "Versuchte Exploit-Ausnutzung", SteamwarUser.get(-1), true); + PunishmentCommand.ban(user, Punishment.PERMA_TIME, "Versuchte Exploit-Ausnutzung", SteamwarUser.byId(-1), true); VelocityCore.getLogger().log(Level.SEVERE, "%s %s wurde automatisch wegen jndi:ldap gebannt.".formatted(user.getUserName(), user.getId())); return; } diff --git a/VelocityCore/src/de/steamwar/velocitycore/mods/ModUtils.java b/VelocityCore/src/de/steamwar/velocitycore/mods/ModUtils.java index 38ab4f78..51f99849 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/mods/ModUtils.java +++ b/VelocityCore/src/de/steamwar/velocitycore/mods/ModUtils.java @@ -83,7 +83,7 @@ public class ModUtils { if(max == ModType.RED) { user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), message, -1, false); - PunishmentCommand.ban(user, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), message, SteamwarUser.get(-1), false); + PunishmentCommand.ban(user, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), message, SteamwarUser.byId(-1), false); VelocityCore.getLogger().log(Level.SEVERE, "%s %s wurde automatisch wegen der Mods %s gebannt.".formatted(user.getUserName(), user.getId(), modList)); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java index df2bcca8..2925ee34 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java +++ b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java @@ -70,9 +70,9 @@ public class EloPlayerHandler extends PacketHandler { // Die nächsten Zeilen filtern ein Fight innerhalb eines Teams nicht gewertet wird, bzw auch wenn nur Teile beider Teams im // gleichen Team sind dieser ungewertet ist. - Set teamsIds = fightEndsPacket.getBluePlayers().stream().map(SteamwarUser::get).map(SteamwarUser::getTeam).collect(Collectors.toSet()); + Set teamsIds = fightEndsPacket.getBluePlayers().stream().map(SteamwarUser::byId).map(SteamwarUser::getTeam).collect(Collectors.toSet()); for (int redPlayer : fightEndsPacket.getRedPlayers()) { - int team = SteamwarUser.get(redPlayer).getTeam(); + int team = SteamwarUser.byId(redPlayer).getTeam(); if (team != 0 && teamsIds.contains(team)) { return; } @@ -214,7 +214,7 @@ public class EloPlayerHandler extends PacketHandler { } private Player player(int userId) { - return VelocityCore.getProxy().getPlayer(SteamwarUser.get(userId).getUUID()).orElse(null); + return VelocityCore.getProxy().getPlayer(SteamwarUser.byId(userId).getUUID()).orElse(null); } private double getTimeFactor(int duration) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/ExecuteCommandHandler.java b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/ExecuteCommandHandler.java index 254e2e23..d9276b23 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/ExecuteCommandHandler.java +++ b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/ExecuteCommandHandler.java @@ -30,7 +30,7 @@ public class ExecuteCommandHandler extends PacketHandler { @Handler public void handle(ExecuteCommandPacket packet) { - SteamwarUser target = SteamwarUser.get(packet.getPlayerId()); + SteamwarUser target = SteamwarUser.byId(packet.getPlayerId()); String command = packet.getCommand(); VelocityCore.getProxy().getCommandManager().executeAsync(VelocityCore.getProxy().getPlayer(target.getUUID()).orElse(null), command); diff --git a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/InventoryCallbackHandler.java b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/InventoryCallbackHandler.java index 35454e28..c5a42fa1 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/InventoryCallbackHandler.java +++ b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/InventoryCallbackHandler.java @@ -41,7 +41,7 @@ public class InventoryCallbackHandler extends PacketHandler { @Handler public void handle(InventoryCallbackPacket packet) { - SteamwarUser owner = SteamwarUser.get(packet.getOwner()); + SteamwarUser owner = SteamwarUser.byId(packet.getOwner()); InventoryCallbackPacket.CallbackType type = packet.getType(); if(!inventoryHashMap.containsKey(owner.getId())) { Chatter.of(owner).system("UPDATE_INTERRUPTION"); diff --git a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/PrepareSchemHandler.java b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/PrepareSchemHandler.java index e4c3c348..04373cb1 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/PrepareSchemHandler.java +++ b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/PrepareSchemHandler.java @@ -35,7 +35,7 @@ public class PrepareSchemHandler extends PacketHandler { @Handler public void handle(PrepareSchemPacket packet) { - Player player = VelocityCore.getProxy().getPlayer(SteamwarUser.get(packet.getPlayer()).getUUID()).orElse(null); + Player player = VelocityCore.getProxy().getPlayer(SteamwarUser.byId(packet.getPlayer()).getUUID()).orElse(null); int schematicID = packet.getSchem(); GameModeConfig mode = ArenaMode.getBySchemType(SchematicType.fromDB(packet.getSchemType())); diff --git a/VelocityCore/src/de/steamwar/velocitycore/tablist/TablistServer.java b/VelocityCore/src/de/steamwar/velocitycore/tablist/TablistServer.java index ee6a0966..dc0d18ae 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/tablist/TablistServer.java +++ b/VelocityCore/src/de/steamwar/velocitycore/tablist/TablistServer.java @@ -80,7 +80,7 @@ public class TablistServer implements TablistPart { } private void addPlayers(String prefix, List teamPlayers, Collection onlinePlayers) { - teamPlayers.stream().map(SteamwarUser::get).map( + teamPlayers.stream().map(SteamwarUser::byId).map( user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUUID())).findAny() ).filter(Optional::isPresent).map(Optional::get).sorted( (p1, p2) -> p1.getUsername().compareToIgnoreCase(p2.getUsername()) diff --git a/WebsiteBackend/src/de/steamwar/plugins/Auth.kt b/WebsiteBackend/src/de/steamwar/plugins/Auth.kt index 593473b6..e79d9de2 100644 --- a/WebsiteBackend/src/de/steamwar/plugins/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/plugins/Auth.kt @@ -75,7 +75,7 @@ val SWPermissionCheck = createRouteScopedPlugin("SWAuth", ::SWAuthConfig) { return@on } - if (permission != null && !token.user.hasPerm(permission)) { + if (permission != null && !token.user.hasPerm(permission!!)) { call.respond(HttpStatusCode.Forbidden) return@on } diff --git a/WebsiteBackend/src/de/steamwar/routes/Data.kt b/WebsiteBackend/src/de/steamwar/routes/Data.kt index 669737fa..a638a04a 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Data.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Data.kt @@ -46,7 +46,7 @@ data class ResponseSchematicType(val name: String, val db: String) data class ResponseUser(val name: String, val uuid: String, val prefix: String, val perms: List) { constructor(user: SteamwarUser) : this(user.userName, user.uuid.toString(), user.prefix().chatPrefix, user.perms().filter { !it.name.startsWith("PREFIX_") }.map { it.name }) { synchronized(cache) { - cache[user.id] = this + cache[user.getId()] = this } } @@ -55,7 +55,7 @@ data class ResponseUser(val name: String, val uuid: String, val prefix: String, fun get(id: Int): ResponseUser { synchronized(cache) { - return cache[id] ?: ResponseUser(SteamwarUser.get(id)).also { cache[id] = it } + return cache[id] ?: ResponseUser(SteamwarUser.byId(id)!!).also { cache[id] = it } } } @@ -75,7 +75,7 @@ fun Route.configureDataRoutes() { permission = UserPerm.MODERATION } get("/users") { - call.respond(SteamwarUser.getAll().map { ResponseUser(it) }) + call.respond(SteamwarUser.all().map { ResponseUser(it) }) } get("/teams") { call.respond(Team.getAll().map { ResponseTeam(it) }) diff --git a/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt b/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt index 051c31cd..0c8bbf3b 100644 --- a/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt +++ b/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt @@ -21,7 +21,6 @@ package de.steamwar.routes import de.steamwar.sql.Referee import de.steamwar.sql.SteamwarUser -import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* @@ -32,23 +31,23 @@ fun Route.configureEventRefereesRouting() { route("/referees") { get { val event = call.receiveEvent() ?: return@get - call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.get(it)) }) + call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }) } put { val event = call.receiveEvent() ?: return@put val referees = call.receive>() referees.forEach { - Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it)).id) + Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId()) } - call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.get(it)) }) + call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }) } delete { val event = call.receiveEvent() ?: return@delete val referees = call.receive>() referees.forEach { - Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it)).id) + Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId()) } - call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.get(it)) }) + call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }) } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt index 6b2ba25b..ed5ad9ef 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Events.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt @@ -118,7 +118,7 @@ data class ExtendedResponseEvent( TeamTeilnahme.getTeams(event.eventID).map { ResponseTeam(it) }, EventGroup.get(event).map { ResponseGroups(it) }, EventFight.getEvent(event.eventID).map { ResponseEventFight(it) }, - Referee.get(event.eventID).map { ResponseUser(SteamwarUser.get(it)) }, + Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }, EventRelation.get(event).map { ResponseRelation(it) } ) } @@ -221,13 +221,13 @@ fun Route.configureEventsRoute() { if (updateEvent.addReferee != null) { updateEvent.addReferee.forEach { - Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it)).id) + Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId()) } } if (updateEvent.removeReferee != null) { updateEvent.removeReferee.forEach { - Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it)).id) + Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId()) } } event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly) diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index 212d9a26..c0cd8da0 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -128,9 +128,9 @@ fun Route.configureSchematic() { val user = call.principal()!!.user - var node = SchematicNode.getSchematicNode(user.id, schemName, null as Int?) + var node = SchematicNode.getSchematicNode(user.getId(), schemName, null as Int?) if (node == null) { - node = SchematicNode.createSchematic(user.id, schemName, null) + node = SchematicNode.createSchematic(user.getId(), schemName, null) } try { diff --git a/WebsiteBackend/src/de/steamwar/routes/Stats.kt b/WebsiteBackend/src/de/steamwar/routes/Stats.kt index cda9c4df..167c4978 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Stats.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Stats.kt @@ -36,7 +36,7 @@ data class UserStats(val eventFightParticipation: Int, val eventParticipation: I getEventParticipation(user) ?: 0, getAcceptedSchematics(user) ?: 0, getFightCount(user) ?: 0, - user.onlinetime / 3600.0 + user.getOnlinetime() / 3600.0 ) } diff --git a/settings.gradle.kts b/settings.gradle.kts index d2e71175..2657c7bc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -166,6 +166,12 @@ dependencyResolutionManagement { library("ktorRateLimit", "io.ktor:ktor-server-rate-limit:$ktorVersion") library("nbt", "dev.dewy:nbt:1.5.1") + + val exposedVersion = "1.0.0-rc-2" + library("exposedCore", "org.jetbrains.exposed:exposed-core:$exposedVersion") + library("exposedDao", "org.jetbrains.exposed:exposed-dao:$exposedVersion") + library("exposedJdbc", "org.jetbrains.exposed:exposed-jdbc:$exposedVersion") + library("exposedTime", "org.jetbrains.exposed:exposed-java-time:$exposedVersion") } } } From c8ac984ad3acd856d183f79c7056dbb3f8fc66fb Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 19:03:30 +0100 Subject: [PATCH 03/32] Rename .java to .kt --- .../src/de/steamwar/sql/{SchematicNode.java => SchematicNode.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CommonCore/SQL/src/de/steamwar/sql/{SchematicNode.java => SchematicNode.kt} (100%) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java rename to CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt From 1aff7b30a6131c5ebdbc0c8c1968c233aa2fcf96 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 19:03:30 +0100 Subject: [PATCH 04/32] Refactor SchematicNode --- .../SQL/src/de/steamwar/sql/AuditLog.kt | 8 +- .../SQL/src/de/steamwar/sql/NodeData.java | 4 +- .../SQL/src/de/steamwar/sql/SchematicNode.kt | 905 +++++++----------- .../steamwar/sql/internal/KotlinDatabase.kt | 24 + .../commands/schematiccommand/GUI.java | 12 +- .../SchematicCommandUtils.java | 32 +- .../schematiccommand/parts/MemberPart.java | 6 +- .../schematiccommand/parts/ModifyPart.java | 10 +- .../schematiccommand/parts/SavePart.java | 8 +- .../schematiccommand/parts/ViewPart.java | 4 +- .../steamwar/inventory/SchematicSelector.java | 8 +- .../src/de/steamwar/routes/Schematic.kt | 4 +- 12 files changed, 426 insertions(+), 599 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt index 6d48857b..7ab0c8c4 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.kt @@ -30,8 +30,8 @@ import java.time.Instant object AuditLogTable: IntIdTable("AuditLog", "AuditLogId") { val time = timestamp("Time") val server = varchar("ServerName", 255) - val serverOwner = integer("ServerOwner").nullable() - val actor = integer("Actor") + val serverOwner = reference("ServerOwner", SteamwarUserTable).nullable() + val actor = reference("Actor", SteamwarUserTable) val action = enumerationByName("ActionType", 255, AuditLog.Type::class) val actionText = text("ActionText") } @@ -50,8 +50,8 @@ class AuditLog(id: EntityID): IntEntity(id) { new { this.time = Instant.now() this.server = serverName - this.serverOwner = serverOwner?.id?.value - this.actor = actor.id.value + this.serverOwner = serverOwner?.id + this.actor = actor.id this.action = actionType this.actionText = text } diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java b/CommonCore/SQL/src/de/steamwar/sql/NodeData.java index be0bbc95..63d8ccaf 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeData.java @@ -87,7 +87,7 @@ public class NodeData { private Timestamp createdAt; @Field - private SchematicFormat nodeFormat; + public SchematicFormat nodeFormat; public InputStream schemData() throws IOException { return schemData(true); @@ -132,6 +132,6 @@ public class NodeData { SPONGE_V2(".schem"), SPONGE_V3(".schem"); - private final String fileEnding; + public final String fileEnding; } } diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt index 38fab77f..c058df2b 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt @@ -17,618 +17,421 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.*; -import lombok.Getter; +import de.steamwar.sql.internal.fromSql +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.* +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insertAndGetId +import java.sql.Timestamp +import java.util.* +import java.util.function.Consumer -import java.sql.Timestamp; -import java.time.Instant; -import java.util.*; -import java.util.function.Predicate; +object SchematicNodeTable : IntIdTable("SchematicNode", "NodeId") { + val owner = reference("NodeOwner", SteamwarUserTable) + val name = varchar("NodeName", 64) + val parent = optReference("ParentNode", SchematicNodeTable) + val lastUpdate = timestamp("LastUpdate") + val item = text("NodeItem") + val type = varchar("NodeType", 16).nullable() + val config = integer("Config") +} -public class SchematicNode { +class SchematicNode(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(SchematicNodeTable) { + private val fieldIndex: Map, Int> = + SchematicNodeTable.columns.mapIndexed { index, column -> column to index }.toMap() - static { - SchematicType.Normal.name(); // Ensure SchematicType is loaded. - new SqlTypeMapper<>(SchematicNode.class, null, (rs, identifier) -> { - throw new SecurityException("SchematicNode cannot be used as type (recursive select)"); - }, (st, index, value) -> st.setInt(index, value.nodeId)); - } + private val FORBIDDEN_NAMES = listOf("public") + private val FORBIDDEN_CHARS = listOf('/', '\\', '<', '>', '^', '°', '\'', '"', ' ') - private static final Map>> TAB_CACHE = new HashMap<>(); + val tabCache = mutableMapOf>>() - public static void clear() { - TAB_CACHE.clear(); - } + @JvmStatic + fun clear() = tabCache.clear() - private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode "; + private fun List.mapToIds(): Map = this.associateBy { it.nodeId } - private static final Table table = new Table<>(SchematicNode.class); - private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", - "NodeType"); - private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem", - "NodeType", "NodeRank", "Config"); - private static final Statement delete = table.delete(Table.PRIMARY); + @JvmStatic + fun getAll(user: SteamwarUser) = fromSql( + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ?} UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.* FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId", + listOf( + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId() + ), + fieldIndex + ) - private static final SelectStatement byId = new SelectStatement<>(table, - nodeSelector + "WHERE NodeId = ?"); - private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, - nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?"); - private static final SelectStatement byParent = new SelectStatement<>(table, - nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); - private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector - + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); - private static final SelectStatement byOwnerType = new SelectStatement<>(table, - nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); - private static final SelectStatement byType = new SelectStatement<>(table, - nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); - private static final SelectStatement all = new SelectStatement<>(table, - "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId"); - private static final SelectStatement list = new SelectStatement<>(table, - "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " - + Statement.NULL_SAFE_EQUALS - + "? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName"); - private static final SelectStatement byParentName = new SelectStatement<>(table, - "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " - + Statement.NULL_SAFE_EQUALS - + "? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?"); - private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, - "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeId = ?"); - private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, - "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId" - + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); - private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, - "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?"); - private static final SelectStatement byIdAndUser = new SelectStatement<>(table, - "SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE NodeId = ?"); - private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, - "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.Config FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); + @JvmStatic + fun getAllMap(user: SteamwarUser) = getAll(user).mapToIds() - static { - NodeMember.init(); - } + @JvmStatic + fun list(user: SteamwarUser, schematicId: Int?) = fromSql( + "SELECT SchematicNode.NodeId, NodeOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId <=> ? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName", + listOf( + IntegerColumnType() to schematicId, + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + IntegerColumnType() to schematicId, + IntegerColumnType() to user.getId(), + IntegerColumnType() to schematicId, + IntegerColumnType() to schematicId, + ), fieldIndex + ) - @Field(keys = { Table.PRIMARY }, autoincrement = true) - private final int nodeId; - @Field(keys = { "OwnerNameParent" }) - private final int nodeOwner; - @Field(def = "0") - @Getter - private final int effectiveOwner; - @Field(keys = { "OwnerNameParent" }) - private String nodeName; - @Field(keys = { "OwnerNameParent" }, nullable = true) - private Integer parentNode; - @Field(def = "CURRENT_TIMESTAMP") - private Timestamp lastUpdate; - @Field(def = "''") - private String nodeItem; - @Field(def = "'normal'", nullable = true) - private SchematicType nodeType; - @Field(def = "0") - private int nodeRank; - @Field - private int config; + @JvmStatic + fun byParentName(user: SteamwarUser, schematicId: Int?, name: String) = fromSql( + "SELECT SchematicNode.NodeId, NodeOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId <=> ? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?", + listOf( + IntegerColumnType() to schematicId, + IntegerColumnType() to user.getId(), + VarCharColumnType() to name, + IntegerColumnType() to user.getId(), + IntegerColumnType() to schematicId, + IntegerColumnType() to user.getId(), + IntegerColumnType() to schematicId, + IntegerColumnType() to schematicId, + VarCharColumnType() to name, + ), fieldIndex + ).firstOrNull() - private String brCache; + @JvmStatic + fun accessibleByUserType(user: SteamwarUser, type: SchematicType) = fromSql( + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?", + listOf( + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + VarCharColumnType() to type.toDB(), + ), fieldIndex + ) - public SchematicNode( - int nodeId, - int nodeOwner, - int effectiveOwner, - String nodeName, - Integer parentNode, - Timestamp lastUpdate, - String nodeItem, - SchematicType nodeType, - int nodeRank, - int config) { - this.nodeId = nodeId; - this.nodeOwner = nodeOwner; - this.effectiveOwner = effectiveOwner; - this.nodeName = nodeName; - this.parentNode = parentNode; - this.nodeItem = nodeItem; - this.nodeType = nodeType; - this.lastUpdate = lastUpdate; - this.nodeRank = nodeRank; - this.config = config; - } + @JvmStatic + fun accessibleByUserTypeMap(user: SteamwarUser, type: SchematicType) = + accessibleByUserType(user, type).mapToIds() - public static List getAll(SteamwarUser user) { - return all.listSelect(user, user, user); - } + @JvmStatic + fun schematicAccessibleForUser(user: SteamwarUser, schematicId: Int?) = fromSql( + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeId = ?", + listOf( + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + IntegerColumnType() to schematicId, + ), + fieldIndex + ).isNotEmpty() - public static Map> getAllMap(SteamwarUser user) { - return map(getAll(user)); - } + @JvmStatic + fun accessibleByUserTypeParent(user: SteamwarUser, type: SchematicType, parentId: Int?) = fromSql( + "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId <=> ? ORDER BY NodeName", + listOf( + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + VarCharColumnType() to type.toDB(), + IntegerColumnType() to user.getId(), + IntegerColumnType() to parentId, + ), fieldIndex + ) - public static List list(SteamwarUser user, Integer schematicId) { - return list.listSelect(user, schematicId, user, user, schematicId, user, schematicId, schematicId); - } - - public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { - return byParentName.select(user, schematicId, user, name, user, schematicId, user, schematicId, schematicId, - name); - } - - public static List accessibleByUserType(SteamwarUser user, SchematicType type) { - return accessibleByUserType.listSelect(user, user, user, type); - } - - public static Map> accessibleByUserTypeMap(SteamwarUser user, SchematicType type) { - return map(accessibleByUserType(user, type)); - } - - public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { - return schematicAccessibleForUser.select(user, user, user, schematicId) != null; - } - - public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, - Integer parentId) { - return accessibleByUserTypeInParent.listSelect(user, user, type, user, parentId); - } - - public static SchematicNode byIdAndUser(SteamwarUser user, Integer id) { - return byIdAndUser.select(user, id); - } - - public static List parentsOfNode(SteamwarUser user, Integer id) { - return allParentsOfNode.listSelect(id, user, user, user); - } - - private static Map> map(List in) { - Map> map = new HashMap<>(); - for (SchematicNode effectiveSchematicNode : in) { - map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()) - .add(effectiveSchematicNode); + @JvmStatic + @Deprecated("Use byId") + fun byIdAndUser(ignored: SteamwarUser, id: Int) = useDb { + findById(id) } - return map; - } - public static SchematicNode createSchematic(int owner, String name, Integer parent) { - return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), ""); - } + @JvmStatic + fun parentsOfNode(user: SteamwarUser, id: Int) = fromSql( + "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.Config FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId", + listOf( + IntegerColumnType() to id, + IntegerColumnType() to user.getId(), + IntegerColumnType() to user.getId(), + ), fieldIndex + ) - public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) { - return createSchematicNode(owner, name, parent, null, ""); - } + @JvmStatic + fun createSchematic(owner: Int, name: String, parent: Int?) = createSchematicNode( + owner, name, parent, + SchematicType.Normal.toDB(), "" + ) - public static SchematicNode createSchematicNode(int owner, String name, Integer parent, String type, String item) { - if (parent != null && parent == 0) - parent = null; - int nodeId = create.insertGetKey(owner, name, parent, item, type); - return getSchematicNode(nodeId); - } + @JvmStatic + fun createSchematicDirectory(owner: Int, name: String, parent: Int?) = + createSchematicNode(owner, name, parent, null, "") - public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) { - return getSchematicNode(owner, name, parent.getId()); - } - - public static SchematicNode getSchematicNode(int owner, String name, Integer parent) { - return byOwnerNameParent.select(owner, name, parent); - } - - public static List getSchematicNodeInNode(SchematicNode parent) { - return getSchematicNodeInNode(parent.getId()); - } - - public static List getSchematicNodeInNode(Integer parent) { - return byParent.listSelect(parent); - } - - public static List getSchematicDirectoryInNode(Integer parent) { - return dirsByParent.listSelect(parent); - } - - @Deprecated - public static SchematicNode getSchematicDirectory(String name, SchematicNode parent) { - return getSchematicNode(name, parent.getId()); - } - - @Deprecated - public static SchematicNode getSchematicDirectory(String name, Integer parent) { - return getSchematicNode(name, parent); - } - - public static SchematicNode getSchematicNode(String name, Integer parent) { - return byParentName.select(name, parent); - } - - public static SchematicNode getSchematicNode(int id) { - return byId.select(id); - } - - public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, - Integer parent) { - return accessibleByUserTypeParent(SteamwarUser.byId(owner), SchematicType.fromDB(schemType), parent); - } - - public static List getAllAccessibleSchematicsOfType(int user, String schemType) { - return accessibleByUserType(SteamwarUser.byId(user), SchematicType.fromDB(schemType)); - } - - public static List getAllSchematicsOfType(int owner, String schemType) { - return byOwnerType.listSelect(owner, schemType); - } - - @Deprecated - public static List getAllSchematicsOfType(String schemType) { - return byType.listSelect(schemType); - } - - public static List getAllSchematicsOfType(SchematicType schemType) { - return byType.listSelect(schemType); - } - - public static List deepGet(Integer parent, Predicate filter) { - List finalList = new ArrayList<>(); - List nodes = SchematicNode.getSchematicNodeInNode(parent); - nodes.forEach(node -> { - if (node.isDir()) { - finalList.addAll(deepGet(node.getId(), filter)); - } else { - if (filter.test(node)) - finalList.add(node); + @JvmStatic + fun createSchematicNode(owner: Int, name: String, parent: Int?, type: String?, item: String) = useDb { + val id = SchematicNodeTable.insertAndGetId { + it[this.owner] = EntityID(owner, SteamwarUserTable) + it[this.name] = name + it[this.parent] = + parent?.let { p -> if (p == 0) null else p }?.let { p -> EntityID(p, SchematicNodeTable) } + it[this.item] = item + it[this.type] = type } - }); - return finalList; - } - - @Deprecated - public static List getSchematicsAccessibleByUser(int user, Integer parent) { - return list(SteamwarUser.byId(user), parent); - } - - @Deprecated - public static List getAllSchematicsAccessibleByUser(int user) { - return getAll(SteamwarUser.byId(user)); - } - - public static List getAllParentsOfNode(SchematicNode node) { - return getAllParentsOfNode(node.getId()); - } - - public static List getAllParentsOfNode(int node) { - return allParentsOfNode.listSelect(node); - } - - public static SchematicNode getNodeFromPath(SteamwarUser user, String s) { - if (s.startsWith("/")) { - s = s.substring(1); + return@useDb findById(id) ?: throw IllegalStateException("SchematicNode $id not found") } - if (s.endsWith("/")) { - s = s.substring(0, s.length() - 1); + + @JvmStatic + fun byId(id: Int) = useDb { findById(id) } + + @JvmStatic + fun getSchematicNode(owner: Int, name: String, parent: Int?) = useDb { + find { (SchematicNodeTable.owner eq owner) and (SchematicNodeTable.name eq name) and (SchematicNodeTable.parent eq parent) }.firstOrNull() } - if (s.isEmpty()) { - return null; + + @JvmStatic + fun getSchematicNode(owner: Int, name: String, parent: SchematicNode) = + getSchematicNode(owner, name, parent.nodeId) + + @JvmStatic + fun getSchematicNodeInNode(parent: Int?) = useDb { + find { (SchematicNodeTable.parent eq parent) }.orderBy(SchematicNodeTable.name to SortOrder.ASC).toList() } - if (s.contains("/")) { - String[] layers = s.split("/"); - Optional currentNode = Optional - .ofNullable(SchematicNode.byParentName(user, null, layers[0])); - for (int i = 1; i < layers.length; i++) { - int finalI = i; - Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode - .byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); - if (!node.isPresent()) { - return null; - } else { - currentNode = node; - if (!currentNode.map(SchematicNode::isDir).orElse(false) && i != layers.length - 1) { - return null; + + @JvmStatic + fun getSchematicNodeInNode(parent: SchematicNode) = getSchematicNodeInNode(parent.nodeId) + + @JvmStatic + fun getSchematicNode(name: String, parent: Int?) = useDb { + find { (SchematicNodeTable.name eq name) and (SchematicNodeTable.parent eq parent) }.firstOrNull() + } + + @JvmStatic + fun getSchematicNode(id: Int) = byId(id) + + @JvmStatic + fun getAllAccessibleSchematicsOfType(user: Int, type: String) = + accessibleByUserType(SteamwarUser.byId(user)!!, SchematicType.fromDB(type)) + + @JvmStatic + fun getAllSchematicsAccessibleByUser(user: Int) = getAll(SteamwarUser.byId(user)!!) + + @JvmStatic + fun getAllSchematicsOfType(owner: Int, type: String) = useDb { + find { (SchematicNodeTable.owner eq owner) and (SchematicNodeTable.type eq type) }.orderBy( + SchematicNodeTable.name to SortOrder.ASC + ).toList() + } + + @JvmStatic + fun getAllSchematicsOfType(type: SchematicType) = useDb { + find { (SchematicNodeTable.type eq type.toDB()) }.orderBy(SchematicNodeTable.name to SortOrder.ASC).toList() + } + + @JvmStatic + fun deepGet(parent: Int?, filter: (node: SchematicNode) -> Boolean): List = + getSchematicNodeInNode(parent) + .flatMap { + return@flatMap if (it.isDir()) { + deepGet(it.nodeId, filter) + } else { + if (filter(it)) listOf(it) else listOf() } } - } - return currentNode.orElse(null); - } else { - return SchematicNode.byParentName(user, null, s); - } - } - public static List filterSchems(int user, Predicate filter) { - List finalList = new ArrayList<>(); - List nodes = getSchematicsAccessibleByUser(user, null); - nodes.forEach(node -> { - if (node.isDir()) { - finalList.addAll(deepGet(node.getId(), filter)); + @JvmStatic + fun getNodeFromPath(user: SteamwarUser, path: String): SchematicNode? { + var s = path + if (s.startsWith("/")) { + s = s.drop(1) + } + if (s.endsWith("/")) { + s = s.dropLast(1) + } + if (s.isEmpty()) return null + if (s.contains("/")) { + val layers: Array = s.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + var currentNode = byParentName(user, null, layers[0]!!) + for (i in 1.. byParentName(user, n.getId(), layers[i]!!) } + if (node == null) { + return null + } else { + currentNode = node + if (!currentNode.isDir() && i != layers.size - 1 + ) { + return null + } + } + } + return currentNode } else { - if (filter.test(node)) - finalList.add(node); + return byParentName(user, null, s) } - }); - return finalList; - } - - public int getId() { - return nodeId; - } - - public int getOwner() { - return nodeOwner; - } - - public String getName() { - return nodeName; - } - - public void setName(String name) { - this.nodeName = name; - updateDB(); - } - - public Integer getParent() { - return parentNode; - } - - public Optional getOptionalParent() { - return Optional.ofNullable(parentNode); - } - - public void setParent(Integer parent) { - this.parentNode = parent; - updateDB(); - } - - public String getItem() { - if (nodeItem.isEmpty()) { - return isDir() ? "CHEST" : "CAULDRON_ITEM"; } - return nodeItem; + + @JvmStatic + fun invalidSchemName(layers: Array) = layers.any { + it.isEmpty() || FORBIDDEN_CHARS.any { c -> c in it } || FORBIDDEN_NAMES.any { n -> n == it.lowercase() } + } + + @JvmStatic + fun getNodeTabcomplete(user: SteamwarUser, s: String): List { + var s = s + val sws = s.startsWith("/") + if (sws) { + s = s.substring(1) + } + val index = s.lastIndexOf("/") + val cacheKey = if (index == -1) "" else s.take(index) + tabCache[user.getId()]?.get(cacheKey)?.also { return it } + + val list = mutableListOf() + if (s.contains("/")) { + val preTab = s.take(s.lastIndexOf("/") + 1) + val pa = getNodeFromPath(user, preTab) ?: return emptyList() + val nodes: List = list(user, pa.getId()) + val br = pa.generateBreadcrumbs(user) + nodes.forEach(Consumer { node: SchematicNode? -> list.add((if (sws) "/" else "") + br + node!!.name + (if (node.isDir()) "/" else "")) }) + } else { + val nodes: List = list(user, null) + nodes.forEach(Consumer { node: SchematicNode? -> list.add((if (sws) "/" else "") + node!!.name + (if (node.isDir()) "/" else "")) }) + } + list.remove("//copy") + tabCache.computeIfAbsent(user.getId()) { i -> mutableMapOf() }.putIfAbsent(cacheKey, list) + return list + } } - public void setItem(String item) { - this.nodeItem = item; - updateDB(); + val nodeId by SchematicNodeTable.id.transform({ EntityID(it, SchematicNodeTable) }, { it.value }) + val nodeOwner by SchematicNodeTable.owner + val owner: Int get() = nodeOwner.value + private var nodeName by SchematicNodeTable.name + var name: String + get() = nodeName + set(value) = useDb { + nodeName = value + } + private var parentNodeId by SchematicNodeTable.parent + var parent: Int? + get() = parentNodeId?.value + set(value) = useDb { + parentNodeId = value?.let { EntityID(it, SchematicNodeTable) } + } + val parentNode: SchematicNode? + get() = parent?.let { findById(it) } + + val optionalParent: Optional get() = Optional.ofNullable(parent) + var lastUpdate by SchematicNodeTable.lastUpdate.transform({ it.toInstant() }, { Timestamp.from(it) }) + private var nodeItem by SchematicNodeTable.item + var item: String + get() = nodeItem.ifEmpty { + if (isDir()) "CHEST" else "CAULDRON_ITEM" + } + set(value) = useDb { + nodeItem = value + } + private var nodeType by SchematicNodeTable.type + var schemtype: SchematicType + get() = checkDir { SchematicType.fromDB(nodeType) } + set(value) = checkDir { useDb { nodeType = value.toDB() } } + var config by SchematicNodeTable.config + + val members: Set by lazy { NodeMember.getNodeMembers(nodeId) } + private lateinit var breadcrumbs: String + + fun getFileEnding(): String = checkDir { NodeData.getLatest(this).nodeFormat.fileEnding } + fun getId() = nodeId + fun isDir() = nodeType == null + + private fun checkDir(block: () -> T): T { + if (!isDir()) { + throw IllegalStateException("Node is not a directory") + } + + return block() } - @Deprecated - public String getType() { - return nodeType.name(); - } + fun replaceColor() = getConfig(ConfigFlags.REPLACE_COLOR) + fun setReplaceColor(value: Boolean) = setConfig(ConfigFlags.REPLACE_COLOR, value) - @Deprecated - public void setType(String type) { - if (isDir()) - throw new SecurityException("Node is Directory"); - this.nodeType = SchematicType.fromDB(type); - updateDB(); - } + fun allowReplay() = getConfig(ConfigFlags.ALLOW_REPLAY) + fun setAllowReplay(value: Boolean) = setConfig(ConfigFlags.ALLOW_REPLAY, value) - public boolean isDir() { - return nodeType == null; - } + fun isPrepared() = getConfig(ConfigFlags.IS_PREPARED) + fun setPrepared(value: Boolean) = setConfig(ConfigFlags.IS_PREPARED, value) - public String getFileEnding() { - if (isDir()) - throw new SecurityException("Node is Directory"); - return NodeData.getLatest(this).getNodeFormat().getFileEnding(); - } - - public int getRank() { - if (isDir()) - throw new SecurityException("Node is Directory"); - return nodeRank; - } - - @Deprecated - public int getRankUnsafe() { - return nodeRank; - } - - public void setRank(int rank) { - if (isDir()) - throw new SecurityException("Node is Directory"); - this.nodeRank = rank; - } - - public SchematicType getSchemtype() { - if (isDir()) - throw new SecurityException("Is Directory"); - return nodeType; - } - - public void setSchemtype(SchematicType type) { - if (isDir()) - throw new SecurityException("Is Directory"); - this.nodeType = type; - updateDB(); - } - - public boolean replaceColor() { - return getConfig(ConfigFlags.REPLACE_COLOR); - } - - public void setReplaceColor(boolean replaceColor) { - if (isDir()) - throw new SecurityException("Is Directory"); - setConfig(ConfigFlags.REPLACE_COLOR, replaceColor); - } - - public boolean allowReplay() { - return getConfig(ConfigFlags.ALLOW_REPLAY); - } - - public void setAllowReplay(boolean allowReplay) { - if (isDir()) - throw new SecurityException("Is Directory"); - setConfig(ConfigFlags.ALLOW_REPLAY, allowReplay); - } - - public boolean isPrepared() { - return getConfig(ConfigFlags.IS_PREPARED); - } - - public void setPrepared(boolean prepared) { - if (isDir()) - throw new SecurityException("Is Directory"); - setConfig(ConfigFlags.IS_PREPARED, prepared); - } - - public boolean getConfig(ConfigFlags flag) { - return (config & (1 << flag.ordinal())) != 0; - } - - public void setConfig(ConfigFlags flag, boolean value) { - if (value) { - config |= (1 << flag.ordinal()); + fun getConfig(flag: ConfigFlags) = config and (1 shl flag.ordinal) != 0 + fun setConfig(flag: ConfigFlags, value: Boolean) = useDb { + config = if (value) { + config or (1 shl flag.ordinal) } else { - config &= ~(1 << flag.ordinal()); + config and (1 shl flag.ordinal).inv() } - updateDB(); } - public SchematicNode getParentNode() { - if (parentNode == null) - return null; - return SchematicNode.getSchematicNode(parentNode); + fun getElo(season: Int) = SchemElo.getElo(this, season) + + override fun delete() = useDb { + super.delete() } - public int getElo(int season) { - return SchemElo.getElo(this, season); + override fun hashCode() = nodeId + + override fun equals(other: Any?): Boolean { + if (other !is SchematicNode) return false + return nodeId == other.nodeId } - public boolean accessibleByUser(SteamwarUser user) { - return NodeMember.getNodeMember(nodeId, user) != null; - } - - public Set getMembers() { - return NodeMember.getNodeMembers(nodeId); - } - - public Timestamp getLastUpdate() { - return lastUpdate; - } - - private void updateDB() { - this.lastUpdate = Timestamp.from(Instant.now()); - update.update(nodeName, parentNode, nodeItem, nodeType, nodeRank, config, nodeId); - TAB_CACHE.clear(); - } - - public void delete() { - delete.update(nodeId); - } - - @Override - public int hashCode() { - return nodeId; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof SchematicNode)) - return false; - - return ((SchematicNode) obj).getId() == nodeId; - } - - public String generateBreadcrumbs(SteamwarUser user) { - return byIdAndUser(user, nodeId).generateBreadcrumbs(); - } - - public String generateBreadcrumbs(String split, SteamwarUser user) { - return byIdAndUser(user, nodeId).generateBreadcrumbs(split); - } - - public String generateBreadcrumbs() { - if (brCache == null) { - brCache = generateBreadcrumbs("/"); + fun generateBreadcrumbs(user: SteamwarUser): String { + if (!this::breadcrumbs.isInitialized) { + breadcrumbs = generateBreadcrumbs("/", user) } - return brCache; + return breadcrumbs } - public String generateBreadcrumbs(String split) { - StringBuilder builder = new StringBuilder(getName()); - Optional currentNode = Optional.of(this); - if (currentNode.map(SchematicNode::isDir).orElse(false)) { - builder.append(split); + fun generateBreadcrumbs(split: String, user: SteamwarUser): String { + val builder: StringBuilder = StringBuilder(name) + if (isDir()) { + builder.append(split) } - while (currentNode.isPresent()) { + var currentNode: SchematicNode? = this + while (currentNode != null) { currentNode = currentNode - .flatMap(schematicNode -> Optional - .ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)) - .map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())) - .map(SchematicNode::getSchematicNode); - currentNode.ifPresent(node -> builder.insert(0, split).insert(0, node.getName())); + .let { + NodeMember.getNodeMember(it.nodeId, user.getId()) + ?.parent?.orElse(null) ?: it.parent + } + ?.let { findById(it) } + ?.also { + builder.insert(0, split).insert(0, it.name) + } } - return builder.toString(); + return builder.toString() } - public List> generateBreadcrumbsMap(SteamwarUser user) { - List> map = new ArrayList<>(); - Optional currentNode = Optional.of(this); - if (currentNode.map(SchematicNode::isDir).orElse(false)) { - map.add(new AbstractMap.SimpleEntry<>(getName(), getId())); - } - while (currentNode.isPresent()) { + fun generateBreadcrumbsMap(user: SteamwarUser): List> { + val map = mutableListOf>() + var currentNode: SchematicNode? = this + while (currentNode != null) { currentNode = currentNode - .flatMap(schematicNode -> Optional - .ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)) - .map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())) - .map(SchematicNode::getSchematicNode); - currentNode.ifPresent(node -> map.add(0, new AbstractMap.SimpleEntry<>(node.getName(), node.getId()))); + .also { + map.add(0, Pair(it.name, it.nodeId)) + } + .let { + NodeMember.getNodeMember(it.nodeId, user.getId()) + ?.parent?.orElse(null) ?: it.parent + } + ?.let { findById(it) } } - return map; + return map } - private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); + fun accessibleByUser(user: SteamwarUser) = schematicAccessibleForUser(user, nodeId) - public static boolean invalidSchemName(String[] layers) { - for (String layer : layers) { - if (layer.isEmpty()) { - return true; - } - if (layer.contains("/") || - layer.contains("\\") || - layer.contains("<") || - layer.contains(">") || - layer.contains("^") || - layer.contains("°") || - layer.contains("'") || - layer.contains("\"") || - layer.contains(" ")) { - return true; - } - if (FORBIDDEN_NAMES.contains(layer.toLowerCase())) { - return true; - } - } - return false; - } - - public static List getNodeTabcomplete(SteamwarUser user, String s) { - boolean sws = s.startsWith("/"); - if (sws) { - s = s.substring(1); - } - int index = s.lastIndexOf("/"); - String cacheKey = index == -1 ? "" : s.substring(0, index); - if (TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { - return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); - } - List list = new ArrayList<>(); - if (s.contains("/")) { - String preTab = s.substring(0, s.lastIndexOf("/") + 1); - SchematicNode pa = SchematicNode.getNodeFromPath(user, preTab); - if (pa == null) - return new ArrayList<>(); - List nodes = SchematicNode.list(user, pa.getId()); - String br = pa.generateBreadcrumbs(); - nodes.forEach(node -> list.add((sws ? "/" : "") + br + node.getName() + (node.isDir() ? "/" : ""))); - } else { - List nodes = SchematicNode.list(user, null); - nodes.forEach(node -> list.add((sws ? "/" : "") + node.getName() + (node.isDir() ? "/" : ""))); - } - list.remove("//copy"); - TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); - return list; - } - - public static enum ConfigFlags { + enum class ConfigFlags { REPLACE_COLOR, ALLOW_REPLAY, IS_PREPARED } + + @Deprecated("Removed") + var rank = 0 } diff --git a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt index d4869623..4da6e413 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt @@ -19,11 +19,21 @@ package de.steamwar.sql.internal +import org.intellij.lang.annotations.Language +import org.jetbrains.exposed.v1.core.ColumnType +import org.jetbrains.exposed.v1.core.Expression +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.statements.StatementType +import org.jetbrains.exposed.v1.core.statements.api.RowApi +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass import org.jetbrains.exposed.v1.jdbc.Database import org.jetbrains.exposed.v1.jdbc.JdbcTransaction +import org.jetbrains.exposed.v1.jdbc.statements.jdbc.JdbcResult import org.jetbrains.exposed.v1.jdbc.transactions.TransactionManager import org.jetbrains.exposed.v1.jdbc.transactions.transaction import java.io.File +import java.sql.ResultSet import java.util.Properties object KotlinDatabase { @@ -55,4 +65,18 @@ object KotlinDatabase { fun useDb(statement: JdbcTransaction.() -> T): T { KotlinDatabase.ensureConnected() return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db, statement) +} + +fun IntEntityClass.fromSql( + @Language("MySQL") stmt: String, + args: List, Any?>>, + fieldIndex: Map, Int> +): List = useDb { + exec(stmt, explicitStatementType = StatementType.SELECT, args = args) { + val list = mutableListOf() + while (it.next()) { + list.add(wrapRow(ResultRow.create(JdbcResult(it), fieldIndex))) + } + list + } ?: listOf() } \ No newline at end of file diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java index 51e3589e..287d9b65 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/GUI.java @@ -92,7 +92,7 @@ public class GUI { private static void info(Player player, SchematicNode node, SchematicSelector back) { SteamwarUser user = getUser(player); - SWInventory inv = new SWInventory(player, 9 * 2, node.generateBreadcrumbs()); + SWInventory inv = new SWInventory(player, 9 * 2, node.generateBreadcrumbs(user)); if(!node.isDir()) { inv.setItem(0, SWItem.getMaterial("WOOD_AXE"), SchematicSystem.MESSAGE.parse("GUI_INFO_LOAD", player), Arrays.asList( SchematicSystem.MESSAGE.parse("GUI_LOAD_LATEST", player), @@ -108,7 +108,7 @@ public class GUI { entries.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(node.getItem()), "§e" + SchematicSystem.MESSAGE.parse("BLANK", player, datas.get(i).getCreatedAt())), i)); } - SWListInv listInv = new SWListInv<>(player, SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION_TITLE", player, node.generateBreadcrumbs()), entries, (clickType, revision) -> { + SWListInv listInv = new SWListInv<>(player, SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION_TITLE", player, node.generateBreadcrumbs(user)), entries, (clickType, revision) -> { if(revision == null) return; player.closeInventory(); SchematicCommandUtils.loadSchem(player, node, revision); @@ -268,9 +268,9 @@ public class GUI { private static void deleteOwn(Player p, SchematicNode schem, SchematicSelector back){ SteamwarUser user = getUser(p); - SWInventory inv = new SWInventory(p, 9, SchematicSystem.MESSAGE.parse("GUI_DELETE_OWN_TITLE", p, schem.generateBreadcrumbs())); + SWInventory inv = new SWInventory(p, 9, SchematicSystem.MESSAGE.parse("GUI_DELETE_OWN_TITLE", p, schem.generateBreadcrumbs(user))); inv.setItem(0, SWItem.getDye(1), (byte) 1, SchematicSystem.MESSAGE.parse("CONFIRM", p), click -> { - p.performCommand("schematic delete " + schem.generateBreadcrumbs()); + p.performCommand("schematic delete " + schem.generateBreadcrumbs(user)); if(back != null) { if(schem.isDir()) { @@ -287,12 +287,12 @@ public class GUI { private static void deleteMembership(Player p, SchematicNode schem, SchematicSelector back){ SteamwarUser user = getUser(p); - SWInventory inv = new SWInventory(p, 9, SchematicSystem.MESSAGE.parse("GUI_DELETE_MEMBER_TITLE", p, schem.generateBreadcrumbs())); + SWInventory inv = new SWInventory(p, 9, SchematicSystem.MESSAGE.parse("GUI_DELETE_MEMBER_TITLE", p, schem.generateBreadcrumbs(user))); inv.setItem(0, SWItem.getDye(1), (byte) 1, SchematicSystem.MESSAGE.parse("CONFIRM", p), click -> { NodeMember member = NodeMember.getNodeMember(schem.getId(), user.getId()); if(member != null) member.delete(); - SchematicSystem.MESSAGE.send("GUI_DELETE_MEMBER_DONE", p, schem.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("GUI_DELETE_MEMBER_DONE", p, schem.generateBreadcrumbs(user)); if(back != null) { if(schem.isDir()) { back.reOpenDirUp(); diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java index e872562b..e2f6626e 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java @@ -113,7 +113,7 @@ public class SchematicCommandUtils { int pageCount = (int) Math.ceil(nodes.size() / (double) CHUNK_SIZE); SchematicSystem.MESSAGE.sendPrefixless("UTIL_LIST_HEAD", player, nodes.size()); - String breadcrumbs = parent == null ? "" : parent.generateBreadcrumbs(); + String breadcrumbs = parent == null ? "" : parent.generateBreadcrumbs(user); SchematicSystem.MESSAGE.sendPrefixless("UTIL_LIST_PATH", player, (breadcrumbs.isEmpty() ? "/" : breadcrumbs)); if (!breadcrumbs.isEmpty()) { String str = breadcrumbs.substring(0, Math.max(0, breadcrumbs.substring(0, breadcrumbs.length() - 1).lastIndexOf("/"))); @@ -147,10 +147,10 @@ public class SchematicCommandUtils { if (node.isDir()) { schematics.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(SchematicSystem.MESSAGE.parse("UTIL_LIST_OPEN_DIR", player)).create())); - schematics.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem list " + (behavior.isPublics() ? "public " : "") + (behavior.nonCachedBreadcrumbs ? node.generateBreadcrumbs() : breadcrumbs + node.getName() + "/"))); + schematics.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem list " + (behavior.isPublics() ? "public " : "") + (behavior.nonCachedBreadcrumbs ? node.generateBreadcrumbs(user) : breadcrumbs + node.getName() + "/"))); } else { schematics.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(SchematicSystem.MESSAGE.parse("UTIL_LIST_OPEN_SCHEM", player)).create())); - schematics.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem info " + (behavior.isPublics() ? "public " : "") + (behavior.nonCachedBreadcrumbs ? node.generateBreadcrumbs() : breadcrumbs + node.getName()))); + schematics.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem info " + (behavior.isPublics() ? "public " : "") + (behavior.nonCachedBreadcrumbs ? node.generateBreadcrumbs(user) : breadcrumbs + node.getName()))); } player.spigot().sendMessage(schematics); @@ -160,7 +160,7 @@ public class SchematicCommandUtils { TextComponent deadd = SchematicSystem.MESSAGE.parseToComponent("UTIL_LIST_REMOVE", false, player); deadd.setColor(ChatColor.RED); deadd.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {SchematicSystem.MESSAGE.parseToComponent("UTIL_LIST_REMOVE_HOVER", false, player)})); - deadd.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem delete " + parent.generateBreadcrumbs())); + deadd.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem delete " + parent.generateBreadcrumbs(user))); player.spigot().sendMessage(deadd); } @@ -202,12 +202,12 @@ public class SchematicCommandUtils { public static void printSchemInfo(Player player, SchematicNode node) { SteamwarUser user = getUser(player); - SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_SCHEM", player, node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_SCHEM", player, node.generateBreadcrumbs(user)); if(node.getOwner() == user.getId()) { player.spigot().sendMessage( new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_NAME", false, player, node.getName())) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_RENAME_HOVER", false, player)})) - .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem rename " + node.generateBreadcrumbs() + " ")) + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem rename " + node.generateBreadcrumbs(user) + " ")) .create() ); } else { @@ -216,18 +216,18 @@ public class SchematicCommandUtils { SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_OWNER", player, node.getOwner() == user.getId() ? user.getUserName() : SteamwarUser.byId(node.getOwner()).getUserName()); if(node.getOwner() == user.getId()) { player.spigot().sendMessage( - new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_PARENT", false, player, node.getParent() == null ? "/" : node.getParentNode().generateBreadcrumbs())) + new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_PARENT", false, player, node.getParent() == null ? "/" : node.getParentNode().generateBreadcrumbs(user))) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_MOVE_HOVER", false, player)})) - .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem move " + node.generateBreadcrumbs() + " " + node.generateBreadcrumbs().replace("/" + node.getName(), ""))) + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem move " + node.generateBreadcrumbs(user) + " " + node.generateBreadcrumbs(user).replace("/" + node.getName(), ""))) .create() ); } else { - SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_PARENT", player, node.getParent() == null ? "/" : node.getParentNode().generateBreadcrumbs()); + SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_PARENT", player, node.getParent() == null ? "/" : node.getParentNode().generateBreadcrumbs(user)); } player.spigot().sendMessage( new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_REVISIONS", false, player, NodeData.getRevisions(node))) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_REVISIONS_HOVER", false, player)})) - .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem revisions " + node.generateBreadcrumbs())) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem revisions " + node.generateBreadcrumbs(user))) .create()); SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_UPDATED", player, node.getLastUpdate()); if (!node.isDir()) { @@ -235,7 +235,7 @@ public class SchematicCommandUtils { player.spigot().sendMessage( new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_TYPE", false, player, node.getSchemtype().name())) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_TYPE_HOVER", false, player)})) - .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem changetype " + node.generateBreadcrumbs())) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem changetype " + node.generateBreadcrumbs(user))) .create() ); } else { @@ -264,14 +264,14 @@ public class SchematicCommandUtils { SteamwarUser member = SteamwarUser.byId(nodeMember.getMember()); memberBuilder.append(member.getUserName()) .color(ChatColor.YELLOW) - .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem delmember " + node.generateBreadcrumbs() + " " + member.getUserName())) + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem delmember " + node.generateBreadcrumbs(user) + " " + member.getUserName())) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_REMOVE_HOVER", false, player, member.getUserName())})) .append(" ", ComponentBuilder.FormatRetention.NONE); }); memberBuilder.append("(+)", ComponentBuilder.FormatRetention.NONE) .color(ChatColor.GREEN) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_ADD_HOVER", false, player)})) - .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem addmember " + node.generateBreadcrumbs() + " ")); + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem addmember " + node.generateBreadcrumbs(user) + " ")); player.spigot().sendMessage(memberBuilder.create()); } else { List schematicMembers = new ArrayList<>(); @@ -287,14 +287,14 @@ public class SchematicCommandUtils { TextComponent load = SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_LOAD", false, player); load.setColor(ChatColor.GREEN); load.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_LOAD_HOVER", false, player)})); - load.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + (node.getOwner() == 0 ? "public " : "") + node.generateBreadcrumbs())); + load.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + (node.getOwner() == 0 ? "public " : "") + node.generateBreadcrumbs(user))); base.addExtra(load); if (node.getOwner() == user.getId()) { TextComponent download = SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_DOWNLOAD", false, player); download.setColor(ChatColor.GOLD); download.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_DOWNLOAD_HOVER", false, player)})); - download.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem download " + node.generateBreadcrumbs())); + download.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem download " + node.generateBreadcrumbs(user))); base.addExtra(download); } } @@ -303,7 +303,7 @@ public class SchematicCommandUtils { TextComponent delete = SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_DELETE", false, player); delete.setColor(ChatColor.DARK_RED); delete.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_DELETE_HOVER", false, player)})); - delete.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem delete " + node.generateBreadcrumbs())); + delete.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/schem delete " + node.generateBreadcrumbs(user))); base.addExtra(delete); } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java index 8e42ef86..751e1c9b 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java @@ -77,7 +77,7 @@ public class MemberPart extends SWCommand { Player t = Bukkit.getPlayer(target.getUUID()); if (t != null) { - SchematicSystem.MESSAGE.send("COMMAND_ADD_ADDED", t, node.generateBreadcrumbs(), player.getName()); + SchematicSystem.MESSAGE.send("COMMAND_ADD_ADDED", t, node.generateBreadcrumbs(user), player.getName()); } } @@ -97,7 +97,7 @@ public class MemberPart extends SWCommand { List nodes = SchematicNode.deepGet(node.getId(), node1 -> node1.getOwner() != user.getId()); if (!nodes.isEmpty()) { for (SchematicNode schematicNode : nodes) { - SchematicNode newNode = mkdirs(schematicNode.generateBreadcrumbs().split("/"), target, 1); + SchematicNode newNode = mkdirs(schematicNode.generateBreadcrumbs(user).split("/"), target, 1); if(SchematicNode.getSchematicNode(schematicNode.getName(), newNode == null ? 0 : newNode.getId()) != null) { schematicNode.setName(schematicNode.getName() + "-" + Instant.now().getEpochSecond() % 1000); } @@ -106,7 +106,7 @@ public class MemberPart extends SWCommand { } member.delete(); - SchematicSystem.MESSAGE.send("COMMAND_DELMEM_DONE", player, target.getUserName(), node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("COMMAND_DELMEM_DONE", player, target.getUserName(), node.generateBreadcrumbs(user)); Player t = Bukkit.getPlayer(target.getUUID()); if (t != null) { diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ModifyPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ModifyPart.java index 99006559..2dc5ad04 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ModifyPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ModifyPart.java @@ -58,7 +58,7 @@ public class ModifyPart extends SWCommand { Clipboard finalClipboard = clipboard; - String breadcrumb = node.generateBreadcrumbs(); + String breadcrumb = node.generateBreadcrumbs(SteamwarUser.get(player.getUniqueId())); SchematicType.values().parallelStream() .filter(SchematicType::isAssignable) @@ -131,7 +131,7 @@ public class ModifyPart extends SWCommand { return; } } - SchematicSystem.MESSAGE.send("COMMAND_MOVE_DONE", player, SchematicNode.byIdAndUser(user, node.getId()).generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("COMMAND_MOVE_DONE", player, SchematicNode.byIdAndUser(user, node.getId()).generateBreadcrumbs(user)); } @Register("rename") @@ -145,7 +145,7 @@ public class ModifyPart extends SWCommand { result.sendError(player); return; } - SchematicSystem.MESSAGE.send("COMMAND_RENAME_DONE", player, node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("COMMAND_RENAME_DONE", player, node.generateBreadcrumbs(user)); } @Register("delete") @@ -164,13 +164,13 @@ public class ModifyPart extends SWCommand { if (node.isDir()) { if (SchematicNode.getSchematicNodeInNode(node).isEmpty()) { - SchematicSystem.MESSAGE.send("COMMAND_DELETE_DIR", player, node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("COMMAND_DELETE_DIR", player, node.generateBreadcrumbs(user)); node.delete(); } else { SchematicSystem.MESSAGE.send("COMMAND_DELETE_DIR_FULL", player); } } else { - SchematicSystem.MESSAGE.send("COMMAND_DELETE_SCHEM", player, node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("COMMAND_DELETE_SCHEM", player, node.generateBreadcrumbs(user)); node.delete(); } } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java index 32178e1a..7f025b58 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/SavePart.java @@ -49,11 +49,11 @@ public class SavePart extends SWCommand { SchematicSelector selector = new SchematicSelector(player, SchematicSelector.selectSchematicNode(), schematicNode -> { if(schematicNode == null || schematicNode.isDir()) { SWAnvilInv anvilInv = new SWAnvilInv(player, SchematicSystem.MESSAGE.parse("COMMAND_ENTER_NAME", player)); - anvilInv.setCallback(s -> saveSchem(player, schematicNode==null?s:(schematicNode.generateBreadcrumbs() + s))); + anvilInv.setCallback(s -> saveSchem(player, schematicNode==null?s:(schematicNode.generateBreadcrumbs(getUser(player)) + s))); anvilInv.setItem(Material.CAULDRON); anvilInv.open(); } else { - saveSchem(player, schematicNode.generateBreadcrumbs()); + saveSchem(player, schematicNode.generateBreadcrumbs(getUser(player))); } }); selector.setSingleDirOpen(false); @@ -111,7 +111,7 @@ public class SavePart extends SWCommand { return; } - SchematicSystem.MESSAGE.send(newSchem?"COMMAND_SAVE_DONE":"COMMAND_SAVE_OVERWRITE", player, node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send(newSchem?"COMMAND_SAVE_DONE":"COMMAND_SAVE_OVERWRITE", player, node.generateBreadcrumbs(user)); } @Register("dir") @@ -124,6 +124,6 @@ public class SavePart extends SWCommand { String[] layers = name.split("/"); if (invalidSchemName(player, layers)) return; SchematicNode node = mkdirs(layers, user, 0); - SchematicSystem.MESSAGE.send("COMMAND_DIR_DONE", player, node.generateBreadcrumbs()); + SchematicSystem.MESSAGE.send("COMMAND_DIR_DONE", player, node.generateBreadcrumbs(user)); } } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java index b4421fa9..ef8f883b 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/ViewPart.java @@ -66,7 +66,7 @@ public class ViewPart extends SWCommand { @Register("list") public void schemList(Player player, @Validator("isDirValidator") @Mapper("dirMapper") SchematicNode node, @OptionalValue("1") int page) { SteamwarUser user = getUser(player); - createCachedSchemList(player, SchematicNode.list(user, node.getId()), Math.max(page - 1, 0), node, SchematicCommandUtils.SchematicListBehavior.builder().setPublics(node.getOwner() == 0).setPageCommandGen(value -> "/schem list " + (node.getOwner()==0?"public ":"") + node.generateBreadcrumbs() + " " + value).build()); + createCachedSchemList(player, SchematicNode.list(user, node.getId()), Math.max(page - 1, 0), node, SchematicCommandUtils.SchematicListBehavior.builder().setPublics(node.getOwner() == 0).setPageCommandGen(value -> "/schem list " + (node.getOwner()==0?"public ":"") + node.generateBreadcrumbs(user) + " " + value).build()); } @Register({"info", "public"}) @@ -91,7 +91,7 @@ public class ViewPart extends SWCommand { for (int j = Math.max(0, revisions.size() - 10); j < revisions.size(); j++) { player.spigot().sendMessage( new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("REVISIONS_REVISION_NUMBER", false, player, j + 1, revisions.get(j).getCreatedAt())) - .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + (node.getOwner() == 0 ? "public " : "") + node.generateBreadcrumbs() + " " + (j + 1))) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + (node.getOwner() == 0 ? "public " : "") + node.generateBreadcrumbs(getUser(player)) + " " + (j + 1))) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_LOAD_HOVER", false, player)})) .create() ); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java index 5cfbc78e..795ac70a 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java @@ -122,7 +122,7 @@ public class SchematicSelector { list.add(renderItem(node)); } - SWListInv inv = new SWListInv<>(player, MessageFormat.format(injectable.createTitle(player), target.target.getName(player), (filter == null || filter.getName() == null)?(parent == null?"/":parent.generateBreadcrumbs()):filter.getName()), false, list, (clickType, node) -> handleClick(node, parent)); + SWListInv inv = new SWListInv<>(player, MessageFormat.format(injectable.createTitle(player), target.target.getName(player), (filter == null || filter.getName() == null)?(parent == null?"/":parent.generateBreadcrumbs(user)):filter.getName()), false, list, (clickType, node) -> handleClick(node, parent)); if(publicMode == PublicMode.ALL) { if(user.getId() == 0) { inv.setItem(48, new SWItem(Material.BUCKET, Core.MESSAGE.parse("SCHEM_SELECTOR_OWN", player), clickType -> { @@ -178,7 +178,7 @@ public class SchematicSelector { Optional currentParent = Optional.of(parent); do { sdoTrigger = false; - currentParent = currentParent.flatMap(SchematicSelector::getParent); + currentParent = currentParent.flatMap(this::getParent); if(!currentParent.isPresent()) { break; } @@ -484,8 +484,8 @@ public class SchematicSelector { return nodes; } - private static Optional getParent(SchematicNode node) { - return node.getOptionalParent().map(integer -> SchematicNode.byIdAndUser(SteamwarUser.byId(node.getEffectiveOwner()), integer)); + private Optional getParent(SchematicNode node) { + return node.getOptionalParent().map(integer -> SchematicNode.byIdAndUser(user, integer)); } public static SelectorTarget selectSchematic() { diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index c0cd8da0..d429af5c 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -45,12 +45,12 @@ import java.util.zip.GZIPInputStream @Serializable data class ResponseSchematic(val name: String, val id: Int, val type: String?, val owner: Int, val item: String, val lastUpdate: Long, val rank: Int, val replaceColor: Boolean, val allowReplay: Boolean) { - constructor(node: SchematicNode) : this(node.name, node.id, node.schemtype?.name(), node.owner, node.item, node.lastUpdate.time, node.rank, node.replaceColor(), node.allowReplay()) + constructor(node: SchematicNode) : this(node.name, node.getId(), node.schemtype?.name(), node.owner, node.item, node.lastUpdate.time, node.rank, node.replaceColor(), node.allowReplay()) } @Serializable data class ResponseSchematicLong(val members: List, val path: String, val schem: ResponseSchematic) { - constructor(node: SchematicNode, path: String): this(NodeMember.getNodeMembers(node.id).map { ResponseUser.get(it.member) }, path, ResponseSchematic(node)) + constructor(node: SchematicNode, path: String): this(NodeMember.getNodeMembers(node.getId()).map { ResponseUser.get(it.member) }, path, ResponseSchematic(node)) } @Serializable From 8bef19ed8bcc2aa4d0d3c25f92a70f008ea45e54 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 20:38:02 +0100 Subject: [PATCH 05/32] Rename .java to .kt Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/{UserConfig.java => UserConfig.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CommonCore/SQL/src/de/steamwar/sql/{UserConfig.java => UserConfig.kt} (100%) diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.java b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/UserConfig.java rename to CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt From b51ea484e414808dd180ce3fb4b79b1262fdeba1 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 20:38:02 +0100 Subject: [PATCH 06/32] Refactor UserConfig Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/UserConfig.kt | 106 +++++++++--------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt index c2525a57..7d8b4ff4 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt @@ -17,57 +17,63 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.jdbc.upsert +import java.util.UUID -import java.util.UUID; +object UserConfigTable: CompositeIdTable("UserConfig") { + val userId = reference("userId", SteamwarUserTable) + val key = varchar("Key", 32) + val value = text("Value") -@AllArgsConstructor -public class UserConfig { - - private static final Table table = new Table<>(UserConfig.class); - private static final SelectStatement select = table.select(Table.PRIMARY); - private static final Statement insert = table.insertAll(); - private static final Statement delete = table.delete(Table.PRIMARY); - - @Field(keys = {Table.PRIMARY}) - private final int user; - @Field(keys = {Table.PRIMARY}) - private final String config; - @Field - private final String value; - - public static String getConfig(UUID player, String config) { - return getConfig(SteamwarUser.get(player).getId(), config); - } - - public static String getConfig(int player, String config) { - UserConfig value = select.select(player, config); - return value != null ? value.value : null; - } - - public static void updatePlayerConfig(UUID uuid, String config, String value) { - updatePlayerConfig(SteamwarUser.get(uuid).getId(), config, value); - } - - public static void updatePlayerConfig(int id, String config, String value) { - if (value == null) { - removePlayerConfig(id, config); - return; - } - insert.update(id, config, value); - } - - public static void removePlayerConfig(UUID uuid, String config) { - removePlayerConfig(SteamwarUser.get(uuid).getId(), config); - } - - public static void removePlayerConfig(int id, String config) { - delete.update(id, config); - } + override val primaryKey = PrimaryKey(userId, key) } + +class UserConfig(id: EntityID): CompositeEntity(id) { + val userId by UserConfigTable.userId + val key by UserConfigTable.key + var value by UserConfigTable.value + + companion object: CompositeEntityClass(UserConfigTable) { + @JvmStatic + fun getConfig(userId: Int, config: String) = useDb { + find { (UserConfigTable.userId eq userId) and (UserConfigTable.key eq config) }.firstOrNull()?.value + } + + @JvmStatic + fun getConfig(user: UUID, config: String) = getConfig(SteamwarUser.get(user)!!.id.value, config) + + @JvmStatic + fun updatePlayerConfig(id: Int, config: String, value: String?) = useDb { + if (value == null) { + removePlayerConfig(id, config) + } else { + UserConfigTable.upsert { + it[UserConfigTable.userId] = id + it[UserConfigTable.key] = config + it[UserConfigTable.value] = value + } + } + } + + @JvmStatic + fun updatePlayerConfig(user: UUID, config: String, value: String?) = updatePlayerConfig(SteamwarUser.get(user)!!.id.value, config, value) + + @JvmStatic + fun removePlayerConfig(id: Int, config: String) = useDb { + find { (UserConfigTable.userId eq id) and (UserConfigTable.key eq config) }.firstOrNull()?.delete() + } + + @JvmStatic + fun removePlayerConfig(user: UUID, config: String) = removePlayerConfig(SteamwarUser.get(user)!!.id.value, config) + } +} \ No newline at end of file From a8eaf3daa71f1dedee1b560168e435a93d88898c Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 21:31:57 +0100 Subject: [PATCH 07/32] Fixes Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/SchematicNode.kt | 24 +++++++++---------- .../SQL/src/de/steamwar/sql/SteamwarUser.kt | 4 ++-- .../SQL/src/de/steamwar/sql/UserConfig.kt | 16 ++++++------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt index c058df2b..d1495b46 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt @@ -59,7 +59,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) { @JvmStatic fun getAll(user: SteamwarUser) = fromSql( - "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ?} UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.* FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId", + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.* FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId", listOf( IntegerColumnType() to user.getId(), IntegerColumnType() to user.getId() @@ -72,11 +72,10 @@ class SchematicNode(id: EntityID) : IntEntity(id) { @JvmStatic fun list(user: SteamwarUser, schematicId: Int?) = fromSql( - "SELECT SchematicNode.NodeId, NodeOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId <=> ? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName", + "SELECT SchematicNode.NodeId, NodeOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId <=> ? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName", listOf( IntegerColumnType() to schematicId, IntegerColumnType() to user.getId(), - IntegerColumnType() to user.getId(), IntegerColumnType() to schematicId, IntegerColumnType() to user.getId(), IntegerColumnType() to schematicId, @@ -86,12 +85,11 @@ class SchematicNode(id: EntityID) : IntEntity(id) { @JvmStatic fun byParentName(user: SteamwarUser, schematicId: Int?, name: String) = fromSql( - "SELECT SchematicNode.NodeId, NodeOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId <=> ? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?", + "SELECT SchematicNode.NodeId, NodeOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId <=> ? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?", listOf( IntegerColumnType() to schematicId, IntegerColumnType() to user.getId(), VarCharColumnType() to name, - IntegerColumnType() to user.getId(), IntegerColumnType() to schematicId, IntegerColumnType() to user.getId(), IntegerColumnType() to schematicId, @@ -342,8 +340,8 @@ class SchematicNode(id: EntityID) : IntEntity(id) { fun isDir() = nodeType == null private fun checkDir(block: () -> T): T { - if (!isDir()) { - throw IllegalStateException("Node is not a directory") + if (isDir()) { + throw IllegalStateException("Node is a directory") } return block() @@ -387,12 +385,12 @@ class SchematicNode(id: EntityID) : IntEntity(id) { return breadcrumbs } - fun generateBreadcrumbs(split: String, user: SteamwarUser): String { + fun generateBreadcrumbs(split: String, user: SteamwarUser): String = useDb { val builder: StringBuilder = StringBuilder(name) if (isDir()) { builder.append(split) } - var currentNode: SchematicNode? = this + var currentNode: SchematicNode? = this@SchematicNode while (currentNode != null) { currentNode = currentNode .let { @@ -404,12 +402,12 @@ class SchematicNode(id: EntityID) : IntEntity(id) { builder.insert(0, split).insert(0, it.name) } } - return builder.toString() + return@useDb builder.toString() } - fun generateBreadcrumbsMap(user: SteamwarUser): List> { + fun generateBreadcrumbsMap(user: SteamwarUser): List> = useDb { val map = mutableListOf>() - var currentNode: SchematicNode? = this + var currentNode: SchematicNode? = this@SchematicNode while (currentNode != null) { currentNode = currentNode .also { @@ -421,7 +419,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) { } ?.let { findById(it) } } - return map + return@useDb map } fun accessibleByUser(user: SteamwarUser) = schematicAccessibleForUser(user, nodeId) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt index c48351bc..3ea8aa6e 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt @@ -42,7 +42,7 @@ object SteamwarUserTable : IntIdTable("UserData", "id") { val team = integer("Team") val leader = bool("Leader") val locale = varchar("Locale", 16).nullable() - val manualeLocale = bool("ManualeLocale") + val manualLocale = bool("ManualLocale") val bedrock = bool("Bedrock") val password = text("Password").nullable() val discordId = long("DiscordId").nullable() @@ -171,7 +171,7 @@ class SteamwarUser(id: EntityID): IntEntity(id) { var locale: Locale by SteamwarUserTable.locale .transform({ it.toLanguageTag() }, { it?.let { Locale.forLanguageTag(it) } ?: Locale.getDefault()}) - var manualLocale by SteamwarUserTable.manualeLocale + var manualLocale by SteamwarUserTable.manualLocale var bedrock by SteamwarUserTable.bedrock private var passwordInternal by SteamwarUserTable.password var password: String? diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt index 7d8b4ff4..11bc2e4d 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt @@ -31,22 +31,22 @@ import org.jetbrains.exposed.v1.jdbc.upsert import java.util.UUID object UserConfigTable: CompositeIdTable("UserConfig") { - val userId = reference("userId", SteamwarUserTable) - val key = varchar("Key", 32) - val value = text("Value") + val userId = reference("User", SteamwarUserTable) + val config = varchar("Config", 32) + val value = text("Value", eagerLoading = true) - override val primaryKey = PrimaryKey(userId, key) + override val primaryKey = PrimaryKey(userId, config) } class UserConfig(id: EntityID): CompositeEntity(id) { val userId by UserConfigTable.userId - val key by UserConfigTable.key + val config by UserConfigTable.config var value by UserConfigTable.value companion object: CompositeEntityClass(UserConfigTable) { @JvmStatic fun getConfig(userId: Int, config: String) = useDb { - find { (UserConfigTable.userId eq userId) and (UserConfigTable.key eq config) }.firstOrNull()?.value + find { (UserConfigTable.userId eq userId) and (UserConfigTable.config eq config) }.firstOrNull()?.value } @JvmStatic @@ -59,7 +59,7 @@ class UserConfig(id: EntityID): CompositeEntity(id) { } else { UserConfigTable.upsert { it[UserConfigTable.userId] = id - it[UserConfigTable.key] = config + it[UserConfigTable.config] = config it[UserConfigTable.value] = value } } @@ -70,7 +70,7 @@ class UserConfig(id: EntityID): CompositeEntity(id) { @JvmStatic fun removePlayerConfig(id: Int, config: String) = useDb { - find { (UserConfigTable.userId eq id) and (UserConfigTable.key eq config) }.firstOrNull()?.delete() + find { (UserConfigTable.userId eq id) and (UserConfigTable.config eq config) }.firstOrNull()?.delete() } @JvmStatic From 14e82f36a56ce329c8d93efe49727b7938592916 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 22:25:31 +0100 Subject: [PATCH 08/32] Rename .java to .kt Signed-off-by: Chaoscaot --- CommonCore/SQL/src/de/steamwar/sql/{NodeData.java => NodeData.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CommonCore/SQL/src/de/steamwar/sql/{NodeData.java => NodeData.kt} (100%) diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt similarity index 100% rename from CommonCore/SQL/src/de/steamwar/sql/NodeData.java rename to CommonCore/SQL/src/de/steamwar/sql/NodeData.kt From 6ea73f4890934d9dc0407fdbbbf058fb7cd4b5e8 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 28 Oct 2025 22:25:31 +0100 Subject: [PATCH 09/32] Refactor NodeData Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/NodeData.kt | 154 +++++++----------- .../SQL/src/de/steamwar/sql/SchematicNode.kt | 2 +- .../SQL/src/de/steamwar/sql/UserConfig.kt | 6 +- .../steamwar/sql/internal/KotlinDatabase.kt | 6 +- .../src/de/steamwar/routes/Schematic.kt | 1 + 5 files changed, 70 insertions(+), 99 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt index 63d8ccaf..fd9a2446 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt @@ -17,121 +17,83 @@ * along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.sql -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.SortOrder +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.statements.api.ExposedBlob +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insertIgnore +import java.io.InputStream +import java.util.zip.GZIPInputStream -import javax.swing.plaf.nimbus.State; -import java.io.*; -import java.sql.PreparedStatement; -import java.sql.Timestamp; -import java.time.Instant; -import java.util.List; -import java.util.Optional; -import java.util.zip.GZIPInputStream; +object NodeDataTable: CompositeIdTable("NodeData") { + val nodeId = reference("NodeId", SchematicNodeTable) + val createdAt = timestamp("CreatedAt").entityId() + val nodeFormat = enumeration("NodeFormat", NodeData.SchematicFormat::class) + val schemData = blob("SchemData") -@AllArgsConstructor -@Getter -public class NodeData { - static { - new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); - new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); - new SqlTypeMapper<>(BufferedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("BufferedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); + override val primaryKey = PrimaryKey(nodeId, createdAt) - SqlTypeMapper.ordinalEnumMapper(SchematicFormat.class); + init { + addIdColumn(nodeId) } +} - private static final Table table = new Table<>(NodeData.class); +class NodeData(id: EntityID): CompositeEntity(id) { + val nodeId by NodeDataTable.nodeId + val createdAt by NodeDataTable.createdAt + val nodeFormat by NodeDataTable.nodeFormat + val schemData by NodeDataTable.schemData - private static final Statement updateDatabase = new Statement("INSERT INTO NodeData(NodeId, NodeFormat, SchemData) VALUES (?, ?, ?)", true); - private static final Statement selSchemData = new Statement("SELECT SchemData FROM NodeData WHERE NodeId = ? AND CreatedAt = ?"); - private static final Statement delete = table.delete(Table.PRIMARY); + companion object: CompositeEntityClass(NodeDataTable) { + @JvmStatic + fun getLatest(node: SchematicNode) = useDb { + find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.DESC).firstOrNull() + } - private static final SelectStatement get = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt "); - private static final Statement getRevisions = new Statement("SELECT COUNT(DISTINCT CreatedAt) as CNT FROM NodeData WHERE NodeId = ?"); - private static final SelectStatement getLatest = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt DESC LIMIT 1"); + @JvmStatic + fun get(node: SchematicNode) = useDb { + find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList() + } - public static NodeData getLatest(SchematicNode node) { - if (node.isDir()) throw new IllegalArgumentException("Node is dir"); - return Optional.ofNullable(getLatest.select(node)).orElseGet(() -> new NodeData(node.getId(), Timestamp.from(Instant.now()), SchematicFormat.MCEDIT)); - } + @JvmStatic + fun get(node: SchematicNode, revision: Int) = useDb { + find { NodeDataTable.nodeId eq node.nodeId }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList().get(revision - 1) + } - public static List get(SchematicNode node) { - return get.listSelect(node); - } + @JvmStatic + fun getRevisions(node: SchematicNode) = useDb { + count(NodeDataTable.nodeId eq node.nodeId).toInt() + } - public static NodeData get(SchematicNode node, int revision) { - return get.listSelect(node).get(revision - 1); - } - - public static int getRevisions(SchematicNode node) { - return getRevisions.select(rs -> { - if (rs.next()) { - return rs.getInt("CNT"); - } else { - return 0; + @JvmStatic + fun saveFromStream(node: SchematicNode, blob: InputStream, format: SchematicFormat) { + NodeDataTable.insertIgnore { + it[NodeDataTable.nodeId] = EntityID(node.getId(), SchematicNodeTable) + it[NodeDataTable.nodeFormat] = format + it[NodeDataTable.schemData] = ExposedBlob(blob) } - }, node); - } - - public static void saveFromStream(SchematicNode node, InputStream blob, SchematicFormat format) { - updateDatabase.update(node.getId(), format, blob); - } - - @Field(keys = {Table.PRIMARY}) - private final int nodeId; - - @Field(keys = {Table.PRIMARY}) - private Timestamp createdAt; - - @Field - public SchematicFormat nodeFormat; - - public InputStream schemData() throws IOException { - return schemData(true); - } - - public InputStream schemData(boolean decompress) throws IOException { - try { - return selSchemData.select(rs -> { - rs.next(); - InputStream schemData = rs.getBinaryStream("SchemData"); - try { - if(rs.wasNull() || schemData.available() == 0) { - throw new SecurityException("SchemData is null"); - } - if (decompress) { - return new GZIPInputStream(schemData); - } else { - return schemData; - } - } catch (IOException e) { - throw new SecurityException("SchemData is wrong", e); - } - }, nodeId, createdAt); - } catch (Exception e) { - throw new IOException(e); } } - @Deprecated - public void saveFromStream(InputStream blob, SchematicFormat newFormat) { - saveFromStream(SchematicNode.getSchematicNode(nodeId), blob, newFormat); + fun schemData(decompress: Boolean) = useDb { + schemData.inputStream.let { if(decompress) GZIPInputStream(it) else it } } - public void delete() { - delete.update(nodeId, createdAt); - } + fun schemData() = schemData(true) - @AllArgsConstructor - @Getter - public enum SchematicFormat { + override fun delete() = useDb { super.delete() } + + enum class SchematicFormat(val fileEnding: String) { MCEDIT(".schematic"), SPONGE_V2(".schem"), SPONGE_V3(".schem"); - - public final String fileEnding; } -} +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt index d1495b46..5117eb13 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt @@ -335,7 +335,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) { val members: Set by lazy { NodeMember.getNodeMembers(nodeId) } private lateinit var breadcrumbs: String - fun getFileEnding(): String = checkDir { NodeData.getLatest(this).nodeFormat.fileEnding } + fun getFileEnding(): String = checkDir { NodeData.getLatest(this)!!.nodeFormat.fileEnding } fun getId() = nodeId fun isDir() = nodeType == null diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt index 11bc2e4d..14dcd201 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt @@ -32,10 +32,14 @@ import java.util.UUID object UserConfigTable: CompositeIdTable("UserConfig") { val userId = reference("User", SteamwarUserTable) - val config = varchar("Config", 32) + val config = varchar("Config", 32).entityId() val value = text("Value", eagerLoading = true) override val primaryKey = PrimaryKey(userId, config) + + init { + addIdColumn(userId) + } } class UserConfig(id: EntityID): CompositeEntity(id) { diff --git a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt index 4da6e413..735d4e22 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt @@ -23,6 +23,7 @@ import org.intellij.lang.annotations.Language import org.jetbrains.exposed.v1.core.ColumnType import org.jetbrains.exposed.v1.core.Expression import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.StdOutSqlLogger import org.jetbrains.exposed.v1.core.statements.StatementType import org.jetbrains.exposed.v1.core.statements.api.RowApi import org.jetbrains.exposed.v1.dao.IntEntity @@ -64,7 +65,10 @@ object KotlinDatabase { fun useDb(statement: JdbcTransaction.() -> T): T { KotlinDatabase.ensureConnected() - return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db, statement) + return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db) { + addLogger(StdOutSqlLogger) + statement() + } } fun IntEntityClass.fromSql( diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index d429af5c..d1ada3fa 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -36,6 +36,7 @@ import kotlinx.serialization.Serializable import java.io.BufferedInputStream import java.io.ByteArrayInputStream import java.io.DataInputStream +import java.io.InputStream import java.security.MessageDigest import java.time.Duration import java.time.Instant From 702aa1cfa672efdef8cbf29c209a706ec19ae445 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 29 Oct 2025 17:42:29 +0100 Subject: [PATCH 10/32] Refactor CheckedSchematic and migrate to Kotlin Signed-off-by: Chaoscaot --- .../src/de/steamwar/sql/CheckedSchematic.java | 101 ------------------ .../src/de/steamwar/sql/CheckedSchematic.kt | 100 +++++++++++++++++ 2 files changed, 100 insertions(+), 101 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.java b/CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.java deleted file mode 100644 index 5a0e553c..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.sql.Timestamp; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -@AllArgsConstructor -public class CheckedSchematic { - - private static final Table table = new Table<>(CheckedSchematic.class); - private static final SelectStatement statusOfNode = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC"); - private static final SelectStatement nodeHistory = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC"); - private static final Statement insert = table.insertAll(); - - private static final SelectStatement getUnseen = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE Seen = 0 AND NodeOwner = ? ORDER BY StartTime DESC"); - private static final Statement updateSeen = new Statement("UPDATE CheckedSchematic SET Seen = ? WHERE StartTime = ? AND EndTime = ? AND NodeName = ?"); - - public static void create(SchematicNode node, int validator, Timestamp startTime, Timestamp endTime, String reason, boolean seen) { - insert.update(node.getId(), node.getOwner(), node.getName(), validator, startTime, endTime, reason, seen, node.getSchemtype().toDB().substring(1)); - } - - public static List getLastDeclinedOfNode(int node) { - return statusOfNode.listSelect(node); - } - - public static List previousChecks(SchematicNode node) { - return nodeHistory.listSelect(node.getId()); - } - - public static List getUnseen(SteamwarUser owner) { - return getUnseen.listSelect(owner); - } - - @Field(nullable = true) - private final Integer nodeId; - @Field - private final int nodeOwner; - @Field - private final String nodeName; - @Getter - @Field - private final int validator; - @Getter - @Field - private final Timestamp startTime; - @Getter - @Field - private final Timestamp endTime; - @Getter - @Field - private final String declineReason; - @Getter - @Field - private boolean seen; - @Getter - @Field - private final String nodeType; - - public int getNode() { - return nodeId; - } - - public String getSchemName() { - return nodeName; - } - - public int getSchemOwner() { - return nodeOwner; - } - - public void setSeen(boolean seen) { - this.seen = seen; - updateSeen.update(seen, startTime, endTime, nodeName); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.kt b/CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.kt new file mode 100644 index 00000000..3e51d24e --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/CheckedSchematic.kt @@ -0,0 +1,100 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.SortOrder +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.neq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insertIgnore +import java.sql.Timestamp + +object CheckedSchematicTable: CompositeIdTable("CheckedSchematic") { + val nodeId = optReference("NodeId", SchematicNodeTable) + val nodeOwner = reference("NodeOwner", SteamwarUserTable) + val nodeName = varchar("NodeName", 64).entityId() + val validator = reference("Validator", SteamwarUserTable) + val startTime = timestamp("StartTime").entityId() + val endTime = timestamp("EndTime") + val declineReason = text("DeclineReason") + val seen = bool("Seen") + val nodeType = varchar("NodeType", 16) + + init { + addIdColumn(nodeOwner) + addIdColumn(nodeName) + } +} + +class CheckedSchematic(id: EntityID): CompositeEntity(id) { + companion object: CompositeEntityClass(CheckedSchematicTable) { + @JvmStatic + fun create(node: SchematicNode, validator: Int, startTime: Timestamp, endTime: Timestamp, reason: String, seen: Boolean) = useDb { + CheckedSchematicTable.insertIgnore { + it[this.nodeId] = node.id + it[this.nodeOwner] = EntityID(node.owner, SteamwarUserTable) + it[this.nodeName] = node.name + it[this.validator] = EntityID(validator, SteamwarUserTable) + it[this.startTime] = startTime.toInstant() + it[this.endTime] = endTime.toInstant() + it[this.declineReason] = reason + it[this.seen] = seen + it[this.nodeType] = node.schemtype.toDB().substring(1) + } + } + + @JvmStatic + fun getLastDeclinedOfNode(node: Int) = useDb { + find { (CheckedSchematicTable.nodeId eq node) and (CheckedSchematicTable.declineReason neq "Prüfvorgang abgebrochen") }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList() + } + + @JvmStatic + fun previousChecks(node: SchematicNode) = useDb { + find { (CheckedSchematicTable.nodeId eq node.id) and (CheckedSchematicTable.declineReason neq "") and (CheckedSchematicTable.declineReason neq "Prüfvorgang abgebrochen") }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList() + } + + @JvmStatic + fun getUnseen(owner: SteamwarUser) = useDb { + find { (CheckedSchematicTable.nodeOwner eq owner.id) and (CheckedSchematicTable.seen eq false) }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList() + } + } + + val node by CheckedSchematicTable.nodeId.transform({ it?.let { EntityID(it, SchematicNodeTable) } }, { it?.value }) + val schemOwner by CheckedSchematicTable.nodeOwner.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + val nodeName by CheckedSchematicTable.nodeName + val schemName get() = nodeName.value + val validator by CheckedSchematicTable.validator.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + val startTimeId by CheckedSchematicTable.startTime + val startTime get() = Timestamp.from(startTimeId.value) + val endTime by CheckedSchematicTable.endTime.transform({ it.toInstant() }, { Timestamp.from(it) }) + val declineReason by CheckedSchematicTable.declineReason + private var wasSeen by CheckedSchematicTable.seen + var seen: Boolean + get() = wasSeen + set(value) = useDb { wasSeen = value } + val nodeType by CheckedSchematicTable.nodeType +} \ No newline at end of file From eea1073892c6a6b622e95ccf8fa4c52e2b8143f1 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 29 Oct 2025 23:17:17 +0100 Subject: [PATCH 11/32] Migrate Event class to Kotlin and update references across modules Signed-off-by: Chaoscaot --- CommonCore/SQL/src/de/steamwar/sql/Event.java | 125 ------------------ CommonCore/SQL/src/de/steamwar/sql/Event.kt | 123 +++++++++++++++++ .../src/de/steamwar/sql/TeamTeilnahme.java | 2 +- .../src/de/steamwar/fightsystem/Config.java | 2 +- .../lobby/particle/ParticleRequirement.java | 4 +- .../src/de/steamwar/misslewars/Config.java | 2 +- .../tntleague/config/TNTLeagueConfig.kt | 2 +- .../de/steamwar/towerrun/config/Config.java | 2 +- .../discord/listeners/DiscordTeamEvent.java | 2 +- .../src/de/steamwar/routes/Events.kt | 6 +- 10 files changed, 134 insertions(+), 136 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Event.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Event.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/Event.java b/CommonCore/SQL/src/de/steamwar/sql/Event.java deleted file mode 100644 index e65a1533..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Event.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.sql.Timestamp; -import java.time.Instant; -import java.util.List; - -@AllArgsConstructor -public class Event { - - static { - SchematicType.Normal.name(); // Ensure SchematicType is loaded. - } - - private static final Table table = new Table<>(Event.class); - - private static final SelectStatement byCurrent = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start < now() AND End > now()"); - private static final SelectStatement byId = table.select(Table.PRIMARY); - private static final SelectStatement byName = table.select("eventName"); - private static final SelectStatement byComing = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start > now()"); - private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM Event"); - - private static final Statement create = table.insertFields(true, "eventName", "deadline", "start", "end", "maximumTeamMembers", "publicSchemsOnly"); - private static final Statement update = table.update(Table.PRIMARY, "eventName", "deadline", "start", "end", "schemType", "maximumTeamMembers", "publicSchemsOnly"); - private static final Statement delete = table.delete(Table.PRIMARY); - - private static Event current = null; - - public static Event get(){ - if(current != null && current.now()) - return current; - - current = byCurrent.select(); - return current; - } - - public static List getAll(){ - return all.listSelect(); - } - - public static Event create(String eventName, Timestamp start, Timestamp end){ - return get(create.insertGetKey(eventName, start, start, end, 5, false)); - } - - public static Event get(int eventID){ - return byId.select(eventID); - } - - public static Event get(String eventName) { - return byName.select(eventName); - } - - public static List getComing() { - return byComing.listSelect(); - } - - @Getter - @Field(keys = {Table.PRIMARY}, autoincrement = true) - private final int eventID; - @Getter - @Field(keys = {"eventName"}) - private final String eventName; - @Getter - @Field - private final Timestamp deadline; - @Getter - @Field - private final Timestamp start; - @Getter - @Field - private final Timestamp end; - @Getter - @Field - private final int maximumTeamMembers; - @Field(nullable = true) - private final SchematicType schemType; - @Field - private final boolean publicSchemsOnly; - - public boolean publicSchemsOnly() { - return publicSchemsOnly; - } - - public SchematicType getSchematicType() { - return schemType; - } - - private boolean now() { - Instant now = Instant.now(); - return now.isAfter(start.toInstant()) && now.isBefore(end.toInstant()); - } - - public void update(String eventName, Timestamp deadline, Timestamp start, Timestamp end, SchematicType schemType, int maximumTeamMembers, boolean publicSchemsOnly) { - update.update(eventName, deadline, start, end, schemType, maximumTeamMembers, publicSchemsOnly, eventID); - } - - public void delete() { - delete.update(eventID); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/Event.kt b/CommonCore/SQL/src/de/steamwar/sql/Event.kt new file mode 100644 index 00000000..5ca83078 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/Event.kt @@ -0,0 +1,123 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.greater +import org.jetbrains.exposed.v1.core.lessEq +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insertAndGetId +import org.jetbrains.exposed.v1.jdbc.update +import java.sql.Timestamp +import java.time.Instant +import kotlin.math.max + +object EventTable : IntIdTable("Event", "EventId") { + val name = varchar("EventName", 100).uniqueIndex() + val deadline = timestamp("Deadline") + val start = timestamp("Start") + val end = timestamp("End") + val maxPlayers = integer("MaximumTeamMembers") + val schemType = varchar("SchemType", 16).nullable() + val publicsOnly = bool("PublicSchemsOnly") +} + +class Event(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(EventTable) { + private var current: Event? = null + + @JvmStatic + fun get(): Event? = if (current?.now() == true) { + current + } else useDb { + find { EventTable.start.lessEq(Instant.now()) and EventTable.end.greater(Instant.now()) }.firstOrNull() + ?.also { current == it } + } + + @JvmStatic + fun getAll() = useDb { all().toList() } + + @JvmStatic + fun create(name: String, start: Timestamp, end: Timestamp) = useDb { + EventTable.insertAndGetId { + it[this.name] = name + it[this.deadline] = start.toInstant() + it[this.start] = start.toInstant() + it[this.end] = end.toInstant() + it[this.maxPlayers] = 5 + it[this.publicsOnly] = false + }.let { get(it) } + } + + @JvmStatic + fun byId(id: Int) = useDb { findById(id) } + + @JvmStatic + fun get(name: String) = useDb { find { EventTable.name eq name }.firstOrNull() } + + @JvmStatic + fun getComing() = useDb { find { EventTable.start greater Instant.now() }.toList() } + } + + val eventID by EventTable.id.transform({ EntityID(it, EventTable) }, { it.value }) + var eventName by EventTable.name + private set + var deadline: Timestamp by EventTable.deadline.transform({ it.toInstant() }, { Timestamp.from(it) }) + private set + var start: Timestamp by EventTable.start.transform({ it.toInstant() }, { Timestamp.from(it) }) + private set + var end: Timestamp by EventTable.end.transform({ it.toInstant() }, { Timestamp.from(it) }) + private set + var maximumTeamMembers by EventTable.maxPlayers + private set + var schematicType by EventTable.schemType.transform({ it?.toDB() }, { it?.let { SchematicType.fromDB(it) } }) + private set + var publicSchemsOnly by EventTable.publicsOnly + private set + + fun publicSchemsOnly() = publicSchemsOnly + fun now() = Instant.now().let { it.isAfter(start.toInstant()) && it.isBefore(end.toInstant()) } + + fun update( + name: String, + deadline: Timestamp, + start: Timestamp, + end: Timestamp, + schematicType: SchematicType?, + maxPlayers: Int, + publicSchemsOnly: Boolean + ) = useDb { + this@Event.eventName = name + this@Event.deadline = deadline + this@Event.start = start + this@Event.end = end + this@Event.maximumTeamMembers = maxPlayers + this@Event.schematicType = schematicType + this@Event.publicSchemsOnly = publicSchemsOnly + } + + override fun delete() = useDb { super.delete() } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java b/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java index 499a1a66..620710ff 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java +++ b/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java @@ -65,6 +65,6 @@ public class TeamTeilnahme { } public static Set getEvents(int teamID){ - return selectEvents.listSelect(teamID).stream().map(tt -> Event.get(tt.eventId)).collect(Collectors.toSet()); // suboptimal performance (O(n) database queries) + return selectEvents.listSelect(teamID).stream().map(tt -> Event.byId(tt.eventId)).collect(Collectors.toSet()); // suboptimal performance (O(n) database queries) } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java index a5c89bca..8d2b722d 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java @@ -239,7 +239,7 @@ public class Config { LiveReplay = SpectatePort != 0; Referees = Referee.get(Config.EventKampf.getEventID()); - Event event = Event.get(EventKampf.getEventID()); + Event event = Event.byId(EventKampf.getEventID()); if(BothTeamsPublic) { OnlyPublicSchematics = true; MaximumTeamMembers = Integer.MAX_VALUE; diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java index 1ac5679a..754f5d2b 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java @@ -123,7 +123,7 @@ public interface ParticleRequirement { } static ParticleRequirement eventParticipation(int eventId) { - String eventName = Event.get(eventId).getEventName(); + String eventName = Event.byId(eventId).getEventName(); return new ParticleRequirement() { @Override public String getRequirementName(Player player) { @@ -138,7 +138,7 @@ public interface ParticleRequirement { } static ParticleRequirement eventPlacement(int eventId, int... placementTeams) { - String eventName = Event.get(eventId).getEventName(); + String eventName = Event.byId(eventId).getEventName(); Set teams = new HashSet<>(); for (int i : placementTeams) teams.add(i); return new ParticleRequirement() { diff --git a/MissileWars/src/de/steamwar/misslewars/Config.java b/MissileWars/src/de/steamwar/misslewars/Config.java index b9ebc688..eb223c5d 100644 --- a/MissileWars/src/de/steamwar/misslewars/Config.java +++ b/MissileWars/src/de/steamwar/misslewars/Config.java @@ -148,7 +148,7 @@ public class Config { EventTeamBlueID = team1.getTeamId(); EventTeamRedID = team2.getTeamId(); - Event event = Event.get(EventKampf.getEventID()); + Event event = Event.byId(EventKampf.getEventID()); if (EventTeamBlueID == 0 && EventTeamRedID == 0) { MaximumTeamMembers = Integer.MAX_VALUE; } else { diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index 3f51d535..7f0e7526 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -55,7 +55,7 @@ data class TNTLeagueConfig( if (eventFightId != null && eventFightId > 0) { eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") - event = Event.get(eventFight.eventID) + event = Event.byId(eventFight.eventID)!! eventTeamBlue = Team.get(eventFight.teamBlue) eventTeamRed = Team.get(eventFight.teamRed) diff --git a/TowerRun/src/de/steamwar/towerrun/config/Config.java b/TowerRun/src/de/steamwar/towerrun/config/Config.java index 1d262066..7a7b6795 100644 --- a/TowerRun/src/de/steamwar/towerrun/config/Config.java +++ b/TowerRun/src/de/steamwar/towerrun/config/Config.java @@ -74,7 +74,7 @@ public class Config { throw new IllegalStateException("Event not found"); } - Event event = Event.get(EVENT_FIGHT.getEventID()); + Event event = Event.byId(EVENT_FIGHT.getEventID()); EVENT_TEAM_BLUE_ID = EVENT_FIGHT.getTeamBlue(); EVENT_TEAM_RED_ID = EVENT_FIGHT.getTeamRed(); diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java index 146c06d0..8e0f3955 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java @@ -55,7 +55,7 @@ public class DiscordTeamEvent extends ListenerAdapter { return; } - Event tournament = Event.get(eventId); + Event tournament = Event.byId(eventId); if(tournament == null){ reply.system("UNKNOWN_EVENT"); return; diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt index ed5ad9ef..faeae862 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Events.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt @@ -231,7 +231,7 @@ fun Route.configureEventsRoute() { } } event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly) - call.respond(ResponseEvent(Event.get(event.eventID))) + call.respond(ResponseEvent(Event.byId(event.eventID)!!)) } delete { val id = call.parameters["id"]?.toIntOrNull() @@ -239,7 +239,7 @@ fun Route.configureEventsRoute() { call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID")) return@delete } - val event = Event.get(id) + val event = Event.byId(id) if (event == null) { call.respond(HttpStatusCode.NotFound, ResponseError("Event not found")) return@delete @@ -263,7 +263,7 @@ suspend fun ApplicationCall.receiveEvent(fieldName: String = "id"): Event? { return null } - val event = Event.get(eventId) + val event = Event.byId(eventId) if (event == null) { respond(HttpStatusCode.NotFound, ResponseError("Event not found")) return null From 4e6933f2fd5ff1cde47ea99a0cf93727253e14b6 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 30 Oct 2025 23:14:25 +0100 Subject: [PATCH 12/32] Remove Event-related SQL classes and update relevant references across modules Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/EventFight.java | 216 ------------------ .../SQL/src/de/steamwar/sql/EventFight.kt | 194 ++++++++++++++++ .../SQL/src/de/steamwar/sql/EventGroup.java | 173 -------------- .../SQL/src/de/steamwar/sql/EventGroup.kt | 151 ++++++++++++ .../src/de/steamwar/sql/EventRelation.java | 192 ---------------- .../SQL/src/de/steamwar/sql/EventRelation.kt | 146 ++++++++++++ CommonCore/SQL/src/de/steamwar/sql/Team.java | 140 ------------ CommonCore/SQL/src/de/steamwar/sql/Team.kt | 112 +++++++++ .../src/de/steamwar/sql/TeamTeilnahme.java | 2 +- .../src/de/steamwar/fightsystem/Config.java | 6 +- .../fightsystem/record/PacketProcessor.java | 2 +- .../lobby/particle/ParticleRequirement.java | 4 +- .../src/de/steamwar/misslewars/Config.java | 6 +- .../schematiccommand/parts/MemberPart.java | 4 +- .../tntleague/config/TNTLeagueConfig.kt | 6 +- .../de/steamwar/towerrun/config/Config.java | 2 +- .../steamwar/velocitycore/EventStarter.java | 4 +- .../steamwar/velocitycore/ServerStarter.java | 2 +- .../velocitycore/commands/EventCommand.java | 8 +- .../velocitycore/commands/TeamCommand.java | 34 +-- .../velocitycore/commands/TpCommand.java | 2 +- .../velocitycore/commands/WhoisCommand.java | 2 +- .../discord/channels/EventChannel.java | 4 +- .../velocitycore/listeners/ChatListener.java | 2 +- WebsiteBackend/src/de/steamwar/routes/Data.kt | 16 +- .../src/de/steamwar/routes/EventFights.kt | 6 +- .../src/de/steamwar/routes/EventGroups.kt | 4 +- .../src/de/steamwar/routes/EventReferees.kt | 6 +- .../src/de/steamwar/routes/EventRelations.kt | 12 +- .../src/de/steamwar/routes/Events.kt | 18 +- 30 files changed, 679 insertions(+), 797 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/EventFight.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/EventFight.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/EventGroup.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/EventRelation.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Team.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Team.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventFight.java b/CommonCore/SQL/src/de/steamwar/sql/EventFight.java deleted file mode 100644 index a1472918..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/EventFight.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.sql.Timestamp; -import java.util.*; - -import static java.time.temporal.ChronoUnit.SECONDS; - -@AllArgsConstructor -public class EventFight implements Comparable { - - private static final Table table = new Table<>(EventFight.class); - private static final SelectStatement byId = table.select(Table.PRIMARY); - private static final SelectStatement byGroup = new SelectStatement(table, "SELECT * FROM EventFight WHERE GroupID = ? ORDER BY StartTime ASC"); - private static final SelectStatement byGroupLast = new SelectStatement(table, "SELECT * FROM EventFight WHERE GroupID = ? ORDER BY StartTime DESC LIMIT 1"); - private static final SelectStatement allComing = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE StartTime > now() ORDER BY StartTime ASC"); - private static final SelectStatement event = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID = ? ORDER BY StartTime ASC"); - private static final SelectStatement activeFights = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID IN (SELECT EventID FROM Event WHERE Start < now() and End > now()) AND Fight IS NULL AND StartTime < now()"); - private static final Statement reschedule = table.update(Table.PRIMARY, "StartTime"); - private static final Statement setResult = table.update(Table.PRIMARY, "Ergebnis"); - private static final Statement setFight = table.update(Table.PRIMARY, "Fight"); - - private static final Statement create = table.insertFields(true, "eventID", "startTime", "spielmodus", "map", "teamBlue", "teamRed", "spectatePort"); - private static final Statement update = table.update(Table.PRIMARY, "startTime", "spielModus", "map", "teamBlue", "teamRed", "spectatePort"); - private static final Statement setGroup = table.update(Table.PRIMARY, "GroupID"); - private static final Statement delete = table.delete(Table.PRIMARY); - - @Getter - private static final Queue fights = new PriorityQueue<>(); - - public static EventFight get(int fightID) { - return byId.select(fightID); - } - - public static List get(EventGroup group) { - return byGroup.listSelect(group.getId()); - } - - public static Optional getLast(EventGroup group) { - return Optional.ofNullable(byGroupLast.select(group.getId())); - } - - public static void loadAllComingFights() { - fights.clear(); - fights.addAll(allComing.listSelect()); - } - - public static List getEvent(int eventID) { - return event.listSelect(eventID); - } - - private static List activeFightsCache = null; - - public static void clearActiveFightsCache() { - activeFightsCache = null; - } - - public static List getActiveFights() { - if (activeFightsCache == null) { - activeFightsCache = activeFights.listSelect(); - } - return activeFightsCache; - } - - public static EventFight create(int event, Timestamp from, String spielmodus, String map, int blueTeam, int redTeam, Integer spectatePort) { - return get(create.insertGetKey(event, from, spielmodus, map, blueTeam, redTeam, spectatePort)); - } - - @Getter - @Field - private final int eventID; - @Getter - @Field(keys = {Table.PRIMARY}, autoincrement = true) - private final int fightID; - @Getter - @Setter - @Field(nullable = true, def = "null") - private Integer groupId; - @Getter - @Setter - @Field - private Timestamp startTime; - @Getter - @Setter - @Field - private String spielmodus; - @Getter - @Setter - @Field - private String map; - @Getter - @Setter - @Field - private int teamBlue; - @Getter - @Setter - @Field - private int teamRed; - @Getter - @Setter - @Field(nullable = true) - private Integer spectatePort; - @Getter - @Setter - @Field(def = "1") - private int bestOf; - @Getter - @Field(def = "0") - private int ergebnis; - @Field(nullable = true) - private int fight; - - public Optional getGroup() { - return Optional.ofNullable(groupId).flatMap(EventGroup::get); - } - - public Optional getWinner() { - if(ergebnis == 0) - return Optional.empty(); - return Optional.ofNullable(ergebnis == 1 ? Team.get(teamBlue) : Team.get(teamRed)); - } - - public Optional getLosser() { - if(ergebnis == 0) - return Optional.empty(); - return Optional.ofNullable(ergebnis == 1 ? Team.get(teamRed) : Team.get(teamBlue)); - } - - public List getDependents() { - return EventRelation.getFightRelations(this); - } - - public void setErgebnis(int winner) { - this.ergebnis = winner; - setResult.update(winner, fightID); - } - - public void setFight(int fight) { - //Fight.FightID, not EventFight.FightID - this.fight = fight; - setFight.update(fight, fightID); - } - - public void setGroup(Integer group) { - setGroup.update(group, fightID); - this.groupId = group; - } - - public boolean hasFinished() { - return fight != 0 || ergebnis != 0; - } - - public void reschedule() { - startTime = Timestamp.from(new Date().toInstant().plus(30, SECONDS)); - reschedule.update(startTime, fightID); - } - - @Override - public int hashCode(){ - return fightID; - } - - @Override - public boolean equals(Object o){ - if(o == null) - return false; - if(!(o instanceof EventFight)) - return false; - return fightID == ((EventFight) o).fightID; - } - - @Override - public int compareTo(EventFight o) { - return startTime.compareTo(o.startTime); - } - - public void update(Timestamp startTime, String spielmodus, String map, int teamBlue, int teamRed, Integer spectatePort) { - update.update(startTime, spielmodus, map, teamBlue, teamRed, spectatePort, fightID); - this.startTime = startTime; - this.spielmodus = spielmodus; - this.map = map; - this.teamBlue = teamBlue; - this.teamRed = teamRed; - this.spectatePort = spectatePort; - } - - public void delete() { - delete.update(fightID); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt b/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt new file mode 100644 index 00000000..9449781c --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt @@ -0,0 +1,194 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.SortOrder +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.greater +import org.jetbrains.exposed.v1.core.greaterEq +import org.jetbrains.exposed.v1.core.inList +import org.jetbrains.exposed.v1.core.inSubQuery +import org.jetbrains.exposed.v1.core.isNull +import org.jetbrains.exposed.v1.core.less +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insertAndGetId +import org.jetbrains.exposed.v1.jdbc.select +import java.sql.Timestamp +import java.time.Instant +import java.util.Optional +import java.util.PriorityQueue +import java.util.Queue + +object EventFightTable : IntIdTable("EventFight", "FightID") { + val eventId = reference("EventID", EventTable) + val startTime = timestamp("StartTime") + val gamemode = text("Spielmodus") + val map = text("Map") + val groupId = optReference("GroupId", EventGroupTable) + val teamBlue = reference("TeamBlue", TeamTable) + val teamRed = reference("TeamRed", TeamTable) + val spectatePort = integer("SpectatePort").nullable() + val bestOf = integer("BestOf") + val ergebnis = integer("Ergebnis") + val fight = integer("Fight").entityId().nullable() +} + +class EventFight(id: EntityID) : IntEntity(id), Comparable { + companion object : IntEntityClass(EventFightTable) { + val fights: Queue = PriorityQueue() + @JvmStatic get + + @JvmStatic + fun byId(fightId: Int) = useDb { findById(fightId) } + + @JvmStatic + fun byId(group: EventGroup) = useDb { + find { EventFightTable.groupId eq group.id }.orderBy(EventFightTable.startTime to SortOrder.DESC).toList() + } + + @JvmStatic + fun getLast(group: EventGroup) = useDb { + Optional.ofNullable( + find { EventFightTable.groupId eq group.id }.orderBy(EventFightTable.startTime to SortOrder.DESC) + .firstOrNull() + ) + } + + @JvmStatic + fun loadAllComingFights() = useDb { + fights.clear() + fights.addAll(find { EventFightTable.startTime greaterEq Instant.now() }.orderBy(EventFightTable.startTime to SortOrder.ASC)) + } + + @JvmStatic + fun getEvent(eventId: Int) = useDb { + find { EventFightTable.eventId eq eventId }.orderBy(EventFightTable.startTime to SortOrder.ASC).toList() + } + + private var activeFightsCache: List? = null + + @JvmStatic + fun clearActiveFightsCache() { + activeFightsCache = null + } + + @JvmStatic + fun getActiveFights(): List { + if (activeFightsCache == null) { + activeFightsCache = useDb { + find { + EventFightTable.fight.isNull() and (EventFightTable.startTime less Instant.now()) and (EventFightTable.eventId.inSubQuery( + EventTable.select( + EventTable.id + ) + .where { (EventTable.start less Instant.now()) and (EventTable.end greater Instant.now()) })) + }.orderBy(EventFightTable.startTime to SortOrder.ASC).toList() + } + } + + return activeFightsCache!! + } + + @JvmStatic + fun create( + event: Int, + from: Timestamp, + spielmodus: String, + map: String, + blueTeam: Int, + redTeam: Int, + spectatePort: Int? + ) = useDb { + get( + EventFightTable.insertAndGetId { + it[eventId] = EntityID(event, EventTable) + it[startTime] = from.toInstant() + it[gamemode] = spielmodus + it[EventFightTable.map] = map + it[teamBlue] = EntityID(blueTeam, TeamTable) + it[teamRed] = EntityID(redTeam, TeamTable) + it[EventFightTable.spectatePort] = spectatePort + } + ) + } + } + + val fightID by EventFightTable.id.transform({ EntityID(it, EventFightTable) }, { it.value }) + var teamBlue by EventFightTable.teamBlue.transform({ EntityID(it, TeamTable) }, { it.value }) + var teamRed by EventFightTable.teamRed.transform({ EntityID(it, TeamTable) }, { it.value }) + private var fightErgebnis by EventFightTable.ergebnis + var ergebnis: Int + get() = fightErgebnis + set(value) = useDb { + fightErgebnis = value + } + var eventID by EventFightTable.eventId.transform({ EntityID(it, EventTable) }, { it.value }) + var startTime by EventFightTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) }) + var spielmodus by EventFightTable.gamemode + var map by EventFightTable.map + var groupId by EventFightTable.groupId + val group by lazy { Optional.ofNullable(groupId).map { EventGroup[it] } } + var spectatePort by EventFightTable.spectatePort + private var fightStat by EventFightTable.fight.transform({ it?.let { EntityID(it, EventFightTable) } }, { it?.value }) + var fight: Int? + get() = fightStat + set(value) = useDb { + fightStat = value + } + val dependents by lazy { useDb { EventRelation.getFightRelations(this@EventFight) } } + + val winner: Team? + get() = if (ergebnis == 1) Team[teamBlue] else if (ergebnis == 2) Team[teamRed] else null + val losser: Team? + get() = if (ergebnis == 1) Team[teamRed] else if (ergebnis == 2) Team[teamBlue] else null + + fun setGroup(group: Int?) = useDb { groupId = group?.let { EntityID(it, EventGroupTable) } } + fun hasFinished() = fight != null || ergebnis != 0 + + fun reschedule() = useDb { + startTime = Timestamp.from(Instant.now().plusSeconds(30)) + } + + override fun hashCode() = fightID + override fun equals(other: Any?) = other is EventFight && other.fightID == fightID + override fun compareTo(other: EventFight): Int = startTime.compareTo(other.startTime) + + fun update( + startTime: Timestamp, + spielmodus: String, + map: String, + teamBlue: Int, + teamRed: Int, + spectatePort: Int? + ) = useDb { + this@EventFight.startTime = startTime + this@EventFight.spielmodus = spielmodus + this@EventFight.map = map + this@EventFight.teamBlue = teamBlue + this@EventFight.teamRed = teamRed + this@EventFight.spectatePort = spectatePort + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.java b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.java deleted file mode 100644 index 68934765..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.*; -import lombok.Getter; -import lombok.Setter; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Getter -@Setter -public class EventGroup { - static { - SqlTypeMapper.ordinalEnumMapper(EventGroupType.class); - } - - private static final Table table = new Table<>(EventGroup.class); - - private static final SelectStatement get = table.select(Table.PRIMARY); - private static final SelectStatement byEvent = new SelectStatement<>(table, "SELECT * FROM EventGroup WHERE EventID = ?"); - - private static final Statement insert = table.insertFields(true, "EventID", "Name", "Type"); - private static final Statement update = table.update(Table.PRIMARY, "Name", "Type", "PointsPerWin", "PointsPerLoss", "PointsPerDraw"); - private static final Statement delete = table.delete(Table.PRIMARY); - - public static List get(Event eventID) { - return byEvent.listSelect(eventID.getEventID()); - } - - public static EventGroup create(Event event, String name, EventGroupType type) { - int key = insert.insertGetKey(event.getEventID(), name, type); - return EventGroup.get(key).get(); - } - - public static Optional get(int id) { - return Optional.ofNullable(get.select(id)); - } - - @Field(keys = Table.PRIMARY) - private final int id; - - @Field(keys = "EVENT_NAME") - private int eventID; - - @Field(keys = "EVENT_NAME") - private String name; - - @Field - private EventGroupType type; - - @Field - private int pointsPerWin; - - @Field - private int pointsPerLoss; - - @Field - private int pointsPerDraw; - - public EventGroup(int id, int eventID, String name, EventGroupType type, int pointsPerWin, int pointsPerLoss, int pointsPerDraw) { - this.id = id; - this.eventID = eventID; - this.name = name; - this.type = type; - this.pointsPerWin = pointsPerWin; - this.pointsPerLoss = pointsPerLoss; - this.pointsPerDraw = pointsPerDraw; - } - - private Map points; - - public List getFights() { - return EventFight.get(this); - } - - public Set getTeamsId() { - return getFights().stream().flatMap(fight -> Stream.of(fight.getTeamBlue(), fight.getTeamRed())) - .collect(Collectors.toSet()); - } - - public Set getTeams() { - return getTeamsId().stream().map(Team::get).collect(Collectors.toSet()); - } - - public Optional getLastFight() { - return EventFight.getLast(this); - } - - public List getDependents() { - return EventRelation.getGroupRelations(this); - } - - public Map calculatePoints() { - if (points == null) { - Map p = getTeamsId().stream().collect(Collectors.toMap(team -> team, team -> 0)); - - for (EventFight fight : getFights()) { - int blueTeamAdd = 0; - int redTeamAdd = 0; - - if (!fight.hasFinished()) { - continue; - } - - switch (fight.getErgebnis()) { - case 1: - blueTeamAdd += pointsPerWin; - redTeamAdd += pointsPerLoss; - break; - case 2: - blueTeamAdd += pointsPerLoss; - redTeamAdd += pointsPerWin; - break; - case 0: - if (fight.getFightID() != 0) { - blueTeamAdd += pointsPerDraw; - redTeamAdd += pointsPerDraw; - } - break; - } - - p.put(fight.getTeamBlue(), p.get(fight.getTeamBlue()) + blueTeamAdd); - p.put(fight.getTeamRed(), p.get(fight.getTeamRed()) + redTeamAdd); - } - - points = p.entrySet().stream().collect(Collectors.toMap(integerIntegerEntry -> Team.get(integerIntegerEntry.getKey()), Map.Entry::getValue)); - } - - return points; - } - - public void update(String name, EventGroupType type, int pointsPerWin, int pointsPerLoss, int pointsPerDraw) { - update.update(name, type, pointsPerWin, pointsPerLoss, pointsPerDraw, id); - this.name = name; - this.type = type; - this.pointsPerWin = pointsPerWin; - this.pointsPerLoss = pointsPerLoss; - this.pointsPerDraw = pointsPerDraw; - } - - public boolean needsTieBreak() { - return calculatePoints().values().stream().sorted().limit(2).distinct().count() < 2; - } - - public void delete() { - delete.update(id); - } - - public static enum EventGroupType { - GROUP_STAGE, - ELIMINATION_STAGE - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt new file mode 100644 index 00000000..a8a87094 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt @@ -0,0 +1,151 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import java.util.Optional + +object EventGroupTable : IntIdTable("EventGroup", "Id") { + val event = reference("EventID", EventTable) + val name = varchar("Name", 64) + val type = enumeration("Type", EventGroup.EventGroupType::class) + val pointsPerWin = integer("PointsPerWin") + val pointsPerLoss = integer("PointsPerLoss") + val pointsPerDraw = integer("PointsPerDraw") +} + +class EventGroup(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(EventGroupTable) { + + @JvmStatic + fun get(event: Event) = useDb { find { EventGroupTable.event eq event.id }.toList() } + + @JvmStatic + fun byId(groupId: Int) = useDb { Optional.ofNullable(findById(groupId)) } + + @JvmStatic + fun create(event: Event, name: String, type: EventGroupType) = useDb { + new { + this.eventID = event.id.value + this.groupName = name + this.groupType = type + } + } + } + + var eventID by EventGroupTable.event.transform({ EntityID(it, EventTable) }, { it.value }) + private set + private var groupName by EventGroupTable.name + private var groupType by EventGroupTable.type + private var groupPointsPerWin by EventGroupTable.pointsPerWin + private var groupPointsPerLoss by EventGroupTable.pointsPerLoss + private var groupPointsPerDraw by EventGroupTable.pointsPerDraw + val fights by lazy { useDb { EventFight.find { EventFightTable.groupId eq id }.toList() } } + val teamsId by lazy { fights.flatMap { listOf(it.teamBlue, it.teamRed) }.toSet() } + + var name: String + get() = groupName + set(value) { + groupName = value + } + var type: EventGroupType + get() = groupType + set(value) { + groupType = value + } + var pointsPerWin: Int + get() = groupPointsPerWin + set(value) { + groupPointsPerWin = value + } + var pointsPerLoss: Int + get() = groupPointsPerLoss + set(value) { + groupPointsPerLoss = value + } + var pointsPerDraw: Int + get() = groupPointsPerDraw + set(value) { + groupPointsPerDraw = value + } + val dependents by lazy { EventRelation.getGroupRelations(this) } + val lastFight by lazy { Optional.ofNullable(fights.maxByOrNull { it.startTime }) } + + fun getId() = id.value + + private var points: Map? = null + + fun calculatePoints(): Map { + if (points == null) { + val p: MutableMap = teamsId.associateWith { 0 }.toMutableMap() + + for (fight in fights) { + var blueTeamAdd = 0 + var redTeamAdd = 0 + + if (!fight.hasFinished()) { + continue + } + + when (fight.ergebnis) { + 1 -> { + blueTeamAdd += pointsPerWin + redTeamAdd += pointsPerLoss + } + 2 -> { + blueTeamAdd += pointsPerLoss + redTeamAdd += pointsPerWin + } + 0 -> if (fight.fight != null) { + blueTeamAdd += pointsPerDraw + redTeamAdd += pointsPerDraw + } + } + + p[fight.teamBlue] = p[fight.teamBlue]?.plus(blueTeamAdd) ?: blueTeamAdd + p[fight.teamRed] = p[fight.teamRed]?.plus(redTeamAdd) ?: redTeamAdd + } + + return p.mapKeys { Team.byId(it.key) }.also { points = it } + } else { + return points!! + } + } + + fun needsTieBreak() = calculatePoints().values.let { it.size == it.toSet().size } + + fun update(name: String, type: EventGroupType, pointsPerWin: Int, pointsPerLoss: Int, pointsPerDraw: Int) = useDb { + this@EventGroup.name = name + this@EventGroup.type = type + this@EventGroup.pointsPerWin = pointsPerWin + this@EventGroup.pointsPerLoss = pointsPerLoss + this@EventGroup.pointsPerDraw = pointsPerDraw + } + + enum class EventGroupType { + GROUP_STAGE, + ELIMINATION_STAGE + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.java b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.java deleted file mode 100644 index 539908de..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -@AllArgsConstructor -@Getter -@Setter -public class EventRelation { - - static { - SqlTypeMapper.ordinalEnumMapper(FightTeam.class); - SqlTypeMapper.ordinalEnumMapper(FromType.class); - } - - private static final Table table = new Table<>(EventRelation.class); - - private static final SelectStatement get = new SelectStatement<>(table, "SELECT * FROM EventRelation WHERE FromType = ? AND FromId = ?"); - private static final SelectStatement byId = new SelectStatement<>(table, "SELECT * FROM EventRelation WHERE id = ?"); - private static final SelectStatement byEvent = new SelectStatement<>(table, "SELECT ER.* FROM EventRelation ER JOIN EventFight EF ON EF.fightId = ER.fightId WHERE EF.EventID = ?"); - private static final Statement insert = table.insertFields(true, "fightId", "fightTeam", "fromType", "fromId", "fromPlace"); - private static final Statement update = table.update(Table.PRIMARY, "fromType", "fromId", "fromPlace"); - private static final Statement updateTeam = table.update(Table.PRIMARY, "fightTeam"); - private static final Statement delete = table.delete(Table.PRIMARY); - - public static List get(Event event) { - return byEvent.listSelect(event.getEventID()); - } - - public static EventRelation get(int id) { - return byId.select(id); - } - - public static List getFightRelations(EventFight fight) { - return get.listSelect(FromType.FIGHT, fight.getFightID()); - } - - public static List getGroupRelations(EventGroup group) { - return get.listSelect(FromType.GROUP, group.getId()); - } - - public static EventRelation create(EventFight fight, FightTeam fightTeam, FromType fromType, int fromId, int fromPlace) { - int id = insert.insertGetKey(fight.getFightID(), fightTeam, fromType, fromId, fromPlace); - return get(id); - } - - @Field(keys = Table.PRIMARY) - private final int id; - - @Field - private int fightId; - - @Field - private FightTeam fightTeam; - - @Field - private FromType fromType; - - @Field - private int fromId; - - @Field - private int fromPlace; - - public EventFight getFight() { - return EventFight.get(fightId); - } - - public Optional getFromFight() { - if(fromType == FromType.FIGHT) { - return Optional.of(EventFight.get(fromId)); - } else { - return Optional.empty(); - } - } - - public Optional getFromGroup() { - if(fromType == FromType.GROUP) { - return EventGroup.get(fromId); - } else { - return Optional.empty(); - } - } - - public void delete() { - delete.update(id); - } - - public void setUpdateTeam(FightTeam team) { - updateTeam.update(id, team); - this.fightTeam = team; - } - - public void setFromFight(EventFight fight, int place) { - setFrom(fight.getFightID(), place, FromType.FIGHT); - } - - public void setFromGroup(EventGroup group, int place) { - setFrom(group.getId(), place, FromType.GROUP); - } - - private void setFrom(int fightId, int place, FromType type) { - update.update(type, fightId, place, id); - this.fromType = type; - this.fromId = fightId; - this.fromPlace = place; - } - - public Optional getAdvancingTeam() { - if (fromType == FromType.FIGHT) { - if (fromPlace == 0) { - return getFromFight().flatMap(EventFight::getWinner); - } else { - return getFromFight().flatMap(EventFight::getLosser); - } - } else if (fromType == FromType.GROUP) { - return getFromGroup().map(EventGroup::calculatePoints) - .flatMap(points -> points.entrySet().stream() - .sorted(Map.Entry.comparingByValue().reversed()) - .skip(fromPlace) - .findFirst() - .map(Map.Entry::getKey)); - } else { - return Optional.empty(); - } - } - - public boolean apply() { - Optional team = getAdvancingTeam().map(Team::getTeamId); - if(!team.isPresent()) - return false; - - EventFight fight = getFight(); - if(fightTeam == FightTeam.RED) { - fight.update( - fight.getStartTime(), - fight.getSpielmodus(), - fight.getMap(), - fight.getTeamBlue(), - team.get(), - fight.getSpectatePort() - ); - } else { - fight.update( - fight.getStartTime(), - fight.getSpielmodus(), - fight.getMap(), - team.get(), - fight.getTeamRed(), - fight.getSpectatePort() - ); - } - - return true; - } - - public static enum FightTeam { - BLUE, - RED - } - - public static enum FromType { - FIGHT, - GROUP - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt new file mode 100644 index 00000000..e02119ed --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt @@ -0,0 +1,146 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.jdbc.select +import java.util.Optional + +object EventRelationTable : IntIdTable("EventRelation") { + val fightId = reference("FightId", EventFightTable) + val fightTeam = enumeration("FightTeam", EventRelation.FightTeam::class) + val fromType = enumeration("FromType", EventRelation.FromType::class) + val fromId = integer("FromId") + val fromPlace = integer("FromPlace") +} + +class EventRelation(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(EventRelationTable) { + @JvmStatic + fun get(event: Event) = useDb { + EventRelationTable.innerJoin(EventFightTable) + .select(EventRelationTable.columns) + .where { EventFightTable.eventId eq event.id } + .map { wrapRow(it) } + } + + @JvmStatic + fun byId(id: Int) = useDb { findById(id) } + + @JvmStatic + fun getFightRelations(fight: EventFight) = + useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) } } + + @JvmStatic + fun getGroupRelations(group: EventGroup) = + useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) } } + + @JvmStatic + fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb { + new { + this.fightEntityId = fight.id + this.fightTeam = fightTeam + this.fromType = fromType + this.fromId = fromId + this.fromPlace = fromPlace + } + } + } + + var fightEntityId by EventRelationTable.fightId + var fightId: Int + get() = fightEntityId.value + set(value) = useDb { fightEntityId = EntityID(value, EventFightTable) } + val fight by lazy { useDb { EventFight[fightEntityId] } } + var fightTeam by EventRelationTable.fightTeam + private set + var fromType by EventRelationTable.fromType + private set + var fromId by EventRelationTable.fromId + private set + + var fromFightId: Int? + get() = if (fromType == FromType.FIGHT) fromId else null + set(value) = useDb { + fromType = FromType.FIGHT + fromId = value!! + } + val fromFight: EventFight? + get() = fromFightId?.let { EventFight[it] } + var fromGroupId: Int? + get() = if (fromType == FromType.GROUP) fromId else null + set(value) = useDb { + fromType = FromType.GROUP + fromId = value!! + } + val fromGroup: EventGroup? + get() = fromGroupId?.let { EventGroup[it] } + var fromPlace by EventRelationTable.fromPlace + private set + + fun getId() = id.value + fun setUpdateTeam(team: FightTeam) = useDb { + fightTeam = team + } + + fun setFromFight(fight: EventFight, place: Int) = useDb { + fromType = FromType.FIGHT + fromId = fight.id.value + fromPlace = place + } + + fun setFromGroup(group: EventGroup, place: Int) = useDb { + fromType = FromType.GROUP + fromId = group.id.value + fromPlace = place + } + + fun getAdvancingTeam(): Team? = when(fromType) { + FromType.FIGHT -> if (fromPlace == 0) fromFight?.winner else fromFight?.losser + FromType.GROUP -> fromGroup?.calculatePoints()?.toList()?.sortedBy { (_, v) -> v }?.reversed()?.elementAt(fromPlace)?.first + } + + fun apply(): Boolean { + val team = getAdvancingTeam() ?: return false + + useDb { + when(fightTeam) { + FightTeam.BLUE -> fight.teamBlue = team.teamId + FightTeam.RED -> fight.teamRed = team.teamId + } + } + + return true + } + + enum class FightTeam { + BLUE, RED + } + + enum class FromType { + FIGHT, GROUP + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/Team.java b/CommonCore/SQL/src/de/steamwar/sql/Team.java deleted file mode 100644 index 71921de6..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Team.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@AllArgsConstructor -public class Team { - - private static final Map teamCache = new HashMap<>(); - - public static void clear() { - teamCache.clear(); - } - - private static final Table table = new Table<>(Team.class); - private static final SelectStatement byId = table.select(Table.PRIMARY); - private static final SelectStatement byName = new SelectStatement<>(table, "SELECT * FROM Team WHERE (lower(TeamName) = ? OR lower(TeamKuerzel) = ?) AND NOT TeamDeleted"); - private static final SelectStatement all = table.selectFields("TeamDeleted"); - private static final Statement insert = table.insertFields("TeamKuerzel", "TeamName"); - private static final Statement update = table.update(Table.PRIMARY, "TeamKuerzel", "TeamName", "TeamColor", "Address", "Port"); - private static final Statement delete = table.update(Table.PRIMARY, "TeamDeleted"); - private static final Statement getSize = new Statement("SELECT COUNT(id) FROM UserData WHERE Team = ?"); - - @Field(keys = {Table.PRIMARY}, autoincrement = true) - @Getter - private final int teamId; - @Field - @Getter - private String teamKuerzel; - @Field - @Getter - private String teamName; - @Field(def = "'8'") - @Getter - private String teamColor; - @Field(nullable = true) - @Getter - private String address; - @Field(def = "'25565'") - @Getter - private int port; - @Field(def = "0") - private boolean teamDeleted; - - public static void create(String kuerzel, String name){ - insert.update(kuerzel, name); - } - - public static Team get(int id) { - return teamCache.computeIfAbsent(id, byId::select); - } - - public static Team get(String name){ - // No cache lookup due to low frequency use - name = name.toLowerCase(); - return byName.select(name, name); - } - - public static List getAll(){ - clear(); - List teams = all.listSelect(false); - teams.forEach(team -> teamCache.put(team.getTeamId(), team)); - return teams; - } - - public List getMembers(){ - return SteamwarUser.getTeam(teamId).stream().map(SteamwarUser::getId).collect(Collectors.toList()); - } - - public int size(){ - return getSize.select(rs -> { - rs.next(); - return rs.getInt("COUNT(id)"); - }, teamId); - } - - public void disband(SteamwarUser user){ - user.setLeader(false); - delete.update(true, teamId); - teamCache.remove(teamId); - TeamTeilnahme.deleteFuture(teamId); - } - - public void setTeamKuerzel(String teamKuerzel) { - this.teamKuerzel = teamKuerzel; - updateDB(); - } - - public void setTeamName(String teamName) { - this.teamName = teamName; - updateDB(); - } - - public void setTeamColor(String teamColor) { - this.teamColor = teamColor; - updateDB(); - } - - public void setAddress(String address) { - this.address = address; - updateDB(); - } - - public void setPort(int port) { - this.port = port; - updateDB(); - } - - private void updateDB(){ - update.update(teamKuerzel, teamName, teamColor, address, port, teamId); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/Team.kt b/CommonCore/SQL/src/de/steamwar/sql/Team.kt new file mode 100644 index 00000000..87419fad --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/Team.kt @@ -0,0 +1,112 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.lowerCase +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.jdbc.select + +object TeamTable : IntIdTable("Team", "TeamID") { + val kuerzel = varchar("TeamKuerzel", 10) + val color = char("TeamColor", 1) + val name = varchar("TeamName", 16) + val deleted = bool("TeamDeleted") + val address = text("Address") + val port = ushort("Port") +} + +class Team(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(TeamTable) { + private val teamCache = mutableMapOf() + + @JvmStatic + fun clear() = teamCache.clear() + + @JvmStatic + fun byId(id: Int) = teamCache.computeIfAbsent(id) { useDb { Team[id] } } + + @JvmStatic + fun get(name: String) = useDb { find { TeamTable.name.lowerCase() eq name.lowercase() }.firstOrNull() } + + @JvmStatic + fun getAll() = useDb { all().toList() } + + @JvmStatic + fun create(kuerzel: String, name: String) = useDb { + new { + this.kuerzel = kuerzel + this.name = name + } + } + } + + val teamId by TeamTable.id.transform({ EntityID(it, TeamTable) }, { it.value }) + private var kuerzel by TeamTable.kuerzel + private var color by TeamTable.color + private var name by TeamTable.name + var deleted by TeamTable.deleted + private set + private var teamAddress by TeamTable.address + private var teamPort by TeamTable.port + val members by lazy { SteamwarUserTable.select(SteamwarUserTable.id).where { SteamwarUserTable.team eq teamId }.map { it[SteamwarUserTable.id].value } } + + fun size() = useDb { SteamwarUser.find { SteamwarUserTable.team eq teamId }.count().toInt() } + fun disband(user: SteamwarUser) = useDb { + user.team = 0 + deleted = true + teamCache.remove(teamId) + TeamTeilnahme.deleteFuture(teamId) + } + + var teamKuerzel: String + get() = kuerzel + set(value) = useDb { + kuerzel = value + } + + var teamColor: String + get() = color + set(value) = useDb { + color = value + } + + var teamName: String + get() = name + set(value) = useDb { + name = value + } + + var address: String + get() = teamAddress + set(value) = useDb { + teamAddress = value + } + + var port: Int + get() = teamPort.toInt() + set(value) = useDb { + teamPort = value.toUShort() + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java b/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java index 620710ff..d7c4c9e6 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java +++ b/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java @@ -61,7 +61,7 @@ public class TeamTeilnahme { } public static Set getTeams(int eventID){ - return selectTeams.listSelect(eventID).stream().map(tt -> Team.get(tt.teamId)).collect(Collectors.toSet()); // suboptimal performance (O(n) database queries) + return selectTeams.listSelect(eventID).stream().map(tt -> Team.byId(tt.teamId)).collect(Collectors.toSet()); // suboptimal performance (O(n) database queries) } public static Set getEvents(int teamID){ diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java index 8d2b722d..a8c8019e 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java @@ -211,15 +211,15 @@ public class Config { int eventKampfID = Integer.parseInt(System.getProperty("fightID", "0")); if(eventKampfID >= 1){ - EventKampf = EventFight.get(eventKampfID); + EventKampf = EventFight.byId(eventKampfID); if(EventKampf == null){ Bukkit.getLogger().log(Level.SEVERE, "Failed to load EventFight"); Bukkit.shutdown(); } assert EventKampf != null; - Team team1 = Team.get(EventKampf.getTeamBlue()); - Team team2 = Team.get(EventKampf.getTeamRed()); + Team team1 = Team.byId(EventKampf.getTeamBlue()); + Team team2 = Team.byId(EventKampf.getTeamRed()); if(team1 == null || team2 == null){ Bukkit.getLogger().log(Level.SEVERE, "Failed to load Team"); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java index 26ea3d58..cbb79a5e 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java @@ -549,7 +549,7 @@ public class PacketProcessor implements Listener { } private void pasteForTeam(int teamId, FightTeam fightTeam){ - Team team = Team.get(teamId); + Team team = Team.byId(teamId); fightTeam.setPrefixAndName("§" + team.getTeamColor(), team.getTeamKuerzel()); fightTeam.pasteTeamName(); } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java index 754f5d2b..f0e82439 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java @@ -108,7 +108,7 @@ public interface ParticleRequirement { static ParticleRequirement specificTeam(int teamId) { if (teamId == 0) return NO_REQUIRMENT; - String teamKuerzel = Team.get(teamId).getTeamKuerzel(); + String teamKuerzel = Team.byId(teamId).getTeamKuerzel(); return new ParticleRequirement() { @Override public String getRequirementName(Player player) { @@ -216,7 +216,7 @@ public interface ParticleRequirement { static ParticleRequirement easterEventSpecificTeam(int teamId) { if (teamId == 0) return NO_REQUIRMENT; - String teamKuerzel = Team.get(teamId).getTeamKuerzel(); + String teamKuerzel = Team.byId(teamId).getTeamKuerzel(); return new ParticleRequirement() { @Override public String getRequirementName(Player player) { diff --git a/MissileWars/src/de/steamwar/misslewars/Config.java b/MissileWars/src/de/steamwar/misslewars/Config.java index eb223c5d..586db3b2 100644 --- a/MissileWars/src/de/steamwar/misslewars/Config.java +++ b/MissileWars/src/de/steamwar/misslewars/Config.java @@ -124,15 +124,15 @@ public class Config { EventKampfID = Integer.parseInt(System.getProperty("fightID", "0")); if (EventKampfID >= 1) { - EventKampf = EventFight.get(EventKampfID); + EventKampf = EventFight.byId(EventKampfID); if (EventKampf == null) { Bukkit.getLogger().log(Level.SEVERE, "Failed to load EventFight"); Bukkit.shutdown(); } assert EventKampf != null; - Team team1 = Team.get(EventKampf.getTeamBlue()); - Team team2 = Team.get(EventKampf.getTeamRed()); + Team team1 = Team.byId(EventKampf.getTeamBlue()); + Team team2 = Team.byId(EventKampf.getTeamRed()); if (team1 == null || team2 == null) { Bukkit.getLogger().log(Level.SEVERE, "Failed to load Team"); diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java index 751e1c9b..38c4d202 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/parts/MemberPart.java @@ -117,7 +117,7 @@ public class MemberPart extends SWCommand { @Register("addteam") public void addTeam(Player player, @Validator("isOwnerValidator") SchematicNode node) { SteamwarUser user = getUser(player); - Team team = Team.get(user.getTeam()); + Team team = Team.byId(user.getTeam()); if (team == null || team.getTeamId() == 0) { SchematicSystem.MESSAGE.send("COMMAND_ADD_TEAM_NOT_IN_TEAM", player); return; @@ -129,7 +129,7 @@ public class MemberPart extends SWCommand { @Register("delteam") public void remTeam(Player player, @Validator("isOwnerValidator") SchematicNode node) { SteamwarUser user = getUser(player); - Team team = Team.get(user.getTeam()); + Team team = Team.byId(user.getTeam()); if (team == null || team.getTeamId() == 0) { SchematicSystem.MESSAGE.send("COMMAND_DEL_TEAM_NOT_IN_TEAM", player); return; diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index 7f0e7526..70b52169 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -53,12 +53,12 @@ data class TNTLeagueConfig( init { if (eventFightId != null && eventFightId > 0) { - eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") + eventFight = EventFight.byId(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") event = Event.byId(eventFight.eventID)!! - eventTeamBlue = Team.get(eventFight.teamBlue) - eventTeamRed = Team.get(eventFight.teamRed) + eventTeamBlue = Team.byId(eventFight.teamBlue) + eventTeamRed = Team.byId(eventFight.teamRed) blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage("PLAIN_STRING", "§${eventTeamBlue.teamColor}${eventTeamBlue.teamName}"), eventTeamBlue.teamColor[0]) redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage("PLAIN_STRING", "§${eventTeamRed.teamColor}${eventTeamRed.teamName}"), eventTeamRed.teamColor[0]) diff --git a/TowerRun/src/de/steamwar/towerrun/config/Config.java b/TowerRun/src/de/steamwar/towerrun/config/Config.java index 7a7b6795..6e4d4f5f 100644 --- a/TowerRun/src/de/steamwar/towerrun/config/Config.java +++ b/TowerRun/src/de/steamwar/towerrun/config/Config.java @@ -67,7 +67,7 @@ public class Config { EVENT_KAMPF_ID = Integer.parseInt(System.getProperty("fightID", "0")); if (event()) { - EVENT_FIGHT = EventFight.get(EVENT_KAMPF_ID); + EVENT_FIGHT = EventFight.byId(EVENT_KAMPF_ID); if (EVENT_FIGHT == null) { Bukkit.shutdown(); diff --git a/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java b/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java index b3419a1c..eb0ee02c 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/EventStarter.java @@ -64,8 +64,8 @@ public class EventStarter { EventFight next; while((next = nextFight(fights)) != null){ - Team blue = Team.get(next.getTeamBlue()); - Team red = Team.get(next.getTeamRed()); + Team blue = Team.byId(next.getTeamBlue()); + Team red = Team.byId(next.getTeamRed()); //Don't start EventServer if not the event bungee String command; diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index 3b56256a..3ea195cd 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -110,7 +110,7 @@ public class ServerStarter { fightMap = eventFight.getMap(); gameMode = eventFight.getSpielmodus(); - String serverName = Team.get(eventFight.getTeamBlue()).getTeamKuerzel() + "_vs_" + Team.get(eventFight.getTeamRed()).getTeamKuerzel(); + String serverName = Team.byId(eventFight.getTeamBlue()).getTeamKuerzel() + "_vs_" + Team.byId(eventFight.getTeamRed()).getTeamKuerzel(); serverNameProvider = port -> serverName; worldName = serverToWorldName(serverName + eventFight.getStartTime().toLocalDateTime().format(DateTimeFormatter.ISO_TIME)); return this; diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/EventCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/EventCommand.java index 04755885..57cedf3a 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/EventCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/EventCommand.java @@ -87,8 +87,8 @@ public class EventCommand extends SWCommand { DateTimeFormatter format = DateTimeFormatter.ofPattern(sender.parseToPlain("EVENT_TIME_FORMAT")); for (EventFight fight : EventFight.getEvent(currentEvent.getEventID())) { - Team blue = Team.get(fight.getTeamBlue()); - Team red = Team.get(fight.getTeamRed()); + Team blue = Team.byId(fight.getTeamBlue()); + Team red = Team.byId(fight.getTeamRed()); StringBuilder fline = new StringBuilder(sender.parseToLegacy("EVENT_CURRENT_FIGHT", fight.getStartTime().toLocalDateTime().format(format), blue.getTeamColor(), blue.getTeamKuerzel(), red.getTeamColor(), red.getTeamKuerzel())); if (fight.hasFinished()) { @@ -125,7 +125,7 @@ public class EventCommand extends SWCommand { @Override public Team map(Chatter sender, PreviousArguments previousArguments, String s) { if ("PUB".equalsIgnoreCase(s) || "public".equalsIgnoreCase(s)) { - return Team.get(0); + return Team.byId(0); } return Team.get(s); } @@ -137,7 +137,7 @@ public class EventCommand extends SWCommand { for (EventFight fight : EventFight.getEvent(currentEvent.getEventID())) { if (fight.hasFinished()) continue; teamMapper.apply(fight).forEach(integer -> { - Team team = Team.get(integer); + Team team = Team.byId(integer); teams.add(team.getTeamName()); teams.add(team.getTeamKuerzel()); }); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java index 3606348b..9fce599b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java @@ -83,7 +83,7 @@ public class TeamCommand extends SWCommand { @Register(value = "create", description = "TEAM_CREATE_USAGE") public void create(@Validator("isNotInTeam") Chatter sender, @Length(min = 2, max = 4) @ErrorMessage("TEAM_KUERZEL_LENGTH") String kuerzel, @Length(min = 4, max = 15) @ErrorMessage("TEAM_NAME_LENGTH") String name){ SteamwarUser user = sender.user(); - Team team = Team.get(user.getTeam()); + Team team = Team.byId(user.getTeam()); if(checkTeamKuerzel(sender, team, kuerzel) || checkTeamName(sender, team, name)) return; @@ -116,7 +116,7 @@ public class TeamCommand extends SWCommand { sender.system("TEAM_JOIN_USAGE"); StringBuilder sb = new StringBuilder(); for(int inv : invs){ - Team team = Team.get(inv); + Team team = Team.byId(inv); sb.append(team.getTeamName()).append(" "); } sender.system("TEAM_JOIN_INVITED", sb.toString()); @@ -124,7 +124,7 @@ public class TeamCommand extends SWCommand { } for(int inv : invs){ - Team team = Team.get(inv); + Team team = Team.byId(inv); if(team.getTeamKuerzel().equalsIgnoreCase(args[0]) || team.getTeamName().equalsIgnoreCase(args[0])){ t = inv; break; @@ -139,13 +139,13 @@ public class TeamCommand extends SWCommand { user.setTeam(t); teamInvitations.remove(user.getId()); - sender.system("TEAM_JOIN_JOINED", Team.get(t).getTeamName()); + sender.system("TEAM_JOIN_JOINED", Team.byId(t).getTeamName()); } @Register("stepback") public void stepBack(@Validator("isLeader") Chatter sender) { SteamwarUser user = sender.user(); - Team team = Team.get(user.getTeam()); + Team team = Team.byId(user.getTeam()); if(noRemainingLeaders(team, user)){ sender.system("TEAM_OTHER_LEADER_REQUIRED"); @@ -159,7 +159,7 @@ public class TeamCommand extends SWCommand { @Register("leave") public void leave(@Validator("isInTeam") Chatter sender) { SteamwarUser user = sender.user(); - Team team = Team.get(user.getTeam()); + Team team = Team.byId(user.getTeam()); int teamSize = team.size(); if(teamSize > 1 && user.isLeader() && noRemainingLeaders(team, user)) { @@ -182,7 +182,7 @@ public class TeamCommand extends SWCommand { @Register(value = "invite", description = "TEAM_INVITE_USAGE") public void invite(@Validator("isLeader") Chatter sender, @ErrorMessage("TEAM_INVITE_NO_PLAYER") SteamwarUser target){ - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if(notDuringEvent(sender)) return; @@ -205,7 +205,7 @@ public class TeamCommand extends SWCommand { @Register(value = "remove", description = "TEAM_REMOVE_USAGE") public void remove(@Validator("isLeader") Chatter sender, @ErrorMessage("TEAM_REMOVE_NOT_PLAYER") @Mapper("memberList") SteamwarUser target){ - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if (target.isLeader()) { sender.system("TEAM_REMOVE_NOT_LEADER"); @@ -239,7 +239,7 @@ public class TeamCommand extends SWCommand { @Override public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { - return Team.get(sender.user().getTeam()).getMembers().stream() + return Team.byId(sender.user().getTeam()).getMembers().stream() .map(SteamwarUser::byId) .map(SteamwarUser::getUserName) .toList(); @@ -249,7 +249,7 @@ public class TeamCommand extends SWCommand { @Register(value = "changekurzel", description = "TEAM_KUERZEL_USAGE") public void changekuerzel(@Validator("isLeader") Chatter sender, @Length(min = 2, max = 4) @ErrorMessage("TEAM_KUERZEL_LENGTH") String kuerzel){ - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if(notDuringEvent(sender)) return; @@ -263,7 +263,7 @@ public class TeamCommand extends SWCommand { @Register(value = "changename", description = "TEAM_NAME_USAGE") public void changename(@Validator("isLeader") Chatter sender, @Length(min = 4, max = 15) @ErrorMessage("TEAM_NAME_LENGTH") String name){ - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if(notDuringEvent(sender)) return; @@ -291,7 +291,7 @@ public class TeamCommand extends SWCommand { @Register("info") public void info(@Validator("isInTeam") Chatter sender){ - info(sender, Team.get(sender.user().getTeam())); + info(sender, Team.byId(sender.user().getTeam())); } @Register(value = "info", description = "TEAM_INFO_USAGE") @@ -371,7 +371,7 @@ public class TeamCommand extends SWCommand { @Register("event") public void event(@Validator("isInTeam") Chatter sender) { - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); sender.system("TEAM_EVENT_USAGE"); Set events = TeamTeilnahme.getEvents(team.getTeamId()); @@ -385,7 +385,7 @@ public class TeamCommand extends SWCommand { @Register("event") public void event(@Validator("isLeader") Chatter sender, Event event){ - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if(notDuringEvent(sender)) return; @@ -409,7 +409,7 @@ public class TeamCommand extends SWCommand { @Register("tp") public void tp(@Validator("isInTeam") PlayerChatter sender) { - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); tp(sender, team); } @@ -450,7 +450,7 @@ public class TeamCommand extends SWCommand { @Register(value = "server", description = "TEAM_SERVER_USAGE") public void server(@Validator("isLeader") Chatter sender, String server, @Min(intValue = 1) @Max(intValue = 65535) @ErrorMessage("TEAM_SERVER_PORT_INVALID") int port){ - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if (PunishmentCommand.isPunishedWithMessage(sender, Punishment.PunishmentType.NoTeamServer)) { return; } @@ -508,7 +508,7 @@ public class TeamCommand extends SWCommand { @Register("color") @Register("changecolor") public void changeColor(@Validator("isLeader") PlayerChatter sender) { - Team team = Team.get(sender.user().getTeam()); + Team team = Team.byId(sender.user().getTeam()); if(notDuringEvent(sender)) return; diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TpCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TpCommand.java index ea42b271..107e700f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/TpCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TpCommand.java @@ -87,7 +87,7 @@ public class TpCommand extends SWCommand { } if (Event.get() != null) { EventStarter.getEventServer().keySet().forEach(teamId -> { - Team team = Team.get(teamId); + Team team = Team.byId(teamId); list.add(team.getTeamName()); list.add(team.getTeamKuerzel()); }); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java index 1abb69d2..4d096b3f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java @@ -63,7 +63,7 @@ public class WhoisCommand extends SWCommand { public void whois(Chatter sender, SteamwarUser user, WhoisParameterTypes... parameters) { EnumSet parameterTypes = parameters.length == 0 ? EnumSet.noneOf(WhoisParameterTypes.class) : EnumSet.copyOf(Arrays.asList(parameters)); - Team team = Team.get(user.getTeam()); + Team team = Team.byId(user.getTeam()); sender.system("WHOIS_USERNAME", user.getUserName()); sender.system("WHOIS_PREFIX", user.prefix().getColorCode() + user.prefix().getChatPrefix()); diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/EventChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/EventChannel.java index a7f398b9..1d19dab0 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/EventChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/EventChannel.java @@ -96,8 +96,8 @@ public class EventChannel { Instant now = Instant.now(); EventFight.getEvent(event.getEventID()).forEach(eventFight -> { - Team teamBlue = Team.get(eventFight.getTeamBlue()); - Team teamRed = Team.get(eventFight.getTeamRed()); + Team teamBlue = Team.byId(eventFight.getTeamBlue()); + Team teamRed = Team.byId(eventFight.getTeamRed()); if (eventFight.getStartTime().toLocalDateTime().getDayOfYear() != LocalDate.now().getDayOfYear()) { return; diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java index 02e5cc3d..3ab11933 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java @@ -247,7 +247,7 @@ public class ChatListener extends BasicListener { sender, msgReceiver == null ? receiver : msgReceiver, highlightMentions(message, chatColorCode, receiver), - sender.getTeam() == 0 ? "" : "§" + Team.get(sender.getTeam()).getTeamColor() + Team.get(sender.getTeam()).getTeamKuerzel() + " ", + sender.getTeam() == 0 ? "" : "§" + Team.byId(sender.getTeam()).getTeamColor() + Team.byId(sender.getTeam()).getTeamKuerzel() + " ", UserElo.getEmblem(sender, rankedModes), prefix.getColorCode(), prefix.getChatPrefix().length() == 0 ? "§f" : prefix.getChatPrefix() + " ", diff --git a/WebsiteBackend/src/de/steamwar/routes/Data.kt b/WebsiteBackend/src/de/steamwar/routes/Data.kt index a638a04a..5f2ce465 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Data.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Data.kt @@ -44,11 +44,7 @@ data class ResponseSchematicType(val name: String, val db: String) @Serializable data class ResponseUser(val name: String, val uuid: String, val prefix: String, val perms: List) { - constructor(user: SteamwarUser) : this(user.userName, user.uuid.toString(), user.prefix().chatPrefix, user.perms().filter { !it.name.startsWith("PREFIX_") }.map { it.name }) { - synchronized(cache) { - cache[user.getId()] = this - } - } + private constructor(user: SteamwarUser) : this(user.userName, user.uuid.toString(), user.prefix().chatPrefix, user.perms().filter { !it.name.startsWith("PREFIX_") }.map { it.name }) companion object { private val cache = mutableMapOf() @@ -59,6 +55,10 @@ data class ResponseUser(val name: String, val uuid: String, val prefix: String, } } + fun get(user: SteamwarUser): ResponseUser = synchronized(cache) { + return cache[user.getId()] ?: ResponseUser(user).also { cache[user.getId()] = it } + } + fun clearCache() { synchronized(cache) { cache.clear() @@ -75,7 +75,7 @@ fun Route.configureDataRoutes() { permission = UserPerm.MODERATION } get("/users") { - call.respond(SteamwarUser.all().map { ResponseUser(it) }) + call.respond(SteamwarUser.all().map { ResponseUser.get(it) }) } get("/teams") { call.respond(Team.getAll().map { ResponseTeam(it) }) @@ -118,7 +118,7 @@ fun Route.configureDataRoutes() { listOf(UserPerm.PREFIX_ADMIN, UserPerm.PREFIX_DEVELOPER, UserPerm.PREFIX_MODERATOR, UserPerm.PREFIX_SUPPORTER, UserPerm.PREFIX_BUILDER) .associateWith { SteamwarUser.getUsersWithPerm(it) } .mapKeys { UserPerm.prefixes[it.key]!!.chatPrefix } - .mapValues { it.value.map { ResponseUser(it) } } + .mapValues { it.value.map { ResponseUser.get(it) } } ) } get("/skin/{uuid}") { @@ -137,7 +137,7 @@ fun Route.configureDataRoutes() { route("/me") { install(SWPermissionCheck) get { - call.respond(ResponseUser(call.principal()!!.user)) + call.respond(ResponseUser.get(call.principal()!!.user)) } } } diff --git a/WebsiteBackend/src/de/steamwar/routes/EventFights.kt b/WebsiteBackend/src/de/steamwar/routes/EventFights.kt index fc2ab7c0..82569d40 100644 --- a/WebsiteBackend/src/de/steamwar/routes/EventFights.kt +++ b/WebsiteBackend/src/de/steamwar/routes/EventFights.kt @@ -47,8 +47,8 @@ data class ResponseEventFight( eventFight.fightID, eventFight.spielmodus, eventFight.map, - ResponseTeam(Team.get(eventFight.teamBlue)), - ResponseTeam(Team.get(eventFight.teamRed)), + ResponseTeam(Team.byId(eventFight.teamBlue)), + ResponseTeam(Team.byId(eventFight.teamRed)), eventFight.startTime.time, eventFight.ergebnis, eventFight.spectatePort, @@ -162,7 +162,7 @@ suspend fun ApplicationCall.receiveFight(fieldName: String = "fight"): EventFigh return null } - val fight = EventFight.get(fightId) + val fight = EventFight.byId(fightId) if (fight == null) { respond(HttpStatusCode.NotFound, ResponseError("Fight not found")) return null diff --git a/WebsiteBackend/src/de/steamwar/routes/EventGroups.kt b/WebsiteBackend/src/de/steamwar/routes/EventGroups.kt index 38260e74..f784788d 100644 --- a/WebsiteBackend/src/de/steamwar/routes/EventGroups.kt +++ b/WebsiteBackend/src/de/steamwar/routes/EventGroups.kt @@ -66,7 +66,7 @@ fun Route.configureEventGroups() { val pointsPerLoss = updateEventGroup.pointsPerLoss ?: group.pointsPerLoss val pointsPerDraw = updateEventGroup.pointsPerDraw ?: group.pointsPerDraw group.update(name, type, pointsPerWin, pointsPerLoss, pointsPerDraw) - call.respond(ResponseGroups(EventGroup.get(group.id).orElse(null) ?: return@put)) + call.respond(ResponseGroups(EventGroup.byId(group.getId()).orElse(null) ?: return@put)) } delete { val group = call.receiveEventGroup() ?: return@delete @@ -84,7 +84,7 @@ suspend fun ApplicationCall.receiveEventGroup(): EventGroup? { return null } - val group = EventGroup.get(groupId).orElse(null) + val group = EventGroup.byId(groupId).orElse(null) if (group == null) { respond(HttpStatusCode.NotFound) return null diff --git a/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt b/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt index 0c8bbf3b..4997b1fa 100644 --- a/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt +++ b/WebsiteBackend/src/de/steamwar/routes/EventReferees.kt @@ -31,7 +31,7 @@ fun Route.configureEventRefereesRouting() { route("/referees") { get { val event = call.receiveEvent() ?: return@get - call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }) + call.respond(Referee.get(event.eventID).map { ResponseUser.get(SteamwarUser.byId(it)!!) }) } put { val event = call.receiveEvent() ?: return@put @@ -39,7 +39,7 @@ fun Route.configureEventRefereesRouting() { referees.forEach { Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId()) } - call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }) + call.respond(Referee.get(event.eventID).map { ResponseUser.get(SteamwarUser.byId(it)!!) }) } delete { val event = call.receiveEvent() ?: return@delete @@ -47,7 +47,7 @@ fun Route.configureEventRefereesRouting() { referees.forEach { Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it))!!.getId()) } - call.respond(Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }) + call.respond(Referee.get(event.eventID).map { ResponseUser.get(SteamwarUser.byId(it)!!) }) } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/EventRelations.kt b/WebsiteBackend/src/de/steamwar/routes/EventRelations.kt index c8af5866..83c4e505 100644 --- a/WebsiteBackend/src/de/steamwar/routes/EventRelations.kt +++ b/WebsiteBackend/src/de/steamwar/routes/EventRelations.kt @@ -48,11 +48,11 @@ fun Route.configureEventRelations() { post { val create = call.receive() - val fight = EventFight.get(create.fightId) ?: return@post call.respond(HttpStatusCode.NotFound) + val fight = EventFight.byId(create.fightId) ?: return@post call.respond(HttpStatusCode.NotFound) when (create.fromType) { - EventRelation.FromType.FIGHT -> EventFight.get(create.fromId) ?: return@post call.respond(HttpStatusCode.BadRequest) - EventRelation.FromType.GROUP -> EventGroup.get(create.fromId) ?: return@post call.respond(HttpStatusCode.BadRequest) + EventRelation.FromType.FIGHT -> EventFight.byId(create.fromId) ?: return@post call.respond(HttpStatusCode.BadRequest) + EventRelation.FromType.GROUP -> EventGroup.byId(create.fromId) ?: return@post call.respond(HttpStatusCode.BadRequest) } val relation = EventRelation.create(fight, create.team, create.fromType, create.fromId, create.fromPlace) @@ -70,10 +70,10 @@ fun Route.configureEventRelations() { update.from?.let { when(it.fromType) { - EventRelation.FromType.FIGHT -> relation.setFromFight(EventFight.get(it.fromId) ?: return@put call.respond(HttpStatusCode.BadRequest), + EventRelation.FromType.FIGHT -> relation.setFromFight(EventFight.byId(it.fromId) ?: return@put call.respond(HttpStatusCode.BadRequest), it.fromPlace ) - EventRelation.FromType.GROUP -> relation.setFromGroup(EventGroup.get(it.fromId).orElse(null) ?: return@put call.respond(HttpStatusCode.BadRequest), + EventRelation.FromType.GROUP -> relation.setFromGroup(EventGroup.byId(it.fromId).orElse(null) ?: return@put call.respond(HttpStatusCode.BadRequest), it.fromPlace ) } @@ -99,7 +99,7 @@ suspend fun ApplicationCall.receiveEventRelation(): EventRelation? { return null } - val relation = EventRelation.get(relationId) + val relation = EventRelation.byId(relationId) if (relation == null) { respond(HttpStatusCode.NotFound) return null diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt index faeae862..e82fc495 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Events.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt @@ -51,7 +51,7 @@ data class ResponseGroups( val points: Map ) { constructor(group: EventGroup, short: Boolean = false) : this( - group.id, + group.getId(), group.name, group.pointsPerWin, group.pointsPerLoss, @@ -71,12 +71,12 @@ data class ResponseRelation( val fromPlace: Int ) { constructor(relation: EventRelation) : this( - relation.id, + relation.getId(), relation.fightId, relation.fightTeam, relation.fromType, - relation.fromFight.map { ResponseEventFight(it) }.orElse(null), - relation.fromGroup.map { ResponseGroups(it) }.orElse(null), + relation.fromFight?.let { ResponseEventFight(it) }, + relation.fromGroup?.let { ResponseGroups(it) }, relation.fromPlace ) } @@ -118,7 +118,7 @@ data class ExtendedResponseEvent( TeamTeilnahme.getTeams(event.eventID).map { ResponseTeam(it) }, EventGroup.get(event).map { ResponseGroups(it) }, EventFight.getEvent(event.eventID).map { ResponseEventFight(it) }, - Referee.get(event.eventID).map { ResponseUser(SteamwarUser.byId(it)!!) }, + Referee.get(event.eventID).map { ResponseUser.get(SteamwarUser.byId(it)!!) }, EventRelation.get(event).map { ResponseRelation(it) } ) } @@ -176,8 +176,8 @@ fun Route.configureEventsRoute() { csv.append(arrayOf("Start", "BlueTeam", "RedTeam", "WinnerTeam", "Group").joinToString(",")) fights.forEach { csv.appendLine() - val blue = Team.get(it.teamBlue) - val red = Team.get(it.teamRed) + val blue = Team.byId(it.teamBlue) + val red = Team.byId(it.teamRed) val winner = when (it.ergebnis) { 1 -> blue.teamName 2 -> red.teamName @@ -187,8 +187,8 @@ fun Route.configureEventsRoute() { csv.append( arrayOf( it.startTime.toString(), - Team.get(it.teamBlue).teamName, - Team.get(it.teamRed).teamName, + Team.byId(it.teamBlue).teamName, + Team.byId(it.teamRed).teamName, winner, it.group.map { it.name }.orElse("Ungrouped") ).joinToString(",") From 0fbbcdaceaf296b62aa2dd0e816fadccbf31e451 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 1 Nov 2025 13:52:26 +0100 Subject: [PATCH 13/32] Migrate Fight, FightPlayer, and SchematicType classes to Kotlin and remove old Java implementations. Update references across modules. Signed-off-by: Chaoscaot --- CommonCore/SQL/src/de/steamwar/sql/Fight.java | 134 --------------- CommonCore/SQL/src/de/steamwar/sql/Fight.kt | 155 ++++++++++++++++++ .../SQL/src/de/steamwar/sql/FightPlayer.java | 65 -------- .../SQL/src/de/steamwar/sql/FightPlayer.kt | 80 +++++++++ .../SQL/src/de/steamwar/sql/SchematicNode.kt | 2 +- .../src/de/steamwar/sql/SchematicType.java | 143 ---------------- .../SQL/src/de/steamwar/sql/SchematicType.kt | 107 ++++++++++++ 7 files changed, 343 insertions(+), 343 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Fight.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Fight.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/FightPlayer.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/FightPlayer.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/SchematicType.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/Fight.java b/CommonCore/SQL/src/de/steamwar/sql/Fight.java deleted file mode 100644 index 8b589aaf..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Fight.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@AllArgsConstructor -public class Fight { - - private static final Table table = new Table<>(Fight.class); - private static final SelectStatement getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?"); - private static final SelectStatement getById = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId WHERE FightId = ?"); - private static final Statement insert = table.insertFields(true, "GameMode", "Server", "StartTime", "Duration", "BlueLeader", "RedLeader", "BlueSchem", "RedSchem", "Win", "WinCondition"); - private static final Statement updateReplayAvailable = table.update(Table.PRIMARY, "ReplayAvailable"); - - public static List getPage(int page, int elementsPerPage) { - List fights = getPage.listSelect(page * elementsPerPage, elementsPerPage); - - List fightPlayers = FightPlayer.batchGet(fights.stream().map(f -> f.fightID)); - for(Fight fight : fights) { - fight.initPlayers(fightPlayers); - } - - SteamwarUser.batchCache(fightPlayers.stream().map(FightPlayer::getUserID).collect(Collectors.toSet())); - return fights; - } - - public static Fight getById(int fightID) { - return getById.select(fightID); - } - - public static int create(String gamemode, String server, Timestamp starttime, int duration, int blueleader, int redleader, Integer blueschem, Integer redschem, int win, String wincondition){ - return insert.insertGetKey(gamemode, server, starttime, duration, blueleader, redleader, blueschem, redschem, win, wincondition); - } - - public static void markReplayAvailable(int fightID) { - updateReplayAvailable.update(true, fightID); - } - - @Getter - @Field(keys = {Table.PRIMARY}, autoincrement = true) - private final int fightID; - @Field - private final String gameMode; - @Getter - @Field - private final String server; - @Getter - @Field - private final Timestamp startTime; - @Field - private final int duration; - @Field - private final int blueLeader; - @Field - private final int redLeader; - @Field(nullable = true) - private final Integer blueSchem; - @Field(nullable = true) - private final Integer redSchem; - @Getter - @Field - private final int win; - @Field - private final String wincondition; - @Field - private final boolean replayAvailable; - @Field // Virtual field for easy select - private final boolean replayAllowed; - - @Getter - private final List bluePlayers = new ArrayList<>(); - @Getter - private final List redPlayers = new ArrayList<>(); - - public SchematicType getSchemType() { - return SchematicType.fromDB(gameMode); - } - - public SteamwarUser getBlueLeader() { - return SteamwarUser.byId(blueLeader); - } - - public SteamwarUser getRedLeader() { - return SteamwarUser.byId(redLeader); - } - - public boolean replayAllowed() { - return replayExists() && replayAllowed; - } - - public boolean replayExists() { - return getSchemType() != null && replayAvailable; - } - - private void initPlayers(List fightPlayers) { - for(FightPlayer fp : fightPlayers) { - if(fp.getFightID() != fightID) - continue; - - if(fp.getTeam() == 1) - bluePlayers.add(fp); - else - redPlayers.add(fp); - } - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/Fight.kt b/CommonCore/SQL/src/de/steamwar/sql/Fight.kt new file mode 100644 index 00000000..9ea72b35 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/Fight.kt @@ -0,0 +1,155 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.IntegerColumnType +import org.jetbrains.exposed.v1.core.ReferenceOption +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insertAndGetId +import org.jetbrains.exposed.v1.jdbc.update +import java.sql.Timestamp + +object FightTable : IntIdTable("Fight", "FightId") { + val gamemode = varchar("Gamemode", 30) + val server = text("Server") + val startTime = timestamp("StartTime") + val duration = integer("Duration") + val blueLeader = reference("BlueLeader", SteamwarUserTable) + val redLeader = reference("RedLeader", SteamwarUserTable) + val blueSchem = optReference("BlueSchem", SchematicNodeTable, onDelete = ReferenceOption.SET_NULL) + val redSchem = optReference("RedSchem", SchematicNodeTable, onDelete = ReferenceOption.SET_NULL) + val win = integer("Win") + val winCondition = varchar("WinCondition", 100) + val replayAvailable = bool("ReplayAvailable") +} + +class Fight(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(FightTable) { + @JvmStatic + fun getById(id: Int) = useDb { get(id) } + + @JvmStatic + fun create( + gamemode: String, + server: String, + starttime: Timestamp, + duration: Int, + blueleader: Int, + redleader: Int, + blueschem: Int?, + redschem: Int?, + win: Int, + wincondition: String + ): Int = useDb { + FightTable.insertAndGetId { + it[FightTable.gamemode] = gamemode + it[FightTable.server] = server + it[FightTable.startTime] = starttime.toInstant() + it[FightTable.duration] = duration + it[FightTable.blueLeader] = EntityID(blueleader, SteamwarUserTable) + it[FightTable.redLeader] = EntityID(redleader, SteamwarUserTable) + it[FightTable.blueSchem] = blueschem?.let { EntityID(it, SchematicNodeTable) } + it[FightTable.redSchem] = redschem?.let { EntityID(it, SchematicNodeTable) } + it[FightTable.win] = win + it[FightTable.winCondition] = wincondition + }.value + } + + @JvmStatic + fun getPage(page: Int, pageSize: Int): List = useDb { + val fights = all().limit(pageSize).offset((pageSize * page).toLong()) + + val fightPlayer = FightPlayer.batchGet(fights.map { it.id.value }) + for (fight in fights) { + fight.initPlayers(fightPlayer) + } + + SteamwarUser.batchCache(fightPlayer.map { it.userID }.toMutableSet()) + fights.toList() + } + + @JvmStatic + fun markReplayAvailable(id: Int) = useDb { + FightTable.update({ FightTable.id eq id }) { + it[replayAvailable] = true + } + } + } + + val fightID by FightTable.id.transform({ EntityID(it, FightTable) }, { it.value }) + val gameMode by FightTable.gamemode + val server by FightTable.server + val startTime by FightTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) }) + val duration by FightTable.duration + val blueLeaderId by FightTable.blueLeader + val blueLeader by lazy { useDb { SteamwarUser[blueLeaderId] } } + val redLeaderId by FightTable.redLeader + val redLeader by lazy { useDb { SteamwarUser[redLeaderId] } } + val blueSchem by FightTable.blueSchem + val redSchem by FightTable.redSchem + val win by FightTable.win + val winCondition by FightTable.winCondition + val replayAvailable by FightTable.replayAvailable + + val schemType: SchematicType? + get() = SchematicType.fromDB(gameMode) + + val replayAllowed by lazy { + replayExists() && useDb { + exec( + "SELECT (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId WHERE FightId = ?", + args = listOf(IntegerColumnType() to this@Fight.id) + ) { + if (it.next()) { + it.getBoolean("ReplayAllowed") + } else { + false + } + } ?: false + } + } + + fun replayExists() = schemType != null && replayAvailable + fun replayAllowed() = replayAllowed + + lateinit var bluePlayers: List + lateinit var redPlayers: List + + private fun initPlayers(fightPlayers: List) { + val blue = mutableListOf() + val red = mutableListOf() + + for (player in fightPlayers.filter { it.fightID == id.value }) { + if (player.team == 1) + blue.add(player) + else + red.add(player) + } + + bluePlayers = blue + redPlayers = red + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/FightPlayer.java b/CommonCore/SQL/src/de/steamwar/sql/FightPlayer.java deleted file mode 100644 index c45ec806..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/FightPlayer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@AllArgsConstructor -public class FightPlayer { - - private static final Table table = new Table<>(FightPlayer.class); - private static final Statement create = table.insertAll(); - private static final SelectStatement batchGet = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN ?"); - - @Getter - @Field(keys = {Table.PRIMARY}) - private final int fightID; - @Getter - @Field(keys = {Table.PRIMARY}) - private final int userID; - @Getter - @Field - private final int team; - @Field - private final String kit; - @Field - private final int kills; - @Field - private final boolean isOut; - - public static void create(int fightID, int userID, boolean blue, String kit, int kills, boolean isOut) { - create.update(fightID, userID, blue ? 1 : 2, kit, kills, isOut); - } - - public static List batchGet(Stream fightIds) { - try (SelectStatement batch = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN (" + fightIds.map(Object::toString).collect(Collectors.joining(", ")) + ")")) { - return batch.listSelect(); - } - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/FightPlayer.kt b/CommonCore/SQL/src/de/steamwar/sql/FightPlayer.kt new file mode 100644 index 00000000..d0238c96 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/FightPlayer.kt @@ -0,0 +1,80 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.inList +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.jdbc.insertIgnore + +object FightPlayerTable : CompositeIdTable("FightPlayer") { + val fightId = reference("FightId", FightTable) + val userId = reference("UserId", SteamwarUserTable) + val team = integer("Team") + val kit = varchar("Kit", 64) + val kills = integer("Kills") + val out = bool("IsOut") + + init { + addIdColumn(fightId) + addIdColumn(userId) + } +} + +class FightPlayer(id: EntityID) : CompositeEntity(id) { + companion object : CompositeEntityClass(FightPlayerTable) { + @JvmStatic + fun create( + fightId: Int, + userId: Int, + blue: Boolean, + kit: String, + kills: Int, + out: Boolean + ) = useDb { + FightPlayerTable.insertIgnore { + it[this.fightId] = fightId + it[this.userId] = userId + it[this.team] = if (blue) 1 else 2 + it[this.kit] = kit + it[this.kills] = kills + it[this.out] = out + } + } + + @JvmStatic + fun batchGet(fightIds: List) = useDb { + find { FightPlayerTable.fightId inList fightIds.toList() }.toList() + } + } + + val fightID by FightPlayerTable.fightId.transform({ EntityID(it, FightTable) }, { it.value }) + val userID by FightPlayerTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + val team by FightPlayerTable.team + val kit by FightPlayerTable.kit + val kills by FightPlayerTable.kills + val out by FightPlayerTable.out + + fun isOut() = out +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt index 5117eb13..6ea079f5 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt @@ -328,7 +328,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) { } private var nodeType by SchematicNodeTable.type var schemtype: SchematicType - get() = checkDir { SchematicType.fromDB(nodeType) } + get() = checkDir { SchematicType.fromDB(nodeType!!) } set(value) = checkDir { useDb { nodeType = value.toDB() } } var config by SchematicNodeTable.config diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.java b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.java deleted file mode 100644 index 6abaffca..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.SqlTypeMapper; -import lombok.Getter; - -import java.io.File; -import java.util.*; -import java.util.stream.Collectors; - -public class SchematicType { - - public static final SchematicType Normal = new SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false); - - private static final Map fromDB; - private static final List types; - - static { - List tmpTypes = new LinkedList<>(); - Map tmpFromDB = new HashMap<>(); - - tmpTypes.add(Normal); - tmpFromDB.put(Normal.name().toLowerCase(), Normal); - - File folder = SQLWrapper.impl.getSchemTypesFolder(); - if (folder.exists()) { - for (File configFile : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().collect(Collectors.toList())) { - GameModeConfig gameModeConfig = SQLWrapper.impl.loadGameModeConfig(configFile); - if (gameModeConfig.Schematic.Type == null) continue; - if (tmpFromDB.containsKey(gameModeConfig.Schematic.Type.toDB())) continue; - SchematicType current = gameModeConfig.Schematic.Type; - if (!gameModeConfig.CheckQuestions.isEmpty()) { - SchematicType checkType = current.checkType; - tmpTypes.add(checkType); - tmpFromDB.put(checkType.toDB(), checkType); - } - tmpTypes.add(current); - tmpFromDB.put(current.toDB(), current); - SQLWrapper.impl.processSchematicType(gameModeConfig); - } - } - - fromDB = Collections.unmodifiableMap(tmpFromDB); - types = Collections.unmodifiableList(tmpTypes); - } - - static { - new SqlTypeMapper<>(SchematicType.class, "VARCHAR(16)", (rs, identifier) -> { - String t = rs.getString(identifier); - return t != null ? fromDB.get(t) : null; - }, (st, index, value) -> st.setString(index, value.toDB())); - } - - private final String name; - @Getter - private final String kuerzel; - private final Type type; - private final SchematicType checkType; - @Getter - private final String material; - @Getter - private final Date deadline; - @Getter - private final boolean manualCheck; - - SchematicType(String name, String kuerzel, Type type, SchematicType checkType, String material, boolean manualCheck){ - this(name, kuerzel, type, checkType, material, null, manualCheck); - } - - SchematicType(String name, String kuerzel, Type type, SchematicType checkType, String material, Date deadline, boolean manualCheck){ - this.name = name; - this.kuerzel = kuerzel; - this.type = type; - this.checkType = checkType; - this.material = material; - this.deadline = deadline; - this.manualCheck = manualCheck; - } - - public boolean isAssignable(){ - return type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck; - } - - public SchematicType checkType(){ - if (!manualCheck) { - return this; - } - return checkType; - } - - public boolean check(){ - return type == Type.CHECK_TYPE; - } - - public boolean fightType(){ - return type == Type.FIGHT_TYPE; - } - - public boolean writeable(){ - return type == Type.NORMAL; - } - - public String name(){ - return name; - } - - public String toDB(){ - return name.toLowerCase(); - } - - public static SchematicType fromDB(String input) { - if (fromDB == null) return null; - return fromDB.get(input.toLowerCase()); - } - - public static List values(){ - return types; - } - - enum Type{ - NORMAL, - CHECK_TYPE, - FIGHT_TYPE - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt new file mode 100644 index 00000000..50b0311e --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt @@ -0,0 +1,107 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import java.io.File +import java.util.* +import java.util.stream.Collectors + +data class SchematicType( + val name: String, + val kuerzel: String, + val type: Type, + val checkType: SchematicType?, + val material: String, + val deadline: Date?, + val manualCheck: Boolean, +) { + constructor( + name: String, + kuerzel: String, + type: Type, + checkType: SchematicType?, + material: String, + manualCheck: Boolean + ) : this(name, kuerzel, type, checkType, material, null, manualCheck) + + companion object { + @JvmField + val Normal = SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false) + + private val types: List + private val fromDB: Map + + init { + val tmpTypes = mutableListOf() + val tmpFromDB = mutableMapOf() + + tmpTypes.add(Normal) + tmpFromDB[Normal.toDB()] = Normal + + val folder = SQLWrapper.impl.schemTypesFolder + if (folder.exists()) { + for (configFile in Arrays.stream(folder.listFiles { _, name -> + name.endsWith( + ".yml" + ) && !name.endsWith(".kits.yml") + }).sorted().collect(Collectors.toList())) { + val gameModeConfig = SQLWrapper.impl.loadGameModeConfig(configFile) + if (gameModeConfig.Schematic.Type == null) continue + if (tmpFromDB.containsKey(gameModeConfig.Schematic.Type.toDB())) continue + val current = gameModeConfig.Schematic.Type + if (gameModeConfig.CheckQuestions.isNotEmpty()) { + val checkType = current.checkType + tmpTypes.add(checkType!!) + tmpFromDB[checkType.toDB()] = checkType + } + tmpTypes.add(current) + tmpFromDB[current.toDB()] = current + SQLWrapper.impl.processSchematicType(gameModeConfig) + } + } + + types = tmpTypes.toList() + fromDB = tmpFromDB.toMap() + } + + @JvmStatic + fun values() = types + + @JvmStatic + fun fromDB(value: String) = + fromDB[value.lowercase()] ?: throw IllegalArgumentException("Unknown SchematicType: $value") + } + + fun name() = name + fun toDB() = name.lowercase() + + fun check() = type == Type.CHECK_TYPE + fun fightType() = type == Type.FIGHT_TYPE + fun writeable() = type == Type.NORMAL + + fun checkType() = if (manualCheck) checkType else this + fun isAssignable() = type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck + + enum class Type { + NORMAL, + CHECK_TYPE, + FIGHT_TYPE + } +} From 73da9179bfa3cc66c3c5a9bb19a00aa4bc33d3b2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Nov 2025 19:28:14 +0100 Subject: [PATCH 14/32] Migrate SQL-related classes (IgnoreSystem, Mod, NodeDownload, NodeMember) to Kotlin and remove old Java implementations. Update references across modules. Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/IgnoreSystem.java | 59 ---------- .../SQL/src/de/steamwar/sql/IgnoreSystem.kt | 74 +++++++++++++ CommonCore/SQL/src/de/steamwar/sql/Mod.java | 101 ------------------ CommonCore/SQL/src/de/steamwar/sql/Mod.kt | 88 +++++++++++++++ .../SQL/src/de/steamwar/sql/NodeDownload.java | 86 --------------- .../SQL/src/de/steamwar/sql/NodeDownload.kt | 73 +++++++++++++ .../SQL/src/de/steamwar/sql/NodeMember.java | 95 ---------------- .../SQL/src/de/steamwar/sql/NodeMember.kt | 92 ++++++++++++++++ 8 files changed, 327 insertions(+), 341 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Mod.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Mod.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/NodeMember.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java b/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java deleted file mode 100644 index c0c38cc8..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; - -import java.sql.ResultSet; -import java.util.UUID; - -@AllArgsConstructor -public class IgnoreSystem { - - private static final Table table = new Table<>(IgnoreSystem.class, "IgnoredPlayers"); - private static final SelectStatement select = table.select(Table.PRIMARY); - private static final Statement insert = table.insertAll(); - private static final Statement delete = table.delete(Table.PRIMARY); - - @Field(keys = {Table.PRIMARY}) - private final int ignorer; - @Field(keys = {Table.PRIMARY}) - private final int ignored; - - public static boolean isIgnored(UUID ignorer, UUID ignored){ - return isIgnored(SteamwarUser.get(ignorer), SteamwarUser.get(ignored)); - } - - public static boolean isIgnored(SteamwarUser ignorer, SteamwarUser ignored) { - return select.select(ResultSet::next, ignorer.getId(), ignored.getId()); - } - - public static void ignore(SteamwarUser ignorer, SteamwarUser ignored) { - insert.update(ignorer.getId(), ignored.getId()); - } - - public static void unIgnore(SteamwarUser ignorer, SteamwarUser ignored) { - delete.update(ignorer.getId(), ignored.getId()); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt b/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt new file mode 100644 index 00000000..b94c111a --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt @@ -0,0 +1,74 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import java.util.UUID + +object IgnoreSystemTable: CompositeIdTable("IgnoreTable") { + val ignorer = reference("Ignorer", SteamwarUserTable) + val ignored = reference("Ignored", SteamwarUserTable) + + override val primaryKey = PrimaryKey(ignorer, ignored) + + init { + addIdColumn(ignorer) + addIdColumn(ignored) + } +} + +class IgnoreSystem(id: EntityID) : CompositeEntity(id) { + var ignorer by IgnoreSystemTable.ignorer + var ignored by IgnoreSystemTable.ignored + + companion object : CompositeEntityClass(IgnoreSystemTable) { + @JvmStatic + fun isIgnored(ignorer: UUID, ignored: UUID) = useDb { isIgnored(SteamwarUser.get(ignorer)!!, SteamwarUser.get(ignored)!!) } + + @JvmStatic + fun isIgnored(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb { + find { + (IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id) + }.firstOrNull() != null + } + + @JvmStatic + fun ignore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb { + new { + this.ignorer = ignorer.id + this.ignored = ignored.id + } + } + + @JvmStatic + fun unIgnore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb { + find { + (IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id) + }.firstOrNull()?.delete() + } + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/Mod.java b/CommonCore/SQL/src/de/steamwar/sql/Mod.java deleted file mode 100644 index 4d8fcd9d..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Mod.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; - -@AllArgsConstructor -public class Mod { - - static { - SqlTypeMapper.ordinalEnumMapper(Platform.class); - SqlTypeMapper.ordinalEnumMapper(ModType.class); - } - - private static final Table table = new Table<>(Mod.class, "Mods"); - private static final SelectStatement get = table.select(Table.PRIMARY); - private static final SelectStatement findFirst = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = 0 LIMIT 1"); - private static final SelectStatement getPageOfType = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = ? ORDER BY ModName DESC LIMIT ?, ?"); - private static final Statement insert = table.insert(Table.PRIMARY); - private static final Statement set = table.update(Table.PRIMARY, "ModType"); - - public static Mod get(String name, Platform platform) { - return get.select(platform, name); - } - - public static Mod getOrCreate(String name, Platform platform) { - Mod mod = get(name, platform); - if(mod != null) - return mod; - - insert.update(platform, name); - return new Mod(platform, name, ModType.UNKLASSIFIED); - } - - public static List getAllModsFiltered(int page, int elementsPerPage, ModType filter) { - return Mod.getPageOfType.listSelect(filter, page * elementsPerPage, elementsPerPage); - } - - public static Mod findFirstMod() { - return findFirst.select(); - } - - @Getter - @Field(keys = {Table.PRIMARY}) - private final Platform platform; - @Getter - @Field(keys = {Table.PRIMARY}) - private final String modName; - @Getter - @Field(def = "0") - private ModType modType; - - public void setModType(ModType modType) { - set.update(modType, platform, modName); - this.modType = modType; - } - - public enum Platform { - FORGE, - LABYMOD, - FABRIC - } - - public enum ModType { - UNKLASSIFIED("7"), - GREEN("a"), - YELLOW("e"), - RED("c"), - YOUTUBER_ONLY("6"); - - ModType(String colorcode) { - this.colorcode = colorcode; - } - private final String colorcode; - - public String getColorCode() { - return colorcode; - } - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/Mod.kt b/CommonCore/SQL/src/de/steamwar/sql/Mod.kt new file mode 100644 index 00000000..9e3b4d50 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/Mod.kt @@ -0,0 +1,88 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.SortOrder +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass + +object ModTable : CompositeIdTable("Mods") { + val platform = enumeration("Platform", Mod.Platform::class) + val modName = varchar("ModName", 100) + val modeType = enumerationByName("ModType", 10, Mod.ModType::class) +} + +class Mod(id: EntityID) : CompositeEntity(id) { + companion object : CompositeEntityClass(ModTable) { + @JvmStatic + fun get(modName: String, platform: Platform) = useDb { + find { ModTable.platform eq platform and (ModTable.modName eq modName) }.firstOrNull() + } + + @JvmStatic + fun getOrCreate(modName: String, platform: Platform) = useDb { + get(modName, platform) ?: new { + this.platform = platform + this.modName = modName + this.type = ModType.UNKLASSIFIED + } + } + + @JvmStatic + fun getAllModsFiltered(page: Int, elementsPerPage: Int, filter: ModType) = useDb { + find { ModTable.modeType eq filter }.limit(elementsPerPage).offset((elementsPerPage * page).toLong()) + .orderBy( + ModTable.modName to SortOrder.DESC + ).toList() + } + + @JvmStatic + fun findFirstMod() = useDb { + find { ModTable.modeType eq ModType.UNKLASSIFIED }.limit(1).firstOrNull() + } + } + + var platform by ModTable.platform + var modName by ModTable.modName + private var type by ModTable.modeType + var modType: ModType + get() = type + set(value) = useDb { type = value } + + enum class Platform { + FORGE, + LABYMOD, + FABRIC + } + + enum class ModType(val colorCode: String) { + UNKLASSIFIED("7"), + GREEN("a"), + YELLOW("e"), + RED("c"), + YOUTUBER_ONLY("6"); + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java deleted file mode 100644 index 6580b589..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.sql.Timestamp; -import java.time.Instant; - -@AllArgsConstructor -public class NodeDownload { - - private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - private static final String LINK_BASE = "https://api.steamwar.de/download/"; - - private static final Table table = new Table<>(NodeDownload.class); - private static final Statement insert = table.insertFields("NodeId", "Link"); - - private static final SelectStatement select = table.selectFields("link"); - - private static final Statement delete = table.delete(Table.PRIMARY); - - public static NodeDownload get(String link) { - return select.select(link); - } - - @Getter - @Field(keys = {Table.PRIMARY}) - private final int nodeId; - @Field - private final String link; - @Field(def = "CURRENT_TIMESTAMP") - @Getter - private final Timestamp timestamp; - - public static String getLink(SchematicNode schem){ - if(schem.isDir()) - throw new SecurityException("Can not Download Directorys"); - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException(e); - } - digest.reset(); - digest.update((Instant.now().toString() + schem.getOwner() + schem.getId()).getBytes()); - String hash = base16encode(digest.digest()); - insert.update(schem.getId(), hash); - return LINK_BASE + hash; - } - - public static String base16encode(byte[] byteArray) { - StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2); - for (byte b : byteArray) - hexBuffer.append(HEX[(b >>> 4) & 0xF]).append(HEX[b & 0xF]); - return hexBuffer.toString(); - } - - public void delete() { - delete.update(nodeId); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt new file mode 100644 index 00000000..adb25b90 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt @@ -0,0 +1,73 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import java.security.MessageDigest +import java.sql.Timestamp +import java.time.Instant + +object NodeDownloadTable: IdTable("NodeDownload") { + override val id = reference("NodeId", SchematicNodeTable).uniqueIndex() + val link = varchar("Link", 255) + val timestamp = timestamp("Timestamp").default(Instant.now()) +} + +class NodeDownload(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(NodeDownloadTable) { + const val LINK_BASE = "https://api.steamwar.de/download/" + + @JvmStatic + fun getLink(schem: SchematicNode): String { + if (schem.isDir()) + throw IllegalArgumentException("Cannot get link for directory") + + val digest = MessageDigest.getInstance("SHA-1") + digest.update("${Instant.now()}${schem.owner}${schem.nodeId}".toByteArray()) + val hash = digest.digest().joinToString("") { "%02x".format(it) } + useDb { + new { + nodeId = schem.id.value + link = hash + } + } + return "${LINK_BASE}${hash}" + } + + @JvmStatic + fun get(link: String) = useDb { + find { NodeDownloadTable.link eq link }.firstOrNull() + } + } + + var nodeId by NodeDownloadTable.id.transform({ EntityID(it, SchematicNodeTable) }, { it.value }) + var link by NodeDownloadTable.link + var timestamp by NodeDownloadTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) }) + + override fun delete() = useDb { + super.delete() + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.java b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.java deleted file mode 100644 index 8b40b8be..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; - -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; - -@AllArgsConstructor -public class NodeMember { - - public static void init() { - // enforce class initialization - } - - private static final Table table = new Table<>(NodeMember.class); - private static final SelectStatement getNodeMember = table.select(Table.PRIMARY); - private static final SelectStatement getNodeMembers = table.selectFields("NodeId"); - private static final SelectStatement getSchematics = table.selectFields("UserId"); - private static final Statement create = table.insert(Table.PRIMARY); - private static final Statement delete = table.delete(Table.PRIMARY); - private static final Statement updateParent = table.update(Table.PRIMARY, "ParentId"); - - @Field(keys = {Table.PRIMARY}) - private final int nodeId; - @Field(keys = {Table.PRIMARY}) - private final int userId; - @Field(nullable = true, def = "null") - private Integer parentId; - - public int getNode() { - return nodeId; - } - - public int getMember() { - return userId; - } - - public Optional getParent() { - return Optional.ofNullable(parentId); - } - - public void delete() { - delete.update(nodeId, userId); - } - - public static NodeMember createNodeMember(int node, int member) { - create.update(node, member); - return new NodeMember(node, member, null); - } - - public static NodeMember getNodeMember(int node, SteamwarUser member) { - return getNodeMember(node, member.getId()); - } - - public static NodeMember getNodeMember(int node, int member) { - return getNodeMember.select(node, member); - } - - public static Set getNodeMembers(int node) { - return new HashSet<>(getNodeMembers.listSelect(node)); - } - - public static Set getSchematics(int member) { - return new HashSet<>(getSchematics.listSelect(member)); - } - - public void setParentId(Integer parentId) { - this.parentId = parentId; - updateParent.update(this.parentId, nodeId, userId); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt new file mode 100644 index 00000000..a953e90a --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt @@ -0,0 +1,92 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.jdbc.insertIgnore +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +object NodeMemberTable : CompositeIdTable("NodeMember") { + val node = reference("NodeId", SchematicNodeTable) + val nodeOwner = reference("NodeOwner", SteamwarUserTable) + val parentNode = optReference("ParentNodeId", SchematicNodeTable) + + override val primaryKey = PrimaryKey(node, nodeOwner) + + init { + addIdColumn(node) + addIdColumn(nodeOwner) + } +} + +class NodeMember(id: EntityID) : CompositeEntity(id) { + companion object : CompositeEntityClass(NodeMemberTable) { + @JvmStatic + fun createNodeMember(node: Int, member: Int): NodeMember = useDb { + NodeMemberTable.insertIgnore { + it[this.node] = EntityID(node, SchematicNodeTable) + it[this.nodeOwner] = EntityID(member, SteamwarUserTable) + } + getNodeMember(node, member) ?: throw IllegalStateException("NodeMember not created") + } + + @JvmStatic + fun createNodeMember(node: Int, member: SteamwarUser) = createNodeMember(node, member.id.value) + + @JvmStatic + fun getNodeMember(node: Int, member: Int) = useDb { + find { (NodeMemberTable.node eq node) and (NodeMemberTable.nodeOwner eq member) }.firstOrNull() + } + + @JvmStatic + fun getNodeMember(node: Int, member: SteamwarUser) = getNodeMember(node, member.id.value) + + @JvmStatic + fun getNodeMembers(node: Int) = useDb { find { NodeMemberTable.node eq node }.toSet() } + + @JvmStatic + fun getSchematics(member: Int) = useDb { find { NodeMemberTable.nodeOwner eq member }.toSet() } + + @JvmStatic + fun init() = Unit + } + + val node by NodeMemberTable.node.transform({ EntityID(it, SchematicNodeTable) }, { it.value }) + val member by NodeMemberTable.nodeOwner.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + var parent by NodeMemberTable.parentNode.transform( + { it.map { EntityID(it, SchematicNodeTable) }.getOrNull() }, + { Optional.ofNullable(it?.value) }) + + fun setParentId(id: Int?) { + parent = Optional.ofNullable(id) + } + + override fun delete() = useDb { + super.delete() + } +} From 89e2df0eb227a90b7f725a226d660deff799d086 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 4 Nov 2025 21:17:53 +0100 Subject: [PATCH 15/32] Migrate Punishment and PollAnswer classes to Kotlin and remove outdated Java implementations. Update references across modules. Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/PollAnswer.java | 77 ------- .../SQL/src/de/steamwar/sql/PollAnswer.kt | 78 +++++++ .../SQL/src/de/steamwar/sql/Punishment.java | 140 ------------- .../SQL/src/de/steamwar/sql/Punishment.kt | 190 ++++++++++++++++++ .../SQL/src/de/steamwar/sql/SteamwarUser.kt | 2 +- 5 files changed, 269 insertions(+), 218 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/PollAnswer.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/PollAnswer.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Punishment.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Punishment.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/PollAnswer.java b/CommonCore/SQL/src/de/steamwar/sql/PollAnswer.java deleted file mode 100644 index 9376ed18..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/PollAnswer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.util.HashMap; -import java.util.Map; - -@AllArgsConstructor -public class PollAnswer { - - @Getter - @Setter - private static String currentPoll; - - private static final Table table = new Table<>(PollAnswer.class); - - private static final SelectStatement get = table.select(Table.PRIMARY); - private static final Statement getResults = new Statement("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC"); - private static final Statement insert = table.insertAll(); - - @Field(keys = {Table.PRIMARY}) - private final int userID; - @Field(keys = {Table.PRIMARY}) - private final String question; - @Field(def = "0") - private int answer; - - public static PollAnswer get(int userID) { - PollAnswer answer = get.select(userID, currentPoll); - if(answer == null) - return new PollAnswer(userID, currentPoll, 0); - return answer; - } - - public static Map getCurrentResults() { - return getResults.select(rs -> { - Map retMap = new HashMap<>(); - while (rs.next()) - retMap.put(rs.getInt("Answer")-1, rs.getInt("Times")); - return retMap; - }, currentPoll); - } - - public boolean hasAnswered(){ - return answer != 0; - } - - public void setAnswer(int answer){ - this.answer = answer; - insert.update(userID, question, answer); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/PollAnswer.kt b/CommonCore/SQL/src/de/steamwar/sql/PollAnswer.kt new file mode 100644 index 00000000..a4c20b26 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/PollAnswer.kt @@ -0,0 +1,78 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.VarCharColumnType +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass + +object PollAnswerTable: CompositeIdTable("PollAnswer") { + val userId = reference("UserID", SteamwarUserTable) + val question = varchar("Question", 150) + val answer = integer("Answer") +} + +class PollAnswer(id: EntityID): CompositeEntity(id) { + var userId by PollAnswerTable.userId + private set + var question by PollAnswerTable.question + private set + private var answerId by PollAnswerTable.answer + var answer: Int + get() = answerId + set(value) = useDb { + answerId = value + } + + companion object: CompositeEntityClass(PollAnswerTable) { + @JvmStatic + var currentPoll: String? = null + + @JvmStatic + fun get(userId: Int) = useDb { + find { (PollAnswerTable.userId eq userId) and (PollAnswerTable.question eq currentPoll!!) }.firstOrNull() + ?: new { + this.userId = EntityID(userId, SteamwarUserTable) + this.question = currentPoll!! + this.answerId = 0 + } + } + + @JvmStatic + fun getCurrentResults(): Map = useDb { + exec("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC", + args = listOf(VarCharColumnType() to currentPoll!!)) { + val result = mutableMapOf() + while (it.next()) { + result[it.getInt("Answer")] = it.getInt("Times") + } + result + } ?: emptyMap() + } + } + + fun hasAnswered() = answerId != 0 +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/Punishment.java b/CommonCore/SQL/src/de/steamwar/sql/Punishment.java deleted file mode 100644 index f5813792..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Punishment.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.sql.Timestamp; -import java.time.Instant; -import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -@AllArgsConstructor -public class Punishment { - - static { - SqlTypeMapper.nameEnumMapper(PunishmentType.class); - } - - public static final Timestamp PERMA_TIME = Timestamp.from(Instant.ofEpochSecond(946674800)); - - private static final Table table = new Table<>(Punishment.class, "Punishments"); - private static final SelectStatement getPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)"); - private static final SelectStatement getPunishment = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1"); - private static final SelectStatement getAllPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC"); - private static final Statement insert = table.insertFields(true, "UserId", "Punisher", "Type", "EndTime", "Perma", "Reason"); - - public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) { - return getPunishment.select(user, type); - } - - public static Map getPunishmentsOfPlayer(int user) { - return getPunishments.listSelect(user).stream().collect(Collectors.toMap(Punishment::getType, punishment -> punishment)); - } - - public static List getAllPunishmentsOfPlayer(int user) { - return getAllPunishments.listSelect(user); - } - - public static boolean isPunished(SteamwarUser user, PunishmentType type, Consumer callback) { - Punishment punishment = Punishment.getPunishmentOfPlayer(user.getId(), type); - if(punishment == null || !punishment.isCurrent()) { - return false; - } else { - callback.accept(punishment); - return true; - } - } - - public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) { - if(perma && !endTime.equals(PERMA_TIME)) { - throw new IllegalArgumentException("Permanent punishments must have an end time of `Punishment.PERMA_TIME`"); - } - int punishmentId = insert.insertGetKey(user, executor, type.name(), endTime, perma, reason); - return new Punishment(punishmentId, user, executor, type, Timestamp.from(Instant.now()), endTime, perma, reason); - } - - @Field(keys = {Table.PRIMARY}, autoincrement = true) - private final int punishmentId; - @Field - @Getter - private final int userId; - @Field - @Getter - private final int punisher; - @Field - @Getter - private final PunishmentType type; - @Field - @Getter - private final Timestamp startTime; - @Field - @Getter - private final Timestamp endTime; - @Field - @Getter - private final boolean perma; - @Field - @Getter - private final String reason; - - @Deprecated // Not multiling, misleading title - public String getBantime(Timestamp endTime, boolean perma) { - if (perma) { - return "permanent"; - } else { - return endTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")); - } - } - - public boolean isCurrent() { - return isPerma() || getEndTime().after(new Date()); - } - - @AllArgsConstructor - @RequiredArgsConstructor - @Getter - public enum PunishmentType { - Ban(false, "BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN"), - Mute( false, "MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE"), - NoSchemReceiving(true, "NOSCHEMRECEIVING_TEAM", "NOSCHEMRECEIVING_PERMA", "NOSCHEMRECEIVING_UNTIL", "UNNOSCHEMRECEIVING_ERROR", "UNNOSCHEMRECEIVING"), - NoSchemSharing(true, "NOSCHEMSHARING_TEAM", "NOSCHEMSHARING_PERMA", "NOSCHEMSHARING_UNTIL", "UNNOSCHEMSHARING_ERROR", "UNNOSCHEMSHARING"), - NoSchemSubmitting(false, "NOSCHEMSUBMITTING_TEAM", "NOSCHEMSUBMITTING_PERMA", "NOSCHEMSUBMITTING_UNTIL", "UNNOSCHEMSUBMITTING_ERROR", "UNNOSCHEMSUBMITTING"), - NoDevServer(true, "NODEVSERVER_TEAM", "NODEVSERVER_PERMA", "NODEVSERVER_UNTIL", "UNNODEVSERVER_ERROR", "UNNODEVSERVER"), - NoFightServer(true, "NOFIGHTSERVER_TEAM", "NOFIGHTSERVER_PERMA", "NOFIGHTSERVER_UNTIL", "UNNOFIGHTSERVER_ERROR", "UNNOFIGHTSERVER"), - NoTeamServer(true, "NOTEAMSERVER_TEAM", "NOTEAMSERVER_PERMA", "NOTEAMSERVER_UNTIL", "UNNOTEAMSERVER_ERROR", "UNNOTEAMSERVER"), - Note(false, "NOTE_TEAM", null, null, null, null, true); - - private final boolean needsAdmin; - private final String teamMessage; - private final String playerMessagePerma; - private final String playerMessageUntil; - private final String usageNotPunished; - private final String unpunishmentMessage; - private boolean multi = false; - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/Punishment.kt b/CommonCore/SQL/src/de/steamwar/sql/Punishment.kt new file mode 100644 index 00000000..a5fa6baa --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/Punishment.kt @@ -0,0 +1,190 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.SortOrder +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.inSubQuery +import org.jetbrains.exposed.v1.core.max +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.select +import java.sql.Timestamp +import java.time.Instant +import java.util.Date +import java.util.function.Consumer + +object PunishmentTable : IntIdTable("Punishment", "PunishmentId") { + val userId = reference("UserId", SteamwarUserTable) + val punisher = reference("Punisher", SteamwarUserTable) + val type = enumerationByName("Type", 32, Punishment.PunishmentType::class) + val startTime = timestamp("StartTime") + val endTime = timestamp("EndTime") + val perma = bool("Perma") + val reason = text("Reason") +} + +class Punishment(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(PunishmentTable) { + @JvmField + val PERMA_TIME: Timestamp = Timestamp.from(Instant.ofEpochSecond(946674800)) + + @JvmStatic + fun getPunsihmentOfPlayer(user: Int, type: PunishmentType) = useDb { + find { (PunishmentTable.userId eq user) and (PunishmentTable.type eq type) }.orderBy(PunishmentTable.id to SortOrder.DESC).firstOrNull() + } + + @JvmStatic + fun getPunishmentsOfPlayer(user: Int) = useDb { + find { + PunishmentTable.id inSubQuery PunishmentTable.select(PunishmentTable.id.max()) + .where { PunishmentTable.userId eq user }.groupBy( + PunishmentTable.type + ) + }.associateBy { it.type }.toMutableMap() + } + + @JvmStatic + fun getAllPunishmentsOfPlayer(user: Int) = useDb { + find { PunishmentTable.userId eq user }.orderBy(PunishmentTable.id to SortOrder.DESC).toList() + } + + @JvmStatic + fun isPunished(user: SteamwarUser, type: PunishmentType, callback: Consumer): Boolean = useDb { + val punishment = getPunsihmentOfPlayer(user.id.value, type) ?: return@useDb false + + if (punishment.isCurrent()) { + callback.accept(punishment) + return@useDb true + } + + return@useDb false + } + + @JvmStatic + fun createPunishment( + user: Int, + executor: Int, + type: PunishmentType, + reason: String, + endTime: Timestamp, + perma: Boolean + ) = useDb { + new { + this.userId = user + this.punisher = executor + this.type = type + this.startTime = Timestamp.from(Instant.now()) + this.endTime = endTime + this.perma = perma + this.reason = reason + } + } + } + + var userId by PunishmentTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + private set + var punisher by PunishmentTable.punisher.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + private set + var type by PunishmentTable.type + private set + var startTime by PunishmentTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) }) + private set + var endTime by PunishmentTable.endTime.transform({ it.toInstant() }, { Timestamp.from(it) }) + private set + var perma by PunishmentTable.perma + private set + var reason by PunishmentTable.reason + private set + + fun isPerma() = perma + + fun isCurrent() = perma || endTime.after(Date()) + + enum class PunishmentType( + val needsAdmin: Boolean, + val teamMessage: String?, + val playerMessagePerma: String?, + val playerMessageUntil: String?, + val usageNotPunished: String?, + val unpunishmentMessage: String?, + val multi: Boolean = false + ) { + Ban(false, "BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN"), + Mute(false, "MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE"), + NoSchemReceiving( + true, + "NOSCHEMRECEIVING_TEAM", + "NOSCHEMRECEIVING_PERMA", + "NOSCHEMRECEIVING_UNTIL", + "UNNOSCHEMRECEIVING_ERROR", + "UNNOSCHEMRECEIVING" + ), + NoSchemSharing( + true, + "NOSCHEMSHARING_TEAM", + "NOSCHEMSHARING_PERMA", + "NOSCHEMSHARING_UNTIL", + "UNNOSCHEMSHARING_ERROR", + "UNNOSCHEMSHARING" + ), + NoSchemSubmitting( + false, + "NOSCHEMSUBMITTING_TEAM", + "NOSCHEMSUBMITTING_PERMA", + "NOSCHEMSUBMITTING_UNTIL", + "UNNOSCHEMSUBMITTING_ERROR", + "UNNOSCHEMSUBMITTING" + ), + NoDevServer( + true, + "NODEVSERVER_TEAM", + "NODEVSERVER_PERMA", + "NODEVSERVER_UNTIL", + "UNNODEVSERVER_ERROR", + "UNNODEVSERVER" + ), + NoFightServer( + true, + "NOFIGHTSERVER_TEAM", + "NOFIGHTSERVER_PERMA", + "NOFIGHTSERVER_UNTIL", + "UNNOFIGHTSERVER_ERROR", + "UNNOFIGHTSERVER" + ), + NoTeamServer( + true, + "NOTEAMSERVER_TEAM", + "NOTEAMSERVER_PERMA", + "NOTEAMSERVER_UNTIL", + "UNNOTEAMSERVER_ERROR", + "UNNOTEAMSERVER" + ), + Note(false, "NOTE_TEAM", null, null, null, null, true); + + fun isNeedsAdmin() = needsAdmin + fun isMulti() = multi + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt index 3ea8aa6e..a4dc42ba 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.kt @@ -208,7 +208,7 @@ class SteamwarUser(id: EntityID): IntEntity(id) { fun getPunishment(punishment: Punishment.PunishmentType) = punishments[punishment] fun isPunished(punishment: Punishment.PunishmentType) = getPunishment(punishment) ?.let { - if (!it.isCurrent) { + if (!it.isCurrent()) { if (punishment == Punishment.PunishmentType.Ban) { BannedUserIPs.unbanIPs(id.value) } From 9acfb32ae0070cf3c71beb9a2100424012a3de21 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 5 Nov 2025 17:04:01 +0100 Subject: [PATCH 16/32] Refactor SQL classes: update `GameModeConfig` functions, improve null safety in `SchematicNode` and `SchematicType`, and adjust `NodeMemberTable` structure. Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/GameModeConfig.java | 12 ++++++++++-- CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt | 16 ++++++++-------- .../SQL/src/de/steamwar/sql/SchematicNode.kt | 4 ++-- .../SQL/src/de/steamwar/sql/SchematicType.kt | 5 ++--- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java index c7e9ecf8..af6c395d 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java +++ b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java @@ -35,11 +35,19 @@ import java.util.stream.Collectors; public final class GameModeConfig { public static final Function ToString = Function.identity(); - public static final Function ToStaticWarGear = __ -> "WarGear"; - public static final Function ToInternalName = file -> file != null ? file.getName().replace(".yml", "") : "WarGear"; + public static final Function ToStaticWarGear = GameModeConfig::constWarGear; + public static final Function ToInternalName = GameModeConfig::internalName; public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm"); private static final Random random = new Random(); + private static String constWarGear(File f) { + return "WarGear"; + } + + private static String internalName(File f) { + return f.getName().replace(".yml", ""); + } + private static final Map> byFileName; private static final Map> byGameName; private static final Map> bySchematicType; diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt index a953e90a..1d69976d 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt @@ -33,14 +33,14 @@ import kotlin.jvm.optionals.getOrNull object NodeMemberTable : CompositeIdTable("NodeMember") { val node = reference("NodeId", SchematicNodeTable) - val nodeOwner = reference("NodeOwner", SteamwarUserTable) - val parentNode = optReference("ParentNodeId", SchematicNodeTable) + val userId = reference("UserId", SteamwarUserTable) + val parentNode = optReference("ParentId", SchematicNodeTable) - override val primaryKey = PrimaryKey(node, nodeOwner) + override val primaryKey = PrimaryKey(node, userId) init { addIdColumn(node) - addIdColumn(nodeOwner) + addIdColumn(userId) } } @@ -50,7 +50,7 @@ class NodeMember(id: EntityID) : CompositeEntity(id) { fun createNodeMember(node: Int, member: Int): NodeMember = useDb { NodeMemberTable.insertIgnore { it[this.node] = EntityID(node, SchematicNodeTable) - it[this.nodeOwner] = EntityID(member, SteamwarUserTable) + it[this.userId] = EntityID(member, SteamwarUserTable) } getNodeMember(node, member) ?: throw IllegalStateException("NodeMember not created") } @@ -60,7 +60,7 @@ class NodeMember(id: EntityID) : CompositeEntity(id) { @JvmStatic fun getNodeMember(node: Int, member: Int) = useDb { - find { (NodeMemberTable.node eq node) and (NodeMemberTable.nodeOwner eq member) }.firstOrNull() + find { (NodeMemberTable.node eq node) and (NodeMemberTable.userId eq member) }.firstOrNull() } @JvmStatic @@ -70,14 +70,14 @@ class NodeMember(id: EntityID) : CompositeEntity(id) { fun getNodeMembers(node: Int) = useDb { find { NodeMemberTable.node eq node }.toSet() } @JvmStatic - fun getSchematics(member: Int) = useDb { find { NodeMemberTable.nodeOwner eq member }.toSet() } + fun getSchematics(member: Int) = useDb { find { NodeMemberTable.userId eq member }.toSet() } @JvmStatic fun init() = Unit } val node by NodeMemberTable.node.transform({ EntityID(it, SchematicNodeTable) }, { it.value }) - val member by NodeMemberTable.nodeOwner.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) + val member by NodeMemberTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) var parent by NodeMemberTable.parentNode.transform( { it.map { EntityID(it, SchematicNodeTable) }.getOrNull() }, { Optional.ofNullable(it?.value) }) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt index 6ea079f5..c3e01d01 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt @@ -206,7 +206,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) { @JvmStatic fun getAllAccessibleSchematicsOfType(user: Int, type: String) = - accessibleByUserType(SteamwarUser.byId(user)!!, SchematicType.fromDB(type)) + accessibleByUserType(SteamwarUser.byId(user)!!, SchematicType.fromDB(type)!!) @JvmStatic fun getAllSchematicsAccessibleByUser(user: Int) = getAll(SteamwarUser.byId(user)!!) @@ -328,7 +328,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) { } private var nodeType by SchematicNodeTable.type var schemtype: SchematicType - get() = checkDir { SchematicType.fromDB(nodeType!!) } + get() = checkDir { SchematicType.fromDB(nodeType!!)!! } set(value) = checkDir { useDb { nodeType = value.toDB() } } var config by SchematicNodeTable.config diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt index 50b0311e..ea34a1ba 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt @@ -46,7 +46,7 @@ data class SchematicType( val Normal = SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false) private val types: List - private val fromDB: Map + private val fromDB: Map? init { val tmpTypes = mutableListOf() @@ -85,8 +85,7 @@ data class SchematicType( fun values() = types @JvmStatic - fun fromDB(value: String) = - fromDB[value.lowercase()] ?: throw IllegalArgumentException("Unknown SchematicType: $value") + fun fromDB(value: String) = fromDB?.let { it[value] } } fun name() = name From 8272c73b4881a30754b606d7d1dfcc0fc50b2135 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 5 Nov 2025 17:47:30 +0100 Subject: [PATCH 17/32] Migrate SQL-related classes (Referee, SchemElo, Script, Session, SWException, TeamTeilnahme) to Kotlin and remove outdated Java implementations. Update references across modules. Signed-off-by: Chaoscaot --- .../SQL/src/de/steamwar/sql/Referee.java | 56 ------------ CommonCore/SQL/src/de/steamwar/sql/Referee.kt | 67 ++++++++++++++ .../SQL/src/de/steamwar/sql/SWException.java | 68 --------------- .../SQL/src/de/steamwar/sql/SWException.kt | 69 +++++++++++++++ .../SQL/src/de/steamwar/sql/SchemElo.java | 56 ------------ .../SQL/src/de/steamwar/sql/SchemElo.kt | 75 ++++++++++++++++ .../SQL/src/de/steamwar/sql/Script.java | 84 ------------------ CommonCore/SQL/src/de/steamwar/sql/Script.kt | 75 ++++++++++++++++ .../SQL/src/de/steamwar/sql/Session.java | 45 ---------- CommonCore/SQL/src/de/steamwar/sql/Session.kt | 46 ++++++++++ .../SQL/src/de/steamwar/sql/SteamwarUser.kt | 6 +- .../src/de/steamwar/sql/TeamTeilnahme.java | 70 --------------- .../SQL/src/de/steamwar/sql/TeamTeilnahme.kt | 87 +++++++++++++++++++ 13 files changed, 422 insertions(+), 382 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Referee.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Referee.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/SWException.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/SWException.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/SchemElo.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Script.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Script.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Session.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/Session.kt delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java create mode 100644 CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.kt diff --git a/CommonCore/SQL/src/de/steamwar/sql/Referee.java b/CommonCore/SQL/src/de/steamwar/sql/Referee.java deleted file mode 100644 index 3f909643..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Referee.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; - -import java.util.Set; -import java.util.stream.Collectors; - -@AllArgsConstructor -public class Referee { - - private static final Table table = new Table<>(Referee.class); - private static final SelectStatement byEvent = table.selectFields("eventID"); - - private static final Statement insert = table.insertAll(); - private static final Statement delete = table.delete("eventReferee"); - - public static void add(int eventID, int userID) { - insert.update(eventID, userID); - } - - public static void remove(int eventID, int userID) { - delete.update(eventID, userID); - } - - public static Set get(int eventID) { - return byEvent.listSelect(eventID).stream().map(referee -> referee.userID).collect(Collectors.toSet()); - } - - @Field(keys = {"eventReferee"}) - private final int eventID; - @Field(keys = {"eventReferee"}) - private final int userID; -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/Referee.kt b/CommonCore/SQL/src/de/steamwar/sql/Referee.kt new file mode 100644 index 00000000..e5df5bdd --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/Referee.kt @@ -0,0 +1,67 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.jdbc.select + +object RefereeTable: CompositeIdTable("Referee") { + val eventId = reference("EventId", EventTable) + val userId = reference("UserId", SteamwarUserTable) + + override val primaryKey = PrimaryKey(eventId, userId) + + init { + addIdColumn(eventId) + addIdColumn(userId) + } +} + +class Referee(id: EntityID): CompositeEntity(id) { + companion object: CompositeEntityClass(RefereeTable) { + @JvmStatic + fun add(eventId: Int, userId: Int) = useDb { + new { + this.eventID = eventId + this.userID = userId + } + } + + @JvmStatic + fun remove(eventId: Int, userId: Int) = useDb { + find { (RefereeTable.eventId eq eventId) and (RefereeTable.userId eq userId) }.firstOrNull()?.delete() + } + + @JvmStatic + fun get(event: Int) = useDb { + find { RefereeTable.eventId eq event }.map { it.userID }.toSet() + } + } + + var eventID by RefereeTable.eventId.transform({ EntityID(it, EventTable) }, { it.value }) + var userID by RefereeTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value }) +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/SWException.java b/CommonCore/SQL/src/de/steamwar/sql/SWException.java deleted file mode 100644 index 945743f7..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/SWException.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; - -import java.io.File; -import java.sql.Timestamp; - -@AllArgsConstructor -public class SWException { - - public static void init() { - // force class initialialisation - } - - private static final String CWD = System.getProperty("user.dir"); - private static final String SERVER_NAME = new File(CWD).getName(); - - private static final Table table = new Table<>(SWException.class, "Exception"); - private static final Statement insert = table.insertFields(true, "server", "message", "stacktrace"); - - @Field(keys = {Table.PRIMARY}, autoincrement = true) - private final int id; - @Field(def = "CURRENT_TIMESTAMP") - private final Timestamp time; - @Field - private final String server; - @Field - private final String message; - @Field - private final String stacktrace; - - public static void log(String message, String stacktrace){ - insert.update(SERVER_NAME, generateMessage(message), stacktrace); - } - - public static int logGetId(String message, String stacktrace) { - return insert.insertGetKey(SERVER_NAME, generateMessage(message), stacktrace); - } - - private static String generateMessage(String message) { - StringBuilder msgBuilder = new StringBuilder(message); - SQLWrapper.impl.additionalExceptionMetadata(msgBuilder); - msgBuilder.append("\nCWD: ").append(CWD); - return msgBuilder.toString(); - } -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/SWException.kt b/CommonCore/SQL/src/de/steamwar/sql/SWException.kt new file mode 100644 index 00000000..7c5dc33c --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/SWException.kt @@ -0,0 +1,69 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.javatime.timestamp +import org.jetbrains.exposed.v1.jdbc.insert +import org.jetbrains.exposed.v1.jdbc.insertAndGetId +import java.io.File +import java.time.Instant + +object ExceptionTable: IntIdTable("Exception") { + val time = timestamp("Time").default(Instant.now()) + val server = text("Server") + val message = text("Message") + val stackTrace = text("StackTrace") +} + +class SWException { + companion object { + val cwd = System.getProperty("user.dir") + val serverName = File(cwd).name + + @JvmStatic + fun log(message: String, stacktrace: String) = useDb { + ExceptionTable.insert { + it[ExceptionTable.server] = serverName + it[ExceptionTable.message] = generateMessage(message) + it[ExceptionTable.stackTrace] = stacktrace + } + + Unit + } + + @JvmStatic + fun logGetId(message: String, stacktrace: String) = useDb { + ExceptionTable.insertAndGetId { + it[ExceptionTable.server] = serverName + it[ExceptionTable.message] = generateMessage(message) + it[ExceptionTable.stackTrace] = stacktrace + }.value + } + + fun generateMessage(message: String): String { + val msgBuilder = StringBuilder(message) + SQLWrapper.impl.additionalExceptionMetadata(msgBuilder) + msgBuilder.append("\nCWD: ").append(cwd) + return msgBuilder.toString() + } + } +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchemElo.java b/CommonCore/SQL/src/de/steamwar/sql/SchemElo.java deleted file mode 100644 index 0a8641b0..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/SchemElo.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; - -@AllArgsConstructor -public class SchemElo { - private static final int ELO_DEFAULT = 1000; - - private static final Table table = new Table<>(SchemElo.class); - private static final SelectStatement select = table.select(Table.PRIMARY); - private static final Statement setElo = table.insertAll(); - - public static int getElo(SchematicNode node, int season) { - SchemElo elo = select.select(node, season); - return elo != null ? elo.elo : 0; - } - - public static int getCurrentElo(int schemID) { - SchemElo elo = select.select(schemID, Season.getSeason()); - return elo != null ? elo.elo : ELO_DEFAULT; - } - - public static void setElo(int schemID, int elo) { - setElo.update(schemID, elo, Season.getSeason()); - } - - @Field(keys = {Table.PRIMARY}) - private final int schemId; - @Field - private final int elo; - @Field(keys = {Table.PRIMARY}) - private final int season; -} diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt b/CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt new file mode 100644 index 00000000..fc07f8f4 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt @@ -0,0 +1,75 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql + +import de.steamwar.sql.internal.useDb +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.dao.id.CompositeID +import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IdTable +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.dao.CompositeEntity +import org.jetbrains.exposed.v1.dao.CompositeEntityClass +import org.jetbrains.exposed.v1.jdbc.insertIgnore + +object SchemEloTable: CompositeIdTable("SchemElo") { + val schemId = reference("SchemId", SchematicNodeTable) + val season = integer("Season").entityId() + val elo = integer("Elo") + + override val primaryKey = PrimaryKey(schemId, season) + + init { + addIdColumn(schemId) + } +} + +class SchemElo(id: EntityID): CompositeEntity(id) { + companion object: CompositeEntityClass(SchemEloTable) { + @JvmStatic + fun getElo(node: SchematicNode, season: Int, defaultElo: Int = 0) = useDb { + find { (SchemEloTable.schemId eq node.id) and (SchemEloTable.season eq season) }.firstOrNull()?.elo ?: defaultElo + } + + @JvmStatic + fun getCurrentElo(schemId: Int) = getElo(SchematicNode.byId(schemId)!!, Season.getSeason()) + + @JvmStatic + fun setElo(node: Int, elo: Int) = useDb { + findByIdAndUpdate(CompositeID { + it[SchemEloTable.schemId] = node + it[SchemEloTable.season] = Season.getSeason() + }) { + it.elo = elo + } ?: SchemEloTable.insertIgnore { + it[SchemEloTable.schemId] = node + it[SchemEloTable.season] = Season.getSeason() + it[SchemEloTable.elo] = elo + } + + return@useDb + } + } + + var node by SchemEloTable.schemId + var season by SchemEloTable.season + var elo by SchemEloTable.elo +} \ No newline at end of file diff --git a/CommonCore/SQL/src/de/steamwar/sql/Script.java b/CommonCore/SQL/src/de/steamwar/sql/Script.java deleted file mode 100644 index 1a5ccd25..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Script.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2025 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Statement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; - -@AllArgsConstructor -@Getter -public class Script { - - private static final Table