Remove deprecated world management commands and associated SQL logic

Signed-off-by: Chaoscaot <max@maxsp.de>
This commit is contained in:
2026-05-20 16:44:32 +02:00
parent 9aa363de6f
commit a7adfe378f
33 changed files with 257 additions and 1607 deletions
@@ -19,6 +19,7 @@
package de.steamwar.sql
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
@@ -31,37 +32,45 @@ import org.jetbrains.exposed.v1.jdbc.insertIgnore
import java.util.*
object BauweltMemberTable : CompositeIdTable("BauweltMember") {
val worldId = reference("WorldID", WorldTable).index()
val bauweltId = reference("BauweltID", SteamwarUserTable).index()
val memberId = reference("MemberID", SteamwarUserTable).index()
val build = bool("Build")
val worldEdit = bool("WorldEdit")
val world = bool("World")
override val primaryKey = PrimaryKey(worldId, memberId)
override val primaryKey = PrimaryKey(bauweltId, memberId)
init {
addIdColumn(worldId)
addIdColumn(bauweltId)
addIdColumn(memberId)
}
}
class BauweltMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
companion object : CompositeEntityClass<BauweltMember>(BauweltMemberTable) {
private val cache = mutableMapOf<Pair<UUID, Int>, BauweltMember>()
private val cache = mutableMapOf<Int, BauweltMember>()
private fun cache(member: BauweltMember) =
cache.put(member.worldID to member.memberID, member)
cache.put(member.memberID, member)
@JvmStatic
fun clear() =
cache.clear()
@JvmStatic
fun addMember(worldId: UUID, newMemberId: Int) =
@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<Int>, newMemberId: EntityID<Int>) =
useDb {
BauweltMemberTable.insertIgnore {
it[BauweltMemberTable.worldId] = EntityID(worldId, WorldTable)
it[memberId] = EntityID(newMemberId, SteamwarUserTable)
it[bauweltId] = ownerId
it[memberId] = newMemberId
it[build] = false
it[worldEdit] = false
it[world] = false
@@ -69,32 +78,31 @@ class BauweltMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
}
@JvmStatic
fun addMember(worldId: UUID, newMemberId: UUID) =
addMember(worldId, SteamwarUser.get(newMemberId)!!.id.value)
@JvmStatic
fun getBauMember(world: UUID, member: Int) =
cache[world to member]
?: useDb {
find { (BauweltMemberTable.worldId eq world) and (BauweltMemberTable.memberId eq member) }.firstOrNull()?.also { cache(it) }
}
@JvmStatic
fun getBauMember(world: UUID, member: UUID) =
getBauMember(world, SteamwarUser.get(member)!!.id.value)
@JvmStatic
fun getWorldMembers(world: UUID) =
@Deprecated("Use getBauMember(bauwelt: Int, member: Int)")
fun getBauMember(bauwelt: UUID, member: UUID) =
useDb {
find { BauweltMemberTable.worldId eq world }.toList().also { it.forEach { cache(it) } }
find { (bauweltId eq SteamwarUser.get(bauwelt)!!.id) and (BauweltMemberTable.memberId eq SteamwarUser.get(member)!!.id) }.firstOrNull()?.also { cache(it) }
}
@JvmStatic
fun getMembers(world: UUID) =
getWorldMembers(world)
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 worldID by BauweltMemberTable.worldId.transform({ EntityID(it, WorldTable) }, { it.value })
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
@@ -136,4 +144,4 @@ class BauweltMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
useDb {
delete()
}
}
}
@@ -50,8 +50,6 @@ enum class UserPerm {
PUNISHMENTS,
TICKET_LOG,
BUILD,
BUILD_EXTRA_WORLDS,
BUILD_UNLIMITED_WORLDS,
CHECK,
MODERATION,
ADMINISTRATION;
@@ -97,4 +95,4 @@ enum class UserPerm {
}
data class Prefix(val colorCode: String, val chatPrefix: String)
}
}
-345
View File
@@ -1,345 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 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 <https://www.gnu.org/licenses/>.
*/
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.java.UUIDTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.not
import org.jetbrains.exposed.v1.core.or
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.dao.Entity
import org.jetbrains.exposed.v1.dao.EntityClass
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
import org.jetbrains.exposed.v1.javatime.timestamp
import java.io.File
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.UUID
object WorldTable : UUIDTable("world") {
val name = varchar("Name", 512)
val version = integer("Version")
val type = enumeration<WorldType>("Type")
val owner = reference("Owner", SteamwarUserTable).nullable()
val team = reference("Team", TeamTable).nullable()
val lockState = varchar("LockState", 32).nullable()
val deleted = bool("Deleted").default(false)
val created = timestamp("Created").defaultExpression(CurrentTimestamp)
val lastUsed = timestamp("LastUsed").defaultExpression(CurrentTimestamp)
}
enum class WorldType {
BAU,
BUILDER,
TEAM,
ARENA,
TEMPLATE,
}
class SteamwarWorld(id: EntityID<UUID>) : Entity<UUID>(id) {
var name by WorldTable.name
private set
var version by WorldTable.version
private set
var type by WorldTable.type
private set
var owner by WorldTable.owner
private set
var team by WorldTable.team
private set
var lockState by WorldTable.lockState
private set
var deleted by WorldTable.deleted
private set
val created by WorldTable.created
var lastUsed by WorldTable.lastUsed
private set
val archived: Boolean
get() = !storageDirectory.exists() && archiveFile.exists()
val shouldArchive: Boolean
get() = !archived && (deleted || lastUsed.plus(7, ChronoUnit.DAYS).isBefore(Instant.now()))
val uuid: UUID
get() = id.value
val storageDirectory: File
get() = File(WORLD_STORAGE, id.value.toString())
private val archiveFile: File
get() = File(ARCHIVE_WORLD_STORAGE, "${id.value}.zip")
@JvmOverloads
fun setupAndGetStoragePath(prototype: File? = null): String {
if (archived) {
loadFromArchive()
}
val needsInitialization = !storageDirectory.exists() || storageDirectory.list()?.isEmpty() == true
if (needsInitialization) {
if (prototype != null && prototype.exists()) {
prototype.copyRecursively(storageDirectory, overwrite = true)
} else {
storageDirectory.mkdirs()
}
}
useDb {
lastUsed = Instant.now()
}
return storageDirectory.path
}
fun markDeleted() = useDb {
deleted = true
}
fun rename(newName: String) = useDb {
name = newName
}
fun archiveIfNeeded(): Boolean {
if (!shouldArchive) return false
File(ARCHIVE_WORLD_STORAGE).mkdirs()
return archiveWorld() == 0
}
fun changeVersion(newVersion: Int) = useDb {
version = newVersion
}
fun changeLockState(newLockState: String?) = useDb {
lockState = newLockState
}
private fun archiveWorld() = ProcessBuilder("zip", "-u9oymrqq", "$ARCHIVE_WORLD_STORAGE/${id.value}.zip", id.value.toString())
.directory(File(WORLD_STORAGE))
.inheritIO()
.start()
.waitFor()
private fun loadFromArchive() = ProcessBuilder("unzip", "-qq", "-o", "$ARCHIVE_WORLD_STORAGE/${id.value}.zip", "-d", WORLD_STORAGE)
.inheritIO()
.start()
.waitFor()
companion object : EntityClass<UUID, SteamwarWorld>(WorldTable) {
const val WORLD_STORAGE = "/worlds/storage"
const val ARCHIVE_WORLD_STORAGE = "/mnt/storage/worlds/storage"
const val DEFAULT_BAU_WORLD_LIMIT = 3
const val EXTRA_BAU_WORLD_LIMIT = 10
const val TEAM_WORLD_LIMIT = 2
@JvmStatic
fun getWorld(uuid: UUID) = useDb {
findById(uuid)
}
@JvmStatic
fun getBauWorld(user: SteamwarUser, version: Int) = useDb {
find {
(WorldTable.owner eq user.id) and
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.BAU) and
not(WorldTable.deleted)
}.firstOrNull()
}
@JvmStatic
fun getBauWorld(user: SteamwarUser, name: String, version: Int) = useDb {
find {
(WorldTable.owner eq user.id) and
(WorldTable.name eq name) and
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.BAU) and
not(WorldTable.deleted)
}.firstOrNull()
}
@JvmStatic
fun getBauWorlds(user: SteamwarUser) = useDb {
find {
(WorldTable.owner eq user.id) and
(WorldTable.type eq WorldType.BAU) and
not(WorldTable.deleted)
}.orderBy(WorldTable.created to SortOrder.ASC).toList()
}
@JvmStatic
fun countBauWorlds(user: SteamwarUser) = useDb {
find {
(WorldTable.owner eq user.id) and
(WorldTable.type eq WorldType.BAU) and
not(WorldTable.deleted)
}.count()
}
@JvmStatic
@JvmOverloads
fun getOrCreateBauWorld(user: SteamwarUser, version: Int, prototype: File? = null): SteamwarWorld =
getBauWorld(user, version) ?: createWorld(user, user.userName, version, WorldType.BAU, prototype)
@JvmStatic
@JvmOverloads
fun getOrCreateBauWorld(user: SteamwarUser, name: String, version: Int, prototype: File? = null): SteamwarWorld =
getBauWorld(user, name, version) ?: createWorld(user, name, version, WorldType.BAU, prototype)
@JvmStatic
fun getBuilderWorld(name: String, version: Int) = useDb {
find {
(WorldTable.name eq name) and
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.BUILDER) and
not(WorldTable.deleted)
}.firstOrNull()
}
@JvmStatic
fun getBuilderWorlds(version: Int) = useDb {
find {
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.BUILDER) and
not(WorldTable.deleted)
}.toList()
}
@JvmStatic
@JvmOverloads
fun getOrCreateBuilderWorld(name: String, version: Int, prototype: File? = null): SteamwarWorld =
getBuilderWorld(name, version) ?: createWorld(null, name, version, WorldType.BUILDER, prototype)
@JvmStatic
fun getTeamWorld(team: Team, name: String, version: Int) = useDb {
find {
(WorldTable.team eq team.id) and
(WorldTable.name eq name) and
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.TEAM) and
not(WorldTable.deleted)
}.firstOrNull()
}
@JvmStatic
fun getTeamWorlds(team: Team) = useDb {
find {
(WorldTable.team eq team.id) and
(WorldTable.type eq WorldType.TEAM) and
not(WorldTable.deleted)
}.orderBy(WorldTable.created to SortOrder.ASC).toList()
}
@JvmStatic
@JvmOverloads
fun getOrCreateTeamWorld(team: Team, name: String, version: Int, prototype: File? = null): SteamwarWorld =
getTeamWorld(team, name, version) ?: createWorld(null, name, version, WorldType.TEAM, prototype, team)
@JvmStatic
fun countTeamWorlds(team: Team) = useDb {
find {
(WorldTable.team eq team.id) and
(WorldTable.type eq WorldType.TEAM) and
not(WorldTable.deleted)
}.count()
}
@JvmStatic
fun getArenaWorld(mode: String, map: String, version: Int) = useDb {
find {
(WorldTable.name eq arenaWorldName(mode, map)) and
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.ARENA) and
not(WorldTable.deleted)
}.firstOrNull()
}
@JvmStatic
@JvmOverloads
fun getOrCreateArenaWorld(mode: String, map: String, version: Int, prototype: File? = null): SteamwarWorld =
getArenaWorld(mode, map, version) ?: createWorld(null, arenaWorldName(mode, map), version, WorldType.ARENA, prototype)
@JvmStatic
fun getTemplateWorld(name: String, version: Int) = useDb {
find {
(WorldTable.name eq name) and
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.TEMPLATE) and
not(WorldTable.deleted)
}.firstOrNull()
}
@JvmStatic
fun getTemplateWorlds() = useDb {
find {
(WorldTable.type eq WorldType.TEMPLATE) and
not(WorldTable.deleted)
}.orderBy(WorldTable.name to SortOrder.ASC).toList()
}
@JvmStatic
fun getTemplateWorlds(version: Int) = useDb {
find {
(WorldTable.version eq version) and
(WorldTable.type eq WorldType.TEMPLATE) and
not(WorldTable.deleted)
}.orderBy(WorldTable.name to SortOrder.ASC).toList()
}
@JvmStatic
@JvmOverloads
fun getOrCreateTemplateWorld(name: String, version: Int, prototype: File? = null): SteamwarWorld =
getTemplateWorld(name, version) ?: createWorld(null, name, version, WorldType.TEMPLATE, prototype)
@JvmStatic
fun getAllActiveWorlds() = useDb {
find { not(WorldTable.deleted) }.toList()
}
@JvmStatic
fun getWorldsToArchive() = useDb {
find {
not(WorldTable.deleted) or (WorldTable.deleted eq true)
}.toList().filter { it.shouldArchive }
}
private fun arenaWorldName(mode: String, map: String) = "$mode/$map"
@JvmStatic
@JvmOverloads
fun createWorld(user: SteamwarUser?, name: String, version: Int, type: WorldType, prototype: File? = null, team: Team? = null): SteamwarWorld {
val world = useDb { new {
this.name = name
this.version = version
this.type = type
this.owner = user?.id
this.team = team?.id
} }
world.setupAndGetStoragePath(prototype)
return world
}
}
}