From 2405c5e6205f87a16dc8d3c3929625a2f54105b7 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Tue, 8 Apr 2025 21:31:47 +0200 Subject: [PATCH 1/4] Fix spectator handling --- .../de/steamwar/fightsystem/FightSystem.java | 1 + .../de/steamwar/fightsystem/fight/Fight.java | 34 ------ .../steamwar/fightsystem/fight/FightTeam.java | 10 +- .../fightsystem/listener/LeaveableArena.java | 2 +- .../fightsystem/listener/Permanent.java | 6 +- .../fightsystem/listener/Spectator.java | 102 ++++++++++++++++++ .../fightsystem/listener/TeamArea.java | 44 ++------ 7 files changed, 118 insertions(+), 81 deletions(-) create mode 100644 FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index 23e2bb0c..b32a41b9 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -97,6 +97,7 @@ public class FightSystem extends JavaPlugin { new PrepareSchem(); new TestJoin(); new NormalJoin(); + new Spectator(); new RunningWorldInteraction(); new PersonalKitCreator(); new ArrowStopper(); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java index 5b8f62f9..1f205122 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java @@ -104,40 +104,6 @@ public class Fight { return null; } - @SuppressWarnings("deprecation") - public static void setPlayerGamemode(Player player, GameMode gameMode) { - player.setGameMode(gameMode); - - if(gameMode == GameMode.SPECTATOR) { - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.hidePlayer(player); - player.hidePlayer(currentPlayer); - } - } - - if(Config.test() || Config.isReferee(player)) - return; - - Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { - if(!player.isOnline()) - return; - pseudoSpectator(player, true); - }, 1); - }else if(gameMode == GameMode.SURVIVAL) { - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.showPlayer(player); - player.showPlayer(currentPlayer); - } - } - } - } - - public static void pseudoSpectator(Player player, boolean enable) { - TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.GAMEMODE, new GameProfile(player.getUniqueId(), player.getName()), enable ? GameMode.CREATIVE : GameMode.SPECTATOR)); - } - public static boolean publicOnly() { if (Config.OnlyPublicSchematics) { return true; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java index 3c834fd1..0cb68f71 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java @@ -282,9 +282,9 @@ public class FightTeam { FightSystem.getHullHider().updatePlayer(player); if(FightState.Spectate.contains(FightState.getFightState())) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); } else { - Fight.setPlayerGamemode(player, GameMode.SURVIVAL); + player.setGameMode(GameMode.SURVIVAL); (FightState.ingame() ? fightPlayer.getKit() : memberKit).loadToPlayer(player); } }); @@ -317,7 +317,7 @@ public class FightTeam { entity.teleport(Config.SpecSpawn); fightPlayer.ifPlayer(player -> { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); player.getInventory().clear(); if(player.isOnline()){ @@ -517,14 +517,14 @@ public class FightTeam { @Override public void enable() { players.values().forEach(fightPlayer -> { - fightPlayer.ifPlayer(player -> Fight.setPlayerGamemode(player, GameMode.SPECTATOR)); + fightPlayer.ifPlayer(player -> player.setGameMode(GameMode.SPECTATOR)); fightPlayer.getEntity().teleport(FightTeam.this.spawn); }); } @Override public void disable() { - players.values().forEach(fightPlayer -> fightPlayer.ifPlayer(player -> Fight.setPlayerGamemode(player, GameMode.SURVIVAL))); + players.values().forEach(fightPlayer -> fightPlayer.ifPlayer(player -> player.setGameMode(GameMode.SURVIVAL))); } } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java index 9d0bb4e2..36a5a189 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java @@ -84,6 +84,6 @@ public class LeaveableArena implements Listener { private void markInArena(Player player) { spectatorsInArena.put(player, player.getGameMode()); - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java index 2f3138ec..4976463c 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java @@ -74,7 +74,7 @@ public class Permanent implements Listener { public void handlePlayerRespawn(PlayerRespawnEvent event){ Player player = event.getPlayer(); if(Fight.fighting(player)) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); FightTeam team = Fight.getPlayerTeam(player); event.setRespawnLocation(team == null ? Config.SpecSpawn : team.getSpawn()); @@ -98,11 +98,11 @@ public class Permanent implements Listener { FightPlayer fp = Fight.getFightPlayer(player); if (!Config.ArenaLeaveable && fp == null) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); spectatorTeam.addEntry(player.getName()); player.teleport(Config.SpecSpawn); } else if(fp != null && !fp.isLiving()) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); player.teleport(fp.getTeam().getSpawn()); } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java new file mode 100644 index 00000000..cdd034a1 --- /dev/null +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java @@ -0,0 +1,102 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.listener; + +import java.util.HashSet; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerGameModeChangeEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import com.comphenix.tinyprotocol.TinyProtocol; +import com.mojang.authlib.GameProfile; + +import de.steamwar.core.ProtocolWrapper; +import de.steamwar.fightsystem.ArenaMode; +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.fight.Fight; +import de.steamwar.fightsystem.fight.FightPlayer; +import de.steamwar.fightsystem.states.FightState; +import de.steamwar.fightsystem.states.StateDependentListener; +import de.steamwar.fightsystem.states.StateDependentTask; + + +public class Spectator implements Listener { + + private final Set pseudoSpectator = new HashSet<>(); + + public Spectator() { + new StateDependentListener(ArenaMode.All, FightState.All, this); + new StateDependentTask(ArenaMode.AntiTest, FightState.All, this::pseudoSpectatorCheck, 1, 1); + } + + @EventHandler + @SuppressWarnings("deprecation") + public void onGameModeChange(PlayerGameModeChangeEvent e) { + Player player = e.getPlayer(); + + if (e.getNewGameMode() == GameMode.SPECTATOR) { + for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { + if(currentPlayer.getUniqueId() != player.getUniqueId()) + currentPlayer.hidePlayer(player); + } + } else { + for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { + if(currentPlayer.getUniqueId() != player.getUniqueId()) + currentPlayer.showPlayer(player); + } + } + } + + @EventHandler + public void playerQuit(PlayerQuitEvent e) { + pseudoSpectator.remove(e.getPlayer()); + } + + private void pseudoSpectatorCheck() { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getGameMode() != GameMode.SPECTATOR) { + pseudoSpectator.remove(player); + continue; + } + + if (Config.isReferee(player)) + continue; + + FightPlayer fightPlayer = Fight.getFightPlayer(player); + if (fightPlayer == null || !fightPlayer.getTeam().getExtendRegion().playerInRegion(player.getLocation())) { + if (pseudoSpectator.add(player)) + pseudoSpectator(player, true); + } else { + if (pseudoSpectator.remove(player)) + pseudoSpectator(player, false); + } + } + } + + private static void pseudoSpectator(Player player, boolean enable) { + TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.GAMEMODE, new GameProfile(player.getUniqueId(), player.getName()), enable ? GameMode.CREATIVE : GameMode.SPECTATOR)); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java index 2720b25c..2f888452 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java @@ -19,9 +19,14 @@ package de.steamwar.fightsystem.listener; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.Config; -import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.events.BoardingEvent; import de.steamwar.fightsystem.events.TeamDeathEvent; import de.steamwar.fightsystem.events.TeamLeaveEvent; @@ -32,23 +37,12 @@ import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.states.StateDependentListener; -import de.steamwar.fightsystem.states.StateDependentTask; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; - -import java.util.HashSet; -import java.util.Set; public class TeamArea implements Listener { private final FightTeam team; private final Border spectatorBorder; private final Border bordingBorder; - private final Set realSpectator = new HashSet<>(); public TeamArea(FightTeam team) { this.team = team; @@ -56,7 +50,6 @@ public class TeamArea implements Listener { this.bordingBorder = new Border(team.getExtendRegion().to2d(), true, 1, "NO_ENTERN", team.getName() + ".boardingBorder"); new StateDependentListener(ArenaMode.AntiTest, FightState.All, this); - new StateDependentTask(ArenaMode.AntiTest, FightState.TeamFix, this::realSpectatorCheck, 1, 1); new OneShotStateDependent(ArenaMode.AntiTest, FightState.Spectate, () -> Fight.teams().forEach(t -> t.getPlayers().forEach(this::teamSpectator))); } @@ -114,30 +107,5 @@ public class TeamArea implements Listener { Player player = e.getPlayer(); spectatorBorder.removePlayer(player); bordingBorder.removePlayer(player); - realSpectator.remove(player); - } - - private void realSpectatorCheck() { - for(FightPlayer fightPlayer : team.getPlayers()) { - if(fightPlayer.isLiving()) - continue; - - fightPlayer.ifPlayer(player -> { - boolean inRegion = team.getExtendRegion().playerInRegion(player.getLocation()); - if(inRegion && !realSpectator.contains(player)) { - realSpectator.add(player); - - //Later to prevent race condition with Fight.setSpecatator() during respawn - Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { - if(!player.isOnline()) - return; - Fight.pseudoSpectator(player, false); - }, 2); - }else if(!inRegion && realSpectator.contains(player)) { - Fight.pseudoSpectator(player, true); - realSpectator.remove(player); - } - }); - } } } From f2d8c9c02b8809cf5bd37ac20b1a4b426af3a079 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Tue, 8 Apr 2025 21:34:41 +0200 Subject: [PATCH 2/4] Only AntiTest --- .../src/de/steamwar/fightsystem/listener/Spectator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java index cdd034a1..405f2b0d 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java @@ -48,7 +48,7 @@ public class Spectator implements Listener { private final Set pseudoSpectator = new HashSet<>(); public Spectator() { - new StateDependentListener(ArenaMode.All, FightState.All, this); + new StateDependentListener(ArenaMode.AntiTest, FightState.All, this); new StateDependentTask(ArenaMode.AntiTest, FightState.All, this::pseudoSpectatorCheck, 1, 1); } From cf4ac95c2f4d55c3caf47babea81ce695581a3fe Mon Sep 17 00:00:00 2001 From: Lixfel Date: Wed, 9 Apr 2025 21:04:28 +0200 Subject: [PATCH 3/4] Bugfix after testing --- .../fightsystem/listener/Spectator.java | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java index 405f2b0d..399970ca 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java @@ -26,8 +26,10 @@ import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerGameModeChangeEvent; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import com.comphenix.tinyprotocol.TinyProtocol; @@ -52,20 +54,30 @@ public class Spectator implements Listener { new StateDependentTask(ArenaMode.AntiTest, FightState.All, this::pseudoSpectatorCheck, 1, 1); } - @EventHandler - @SuppressWarnings("deprecation") - public void onGameModeChange(PlayerGameModeChangeEvent e) { + @EventHandler(priority = EventPriority.MONITOR) + public void handlePlayerJoin(PlayerJoinEvent e) { Player player = e.getPlayer(); - if (e.getNewGameMode() == GameMode.SPECTATOR) { - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId()) - currentPlayer.hidePlayer(player); + if(player.getGameMode() == GameMode.SPECTATOR) + gameModeChange(player, GameMode.SPECTATOR); + } + + @EventHandler + public void onGameModeChange(PlayerGameModeChangeEvent e) { + gameModeChange(e.getPlayer(), e.getNewGameMode()); + } + + @SuppressWarnings("deprecation") + private void gameModeChange(Player player, GameMode gameMode) { + if (gameMode == GameMode.SPECTATOR) { + for(Player p : Bukkit.getServer().getOnlinePlayers()) { + if(p.getUniqueId() != player.getUniqueId()) + p.hidePlayer(player); } } else { - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId()) - currentPlayer.showPlayer(player); + for(Player p : Bukkit.getServer().getOnlinePlayers()) { + if(p.getUniqueId() != player.getUniqueId()) + p.showPlayer(player); } } } From 130404850982f3a6fbb4ffb64b3b60fbcbd849a1 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Fri, 11 Apr 2025 00:07:53 +0200 Subject: [PATCH 4/4] Refactors SchematicNode queries for efficiency --- .../src/de/steamwar/sql/SchematicNode.java | 136 +++++++++++------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java index bece8549..87b7cac4 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java @@ -31,10 +31,13 @@ public class SchematicNode { 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)); + 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 static final Map>> TAB_CACHE = new HashMap<>(); + public static void clear() { TAB_CACHE.clear(); } @@ -42,39 +45,60 @@ public class SchematicNode { private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode "; private static final Table table = new Table<>(SchematicNode.class); - private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", "NodeType"); - private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem", "NodeType", "NodeRank", "ReplaceColor", "AllowReplay"); + 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", "ReplaceColor", "AllowReplay"); private static final Statement delete = table.delete(Table.PRIMARY); - private static final SelectStatement byId = new SelectStatement<>(table, nodeSelector + "WHERE NodeId = ?"); - private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?"); - private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); - private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); - private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); - private static final SelectStatement byType = new SelectStatement<>(table, nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); - private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); - private static final SelectStatement list = new SelectStatement<>(table, "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay 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, ReplaceColor, AllowReplay FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName"); - private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay 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, ReplaceColor, AllowReplay FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?"); - private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); - private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?"); - private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE NodeId = ?"); - private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); + private static final SelectStatement byId = new SelectStatement<>(table, + nodeSelector + "WHERE NodeId = ?"); + private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, + nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?"); + private static final SelectStatement byParent = new SelectStatement<>(table, + nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); + private static final SelectStatement byOwnerType = new SelectStatement<>(table, + nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); + private static final SelectStatement byType = new SelectStatement<>(table, + nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); + private static final SelectStatement all = new SelectStatement<>(table, + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId"); + private static final SelectStatement list = new SelectStatement<>(table, + "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay 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, ReplaceColor, AllowReplay FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName"); + private static final SelectStatement byParentName = new SelectStatement<>(table, + "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay 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, ReplaceColor, AllowReplay FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?"); + private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeId = ?"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, + "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId" + + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?"); + private static final SelectStatement byIdAndUser = new SelectStatement<>(table, + "SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE NodeId = ?"); + private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, + "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); static { NodeMember.init(); } - @Field(keys = {Table.PRIMARY}, autoincrement = true) + @Field(keys = { Table.PRIMARY }, autoincrement = true) private final int nodeId; - @Field(keys = {"OwnerNameParent"}) + @Field(keys = { "OwnerNameParent" }) private final int nodeOwner; @Field(def = "0") @Getter private final int effectiveOwner; - @Field(keys = {"OwnerNameParent"}) + @Field(keys = { "OwnerNameParent" }) private String nodeName; - @Field(keys = {"OwnerNameParent"}, nullable = true) + @Field(keys = { "OwnerNameParent" }, nullable = true) private Integer parentNode; @Field(def = "CURRENT_TIMESTAMP") private Timestamp lastUpdate; @@ -102,8 +126,7 @@ public class SchematicNode { SchematicType nodeType, int nodeRank, boolean replaceColor, - boolean allowReplay - ) { + boolean allowReplay) { this.nodeId = nodeId; this.nodeOwner = nodeOwner; this.effectiveOwner = effectiveOwner; @@ -118,7 +141,7 @@ public class SchematicNode { } public static List getAll(SteamwarUser user) { - return all.listSelect(user); + return all.listSelect(user, user, user); } public static Map> getAllMap(SteamwarUser user) { @@ -130,7 +153,8 @@ public class SchematicNode { } public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { - return byParentName.select(user, schematicId, user, name, user, schematicId, user, schematicId, schematicId, name); + return byParentName.select(user, schematicId, user, name, user, schematicId, user, schematicId, schematicId, + name); } public static List accessibleByUserType(SteamwarUser user, SchematicType type) { @@ -142,10 +166,11 @@ public class SchematicNode { } public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { - return schematicAccessibleForUser.select(user, schematicId) != null; + return schematicAccessibleForUser.select(user, user, user, schematicId) != null; } - public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { + public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, + Integer parentId) { return accessibleByUserTypeInParent.listSelect(user, user, type, user, parentId); } @@ -160,7 +185,8 @@ public class SchematicNode { private static Map> map(List in) { Map> map = new HashMap<>(); for (SchematicNode effectiveSchematicNode : in) { - map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()).add(effectiveSchematicNode); + map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()) + .add(effectiveSchematicNode); } return map; } @@ -218,7 +244,8 @@ public class SchematicNode { return byId.select(id); } - public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { + public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, + Integer parent) { return accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent); } @@ -283,10 +310,12 @@ public class SchematicNode { } if (s.contains("/")) { String[] layers = s.split("/"); - Optional currentNode = Optional.ofNullable(SchematicNode.byParentName(user, null, layers[0])); + Optional currentNode = Optional + .ofNullable(SchematicNode.byParentName(user, null, layers[0])); for (int i = 1; i < layers.length; i++) { int finalI = i; - Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode.byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); + Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode + .byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); if (!node.isPresent()) { return null; } else { @@ -365,7 +394,7 @@ public class SchematicNode { @Deprecated public void setType(String type) { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); this.nodeType = SchematicType.fromDB(type); updateDB(); @@ -376,13 +405,13 @@ public class SchematicNode { } public String getFileEnding() { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); return NodeData.get(this).getNodeFormat().getFileEnding(); } public int getRank() { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); return nodeRank; } @@ -393,19 +422,19 @@ public class SchematicNode { } public void setRank(int rank) { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); this.nodeRank = rank; } public SchematicType getSchemtype() { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); return nodeType; } public void setSchemtype(SchematicType type) { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); this.nodeType = type; updateDB(); @@ -416,7 +445,7 @@ public class SchematicNode { } public void setReplaceColor(boolean replaceColor) { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); this.replaceColor = replaceColor; updateDB(); @@ -427,14 +456,15 @@ public class SchematicNode { } public void setAllowReplay(boolean allowReplay) { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); this.allowReplay = allowReplay; updateDB(); } public SchematicNode getParentNode() { - if(parentNode == null) return null; + if (parentNode == null) + return null; return SchematicNode.getSchematicNode(parentNode); } @@ -486,7 +516,7 @@ public class SchematicNode { } public String generateBreadcrumbs() { - if(brCache == null) { + if (brCache == null) { brCache = generateBreadcrumbs("/"); } return brCache; @@ -495,11 +525,15 @@ public class SchematicNode { public String generateBreadcrumbs(String split) { StringBuilder builder = new StringBuilder(getName()); Optional currentNode = Optional.of(this); - if(currentNode.map(SchematicNode::isDir).orElse(false)) { + if (currentNode.map(SchematicNode::isDir).orElse(false)) { builder.append(split); } while (currentNode.isPresent()) { - currentNode = currentNode.flatMap(schematicNode -> Optional.ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)).map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())).map(SchematicNode::getSchematicNode); + 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())); } return builder.toString(); @@ -508,17 +542,22 @@ public class SchematicNode { public List> generateBreadcrumbsMap(SteamwarUser user) { List> map = new ArrayList<>(); Optional currentNode = Optional.of(this); - if(currentNode.map(SchematicNode::isDir).orElse(false)) { + if (currentNode.map(SchematicNode::isDir).orElse(false)) { map.add(new AbstractMap.SimpleEntry<>(getName(), getId())); } while (currentNode.isPresent()) { - currentNode = currentNode.flatMap(schematicNode -> Optional.ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)).map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())).map(SchematicNode::getSchematicNode); + 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()))); } return map; } private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); + public static boolean invalidSchemName(String[] layers) { for (String layer : layers) { if (layer.isEmpty()) { @@ -535,7 +574,7 @@ public class SchematicNode { layer.contains(" ")) { return true; } - if(FORBIDDEN_NAMES.contains(layer.toLowerCase())) { + if (FORBIDDEN_NAMES.contains(layer.toLowerCase())) { return true; } } @@ -549,14 +588,15 @@ public class SchematicNode { } 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)) { + if (TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); } List list = new ArrayList<>(); if (s.contains("/")) { String preTab = s.substring(0, s.lastIndexOf("/") + 1); SchematicNode pa = SchematicNode.getNodeFromPath(user, preTab); - if (pa == null) return new ArrayList<>(); + if (pa == null) + return new ArrayList<>(); List nodes = SchematicNode.list(user, pa.getId()); String br = pa.generateBreadcrumbs(); nodes.forEach(node -> list.add((sws ? "/" : "") + br + node.getName() + (node.isDir() ? "/" : "")));