forked from SteamWar/SteamWar
Merge branch 'main' into add-db-indexes
# Conflicts: # CommonCore/SQL/src/de/steamwar/sql/BannedUserIPs.kt
This commit is contained in:
@@ -35,7 +35,11 @@ import java.time.Instant
|
||||
object BannedUserIPsTable: CompositeIdTable("BannedUserIPs") {
|
||||
val userId = reference("UserID", SteamwarUserTable).index()
|
||||
val timestamp = timestamp("Timestamp").index()
|
||||
val ip = varchar("IP", 45).index()
|
||||
val ip = varchar("IP", 45).entityId()
|
||||
|
||||
init {
|
||||
addIdColumn(userId)
|
||||
}
|
||||
|
||||
override val primaryKey = PrimaryKey(userId, ip)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class EventGroup(id: EntityID<Int>) : IntEntity(id) {
|
||||
set(value) {
|
||||
groupPointsPerDraw = value
|
||||
}
|
||||
val dependents by lazy { EventRelation.getGroupRelations(this).toList() }
|
||||
val dependents by lazy { EventRelation.getGroupRelations(this) }
|
||||
val lastFight by lazy { Optional.ofNullable(fights.maxByOrNull { it.startTime }) }
|
||||
|
||||
fun getId() = id.value
|
||||
|
||||
@@ -51,11 +51,11 @@ class EventRelation(id: EntityID<Int>) : IntEntity(id) {
|
||||
|
||||
@JvmStatic
|
||||
fun getFightRelations(fight: EventFight) =
|
||||
useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) } }
|
||||
useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) }.toList() }
|
||||
|
||||
@JvmStatic
|
||||
fun getGroupRelations(group: EventGroup) =
|
||||
useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) } }
|
||||
useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) }.toList() }
|
||||
|
||||
@JvmStatic
|
||||
fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb {
|
||||
|
||||
@@ -52,6 +52,10 @@ public final class GameModeConfig<M, W> {
|
||||
private static final Map<String, GameModeConfig<?, String>> byGameName;
|
||||
private static final Map<SchematicType, GameModeConfig<?, String>> bySchematicType;
|
||||
|
||||
public static <M> Collection<GameModeConfig<M, String>> getAll() {
|
||||
return (Collection) byFileName.values();
|
||||
}
|
||||
|
||||
public static <M> GameModeConfig<M, String> getByFileName(File file) {
|
||||
return (GameModeConfig<M, String>) byFileName.get(file.getName());
|
||||
}
|
||||
@@ -87,8 +91,24 @@ public final class GameModeConfig<M, W> {
|
||||
byFileName = new HashMap<>();
|
||||
byGameName = new HashMap<>();
|
||||
bySchematicType = new HashMap<>();
|
||||
SchematicType.values();
|
||||
DEFAULTS = SQLWrapper.impl.loadGameModeConfig(null);
|
||||
init();
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
byFileName.clear();
|
||||
byGameName.clear();
|
||||
bySchematicType.clear();
|
||||
|
||||
File folder = SQLWrapper.impl.getSchemTypesFolder();
|
||||
if (!folder.exists()) return;
|
||||
if (!folder.isDirectory()) return;
|
||||
|
||||
for (File file : Objects.requireNonNull(folder.listFiles())) {
|
||||
if (!file.getName().endsWith(".yml")) continue;
|
||||
if (file.getName().endsWith(".kits.yml")) continue;
|
||||
SQLWrapper.impl.loadGameModeConfig(file);
|
||||
}
|
||||
|
||||
byFileName.values().forEach(gameModeConfig -> {
|
||||
List<SchematicType> subTypes = Collections.unmodifiableList(gameModeConfig.Schematic.SubTypesStrings.stream()
|
||||
@@ -402,6 +422,13 @@ public final class GameModeConfig<M, W> {
|
||||
*/
|
||||
public final int WaterDepth;
|
||||
|
||||
/**
|
||||
* If TNT should break blocks even underwater
|
||||
*
|
||||
* @implSpec {@code true} by default
|
||||
*/
|
||||
public final boolean WaterDamage;
|
||||
|
||||
/**
|
||||
* The outer border of the arena, measured in blocks around the schematic areas
|
||||
*/
|
||||
@@ -433,6 +460,13 @@ public final class GameModeConfig<M, W> {
|
||||
*/
|
||||
public final boolean DisableSnowMelt;
|
||||
|
||||
/**
|
||||
* Disable ice forming
|
||||
*
|
||||
* @implSpec {@code false} by default
|
||||
*/
|
||||
public final boolean DisableIceForm;
|
||||
|
||||
/**
|
||||
* Allow leaving the arena area as spectator
|
||||
*
|
||||
@@ -457,11 +491,13 @@ public final class GameModeConfig<M, W> {
|
||||
private ArenaConfig(YMLWrapper loader, SchematicConfig.SizeConfig Size, List<Integer> EnterStages) {
|
||||
loaded = loader.canLoad();
|
||||
WaterDepth = loader.getInt("WaterDepth", 0);
|
||||
WaterDamage = loader.getBoolean("WaterDamage", true);
|
||||
Schem2Border = new Schem2BorderConfig(loader.with("Schem2Border"));
|
||||
SpawnOffset = new SpawnOffsetConfig(loader.with("SpawnOffset"), Size);
|
||||
BorderFromSchematic = loader.getInt("BorderFromSchematic", 21);
|
||||
GroundWalkable = loader.getBoolean("GroundWalkable", true);
|
||||
DisableSnowMelt = loader.getBoolean("DisableSnowMelt", false);
|
||||
DisableIceForm = loader.getBoolean("DisableIceForm", false);
|
||||
Leaveable = loader.getBoolean("Leaveable", false);
|
||||
AllowMissiles = loader.getBoolean("AllowMissiles", !EnterStages.isEmpty());
|
||||
NoFloor = loader.getBoolean("NoFloor", false);
|
||||
@@ -597,18 +633,18 @@ public final class GameModeConfig<M, W> {
|
||||
public final boolean IgnorePublicOnly;
|
||||
|
||||
/**
|
||||
* If obsidian and bedrock should be replaced during PRE_RUNNING
|
||||
* Replacements that should be done during PRE_RUNNING with no block updates
|
||||
*
|
||||
* @implSpec {@code false} by default
|
||||
* @implSpec {@code {}} by default
|
||||
*/
|
||||
public final boolean ReplaceObsidianBedrock;
|
||||
public final Map<M, M> ReplacementsWithoutBlockUpdates;
|
||||
|
||||
/**
|
||||
* If the replacement should happen with block updates
|
||||
* Replacements that should be done during PRE_RUNNING with block updates
|
||||
*
|
||||
* @implSpec {@code false} by default
|
||||
* @implSpec {@code {}} by default
|
||||
*/
|
||||
public final boolean ReplaceWithBlockupdates;
|
||||
public final Map<M, M> ReplacementsWithBlockUpdates;
|
||||
|
||||
/**
|
||||
* If the schematic perparation arena mode is time limited
|
||||
@@ -641,7 +677,7 @@ public final class GameModeConfig<M, W> {
|
||||
/**
|
||||
* Maximal blast resistance for the design blocks
|
||||
*
|
||||
* @implSpec {@code Double.MAX_VALUE} by default
|
||||
* @implSpec {@link SchematicConfig#MaxBlastResistance} by default
|
||||
*/
|
||||
public final double MaxDesignBlastResistance;
|
||||
|
||||
@@ -655,9 +691,9 @@ public final class GameModeConfig<M, W> {
|
||||
loaded = loader.canLoad();
|
||||
Size = new SizeConfig(loader.with("Size"));
|
||||
Inset = new InsetConfig(loader.with("Inset"));
|
||||
Type = loader.getSchematicType("Type", "Normal");
|
||||
Type = null;
|
||||
SubTypesStrings = loader.getStringList("SubTypes");
|
||||
SubTypes = loader.getSchematicTypeList("SubTypes");
|
||||
SubTypes = new ArrayList<>();
|
||||
Shortcut = loader.getString("Shortcut", "");
|
||||
Material = loader.getMaterial("Material", "STONE_BUTTON");
|
||||
ManualCheck = loader.getBoolean("ManualCheck", true);
|
||||
@@ -665,13 +701,11 @@ public final class GameModeConfig<M, W> {
|
||||
PasteAligned = loader.getBoolean("PasteAligned", false);
|
||||
OnlyPublicSchematics = loader.getBoolean("OnlyPublicSchematics", false);
|
||||
IgnorePublicOnly = loader.getBoolean("IgnorePublicOnly", false);
|
||||
ReplaceObsidianBedrock = loader.getBoolean("ReplaceObsidianBedrock", false);
|
||||
ReplaceWithBlockupdates = loader.getBoolean("ReplaceWithBlockupdates", false);
|
||||
UnlimitedPrepare = loader.getBoolean("UnlimitedPrepare", false);
|
||||
MaxBlocks = loader.getInt("MaxBlocks", 0);
|
||||
MaxDispenserItems = loader.getInt("MaxDispenserItems", 128);
|
||||
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
|
||||
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", Double.MAX_VALUE);
|
||||
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", MaxBlastResistance);
|
||||
|
||||
Map<Set<M>, Integer> Limited = new HashMap<>();
|
||||
for (Map<?, ?> entry : loader.getMapList("Limited")) {
|
||||
@@ -690,6 +724,9 @@ public final class GameModeConfig<M, W> {
|
||||
Limited.put(Collections.singleton((M) material), 0);
|
||||
});
|
||||
this.Limited = Collections.unmodifiableMap(Limited);
|
||||
|
||||
this.ReplacementsWithoutBlockUpdates = loader.getMap("ReplacementsWithoutBlockUpdates", loader.materialMapper, loader.materialMapper);
|
||||
this.ReplacementsWithBlockUpdates = loader.getMap("ReplacementsWithBlockUpdates", loader.materialMapper, loader.materialMapper);
|
||||
}
|
||||
|
||||
@ToString
|
||||
|
||||
@@ -88,8 +88,6 @@ class NodeData(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||
schemData.inputStream.let { if(decompress) GZIPInputStream(it) else it }
|
||||
}
|
||||
|
||||
fun schemData() = schemData(true)
|
||||
|
||||
override fun delete() = useDb { super.delete() }
|
||||
|
||||
enum class SchematicFormat(val fileEnding: String) {
|
||||
|
||||
@@ -95,7 +95,7 @@ class NodeMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||
{ Optional.ofNullable(it?.value) })
|
||||
private set
|
||||
|
||||
fun setParentId(id: Int?) {
|
||||
fun setParentId(id: Int?) = useDb {
|
||||
parent = Optional.ofNullable(id)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,5 @@ public interface SQLWrapper<M> {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
default void processSchematicType(GameModeConfig<?, String> gameModeConfig) {
|
||||
}
|
||||
|
||||
void additionalExceptionMetadata(StringBuilder builder);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,91 @@ class SchematicNode(id: EntityID<Int>) : IntEntity(id) {
|
||||
|
||||
@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",
|
||||
"""
|
||||
WITH RECURSIVE
|
||||
ESN_R AS (
|
||||
SELECT SchematicNode.NodeId AS NodeId,
|
||||
NM.UserId AS EffectiveOwner,
|
||||
NM.ParentId AS ParentNode
|
||||
FROM SchematicNode
|
||||
INNER JOIN NodeMember NM ON NM.NodeId = SchematicNode.NodeId
|
||||
UNION ALL
|
||||
SELECT S.NodeId AS NodeId,
|
||||
ESN_R.EffectiveOwner AS EffectiveOwner,
|
||||
S.ParentNode AS ParentNode
|
||||
FROM SchematicNode S
|
||||
INNER JOIN ESN_R ON S.ParentNode = ESN_R.NodeId
|
||||
),
|
||||
ESN_R2 AS (
|
||||
SELECT SchematicNode.NodeId AS NodeId,
|
||||
NM.UserId AS UserId,
|
||||
SchematicNode.NodeOwner AS EffectiveOwner,
|
||||
SchematicNode.ParentNode AS ParentNode
|
||||
FROM SchematicNode
|
||||
INNER JOIN NodeMember NM ON NM.NodeId = SchematicNode.NodeId
|
||||
UNION ALL
|
||||
SELECT S.NodeId AS NodeId,
|
||||
ESN_R2.EffectiveOwner AS EffectiveOwner,
|
||||
ESN_R2.UserId AS UserId,
|
||||
S.ParentNode AS ParentNode
|
||||
FROM SchematicNode S
|
||||
INNER JOIN ESN_R2 ON S.ParentNode = ESN_R2.NodeId
|
||||
WHERE S.NodeOwner <> ESN_R2.EffectiveOwner
|
||||
),
|
||||
ESN_R3 AS (
|
||||
SELECT SchematicNode.NodeId AS NodeId,
|
||||
SchematicNode.NodeOwner AS NodeOwner,
|
||||
SchematicNode.NodeOwner AS EffectiveOwner,
|
||||
SchematicNode.ParentNode AS ParentNode
|
||||
FROM SchematicNode
|
||||
UNION ALL
|
||||
SELECT S.NodeId AS NodeId,
|
||||
S.NodeOwner AS NodeOwner,
|
||||
ESN_R3.EffectiveOwner AS EffectiveOwner,
|
||||
S.ParentNode AS ParentNode
|
||||
FROM SchematicNode S
|
||||
INNER JOIN ESN_R3 ON S.ParentNode = ESN_R3.NodeId
|
||||
WHERE ESN_R3.NodeOwner <> S.NodeOwner
|
||||
),
|
||||
ResolvedNodes AS (
|
||||
SELECT ESN_R.NodeId AS NodeId,
|
||||
ESN_R.EffectiveOwner AS EffectiveOwner,
|
||||
ESN_R.ParentNode AS ParentNode
|
||||
FROM ESN_R
|
||||
UNION
|
||||
SELECT ESN_R2.NodeId AS NodeId,
|
||||
ESN_R2.UserId AS EffectiveOwner,
|
||||
ESN_R2.ParentNode AS ParentNode
|
||||
FROM ESN_R2
|
||||
INNER JOIN SchematicNode SN2 ON ESN_R2.NodeId = SN2.NodeId
|
||||
WHERE ESN_R2.ParentNode IS NOT NULL
|
||||
AND SN2.NodeOwner <> ESN_R2.EffectiveOwner
|
||||
UNION
|
||||
SELECT ESN_R3.NodeId AS NodeId,
|
||||
ESN_R3.EffectiveOwner AS EffectiveOwner,
|
||||
ESN_R3.ParentNode AS ParentNode
|
||||
FROM ESN_R3
|
||||
WHERE ESN_R3.NodeOwner <> ESN_R3.EffectiveOwner
|
||||
UNION
|
||||
SELECT SchematicNode.NodeId AS NodeId,
|
||||
SchematicNode.NodeOwner AS EffectiveOwner,
|
||||
SchematicNode.ParentNode AS ParentNode
|
||||
FROM SchematicNode
|
||||
),
|
||||
R AS (
|
||||
SELECT NodeId, ParentNode
|
||||
FROM ResolvedNodes
|
||||
WHERE NodeId = ?
|
||||
UNION
|
||||
SELECT E.NodeId, E.ParentNode
|
||||
FROM R
|
||||
INNER JOIN ResolvedNodes E ON R.ParentNode = E.NodeId
|
||||
WHERE 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
|
||||
""".trimIndent(),
|
||||
listOf(
|
||||
IntegerColumnType() to id,
|
||||
IntegerColumnType() to user.getId()
|
||||
@@ -288,7 +372,7 @@ class SchematicNode(id: EntityID<Int>) : IntEntity(id) {
|
||||
val list = mutableListOf<String>()
|
||||
if (s.contains("/")) {
|
||||
val preTab = s.take(s.lastIndexOf("/") + 1)
|
||||
val pa = getNodeFromPath(user, preTab) ?: return emptyList()
|
||||
val pa = getNodeFromPath(user, preTab) ?: return mutableListOf()
|
||||
val nodes: List<SchematicNode> = 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 "")) })
|
||||
|
||||
@@ -19,11 +19,7 @@
|
||||
|
||||
package de.steamwar.sql
|
||||
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
import java.util.Locale.getDefault
|
||||
import java.util.stream.Collectors
|
||||
|
||||
data class SchematicType(
|
||||
val name: String,
|
||||
@@ -47,58 +43,65 @@ data class SchematicType(
|
||||
@JvmField
|
||||
val Normal = SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false)
|
||||
|
||||
private val types: List<SchematicType>
|
||||
private val fromDB: Map<String, SchematicType>?
|
||||
private val types: MutableList<SchematicType> = mutableListOf()
|
||||
private val fromDB: MutableMap<String, SchematicType> = mutableMapOf()
|
||||
|
||||
init {
|
||||
val tmpTypes = mutableListOf<SchematicType>()
|
||||
val tmpFromDB = mutableMapOf<String, SchematicType>()
|
||||
|
||||
tmpTypes.add(Normal)
|
||||
tmpFromDB[Normal.toDB()] = Normal
|
||||
|
||||
val folder = SQLWrapper.impl.schemTypesFolder
|
||||
if (folder.exists()) {
|
||||
for (configFile in Arrays.stream<File?>(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()
|
||||
GameModeConfig.init()
|
||||
init()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun values() = types
|
||||
fun init() {
|
||||
types.clear()
|
||||
fromDB.clear()
|
||||
|
||||
types.add(Normal)
|
||||
fromDB[Normal.toDB()] = Normal
|
||||
|
||||
for (gameModeConfig in GameModeConfig.getAll<Any>()) {
|
||||
val type = gameModeConfig.Schematic.Type
|
||||
?: continue
|
||||
if (fromDB.containsKey(type.toDB())) continue
|
||||
|
||||
types.add(type)
|
||||
fromDB[type.toDB()] = type
|
||||
if (gameModeConfig.CheckQuestions.isNotEmpty() && type.checkType != null) {
|
||||
types.add(type.checkType)
|
||||
fromDB[type.checkType.toDB()] = type.checkType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromDB(value: String) = fromDB?.let { it[value.lowercase()] }
|
||||
fun values() =
|
||||
types
|
||||
|
||||
@JvmStatic
|
||||
fun fromDB(value: String) =
|
||||
fromDB[value.lowercase()]
|
||||
}
|
||||
|
||||
fun name() = name
|
||||
fun toDB() = name.lowercase()
|
||||
fun name() =
|
||||
name
|
||||
|
||||
fun check() = type == Type.CHECK_TYPE
|
||||
fun fightType() = type == Type.FIGHT_TYPE
|
||||
fun writeable() = type == Type.NORMAL
|
||||
fun toDB() =
|
||||
name.lowercase()
|
||||
|
||||
fun checkType() = if (manualCheck) checkType else this
|
||||
fun isAssignable() = type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck
|
||||
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,
|
||||
|
||||
@@ -186,10 +186,10 @@ class SteamwarUser(id: EntityID<Int>): IntEntity(id) {
|
||||
|
||||
val salt = ByteArray(16)
|
||||
random.nextBytes(salt)
|
||||
val saltString = Base64.getEncoder().encode(salt)
|
||||
val saltString = Base64.getEncoder().encodeToString(salt)
|
||||
|
||||
val hash = generateHash(value, salt)
|
||||
val hashString = Base64.getEncoder().encode(hash)
|
||||
val hashString = Base64.getEncoder().encodeToString(hash)
|
||||
|
||||
useDb {
|
||||
passwordInternal = "$hashString:$saltString"
|
||||
|
||||
@@ -32,8 +32,6 @@ object TeamTable : IntIdTable("Team", "TeamID") {
|
||||
val color = char("TeamColor", 1).default("8")
|
||||
val name = varchar("TeamName", 16).index()
|
||||
val deleted = bool("TeamDeleted").default(false)
|
||||
val address = text("Address").nullable()
|
||||
val port = ushort("Port").default(25565u)
|
||||
}
|
||||
|
||||
class Team(id: EntityID<Int>) : IntEntity(id) {
|
||||
@@ -67,8 +65,6 @@ class Team(id: EntityID<Int>) : IntEntity(id) {
|
||||
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 { useDb { 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() }
|
||||
@@ -96,16 +92,4 @@ class Team(id: EntityID<Int>) : IntEntity(id) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,7 @@ import org.yaml.snakeyaml.Yaml;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -160,6 +157,22 @@ final class YMLWrapper<M, W> {
|
||||
}
|
||||
}
|
||||
|
||||
public <K, V> Map<K, V> getMap(String path, Function<String, K> keyFunction, Function<String, V> valueFunction) {
|
||||
Object data = this.document.get(path);
|
||||
if (data instanceof Map) {
|
||||
Map<K, V> result = new HashMap<>();
|
||||
((Map<String, String>) data).forEach((keyString, valueString) -> {
|
||||
K key = keyFunction.apply(keyString.toUpperCase());
|
||||
V value = valueFunction.apply(valueString.toUpperCase());
|
||||
if (key == null || value == null) return;
|
||||
result.put(key, value);
|
||||
});
|
||||
return Collections.unmodifiableMap(result);
|
||||
} else {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Map<?, ?>> getMapList(String path) {
|
||||
Object value = this.document.get(path);
|
||||
if (value instanceof List) {
|
||||
|
||||
Reference in New Issue
Block a user