Refactor SchematicNode

This commit is contained in:
2025-10-28 19:03:30 +01:00
parent c8ac984ad3
commit 1aff7b30a6
12 changed files with 426 additions and 599 deletions
@@ -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<Int>): 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
}
@@ -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;
}
}
@@ -17,618 +17,421 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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<Int>) : IntEntity(id) {
companion object : IntEntityClass<SchematicNode>(SchematicNodeTable) {
private val fieldIndex: Map<Expression<*>, 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<Integer, Map<String, List<String>>> TAB_CACHE = new HashMap<>();
val tabCache = mutableMapOf<Int, MutableMap<String, List<String>>>()
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<SchematicNode>.mapToIds(): Map<Int, SchematicNode> = this.associateBy { it.nodeId }
private static final Table<SchematicNode> 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<SchematicNode> byId = new SelectStatement<>(table,
nodeSelector + "WHERE NodeId = ?");
private static final SelectStatement<SchematicNode> byOwnerNameParent = new SelectStatement<>(table,
nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?");
private static final SelectStatement<SchematicNode> byParent = new SelectStatement<>(table,
nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName");
private static final SelectStatement<SchematicNode> dirsByParent = new SelectStatement<>(table, nodeSelector
+ "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName");
private static final SelectStatement<SchematicNode> byOwnerType = new SelectStatement<>(table,
nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName");
private static final SelectStatement<SchematicNode> byType = new SelectStatement<>(table,
nodeSelector + "WHERE NodeType = ? ORDER BY NodeName");
private static final SelectStatement<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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<SchematicNode> byIdAndUser = new SelectStatement<>(table,
"SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE NodeId = ?");
private static final SelectStatement<SchematicNode> 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<SchematicNode> 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<Integer, List<SchematicNode>> 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<SchematicNode> 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<SchematicNode> accessibleByUserType(SteamwarUser user, SchematicType type) {
return accessibleByUserType.listSelect(user, user, user, type);
}
public static Map<Integer, List<SchematicNode>> 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<SchematicNode> 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<SchematicNode> parentsOfNode(SteamwarUser user, Integer id) {
return allParentsOfNode.listSelect(id, user, user, user);
}
private static Map<Integer, List<SchematicNode>> map(List<SchematicNode> in) {
Map<Integer, List<SchematicNode>> 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<SchematicNode> getSchematicNodeInNode(SchematicNode parent) {
return getSchematicNodeInNode(parent.getId());
}
public static List<SchematicNode> getSchematicNodeInNode(Integer parent) {
return byParent.listSelect(parent);
}
public static List<SchematicNode> 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<SchematicNode> getAccessibleSchematicsOfTypeInParent(int owner, String schemType,
Integer parent) {
return accessibleByUserTypeParent(SteamwarUser.byId(owner), SchematicType.fromDB(schemType), parent);
}
public static List<SchematicNode> getAllAccessibleSchematicsOfType(int user, String schemType) {
return accessibleByUserType(SteamwarUser.byId(user), SchematicType.fromDB(schemType));
}
public static List<SchematicNode> getAllSchematicsOfType(int owner, String schemType) {
return byOwnerType.listSelect(owner, schemType);
}
@Deprecated
public static List<SchematicNode> getAllSchematicsOfType(String schemType) {
return byType.listSelect(schemType);
}
public static List<SchematicNode> getAllSchematicsOfType(SchematicType schemType) {
return byType.listSelect(schemType);
}
public static List<SchematicNode> deepGet(Integer parent, Predicate<SchematicNode> filter) {
List<SchematicNode> finalList = new ArrayList<>();
List<SchematicNode> 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<SchematicNode> getSchematicsAccessibleByUser(int user, Integer parent) {
return list(SteamwarUser.byId(user), parent);
}
@Deprecated
public static List<SchematicNode> getAllSchematicsAccessibleByUser(int user) {
return getAll(SteamwarUser.byId(user));
}
public static List<SchematicNode> getAllParentsOfNode(SchematicNode node) {
return getAllParentsOfNode(node.getId());
}
public static List<SchematicNode> 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<SchematicNode> currentNode = Optional
.ofNullable(SchematicNode.byParentName(user, null, layers[0]));
for (int i = 1; i < layers.length; i++) {
int finalI = i;
Optional<SchematicNode> 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<SchematicNode> =
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<SchematicNode> filterSchems(int user, Predicate<SchematicNode> filter) {
List<SchematicNode> finalList = new ArrayList<>();
List<SchematicNode> 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<String?> = s.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
var currentNode = byParentName(user, null, layers[0]!!)
for (i in 1..<layers.size) {
val node = currentNode?.let { n -> 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<Integer> 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<String>) = 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<String> {
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<String>()
if (s.contains("/")) {
val preTab = s.take(s.lastIndexOf("/") + 1)
val pa = getNodeFromPath(user, preTab) ?: return emptyList()
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 "")) })
} else {
val nodes: List<SchematicNode?> = 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<Int> 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<NodeMember> 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 <T> 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<NodeMember> 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<SchematicNode> 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<Map.Entry<String, Integer>> generateBreadcrumbsMap(SteamwarUser user) {
List<Map.Entry<String, Integer>> map = new ArrayList<>();
Optional<SchematicNode> 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<Pair<String, Int>> {
val map = mutableListOf<Pair<String, Int>>()
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<String> 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<String> 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<String> 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<SchematicNode> nodes = SchematicNode.list(user, pa.getId());
String br = pa.generateBreadcrumbs();
nodes.forEach(node -> list.add((sws ? "/" : "") + br + node.getName() + (node.isDir() ? "/" : "")));
} else {
List<SchematicNode> 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
}
@@ -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 <T: Any?> useDb(statement: JdbcTransaction.() -> T): T {
KotlinDatabase.ensureConnected()
return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db, statement)
}
fun <T : IntEntity> IntEntityClass<T>.fromSql(
@Language("MySQL") stmt: String,
args: List<Pair<ColumnType<*>, Any?>>,
fieldIndex: Map<Expression<*>, Int>
): List<T> = useDb {
exec(stmt, explicitStatementType = StatementType.SELECT, args = args) {
val list = mutableListOf<T>()
while (it.next()) {
list.add(wrapRow(ResultRow.create(JdbcResult(it), fieldIndex)))
}
list
} ?: listOf()
}
@@ -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<Integer> listInv = new SWListInv<>(player, SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION_TITLE", player, node.generateBreadcrumbs()), entries, (clickType, revision) -> {
SWListInv<Integer> 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();
@@ -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<String> 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);
}
@@ -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<SchematicNode> 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) {
@@ -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();
}
}
@@ -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));
}
}
@@ -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()
);
@@ -122,7 +122,7 @@ public class SchematicSelector {
list.add(renderItem(node));
}
SWListInv<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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<SchematicNode> getParent(SchematicNode node) {
return node.getOptionalParent().map(integer -> SchematicNode.byIdAndUser(SteamwarUser.byId(node.getEffectiveOwner()), integer));
private Optional<SchematicNode> getParent(SchematicNode node) {
return node.getOptionalParent().map(integer -> SchematicNode.byIdAndUser(user, integer));
}
public static SelectorTarget selectSchematic() {
@@ -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<ResponseUser>, 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