forked from SteamWar/SteamWar
Remove deprecated world management commands and associated SQL logic
Signed-off-by: Chaoscaot <max@maxsp.de>
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user