forked from SteamWar/SteamWar
Merge branch 'main' into 1.21.1/rplayer-fix
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bausystem.utils;
|
||||||
|
|
||||||
|
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class PlayerMovementWrapper21 implements PlayerMovementWrapper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Player player, Object object) {
|
||||||
|
ServerboundMovePlayerPacket packetPlayInFlying = ((ServerboundMovePlayerPacket) object);
|
||||||
|
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
|
||||||
|
if (packetPlayInFlying.hasPos) {
|
||||||
|
serverPlayer.setPosRaw(packetPlayInFlying.x, packetPlayInFlying.y, packetPlayInFlying.z);
|
||||||
|
}
|
||||||
|
if (packetPlayInFlying.hasRot) {
|
||||||
|
serverPlayer.setXRot(packetPlayInFlying.xRot);
|
||||||
|
serverPlayer.setYRot(packetPlayInFlying.yRot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convertToOut(Player player, Object object) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1030,6 +1030,7 @@ SCHEMATIC_GUI_ITEM=§eSchematics
|
|||||||
# TNTListener
|
# TNTListener
|
||||||
TLS_MESSAGE_79=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1}
|
TLS_MESSAGE_79=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1}
|
||||||
TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7with Fuse 80§8)
|
TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7with Fuse 80§8)
|
||||||
TLS_START_HELP=§8/§etls start §8: §7Start the TNT Listener
|
TLS_START_HELP=§8/§etls start §8- §7Start the TNT Listener
|
||||||
TLS_STOP_HELP=§8/§etls stop §8: §7Stop the TNT Listener
|
TLS_STOP_HELP=§8/§etls stop §8- §7Stop the TNT Listener
|
||||||
TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aon
|
TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aon
|
||||||
|
TLS_TOGGLE_HELP=§8/§etls§8: §7Toggle the TNT Listener
|
||||||
@@ -961,6 +961,7 @@ TYPEREPLACE_HELP=§8//§etyreplace §8[§7type§8] §8[§7type§8] §8- §7Erset
|
|||||||
# Schematics
|
# Schematics
|
||||||
SCHEMATIC_GUI_ITEM=§eSchematics
|
SCHEMATIC_GUI_ITEM=§eSchematics
|
||||||
TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7mit Fuse 80§8)
|
TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7mit Fuse 80§8)
|
||||||
TLS_START_HELP=§8/§etls start §8: §7Starte den TNT Listener
|
TLS_START_HELP=§8/§etls start §8- §7Starte den TNT Listener
|
||||||
TLS_STOP_HELP=§8/§etls stop §8: §7Stope den TNT Listener
|
TLS_STOP_HELP=§8/§etls stop §8- §7Stope den TNT Listener
|
||||||
TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aan
|
TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aan
|
||||||
|
TLS_TOGGLE_HELP=§8/§etls §8: §7Toggle den TNT Listener
|
||||||
@@ -27,8 +27,6 @@ import de.steamwar.sql.SteamwarUser;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@@ -39,13 +37,12 @@ public enum Permission {
|
|||||||
return bauweltMember.isSupervisor();
|
return bauweltMember.isSupervisor();
|
||||||
}),
|
}),
|
||||||
BUILD(bauweltMember -> {
|
BUILD(bauweltMember -> {
|
||||||
if (isTempOnlySpectator(bauweltMember)) return false;
|
|
||||||
return bauweltMember.isBuild() || SUPERVISOR.permissionPredicate.test(bauweltMember);
|
return bauweltMember.isBuild() || SUPERVISOR.permissionPredicate.test(bauweltMember);
|
||||||
}),
|
}),
|
||||||
/**
|
/**
|
||||||
* Only used for {@link BauMemberUpdate}
|
* Only used for {@link BauMemberUpdate}
|
||||||
*/
|
*/
|
||||||
REAL_SPECTATOR(bauweltMember -> {
|
SPECTATOR(bauweltMember -> {
|
||||||
return !bauweltMember.isBuild() && !bauweltMember.isSupervisor();
|
return !bauweltMember.isBuild() && !bauweltMember.isSupervisor();
|
||||||
}),
|
}),
|
||||||
/**
|
/**
|
||||||
@@ -55,28 +52,6 @@ public enum Permission {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
private static final Set<Integer> TEMP_ONLY_SPECTATOR = new HashSet<>();
|
|
||||||
|
|
||||||
private static boolean isTempOnlySpectator(BauweltMember bauweltMember) {
|
|
||||||
return TEMP_ONLY_SPECTATOR.contains(bauweltMember.getMemberID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isTempOnlySpectator(Player player) {
|
|
||||||
return TEMP_ONLY_SPECTATOR.contains(SteamwarUser.get(player.getUniqueId()).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forceOnlySpectator(Player player) {
|
|
||||||
TEMP_ONLY_SPECTATOR.add(SteamwarUser.get(player.getUniqueId()).getId());
|
|
||||||
BauMemberUpdate.baumemberUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only used by {@link BauMemberUpdate}
|
|
||||||
*/
|
|
||||||
public static void removeForceOnlySpectator(Player player) {
|
|
||||||
TEMP_ONLY_SPECTATOR.remove(SteamwarUser.get(player.getUniqueId()).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Predicate<BauweltMember> permissionPredicate;
|
private final Predicate<BauweltMember> permissionPredicate;
|
||||||
|
|
||||||
public boolean hasPermission(BauweltMember bauweltMember) {
|
public boolean hasPermission(BauweltMember bauweltMember) {
|
||||||
@@ -86,10 +61,10 @@ public enum Permission {
|
|||||||
|
|
||||||
public boolean hasPermission(Player member) {
|
public boolean hasPermission(Player member) {
|
||||||
if (SteamwarUser.get(member.getUniqueId()).getId() == BauServer.getInstance().getOwnerID()) {
|
if (SteamwarUser.get(member.getUniqueId()).getId() == BauServer.getInstance().getOwnerID()) {
|
||||||
return this != REAL_SPECTATOR;
|
return this != SPECTATOR;
|
||||||
}
|
}
|
||||||
BauweltMember bauweltMember = BauweltMember.getBauMember(BauServer.getInstance().getOwner(), member.getUniqueId());
|
BauweltMember bauweltMember = BauweltMember.getBauMember(BauServer.getInstance().getOwner(), member.getUniqueId());
|
||||||
if (bauweltMember == null) return this == REAL_SPECTATOR;
|
if (bauweltMember == null) return this == SPECTATOR;
|
||||||
return permissionPredicate.test(bauweltMember);
|
return permissionPredicate.test(bauweltMember);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ public class BauServer {
|
|||||||
private Integer owner;
|
private Integer owner;
|
||||||
|
|
||||||
public UUID getOwner() {
|
public UUID getOwner() {
|
||||||
return SteamwarUser.get(getOwnerID()).getUUID();
|
return SteamwarUser.byId(getOwnerID()).getUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOwnerID() {
|
public int getOwnerID() {
|
||||||
|
|||||||
+2
@@ -32,6 +32,7 @@ import org.bukkit.Bukkit;
|
|||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.data.type.Chest;
|
import org.bukkit.block.data.type.Chest;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.TNTPrimed;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||||
@@ -120,6 +121,7 @@ public class AutostartListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onEntityExplode(EntityExplodeEvent event) {
|
public void onEntityExplode(EntityExplodeEvent event) {
|
||||||
|
if (!(event.getEntity() instanceof TNTPrimed)) return;
|
||||||
if (regionStartTime.isEmpty()) {
|
if (regionStartTime.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
-71
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.bau;
|
|
||||||
|
|
||||||
import de.steamwar.bausystem.Permission;
|
|
||||||
import de.steamwar.command.PreviousArguments;
|
|
||||||
import de.steamwar.command.SWCommand;
|
|
||||||
import de.steamwar.command.TypeMapper;
|
|
||||||
import de.steamwar.linkage.Linked;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Linked
|
|
||||||
public class ForceSpectatorCommand extends SWCommand {
|
|
||||||
|
|
||||||
public ForceSpectatorCommand() {
|
|
||||||
super("forcespectator");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Register
|
|
||||||
public void forceSpectator(@Validator("supervisor") Player player, @Mapper("builder") Player other) {
|
|
||||||
Permission.forceOnlySpectator(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Mapper("builder")
|
|
||||||
public TypeMapper<Player> spectatorMapper() {
|
|
||||||
return new TypeMapper<>() {
|
|
||||||
@Override
|
|
||||||
public Player map(CommandSender commandSender, String[] previousArguments, String s) {
|
|
||||||
Player player = Bukkit.getPlayer(s);
|
|
||||||
if (player == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (Permission.BUILD.hasPermission(player) && !Permission.SUPERVISOR.hasPermission(player)) {
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
|
||||||
return Bukkit.getOnlinePlayers().stream()
|
|
||||||
.filter(Permission.BUILD::hasPermission)
|
|
||||||
.filter(player -> !Permission.SUPERVISOR.hasPermission(player))
|
|
||||||
.map(Player::getName)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,7 @@ public class InfoCommand extends SWCommand {
|
|||||||
|
|
||||||
@Register(description = "BAU_INFO_COMMAND_HELP")
|
@Register(description = "BAU_INFO_COMMAND_HELP")
|
||||||
public void genericCommand(Player p) {
|
public void genericCommand(Player p) {
|
||||||
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.get(bauServer.getOwnerID()).getUserName());
|
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.byId(bauServer.getOwnerID()).getUserName());
|
||||||
Region region = Region.getRegion(p.getLocation());
|
Region region = Region.getRegion(p.getLocation());
|
||||||
for (Flag flag : Flag.getFlags()) {
|
for (Flag flag : Flag.getFlags()) {
|
||||||
if (!region.getFlags().has(flag).isApplicable()) continue;
|
if (!region.getFlags().has(flag).isApplicable()) continue;
|
||||||
@@ -97,7 +97,7 @@ public class InfoCommand extends SWCommand {
|
|||||||
st.append("§8, ");
|
st.append("§8, ");
|
||||||
}
|
}
|
||||||
st.append("§7");
|
st.append("§7");
|
||||||
st.append(SteamwarUser.get(bauweltMembers.get(i).getMemberID()).getUserName());
|
st.append(SteamwarUser.byId(bauweltMembers.get(i).getMemberID()).getUserName());
|
||||||
}
|
}
|
||||||
return st.toString();
|
return st.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-60
@@ -21,9 +21,10 @@ package de.steamwar.bausystem.features.countingwand;
|
|||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.bausystem.region.Point;
|
import de.steamwar.bausystem.region.Point;
|
||||||
import de.steamwar.bausystem.shared.Pair;
|
|
||||||
import de.steamwar.bausystem.utils.ItemUtils;
|
import de.steamwar.bausystem.utils.ItemUtils;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.inventory.SWItem;
|
import de.steamwar.inventory.SWItem;
|
||||||
|
import lombok.Data;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -31,13 +32,32 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class Countingwand {
|
public class Countingwand {
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CountingWandComponent implements SWPlayer.Component {
|
||||||
|
private Point pos1;
|
||||||
|
private Point pos2;
|
||||||
|
|
||||||
|
public boolean setPosition(boolean pos1, Point point) {
|
||||||
|
if (this.pos1 == null || this.pos2 == null) {
|
||||||
|
this.pos1 = point;
|
||||||
|
this.pos2 = point;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Point current = pos1 ? this.pos1 : this.pos2;
|
||||||
|
if (current.equals(point)) return false;
|
||||||
|
if (pos1) {
|
||||||
|
this.pos1 = point;
|
||||||
|
} else {
|
||||||
|
this.pos2 = point;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static ItemStack getWandItem(Player player) {
|
public static ItemStack getWandItem(Player player) {
|
||||||
ItemStack itemStack = new SWItem(Material.STICK, BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE1", player), BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE2", player)), false, null).getItemStack();
|
ItemStack itemStack = new SWItem(Material.STICK, BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE1", player), BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE2", player)), false, null).getItemStack();
|
||||||
ItemUtils.setItem(itemStack, "countingwand");
|
ItemUtils.setItem(itemStack, "countingwand");
|
||||||
@@ -47,61 +67,20 @@ public class Countingwand {
|
|||||||
return itemStack;
|
return itemStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, Pair<Point, Point>> selections = new HashMap<>();
|
public boolean isCountingwand(ItemStack itemStack) {
|
||||||
|
return ItemUtils.isItem(itemStack, "countingwand");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCountingwand(ItemStack itemStack) {
|
public void checkSelection(final Point point, final boolean pos1, final Player p) {
|
||||||
return ItemUtils.isItem(itemStack, "countingwand");
|
SWPlayer player = SWPlayer.of(p);
|
||||||
}
|
CountingWandComponent countingWandComponent = player.getComponentOrDefault(CountingWandComponent.class, CountingWandComponent::new);
|
||||||
|
if (countingWandComponent.setPosition(pos1, point)) {
|
||||||
public void checkSelection(final Point point, final boolean pos1, final Player p) {
|
Point point1 = countingWandComponent.pos1;
|
||||||
Pair<Point, Point> selection = selections.get(p.getUniqueId().toString());
|
Point point2 = countingWandComponent.pos2;
|
||||||
final boolean newPos;
|
int amount = (Math.abs(point1.getX() - point2.getX()) + 1) * (Math.abs(point1.getY() - point2.getY()) + 1) * (Math.abs(point1.getZ() - point2.getZ()) + 1);
|
||||||
if (selection != null) {
|
String dimension = player.using(BauSystem.MESSAGE).parse("COUNTINGWAND_MESSAGE_VOLUME", amount);
|
||||||
if (pos1) {
|
String volume = player.parse("COUNTINGWAND_MESSAGE_DIMENSION", Math.abs(point1.getX() - point2.getX()) + 1, Math.abs(point1.getY() - point2.getY()) + 1, Math.abs(point1.getZ() - point2.getZ()) + 1);
|
||||||
newPos = !point.equals(selection.setKey(point));
|
player.sendMessage(pos1 ? "COUNTINGWAND_MESSAGE_RCLICK" : "COUNTINGWAND_MESSAGE_LCLICK", point.getX(), point.getY(), point.getZ(), dimension, volume);
|
||||||
} else {
|
}
|
||||||
newPos = !point.equals(selection.setValue(point));
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (pos1) {
|
|
||||||
selection = new Pair<>(point, null);
|
|
||||||
} else {
|
|
||||||
selection = new Pair<>(null, point);
|
|
||||||
}
|
|
||||||
selections.put(p.getUniqueId().toString(), selection);
|
|
||||||
newPos = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newPos) {
|
|
||||||
String dimension = getDimensions(p, selection.getKey(), selection.getValue());
|
|
||||||
String volume = getVolume(p, selection.getKey(), selection.getValue());
|
|
||||||
if (pos1) {
|
|
||||||
BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_RCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
|
|
||||||
} else {
|
|
||||||
BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_LCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removePlayer(Player p) {
|
|
||||||
selections.remove(p.getUniqueId().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVolume(Player player, final Point point1, final Point point2) {
|
|
||||||
if (point1 == null || point2 == null) {
|
|
||||||
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, 0);
|
|
||||||
}
|
|
||||||
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, getAmount(point1, point2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDimensions(Player player, final Point point1, final Point point2) {
|
|
||||||
if (point1 == null || point2 == null) {
|
|
||||||
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, 0, 0, 0);
|
|
||||||
}
|
|
||||||
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, Math.abs(point1.getX() - point2.getX()) + 1, Math.abs(point1.getY() - point2.getY()) + 1, Math.abs(point1.getZ() - point2.getZ()) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAmount(final Point point1, final Point point2) {
|
|
||||||
return (Math.abs(point1.getX() - point2.getX()) + 1) * (Math.abs(point1.getY() - point2.getY()) + 1) * (Math.abs(point1.getZ() - point2.getZ()) + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
-6
@@ -27,7 +27,6 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.util.RayTraceResult;
|
import org.bukkit.util.RayTraceResult;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -67,9 +66,4 @@ public class CountingwandListener implements Listener {
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
Countingwand.checkSelection(Point.fromLocation(Objects.requireNonNull(event.getClickedBlock()).getLocation()), false, event.getPlayer());
|
Countingwand.checkSelection(Point.fromLocation(Objects.requireNonNull(event.getClickedBlock()).getLocation()), false, event.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onLeave(PlayerQuitEvent event) {
|
|
||||||
Countingwand.removePlayer(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+29
-14
@@ -25,8 +25,11 @@ import de.steamwar.bausystem.configplayer.Config;
|
|||||||
import de.steamwar.bausystem.features.autostart.AutostartListener;
|
import de.steamwar.bausystem.features.autostart.AutostartListener;
|
||||||
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
|
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
|
||||||
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
|
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
import de.steamwar.entity.RFallingBlockEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@@ -45,7 +48,28 @@ import java.util.*;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class Detonator {
|
public class Detonator {
|
||||||
|
|
||||||
private static final Map<Player, REntityServer> ENTITIES_MAP = new HashMap<>();
|
public class DetonatorComponent implements SWPlayer.Component {
|
||||||
|
private final REntityServer entities = new REntityServer();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean hasUpdated = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMount(SWPlayer player) {
|
||||||
|
entities.addPlayer(player.getPlayer());
|
||||||
|
entities.setCallback((player1, entity, action) -> {
|
||||||
|
Vector vector = new Vector(entity.getX(), entity.getY(), entity.getZ());
|
||||||
|
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
entities.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final Vector HALF = new Vector(0.5, 0, 0.5);
|
private static final Vector HALF = new Vector(0.5, 0, 0.5);
|
||||||
|
|
||||||
public static boolean isDetonator(ItemStack itemStack) {
|
public static boolean isDetonator(ItemStack itemStack) {
|
||||||
@@ -53,28 +77,19 @@ public class Detonator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void showDetonator(Player p, List<Location> locs) {
|
public static void showDetonator(Player p, List<Location> locs) {
|
||||||
if (ENTITIES_MAP.containsKey(p)) return;
|
DetonatorComponent detonatorComponent = SWPlayer.of(p).getComponentOrDefault(DetonatorComponent.class, DetonatorComponent::new);
|
||||||
REntityServer entities = new REntityServer();
|
|
||||||
entities.setCallback((player, rEntity, entityAction) -> {
|
|
||||||
Vector vector = new Vector(rEntity.getX(), rEntity.getY(), rEntity.getZ());
|
|
||||||
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player);
|
|
||||||
DetonatorListener.HAS_UPDATED.add(player);
|
|
||||||
});
|
|
||||||
entities.addPlayer(p);
|
|
||||||
ENTITIES_MAP.put(p, entities);
|
|
||||||
|
|
||||||
locs.forEach(location -> {
|
locs.forEach(location -> {
|
||||||
RFallingBlockEntity entity = new RFallingBlockEntity(entities, location.clone().add(HALF), Material.RED_STAINED_GLASS);
|
RFallingBlockEntity entity = new RFallingBlockEntity(detonatorComponent.entities, location.clone().add(HALF), Material.RED_STAINED_GLASS);
|
||||||
entity.setNoGravity(true);
|
entity.setNoGravity(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hideDetonator(Player p) {
|
public static void hideDetonator(Player p) {
|
||||||
ENTITIES_MAP.remove(p).close();
|
SWPlayer.of(p).removeComponent(DetonatorComponent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasActiveDetonatorShow(Player p) {
|
public static boolean hasActiveDetonatorShow(Player p) {
|
||||||
return ENTITIES_MAP.containsKey(p);
|
return SWPlayer.of(p).hasComponent(DetonatorComponent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void activateDetonator(DetonatorStorage detonator) {
|
public static void activateDetonator(DetonatorStorage detonator) {
|
||||||
|
|||||||
+24
-32
@@ -24,6 +24,7 @@ import de.steamwar.bausystem.Permission;
|
|||||||
import de.steamwar.bausystem.SWUtils;
|
import de.steamwar.bausystem.SWUtils;
|
||||||
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
|
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
|
||||||
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
|
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -36,15 +37,11 @@ import org.bukkit.event.player.PlayerItemHeldEvent;
|
|||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Linked
|
@Linked
|
||||||
public class DetonatorListener implements Listener {
|
public class DetonatorListener implements Listener {
|
||||||
|
|
||||||
static final Set<Player> HAS_UPDATED = new HashSet<>();
|
|
||||||
|
|
||||||
static void addLocationToDetonator(Location location, Player p) {
|
static void addLocationToDetonator(Location location, Player p) {
|
||||||
|
SWPlayer.of(p).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
|
||||||
Detoblock detoblock = Detonator.getBlock(location.getBlock());
|
Detoblock detoblock = Detonator.getBlock(location.getBlock());
|
||||||
if (detoblock == Detoblock.INVALID) {
|
if (detoblock == Detoblock.INVALID) {
|
||||||
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_INVALID_BLOCK", p));
|
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_INVALID_BLOCK", p));
|
||||||
@@ -66,64 +63,59 @@ public class DetonatorListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
Player p = event.getPlayer();
|
Player p = event.getPlayer();
|
||||||
if (Detonator.isDetonator(p.getInventory().getItemInMainHand())) {
|
if (Detonator.isDetonator(p.getInventory().getItemInMainHand())) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
addLocationToDetonator(event.getBlock().getLocation(), p);
|
addLocationToDetonator(event.getBlock().getLocation(), p);
|
||||||
HAS_UPDATED.add(event.getPlayer());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
if (!Detonator.isDetonator(event.getItem())) {
|
if (!Detonator.isDetonator(event.getItem())) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
DetonatorStorage detonator = new ItemStorage(event.getPlayer());
|
DetonatorStorage detonator = new ItemStorage(event.getPlayer());
|
||||||
Detonator.activateDetonator(detonator);
|
Detonator.activateDetonator(detonator);
|
||||||
HAS_UPDATED.add(event.getPlayer());
|
SWPlayer.of(event.getPlayer()).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
if (!Permission.BUILD.hasPermission(event.getPlayer()) ||!Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
|
if (!Permission.BUILD.hasPermission(event.getPlayer()) || !Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
|
||||||
if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
|
if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
|
||||||
Detonator.hideDetonator(event.getPlayer());
|
Detonator.hideDetonator(event.getPlayer());
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
if (!Detonator.hasActiveDetonatorShow(event.getPlayer())) {
|
|
||||||
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!Detonator.hasActiveDetonatorShow(event.getPlayer())) {
|
||||||
if (HAS_UPDATED.contains(event.getPlayer())) {
|
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
|
||||||
HAS_UPDATED.remove(event.getPlayer());
|
return;
|
||||||
if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
|
|
||||||
Detonator.hideDetonator(event.getPlayer());
|
|
||||||
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Detonator.DetonatorComponent component = SWPlayer.of(event.getPlayer())
|
||||||
|
.getComponentAndFilter(Detonator.DetonatorComponent.class, Detonator.DetonatorComponent::isHasUpdated)
|
||||||
|
.orElse(null);
|
||||||
|
if (component == null) return;
|
||||||
|
component.setHasUpdated(false);
|
||||||
|
Detonator.hideDetonator(event.getPlayer());
|
||||||
|
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
|
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
if (Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
|
if (!Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) return;
|
||||||
HAS_UPDATED.add(event.getPlayer());
|
SWPlayer.of(event.getPlayer()).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
|
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
if (Detonator.isDetonator(event.getMainHandItem()) || Detonator.isDetonator(event.getOffHandItem())) {
|
if (!(Detonator.isDetonator(event.getMainHandItem()) || Detonator.isDetonator(event.getOffHandItem()))) return;
|
||||||
HAS_UPDATED.add(event.getPlayer());
|
SWPlayer.of(event.getPlayer()).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
|
|||||||
import de.steamwar.bausystem.features.loader.elements.impl.LoaderTNT;
|
import de.steamwar.bausystem.features.loader.elements.impl.LoaderTNT;
|
||||||
import de.steamwar.bausystem.features.loader.elements.impl.LoaderWait;
|
import de.steamwar.bausystem.features.loader.elements.impl.LoaderWait;
|
||||||
import de.steamwar.bausystem.shared.EnumDisplay;
|
import de.steamwar.bausystem.shared.EnumDisplay;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.inventory.SWAnvilInv;
|
import de.steamwar.inventory.SWAnvilInv;
|
||||||
import de.steamwar.inventory.SWItem;
|
import de.steamwar.inventory.SWItem;
|
||||||
import de.steamwar.inventory.SWListInv;
|
import de.steamwar.inventory.SWListInv;
|
||||||
@@ -40,21 +41,17 @@ import org.bukkit.event.inventory.ClickType;
|
|||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class Loader implements Listener {
|
public class Loader implements Listener, SWPlayer.Component {
|
||||||
|
|
||||||
private static final Map<Player, Loader> LOADER_MAP = new HashMap<>();
|
|
||||||
|
|
||||||
public static Loader getLoader(Player player) {
|
public static Loader getLoader(Player player) {
|
||||||
return LOADER_MAP.get(player);
|
return SWPlayer.of(player).getComponent(Loader.class).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void newLoader(Player player) {
|
public static void newLoader(Player player) {
|
||||||
LOADER_MAP.put(player, new Loader(player));
|
SWPlayer.of(player).setComponent(new Loader(player));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Player p;
|
private final Player p;
|
||||||
@@ -145,7 +142,7 @@ public class Loader implements Listener {
|
|||||||
recorder = null;
|
recorder = null;
|
||||||
}
|
}
|
||||||
elements.clear();
|
elements.clear();
|
||||||
LOADER_MAP.remove(p);
|
SWPlayer.of(p).removeComponent(Loader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setTicksBetweenShots(int delay) {
|
public boolean setTicksBetweenShots(int delay) {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.bukkit.boss.BarColor;
|
|||||||
import org.bukkit.boss.BarStyle;
|
import org.bukkit.boss.BarStyle;
|
||||||
import org.bukkit.boss.BossBar;
|
import org.bukkit.boss.BossBar;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.TNTPrimed;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
@@ -156,6 +157,7 @@ public class Loadtimer implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onTntExplode(EntityExplodeEvent event) {
|
public void onTntExplode(EntityExplodeEvent event) {
|
||||||
|
if (!(event.getEntity() instanceof TNTPrimed)) return;
|
||||||
if (region.getBuildArea().inRegion(event.getLocation(), true) && stage == Stage.IGNITION) {
|
if (region.getBuildArea().inRegion(event.getLocation(), true) && stage == Stage.IGNITION) {
|
||||||
stage = Stage.END;
|
stage = Stage.END;
|
||||||
explode = TPSUtils.currentRealTick.get();
|
explode = TPSUtils.currentRealTick.get();
|
||||||
|
|||||||
+2
-1
@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.observer;
|
|||||||
|
|
||||||
import de.steamwar.Reflection;
|
import de.steamwar.Reflection;
|
||||||
import de.steamwar.bausystem.region.Point;
|
import de.steamwar.bausystem.region.Point;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
@@ -34,7 +35,7 @@ import org.bukkit.entity.Player;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ObserverTracer {
|
public class ObserverTracer implements SWPlayer.Component {
|
||||||
|
|
||||||
private static final Set<BlockFace> ALLOWED = EnumSet.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN);
|
private static final Set<BlockFace> ALLOWED = EnumSet.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN);
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.observer;
|
|||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@@ -41,23 +42,23 @@ public class ObserverTracerCommand extends SWCommand {
|
|||||||
@Register(value = "disable", description = "OBSERVER_HELP_DISABLE")
|
@Register(value = "disable", description = "OBSERVER_HELP_DISABLE")
|
||||||
public void disable(Player p) {
|
public void disable(Player p) {
|
||||||
ObserverTracerListener.enabled.remove(p);
|
ObserverTracerListener.enabled.remove(p);
|
||||||
ObserverTracerListener.observerTracerMap.remove(p);
|
SWPlayer.of(p).removeComponent(ObserverTracer.class);
|
||||||
BauSystem.MESSAGE.send("OBSERVER_DISABLE", p);
|
BauSystem.MESSAGE.send("OBSERVER_DISABLE", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Register(value = "delete", description = "OBSERVER_HELP_DELETE")
|
@Register(value = "delete", description = "OBSERVER_HELP_DELETE")
|
||||||
public void delete(@Validator Player p) {
|
public void delete(@Validator Player p) {
|
||||||
ObserverTracerListener.observerTracerMap.remove(p);
|
SWPlayer.of(p).removeComponent(ObserverTracer.class);
|
||||||
BauSystem.MESSAGE.send("OBSERVER_DELETE", p);
|
BauSystem.MESSAGE.send("OBSERVER_DELETE", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Register(value = "retrace", description = "OBSERVER_HELP_RETRACE")
|
@Register(value = "retrace", description = "OBSERVER_HELP_RETRACE")
|
||||||
public void retrace(@Validator Player p) {
|
public void retrace(@Validator Player p) {
|
||||||
if (ObserverTracerListener.observerTracerMap.containsKey(p)) {
|
if (SWPlayer.of(p).hasComponent(ObserverTracer.class)) {
|
||||||
BauSystem.MESSAGE.send("OBSERVER_RETRACE_NO_TRACE", p);
|
BauSystem.MESSAGE.send("OBSERVER_RETRACE_NO_TRACE", p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ObserverTracerListener.observerTracerMap.get(p).trace();
|
SWPlayer.of(p).getComponent(ObserverTracer.class).ifPresent(ObserverTracer::trace);
|
||||||
BauSystem.MESSAGE.send("OBSERVER_RETRACE_DONE", p);
|
BauSystem.MESSAGE.send("OBSERVER_RETRACE_DONE", p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-20
@@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.observer;
|
|||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.bausystem.Permission;
|
import de.steamwar.bausystem.Permission;
|
||||||
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
@@ -34,23 +35,19 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
|||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@Linked
|
@Linked
|
||||||
public class ObserverTracerListener implements Listener {
|
public class ObserverTracerListener implements Listener {
|
||||||
|
|
||||||
static Set<Player> enabled = new HashSet<>();
|
static Set<Player> enabled = new HashSet<>();
|
||||||
static Map<Player, ObserverTracer> observerTracerMap = new HashMap<>();
|
|
||||||
|
|
||||||
public ObserverTracerListener() {
|
public ObserverTracerListener() {
|
||||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
||||||
observerTracerMap.forEach((player, observerTracer) -> {
|
SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
|
||||||
if (player.getGameMode() == GameMode.SPECTATOR) {
|
if (pair.getKey().getGameMode() != GameMode.SPECTATOR) return;
|
||||||
observerTracer.show();
|
pair.getValue().show();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, 15L, 15L);
|
}, 15L, 15L);
|
||||||
}
|
}
|
||||||
@@ -58,20 +55,16 @@ public class ObserverTracerListener implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
if (!enabled.contains(event.getPlayer())) {
|
if (!enabled.contains(event.getPlayer())) return;
|
||||||
return;
|
if (event.getClickedBlock() == null) return;
|
||||||
}
|
ObserverTracer observerTracer = SWPlayer.of(event.getPlayer()).getComponent(ObserverTracer.class).orElse(null);
|
||||||
if (event.getClickedBlock() == null) {
|
if (observerTracer != null) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (observerTracerMap.containsKey(event.getPlayer())) {
|
|
||||||
ObserverTracer observerTracer = observerTracerMap.get(event.getPlayer());
|
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||||
if (!observerTracer.trace()) {
|
if (!observerTracer.trace()) {
|
||||||
createNew(event);
|
createNew(event);
|
||||||
}
|
}
|
||||||
observerTracerMap.forEach((player, o) -> {
|
SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
|
||||||
o.trace();
|
pair.getValue().trace();
|
||||||
});
|
});
|
||||||
}, 1L);
|
}, 1L);
|
||||||
} else {
|
} else {
|
||||||
@@ -86,13 +79,13 @@ public class ObserverTracerListener implements Listener {
|
|||||||
if (event.getClickedBlock().getType() == Material.OBSERVER) {
|
if (event.getClickedBlock().getType() == Material.OBSERVER) {
|
||||||
ObserverTracer observerTracer = new ObserverTracer(event.getPlayer(), event.getClickedBlock());
|
ObserverTracer observerTracer = new ObserverTracer(event.getPlayer(), event.getClickedBlock());
|
||||||
observerTracer.trace();
|
observerTracer.trace();
|
||||||
observerTracerMap.put(event.getPlayer(), observerTracer);
|
SWPlayer.of(event.getPlayer()).setComponent(observerTracer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
||||||
event.getNewSpectator().forEach(observerTracerMap::remove);
|
event.getNewBuilder().forEach(player -> SWPlayer.of(player).removeComponent(ObserverTracer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
@@ -103,6 +96,5 @@ public class ObserverTracerListener implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
enabled.remove(event.getPlayer());
|
enabled.remove(event.getPlayer());
|
||||||
observerTracerMap.remove(event.getPlayer());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -26,8 +26,10 @@ import de.steamwar.bausystem.region.flags.Flag;
|
|||||||
import de.steamwar.bausystem.region.flags.TNTMode;
|
import de.steamwar.bausystem.region.flags.TNTMode;
|
||||||
import de.steamwar.bausystem.utils.ScoreboardElement;
|
import de.steamwar.bausystem.utils.ScoreboardElement;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.TNTPrimed;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
@@ -39,11 +41,14 @@ import java.util.List;
|
|||||||
@Linked
|
@Linked
|
||||||
public class TNTListener implements Listener, ScoreboardElement {
|
public class TNTListener implements Listener, ScoreboardElement {
|
||||||
|
|
||||||
private void explode(List<Block> blockList) {
|
private void explode(List<Block> blockList, boolean destroy) {
|
||||||
blockList.removeIf(block -> {
|
blockList.removeIf(block -> {
|
||||||
Region region = Region.getRegion(block.getLocation());
|
Region region = Region.getRegion(block.getLocation());
|
||||||
TNTMode value = region.getFlags().get(Flag.TNT).getWithDefault();
|
TNTMode value = region.getFlags().get(Flag.TNT).getWithDefault();
|
||||||
if (value == TNTMode.ALLOW) {
|
if (value == TNTMode.ALLOW) {
|
||||||
|
if (destroy && block.getType() != Material.TNT) {
|
||||||
|
block.setType(Material.AIR);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (value == TNTMode.ONLY_TB) {
|
} else if (value == TNTMode.ONLY_TB) {
|
||||||
if (region.getBuildArea().inRegion(block.getLocation(), true)) {
|
if (region.getBuildArea().inRegion(block.getLocation(), true)) {
|
||||||
@@ -57,12 +62,16 @@ public class TNTListener implements Listener, ScoreboardElement {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBlockExplode(BlockExplodeEvent event) {
|
public void onBlockExplode(BlockExplodeEvent event) {
|
||||||
explode(event.blockList());
|
explode(event.blockList(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
public void onExplode(EntityExplodeEvent event) {
|
public void onExplode(EntityExplodeEvent event) {
|
||||||
explode(event.blockList());
|
if (!(event.getEntity() instanceof TNTPrimed)) {
|
||||||
|
event.blockList().clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
explode(event.blockList(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+14
-26
@@ -31,7 +31,6 @@ import de.steamwar.command.SWCommand;
|
|||||||
import de.steamwar.command.TypeMapper;
|
import de.steamwar.command.TypeMapper;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.linkage.LinkedInstance;
|
import de.steamwar.linkage.LinkedInstance;
|
||||||
import de.steamwar.sql.BauweltMember;
|
|
||||||
import de.steamwar.sql.Punishment;
|
import de.steamwar.sql.Punishment;
|
||||||
import de.steamwar.sql.SchematicNode;
|
import de.steamwar.sql.SchematicNode;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
@@ -73,6 +72,14 @@ public class TestblockCommand extends SWCommand {
|
|||||||
resetRegion(p, node, isExtension ? RegionExtensionType.EXTENSION : RegionExtensionType.NORMAL, isIgnoreAir, isOnlyColor, replaceTNT, replaceWater);
|
resetRegion(p, node, isExtension ? RegionExtensionType.EXTENSION : RegionExtensionType.NORMAL, isIgnoreAir, isOnlyColor, replaceTNT, replaceWater);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Register(value="default")
|
||||||
|
public void setTestblockDefault(Player p) {
|
||||||
|
Region region = regionCheck(p);
|
||||||
|
if (region == null) return;
|
||||||
|
region.getRegionData().setTestblockSchematic(null);
|
||||||
|
resetRegion(p, null, RegionExtensionType.EXTENSION, false, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
private void resetRegion(Player p, SchematicNode node, RegionExtensionType regionExtensionType, boolean ignoreAir, boolean onlyColors, boolean removeTNT, boolean removeWater) {
|
private void resetRegion(Player p, SchematicNode node, RegionExtensionType regionExtensionType, boolean ignoreAir, boolean onlyColors, boolean removeTNT, boolean removeWater) {
|
||||||
Region region = regionCheck(p);
|
Region region = regionCheck(p);
|
||||||
if (region == null) return;
|
if (region == null) return;
|
||||||
@@ -93,29 +100,10 @@ public class TestblockCommand extends SWCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beta Tester enabled
|
if (node == null) {
|
||||||
switch (BauServer.getInstance().getOwnerID()) {
|
node = region.getRegionData().getTestblockSchematic();
|
||||||
case 245:
|
} else {
|
||||||
case 403:
|
region.getRegionData().setTestblockSchematic(node);
|
||||||
case 1898:
|
|
||||||
case 3320:
|
|
||||||
case 4603:
|
|
||||||
case 5262:
|
|
||||||
case 5399:
|
|
||||||
case 6032:
|
|
||||||
case 7862:
|
|
||||||
case 11077:
|
|
||||||
case 11888:
|
|
||||||
case 12258:
|
|
||||||
case 16009:
|
|
||||||
if (node == null) {
|
|
||||||
node = region.getRegionData().getTestblockSchematic();
|
|
||||||
} else {
|
|
||||||
region.getRegionData().setTestblockSchematic(node);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PasteBuilder.ClipboardProvider clipboardProvider;
|
PasteBuilder.ClipboardProvider clipboardProvider;
|
||||||
@@ -198,7 +186,7 @@ public class TestblockCommand extends SWCommand {
|
|||||||
@Override
|
@Override
|
||||||
public List<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) {
|
public List<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) {
|
||||||
List<String> stringList = new ArrayList<>(SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s));
|
List<String> stringList = new ArrayList<>(SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s));
|
||||||
stringList.addAll(SchematicNode.getNodeTabcomplete(SteamwarUser.get(0), s));
|
stringList.addAll(SchematicNode.getNodeTabcomplete(SteamwarUser.byId(0), s));
|
||||||
return stringList;
|
return stringList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +194,7 @@ public class TestblockCommand extends SWCommand {
|
|||||||
public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
|
public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
|
||||||
SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s);
|
SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s);
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
node = SchematicNode.getNodeFromPath(SteamwarUser.get(0), s);
|
node = SchematicNode.getNodeFromPath(SteamwarUser.byId(0), s);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ public class ScriptHelper {
|
|||||||
BookMeta meta = (BookMeta) itemStack.getItemMeta();
|
BookMeta meta = (BookMeta) itemStack.getItemMeta();
|
||||||
if(!writeable) {
|
if(!writeable) {
|
||||||
meta.setTitle(script.getName());
|
meta.setTitle(script.getName());
|
||||||
meta.setAuthor(SteamwarUser.get(script.getUserId()).getUserName());
|
meta.setAuthor(SteamwarUser.byId(script.getUserId()).getUserName());
|
||||||
}
|
}
|
||||||
meta.setPages(getScriptPages(script));
|
meta.setPages(getScriptPages(script));
|
||||||
itemStack.setItemMeta(meta);
|
itemStack.setItemMeta(meta);
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ public class ScriptListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
ScriptRunner.remove(event.getPlayer());
|
playerSet.remove(event.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
|||||||
+39
-13
@@ -23,8 +23,11 @@ import de.steamwar.bausystem.BauSystem;
|
|||||||
import de.steamwar.bausystem.features.script.lua.CommandRegister;
|
import de.steamwar.bausystem.features.script.lua.CommandRegister;
|
||||||
import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin;
|
import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin;
|
||||||
import de.steamwar.bausystem.features.script.lua.SteamWarPlatform;
|
import de.steamwar.bausystem.features.script.lua.SteamWarPlatform;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.sql.Script;
|
import de.steamwar.sql.Script;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.Cancellable;
|
||||||
@@ -44,12 +47,25 @@ public class ScriptRunner {
|
|||||||
// Key -> bau-script-<BUCH NAME>
|
// Key -> bau-script-<BUCH NAME>
|
||||||
// Value -> <LUA Script>
|
// Value -> <LUA Script>
|
||||||
|
|
||||||
private static final Map<Player, Map<SteamWarGlobalLuaPlugin.EventType, List<LuaFunction>>> EVENT_MAP = new HashMap<>();
|
public class ScriptData implements SWPlayer.Component {
|
||||||
private static final Map<Player, Map<Hotkey, List<LuaFunction>>> HOTKEY_MAP = new HashMap<>();
|
private Map<SteamWarGlobalLuaPlugin.EventType, List<LuaFunction>> events = new EnumMap<>(SteamWarGlobalLuaPlugin.EventType.class);
|
||||||
private static final Map<Player, Map<String, CommandRegister>> COMMAND_MAP = new HashMap<>();
|
private Map<Hotkey, List<LuaFunction>> hotkeys = new HashMap<>();
|
||||||
|
private Map<String, CommandRegister> commands = new HashMap<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Set<String> calledCommands = new HashSet<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Long lastF = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean ignore;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<String> getCommandsOfPlayer(Player player) {
|
public Set<String> getCommandsOfPlayer(Player player) {
|
||||||
return COMMAND_MAP.getOrDefault(player, new HashMap<>()).keySet();
|
return SWPlayer.of(player).getComponentOrDefault(ScriptData.class, ScriptData::new).commands.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void runScript(String script, Player player) {
|
public static void runScript(String script, Player player) {
|
||||||
@@ -64,10 +80,12 @@ public class ScriptRunner {
|
|||||||
|
|
||||||
public static void createGlobalScript(List<String> scripts, Player player) {
|
public static void createGlobalScript(List<String> scripts, Player player) {
|
||||||
remove(player);
|
remove(player);
|
||||||
|
SWPlayer swPlayer = SWPlayer.of(player);
|
||||||
|
ScriptData scriptData = swPlayer.getComponentOrDefault(ScriptData.class, ScriptData::new);
|
||||||
Globals globals = SteamWarPlatform.createGlobalGlobals(player,
|
Globals globals = SteamWarPlatform.createGlobalGlobals(player,
|
||||||
(s, luaFunction) -> EVENT_MAP.computeIfAbsent(player, player1 -> new EnumMap<>(SteamWarGlobalLuaPlugin.EventType.class)).computeIfAbsent(s, s1 -> new ArrayList<>()).add(luaFunction),
|
(s, luaFunction) -> scriptData.events.computeIfAbsent(s, s1 -> new ArrayList<>()).add(luaFunction),
|
||||||
(s, luaFunction) -> HOTKEY_MAP.computeIfAbsent(player, player1 -> new HashMap<>()).computeIfAbsent(Hotkey.fromString(s), s1 -> new ArrayList<>()).add(luaFunction),
|
(s, luaFunction) -> scriptData.hotkeys.computeIfAbsent(Hotkey.fromString(s), s1 -> new ArrayList<>()).add(luaFunction),
|
||||||
commandRegister -> COMMAND_MAP.computeIfAbsent(player, player1 -> new HashMap<>()).put(commandRegister.getName(), commandRegister));
|
commandRegister -> scriptData.commands.put(commandRegister.getName(), commandRegister));
|
||||||
|
|
||||||
for (String script : scripts) {
|
for (String script : scripts) {
|
||||||
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> globals.load(script).call());
|
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> globals.load(script).call());
|
||||||
@@ -75,13 +93,14 @@ public class ScriptRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void remove(Player player) {
|
public static void remove(Player player) {
|
||||||
EVENT_MAP.remove(player);
|
SWPlayer.of(player).removeComponent(ScriptData.class);
|
||||||
COMMAND_MAP.remove(player);
|
|
||||||
HOTKEY_MAP.remove(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void callEvent(Player player, SteamWarGlobalLuaPlugin.EventType event, LuaValue eventValue, Event wrappedEvent) {
|
public static void callEvent(Player player, SteamWarGlobalLuaPlugin.EventType event, LuaValue eventValue, Event wrappedEvent) {
|
||||||
List<LuaFunction> luaFunctions = EVENT_MAP.getOrDefault(player, Collections.emptyMap()).getOrDefault(event, Collections.emptyList());
|
List<LuaFunction> luaFunctions = SWPlayer.of(player).getComponent(ScriptData.class)
|
||||||
|
.map(scriptData -> scriptData.events)
|
||||||
|
.orElse(Collections.emptyMap())
|
||||||
|
.getOrDefault(event, Collections.emptyList());
|
||||||
if (luaFunctions.isEmpty()) {
|
if (luaFunctions.isEmpty()) {
|
||||||
if(event == SteamWarGlobalLuaPlugin.EventType.DoubleSwap) {
|
if(event == SteamWarGlobalLuaPlugin.EventType.DoubleSwap) {
|
||||||
player.performCommand("gui");
|
player.performCommand("gui");
|
||||||
@@ -124,7 +143,10 @@ public class ScriptRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean callCommand(Player player, String command, String[] argsArray) {
|
public static boolean callCommand(Player player, String command, String[] argsArray) {
|
||||||
CommandRegister commandRegister = COMMAND_MAP.getOrDefault(player, Collections.emptyMap()).get(command);
|
CommandRegister commandRegister = SWPlayer.of(player).getComponent(ScriptData.class)
|
||||||
|
.map(scriptData -> scriptData.commands)
|
||||||
|
.orElse(Collections.emptyMap())
|
||||||
|
.get(command);
|
||||||
if (commandRegister == null) {
|
if (commandRegister == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -188,7 +210,11 @@ public class ScriptRunner {
|
|||||||
|
|
||||||
public static void callHotkey(int mods, int key, Player player, boolean pressed) {
|
public static void callHotkey(int mods, int key, Player player, boolean pressed) {
|
||||||
Hotkey hotkey = Hotkey.fromChar(key, mods);
|
Hotkey hotkey = Hotkey.fromChar(key, mods);
|
||||||
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> HOTKEY_MAP.getOrDefault(player, Collections.emptyMap()).getOrDefault(hotkey, Collections.emptyList()).forEach(luaFunction -> luaFunction.call(LuaValue.valueOf(pressed))));
|
List<LuaFunction> hotkeys = SWPlayer.of(player).getComponent(ScriptData.class)
|
||||||
|
.map(scriptData -> scriptData.hotkeys)
|
||||||
|
.orElse(Collections.emptyMap())
|
||||||
|
.getOrDefault(hotkey, Collections.emptyList());
|
||||||
|
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> hotkeys.forEach(luaFunction -> luaFunction.call(LuaValue.valueOf(pressed))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void catchScript(String errorMsg, Player player, Runnable run) {
|
public static void catchScript(String errorMsg, Player player, Runnable run) {
|
||||||
|
|||||||
+5
-25
@@ -21,44 +21,24 @@ package de.steamwar.bausystem.features.script.event;
|
|||||||
|
|
||||||
import de.steamwar.bausystem.Permission;
|
import de.steamwar.bausystem.Permission;
|
||||||
import de.steamwar.bausystem.features.script.ScriptRunner;
|
import de.steamwar.bausystem.features.script.ScriptRunner;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Linked
|
@Linked
|
||||||
public class CommandListener implements Listener {
|
public class CommandListener implements Listener {
|
||||||
|
|
||||||
private Map<Player, Set<String>> calledCommands = new HashMap<>();
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
String[] split = event.getMessage().split(" ");
|
String[] split = event.getMessage().split(" ");
|
||||||
if (calledCommands.getOrDefault(event.getPlayer(), new HashSet<>()).contains(split[0])) {
|
ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
|
||||||
return;
|
if (scriptData.getCalledCommands().contains(split[0])) return;
|
||||||
}
|
|
||||||
|
|
||||||
calledCommands.getOrDefault(event.getPlayer(), new HashSet<>()).add(split[0]);
|
scriptData.getCalledCommands().add(split[0]);
|
||||||
event.setCancelled(ScriptRunner.callCommand(event.getPlayer(), split[0].substring(1), split));
|
event.setCancelled(ScriptRunner.callCommand(event.getPlayer(), split[0].substring(1), split));
|
||||||
calledCommands.getOrDefault(event.getPlayer(), new HashSet<>()).remove(split[0]);
|
scriptData.getCalledCommands().remove(split[0]);
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
calledCommands.put(event.getPlayer(), new HashSet<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
calledCommands.remove(event.getPlayer());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-25
@@ -25,6 +25,7 @@ import de.steamwar.bausystem.features.script.ScriptRunner;
|
|||||||
import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin;
|
import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin;
|
||||||
import de.steamwar.bausystem.features.script.lua.libs.StorageLib;
|
import de.steamwar.bausystem.features.script.lua.libs.StorageLib;
|
||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.core.TrickyTrialsWrapper;
|
import de.steamwar.core.TrickyTrialsWrapper;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@@ -43,32 +44,27 @@ import org.bukkit.event.player.*;
|
|||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Linked
|
@Linked
|
||||||
public class EventListener implements Listener {
|
public class EventListener implements Listener {
|
||||||
|
|
||||||
private static final Map<Player, Long> LAST_FS = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
||||||
long millis = System.currentTimeMillis();
|
long millis = System.currentTimeMillis();
|
||||||
LAST_FS.entrySet().removeIf(entry -> millis - entry.getValue() > 200);
|
SWPlayer.allWithSingleComponent(ScriptRunner.ScriptData.class)
|
||||||
|
.filter(pair -> millis - pair.getValue().getLastF() > 200)
|
||||||
|
.forEach(pair -> pair.getValue().setLastF(Long.MAX_VALUE));
|
||||||
}, 1, 1);
|
}, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfJoin, LuaValue.NIL, event);
|
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfJoin, LuaValue.NIL, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
if(Permission.BUILD.hasPermission(event.getPlayer())) {
|
if (Permission.BUILD.hasPermission(event.getPlayer())) {
|
||||||
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfLeave, LuaValue.NIL, event);
|
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfLeave, LuaValue.NIL, event);
|
||||||
}
|
}
|
||||||
StorageLib.removePlayer(event.getPlayer());
|
StorageLib.removePlayer(event.getPlayer());
|
||||||
@@ -76,19 +72,20 @@ public class EventListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
|
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
if (LAST_FS.containsKey(event.getPlayer())) {
|
ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
|
||||||
|
if (scriptData.getLastF() != Long.MAX_VALUE) {
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||||
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DoubleSwap, LuaValue.NIL, event);
|
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DoubleSwap, LuaValue.NIL, event);
|
||||||
}, 1);
|
}, 1);
|
||||||
} else {
|
} else {
|
||||||
LAST_FS.put(event.getPlayer(), System.currentTimeMillis());
|
scriptData.setLastF(System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onBlockPlace(BlockPlaceEvent event) {
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
table.set("x", event.getBlock().getX());
|
table.set("x", event.getBlock().getX());
|
||||||
table.set("y", event.getBlock().getY());
|
table.set("y", event.getBlock().getY());
|
||||||
@@ -99,7 +96,7 @@ public class EventListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
table.set("x", event.getBlock().getX());
|
table.set("x", event.getBlock().getX());
|
||||||
table.set("y", event.getBlock().getY());
|
table.set("y", event.getBlock().getY());
|
||||||
@@ -108,12 +105,12 @@ public class EventListener implements Listener {
|
|||||||
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.BreakBlock, table, event);
|
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.BreakBlock, table, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Set<Player> ignore = new HashSet<>();
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOW)
|
@EventHandler(priority = EventPriority.LOW)
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
if (ignore.remove(event.getPlayer())) {
|
ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
|
||||||
|
if (scriptData.isIgnore()) {
|
||||||
|
scriptData.setIgnore(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
@@ -124,7 +121,7 @@ public class EventListener implements Listener {
|
|||||||
table.set("hand", event.getHand().name());
|
table.set("hand", event.getHand().name());
|
||||||
}
|
}
|
||||||
table.set("block", event.getItem() == null ? Material.AIR.name() : event.getItem().getType().name());
|
table.set("block", event.getItem() == null ? Material.AIR.name() : event.getItem().getType().name());
|
||||||
if(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) {
|
if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) {
|
||||||
table.set("hasBlock", LuaValue.valueOf(true));
|
table.set("hasBlock", LuaValue.valueOf(true));
|
||||||
table.set("blockX", event.getClickedBlock().getX());
|
table.set("blockX", event.getClickedBlock().getX());
|
||||||
table.set("blockY", event.getClickedBlock().getY());
|
table.set("blockY", event.getClickedBlock().getY());
|
||||||
@@ -150,7 +147,7 @@ public class EventListener implements Listener {
|
|||||||
Region tntRegion = Region.getRegion(event.getLocation());
|
Region tntRegion = Region.getRegion(event.getLocation());
|
||||||
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if(!Permission.BUILD.hasPermission(player)) continue;
|
if (!Permission.BUILD.hasPermission(player)) continue;
|
||||||
if (tntRegion.getArea().inRegion(player.getLocation(), false)) {
|
if (tntRegion.getArea().inRegion(player.getLocation(), false)) {
|
||||||
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTSpawn, LuaValue.NIL, event);
|
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTSpawn, LuaValue.NIL, event);
|
||||||
}
|
}
|
||||||
@@ -172,7 +169,7 @@ public class EventListener implements Listener {
|
|||||||
boolean inBuild = event.blockList().stream().anyMatch(block -> tntRegion.getBuildArea().inRegion(block.getLocation(), true));
|
boolean inBuild = event.blockList().stream().anyMatch(block -> tntRegion.getBuildArea().inRegion(block.getLocation(), true));
|
||||||
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if(!Permission.BUILD.hasPermission(player)) continue;
|
if (!Permission.BUILD.hasPermission(player)) continue;
|
||||||
if (tntRegion.getArea().inRegion(player.getLocation(), false)) {
|
if (tntRegion.getArea().inRegion(player.getLocation(), false)) {
|
||||||
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTExplode, table, event);
|
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTExplode, table, event);
|
||||||
if (inBuild) {
|
if (inBuild) {
|
||||||
@@ -184,8 +181,9 @@ public class EventListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||||
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
ignore.add(event.getPlayer());
|
ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
|
||||||
|
scriptData.setIgnore(true);
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
table.set("type", event.getItemDrop().getItemStack().getType().name());
|
table.set("type", event.getItemDrop().getItemStack().getType().name());
|
||||||
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DropItem, table, event);
|
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DropItem, table, event);
|
||||||
@@ -194,7 +192,7 @@ public class EventListener implements Listener {
|
|||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onEntityDeath(EntityDeathEvent event) {
|
public void onEntityDeath(EntityDeathEvent event) {
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if(!Permission.BUILD.hasPermission(player)) continue;
|
if (!Permission.BUILD.hasPermission(player)) continue;
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
table.set("type", event.getEntityType().name());
|
table.set("type", event.getEntityType().name());
|
||||||
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.EntityDeath, table, event);
|
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.EntityDeath, table, event);
|
||||||
|
|||||||
+2
-1
@@ -48,6 +48,7 @@ import java.util.logging.Level;
|
|||||||
public class SteamWarLuaPlugin extends TwoArgFunction {
|
public class SteamWarLuaPlugin extends TwoArgFunction {
|
||||||
|
|
||||||
private static final boolean hasFAWE = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null;
|
private static final boolean hasFAWE = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null;
|
||||||
|
private static final Set<String> ignoreCommandFromWorldEdit = Set.of("select", "schem", "/schem", "schematic", "/schematic");
|
||||||
|
|
||||||
protected static final Map<Class<?>, List<LuaLib>> LUA_LIBS = new HashMap<>();
|
protected static final Map<Class<?>, List<LuaLib>> LUA_LIBS = new HashMap<>();
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ public class SteamWarLuaPlugin extends TwoArgFunction {
|
|||||||
command = preprocessEvent.getMessage().substring(1);
|
command = preprocessEvent.getMessage().substring(1);
|
||||||
Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command);
|
Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command);
|
||||||
String[] commandSplit = command.split(" ");
|
String[] commandSplit = command.split(" ");
|
||||||
if (!commandSplit[0].equals("select") && hasFAWE && WorldEditListener.isWorldEditCommand("/" + commandSplit[0])) {
|
if (!ignoreCommandFromWorldEdit.contains(commandSplit[0]) && hasFAWE && WorldEditListener.isWorldEditCommand("/" + commandSplit[0])) {
|
||||||
EditSession editSession = WorldEditUtils.getEditSession(player);
|
EditSession editSession = WorldEditUtils.getEditSession(player);
|
||||||
Actor actor = BukkitAdapter.adapt(player);
|
Actor actor = BukkitAdapter.adapt(player);
|
||||||
WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().handleCommandOnCurrentThread(new CommandEvent(actor, command, editSession));
|
WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().handleCommandOnCurrentThread(new CommandEvent(actor, command, editSession));
|
||||||
|
|||||||
+1
-1
@@ -89,7 +89,7 @@ public class StorageLib implements LuaLib, Enable, Disable {
|
|||||||
jsonObject.keySet().forEach(key -> {
|
jsonObject.keySet().forEach(key -> {
|
||||||
map.put(key, fromJson(jsonObject.get(key)));
|
map.put(key, fromJson(jsonObject.get(key)));
|
||||||
});
|
});
|
||||||
SteamwarUser steamwarUser = SteamwarUser.get(Integer.parseInt(playerStorage.getName().substring(0, playerStorage.getName().length() - ".json".length())));
|
SteamwarUser steamwarUser = SteamwarUser.byId(Integer.parseInt(playerStorage.getName().substring(0, playerStorage.getName().length() - ".json".length())));
|
||||||
PLAYER_STORAGE.put(steamwarUser.getUUID(), map);
|
PLAYER_STORAGE.put(steamwarUser.getUUID(), map);
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -26,6 +26,7 @@ import de.steamwar.bausystem.utils.PasteBuilder;
|
|||||||
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
|
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.TNTPrimed;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
@@ -51,6 +52,7 @@ public class StabGenerator extends StabStep implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onEntityExplode(EntityExplodeEvent event) {
|
public void onEntityExplode(EntityExplodeEvent event) {
|
||||||
|
if (!(event.getEntity() instanceof TNTPrimed)) return;
|
||||||
if (Region.getRegion(event.getEntity().getLocation()) == data.region) {
|
if (Region.getRegion(event.getEntity().getLocation()) == data.region) {
|
||||||
event.blockList().forEach(block -> {
|
event.blockList().forEach(block -> {
|
||||||
if (!data.region.getTestblockArea().inRegion(block.getLocation(), true))
|
if (!data.region.getTestblockArea().inRegion(block.getLocation(), true))
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ public class YAPIONFormatSimulatorLoader implements SimulatorLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String name = file.getName().substring(0, file.getName().length() - 7);
|
String name = file.getName().substring(0, file.getName().length() - 7);
|
||||||
SteamwarUser steamwarUser = SteamwarUser.get(Integer.parseInt(name));
|
SteamwarUser steamwarUser = SteamwarUser.byId(Integer.parseInt(name));
|
||||||
|
|
||||||
List<Simulator> simulators = new ArrayList<>();
|
List<Simulator> simulators = new ArrayList<>();
|
||||||
for (String s : yapionObject.getKeys()) {
|
for (String s : yapionObject.getKeys()) {
|
||||||
|
|||||||
+34
-44
@@ -20,17 +20,14 @@
|
|||||||
package de.steamwar.bausystem.features.slaves.laufbau;
|
package de.steamwar.bausystem.features.slaves.laufbau;
|
||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.inventory.SWItem;
|
import de.steamwar.inventory.SWItem;
|
||||||
import de.steamwar.linkage.Linked;
|
|
||||||
import de.steamwar.sql.UserConfig;
|
import de.steamwar.sql.UserConfig;
|
||||||
import lombok.Cleanup;
|
import lombok.Cleanup;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
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 org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import yapion.hierarchy.output.StreamOutput;
|
import yapion.hierarchy.output.StreamOutput;
|
||||||
import yapion.hierarchy.types.YAPIONObject;
|
import yapion.hierarchy.types.YAPIONObject;
|
||||||
@@ -39,44 +36,45 @@ import yapion.parser.options.StreamOptions;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
@Linked
|
@UtilityClass
|
||||||
public class LaufbauUtils implements Listener {
|
public class LaufbauUtils {
|
||||||
|
|
||||||
private static Map<Player, YAPIONObject> yapionObjectMap = new HashMap<>();
|
public static class LaufbauComponent implements SWPlayer.Component {
|
||||||
|
|
||||||
@EventHandler
|
private YAPIONObject yapionObject = new YAPIONObject();
|
||||||
@SneakyThrows
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
String config = UserConfig.getConfig(event.getPlayer().getUniqueId(), "bausystem-laufbau");
|
|
||||||
if (config == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
byte[] bytes = Base64.getDecoder().decode(config);
|
|
||||||
@Cleanup GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(bytes));
|
|
||||||
YAPIONObject yapionObject = new YAPIONParser(gzipInputStream, new StreamOptions().stopOnStreamEnd(true)).parse().result();
|
|
||||||
yapionObjectMap.put(event.getPlayer(), yapionObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onMount(SWPlayer player) {
|
||||||
YAPIONObject yapionObject = yapionObjectMap.get(event.getPlayer());
|
String config = UserConfig.getConfig(player.getPlayer().getUniqueId(), "bausystem-laufbau");
|
||||||
if (yapionObject == null) {
|
if (config == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
byte[] bytes = Base64.getDecoder().decode(config);
|
||||||
|
@Cleanup GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(bytes));
|
||||||
|
yapionObject = new YAPIONParser(gzipInputStream, new StreamOptions().stopOnStreamEnd(true)).parse().result();
|
||||||
}
|
}
|
||||||
if (yapionObject.isEmpty()) {
|
|
||||||
UserConfig.removePlayerConfig(event.getPlayer().getUniqueId(), "bausystem-laufbau");
|
@Override
|
||||||
return;
|
@SneakyThrows
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
if (yapionObject.isEmpty()) {
|
||||||
|
UserConfig.removePlayerConfig(player.getPlayer().getUniqueId(), "bausystem-laufbau");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@Cleanup ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
@Cleanup GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
|
||||||
|
yapionObject.toYAPION(new StreamOutput(gzipOutputStream)).close();
|
||||||
|
UserConfig.updatePlayerConfig(player.getPlayer().getUniqueId(), "bausystem-laufbau", Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()));
|
||||||
}
|
}
|
||||||
@Cleanup ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
||||||
@Cleanup GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
|
|
||||||
yapionObject.toYAPION(new StreamOutput(gzipOutputStream)).close();
|
|
||||||
UserConfig.updatePlayerConfig(event.getPlayer().getUniqueId(), "bausystem-laufbau", Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cuboid pixelCuboid(double pixelX, double pixelY, double pixelZ, double pixelDX, double pixelDY, double pixelDZ) {
|
public static Cuboid pixelCuboid(double pixelX, double pixelY, double pixelZ, double pixelDX, double pixelDY, double pixelDZ) {
|
||||||
@@ -125,11 +123,7 @@ public class LaufbauUtils implements Listener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String identifier = identifier(bb);
|
String identifier = identifier(bb);
|
||||||
YAPIONObject yapionObject = yapionObjectMap.get(p);
|
return SWPlayer.of(p).getComponentOrDefault(LaufbauComponent.class, LaufbauComponent::new).yapionObject.containsKey(identifier);
|
||||||
if (yapionObject == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return yapionObject.containsKey(identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@@ -138,11 +132,7 @@ public class LaufbauUtils implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String identifier = identifier(bb);
|
String identifier = identifier(bb);
|
||||||
YAPIONObject yapionObject = yapionObjectMap.get(p);
|
YAPIONObject yapionObject = SWPlayer.of(p).getComponentOrDefault(LaufbauComponent.class, LaufbauComponent::new).yapionObject;
|
||||||
if (yapionObject == null) {
|
|
||||||
yapionObject = new YAPIONObject();
|
|
||||||
yapionObjectMap.put(p, yapionObject);
|
|
||||||
}
|
|
||||||
if (yapionObject.containsKey(identifier)) {
|
if (yapionObject.containsKey(identifier)) {
|
||||||
yapionObject.remove(identifier);
|
yapionObject.remove(identifier);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -107,7 +107,7 @@ public class TechHiderCommand extends SWCommand implements Listener, ScoreboardE
|
|||||||
@Override
|
@Override
|
||||||
public Player map(CommandSender commandSender, String[] previousArguments, String s) {
|
public Player map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||||
Player player = Bukkit.getPlayer(s);
|
Player player = Bukkit.getPlayer(s);
|
||||||
if (player != null && Permission.REAL_SPECTATOR.hasPermission(player)) {
|
if (player != null && Permission.SPECTATOR.hasPermission(player)) {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -116,7 +116,7 @@ public class TechHiderCommand extends SWCommand implements Listener, ScoreboardE
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
||||||
return Bukkit.getOnlinePlayers().stream()
|
return Bukkit.getOnlinePlayers().stream()
|
||||||
.filter(Permission.REAL_SPECTATOR::hasPermission)
|
.filter(Permission.SPECTATOR::hasPermission)
|
||||||
.map(Player::getName)
|
.map(Player::getName)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.testblock.blockcounter;
|
|||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.TNTPrimed;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||||
@@ -34,6 +35,7 @@ public class BlockCounterListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onEntityExplode(EntityExplodeEvent event) {
|
public void onEntityExplode(EntityExplodeEvent event) {
|
||||||
|
if (!(event.getEntity() instanceof TNTPrimed)) return;
|
||||||
Region region = Region.getRegion(event.getLocation());
|
Region region = Region.getRegion(event.getLocation());
|
||||||
if (region.getType().isGlobal()) {
|
if (region.getType().isGlobal()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+10
-1
@@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.tntlistener;
|
package de.steamwar.bausystem.features.tls;
|
||||||
|
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
@@ -43,4 +43,13 @@ public class TLSCommand extends SWCommand {
|
|||||||
public void stop(@Validator Player player) {
|
public void stop(@Validator Player player) {
|
||||||
listener.stopListening(player);
|
listener.stopListening(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Register(description = "TLS_TOGGLE_HELP")
|
||||||
|
public void toggle(@Validator Player player) {
|
||||||
|
if (listener.isActiveFor(player)) {
|
||||||
|
listener.stopListening(player);
|
||||||
|
} else {
|
||||||
|
listener.startListening(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.tntlistener;
|
package de.steamwar.bausystem.features.tls;
|
||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.tntlistener;
|
package de.steamwar.bausystem.features.tls;
|
||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.bausystem.Permission;
|
import de.steamwar.bausystem.Permission;
|
||||||
+7
-7
@@ -20,6 +20,7 @@ package de.steamwar.bausystem.features.util;
|
|||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -39,10 +40,11 @@ public class GamemodeCommand extends SWCommand {
|
|||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void genericCommand(final Player p) {
|
public void genericCommand(final Player p) {
|
||||||
if (NoClipCommand.getNOCLIPS().contains(p)) {
|
SWPlayer swPlayer = SWPlayer.of(p);
|
||||||
p.performCommand("noclip");
|
if (swPlayer.hasComponent(NoClipCommand.NoClipData.class)) {
|
||||||
return;
|
swPlayer.removeComponent(NoClipCommand.NoClipData.class);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (p.getGameMode() == GameMode.CREATIVE) {
|
if (p.getGameMode() == GameMode.CREATIVE) {
|
||||||
p.setGameMode(GameMode.SPECTATOR);
|
p.setGameMode(GameMode.SPECTATOR);
|
||||||
} else {
|
} else {
|
||||||
@@ -52,9 +54,7 @@ public class GamemodeCommand extends SWCommand {
|
|||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void gamemodeCommand(final Player p, final GameMode gameMode) {
|
public void gamemodeCommand(final Player p, final GameMode gameMode) {
|
||||||
if (NoClipCommand.getNOCLIPS().contains(p)) {
|
SWPlayer.of(p).removeComponent(NoClipCommand.NoClipData.class);
|
||||||
p.performCommand("noclip");
|
|
||||||
}
|
|
||||||
p.setGameMode(gameMode);
|
p.setGameMode(gameMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+37
-48
@@ -26,6 +26,7 @@ import de.steamwar.bausystem.shared.EnumDisplay;
|
|||||||
import de.steamwar.command.PreviousArguments;
|
import de.steamwar.command.PreviousArguments;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
import de.steamwar.command.TypeMapper;
|
import de.steamwar.command.TypeMapper;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.data.CMDs;
|
import de.steamwar.data.CMDs;
|
||||||
import de.steamwar.inventory.SWAnvilInv;
|
import de.steamwar.inventory.SWAnvilInv;
|
||||||
import de.steamwar.inventory.SWInventory;
|
import de.steamwar.inventory.SWInventory;
|
||||||
@@ -56,11 +57,9 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
WorldEditListener.addCommandExclusion("material");
|
WorldEditListener.addCommandExclusion("material");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Player, Search> searchMap = new HashMap<>();
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
static class Search {
|
public class SearchParameter implements SWPlayer.Component {
|
||||||
SearchType transparent = SearchType.IGNORE;
|
SearchType transparent = SearchType.IGNORE;
|
||||||
SearchType solid = SearchType.IGNORE;
|
SearchType solid = SearchType.IGNORE;
|
||||||
SearchType gravity = SearchType.IGNORE;
|
SearchType gravity = SearchType.IGNORE;
|
||||||
@@ -104,10 +103,10 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void materialGUI(Player p) {
|
public void materialGUI(Player p) {
|
||||||
materialGUI(p, searchMap.get(p));
|
materialGUI(p, SWPlayer.of(p).getComponentOrDefault(SearchParameter.class, SearchParameter::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<String, BiConsumer<Search, SearchType>> elements = new HashMap<>();
|
private static final Map<String, BiConsumer<SearchParameter, SearchType>> elements = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
elements.put("-transparent", (search, searchType) -> search.transparent = searchType);
|
elements.put("-transparent", (search, searchType) -> search.transparent = searchType);
|
||||||
elements.put("-solid", (search, searchType) -> search.solid = searchType);
|
elements.put("-solid", (search, searchType) -> search.solid = searchType);
|
||||||
@@ -122,15 +121,15 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void search(Player p, @Mapper("search") String... searches) {
|
public void search(Player p, @Mapper("search") String... searches) {
|
||||||
Search search = new Search();
|
SearchParameter searchParameter = SWPlayer.of(p).getComponentOrDefault(SearchParameter.class, SearchParameter::new);
|
||||||
for (String s : searches) {
|
for (String s : searches) {
|
||||||
boolean has = false;
|
boolean has = false;
|
||||||
for (Map.Entry<String, BiConsumer<Search, SearchType>> element: elements.entrySet()) {
|
for (Map.Entry<String, BiConsumer<SearchParameter, SearchType>> element: elements.entrySet()) {
|
||||||
if (s.startsWith(element.getKey() + ":")) {
|
if (s.startsWith(element.getKey() + ":")) {
|
||||||
element.getValue().accept(search, SearchType.valueOf(s.substring(element.getKey().length() + 1).toUpperCase()));
|
element.getValue().accept(searchParameter, SearchType.valueOf(s.substring(element.getKey().length() + 1).toUpperCase()));
|
||||||
has = true;
|
has = true;
|
||||||
} else if (s.startsWith(element.getKey().substring(0, 2) + ":")) {
|
} else if (s.startsWith(element.getKey().substring(0, 2) + ":")) {
|
||||||
element.getValue().accept(search, SearchType.valueOf(s.substring(element.getKey().substring(0, 2).length() + 1).toUpperCase()));
|
element.getValue().accept(searchParameter, SearchType.valueOf(s.substring(element.getKey().substring(0, 2).length() + 1).toUpperCase()));
|
||||||
has = true;
|
has = true;
|
||||||
}
|
}
|
||||||
if (has) break;
|
if (has) break;
|
||||||
@@ -141,15 +140,15 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
case "-blastresistance:":
|
case "-blastresistance:":
|
||||||
s = s.substring(s.indexOf(':') + 1).replace('_', ' ');
|
s = s.substring(s.indexOf(':') + 1).replace('_', ' ');
|
||||||
if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) {
|
if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) {
|
||||||
search.blastResistance = s;
|
searchParameter.blastResistance = s;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
search.name = s;
|
searchParameter.name = s;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
materialGUI(p, search);
|
materialGUI(p, searchParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mapper(value = "search", local = true)
|
@Mapper(value = "search", local = true)
|
||||||
@@ -182,7 +181,7 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void materialGUI(Player p, Search search) {
|
public void materialGUI(Player p, SearchParameter search) {
|
||||||
List<SWListInv.SWListEntry<Material>> swListEntries = new ArrayList<>();
|
List<SWListInv.SWListEntry<Material>> swListEntries = new ArrayList<>();
|
||||||
MaterialLazyInit.materialData.forEach(data -> {
|
MaterialLazyInit.materialData.forEach(data -> {
|
||||||
if (data.is(search)) {
|
if (data.is(search)) {
|
||||||
@@ -202,59 +201,59 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
|
|
||||||
private void searchGUI(Player p) {
|
private void searchGUI(Player p) {
|
||||||
SWInventory swInventory = new SWInventory(p, 54, BauSystem.MESSAGE.parse("MATERIAL_SEARCH", p));
|
SWInventory swInventory = new SWInventory(p, 54, BauSystem.MESSAGE.parse("MATERIAL_SEARCH", p));
|
||||||
Search search = searchMap.get(p);
|
SearchParameter searchParameter = SWPlayer.of(p).getComponentOrDefault(SearchParameter.class, SearchParameter::new);
|
||||||
swInventory.setItem(0, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("MATERIAL_BACK", p), clickType -> {
|
swInventory.setItem(0, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("MATERIAL_BACK", p), clickType -> {
|
||||||
materialGUI(p);
|
materialGUI(p);
|
||||||
}).setCustomModelData(CMDs.BACK));
|
}).setCustomModelData(CMDs.BACK));
|
||||||
swInventory.setItem(10, new SWItem(Material.NAME_TAG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.name), clickType -> {
|
swInventory.setItem(10, new SWItem(Material.NAME_TAG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, searchParameter.name), clickType -> {
|
||||||
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p), search.name);
|
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p), searchParameter.name);
|
||||||
swAnvilInv.setCallback(s -> {
|
swAnvilInv.setCallback(s -> {
|
||||||
search.name = s;
|
searchParameter.name = s;
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
});
|
});
|
||||||
swAnvilInv.open();
|
swAnvilInv.open();
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(19, new SWItem(Material.GLASS, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_TRANSPARENT", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.transparent.getChatValue(), p)), clickType -> {
|
swInventory.setItem(19, new SWItem(Material.GLASS, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_TRANSPARENT", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.transparent.getChatValue(), p)), clickType -> {
|
||||||
search.transparent = search.transparent.next();
|
searchParameter.transparent = searchParameter.transparent.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(20, new SWItem(Material.BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_SOLID", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.solid.getChatValue(), p)), clickType -> {
|
swInventory.setItem(20, new SWItem(Material.BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_SOLID", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.solid.getChatValue(), p)), clickType -> {
|
||||||
search.solid = search.solid.next();
|
searchParameter.solid = searchParameter.solid.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(21, new SWItem(Material.BLACK_CONCRETE_POWDER, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_GRAVITY", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.gravity.getChatValue(), p)), clickType -> {
|
swInventory.setItem(21, new SWItem(Material.BLACK_CONCRETE_POWDER, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_GRAVITY", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.gravity.getChatValue(), p)), clickType -> {
|
||||||
search.gravity = search.gravity.next();
|
searchParameter.gravity = searchParameter.gravity.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(22, new SWItem(Material.BIRCH_LOG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_OCCLUDING", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.occluding.getChatValue(), p)), clickType -> {
|
swInventory.setItem(22, new SWItem(Material.BIRCH_LOG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_OCCLUDING", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.occluding.getChatValue(), p)), clickType -> {
|
||||||
search.occluding = search.occluding.next();
|
searchParameter.occluding = searchParameter.occluding.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(23, new SWItem(Material.OAK_BUTTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_INTERACTEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.interacteable.getChatValue(), p)), clickType -> {
|
swInventory.setItem(23, new SWItem(Material.OAK_BUTTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_INTERACTEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.interacteable.getChatValue(), p)), clickType -> {
|
||||||
search.interacteable = search.interacteable.next();
|
searchParameter.interacteable = searchParameter.interacteable.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(24, new SWItem(Material.FLINT_AND_STEEL, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_FLAMMABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.flammable.getChatValue(), p)), clickType -> {
|
swInventory.setItem(24, new SWItem(Material.FLINT_AND_STEEL, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_FLAMMABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.flammable.getChatValue(), p)), clickType -> {
|
||||||
search.flammable = search.flammable.next();
|
searchParameter.flammable = searchParameter.flammable.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(25, new SWItem(Material.LAVA_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BURNABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.burnable.getChatValue(), p)), clickType -> {
|
swInventory.setItem(25, new SWItem(Material.LAVA_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BURNABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.burnable.getChatValue(), p)), clickType -> {
|
||||||
search.burnable = search.burnable.next();
|
searchParameter.burnable = searchParameter.burnable.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(28, new SWItem(Material.WATER_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_WATERLOGGABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.waterloggable.getChatValue(), p)), clickType -> {
|
swInventory.setItem(28, new SWItem(Material.WATER_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_WATERLOGGABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.waterloggable.getChatValue(), p)), clickType -> {
|
||||||
search.waterloggable = search.waterloggable.next();
|
searchParameter.waterloggable = searchParameter.waterloggable.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(29, new SWItem(Material.PISTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_UNMOVEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.unmoveable.getChatValue(), p)), clickType -> {
|
swInventory.setItem(29, new SWItem(Material.PISTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_UNMOVEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.unmoveable.getChatValue(), p)), clickType -> {
|
||||||
search.unmoveable = search.unmoveable.next();
|
searchParameter.unmoveable = searchParameter.unmoveable.next();
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
}));
|
}));
|
||||||
swInventory.setItem(34, new SWItem(Material.NETHER_BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistance), clickType -> {
|
swInventory.setItem(34, new SWItem(Material.NETHER_BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, searchParameter.blastResistance), clickType -> {
|
||||||
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), search.blastResistance);
|
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), searchParameter.blastResistance);
|
||||||
swAnvilInv.setCallback(s -> {
|
swAnvilInv.setCallback(s -> {
|
||||||
if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) {
|
if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) {
|
||||||
search.blastResistance = s;
|
searchParameter.blastResistance = s;
|
||||||
}
|
}
|
||||||
searchGUI(p);
|
searchGUI(p);
|
||||||
});
|
});
|
||||||
@@ -262,14 +261,4 @@ public class MaterialCommand extends SWCommand implements Listener {
|
|||||||
}));
|
}));
|
||||||
swInventory.open();
|
swInventory.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
searchMap.put(event.getPlayer(), new Search());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
searchMap.remove(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -133,7 +133,7 @@ public class MaterialLazyInit {
|
|||||||
}), originalMaterial);
|
}), originalMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean is(MaterialCommand.Search search) {
|
public boolean is(MaterialCommand.SearchParameter search) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
result &= search.transparent.test(transparent);
|
result &= search.transparent.test(transparent);
|
||||||
result &= search.solid.test(solid);
|
result &= search.solid.test(solid);
|
||||||
|
|||||||
+30
-32
@@ -19,17 +19,17 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.features.util;
|
package de.steamwar.bausystem.features.util;
|
||||||
|
|
||||||
import de.steamwar.Reflection;
|
|
||||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import de.steamwar.Reflection;
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||||
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
||||||
import de.steamwar.bausystem.utils.NMSWrapper;
|
import de.steamwar.bausystem.utils.NMSWrapper;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
import de.steamwar.core.ProtocolWrapper;
|
import de.steamwar.core.ProtocolWrapper;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -40,10 +40,6 @@ import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
|||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.event.player.PlayerToggleFlightEvent;
|
import org.bukkit.event.player.PlayerToggleFlightEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
@Linked
|
@Linked
|
||||||
@@ -59,29 +55,34 @@ public class NoClipCommand extends SWCommand implements Listener {
|
|||||||
private static final Class<?> windowClick = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundContainerClickPacket");
|
private static final Class<?> windowClick = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundContainerClickPacket");
|
||||||
private static final Class<?> setSlotStack = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket");
|
private static final Class<?> setSlotStack = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket");
|
||||||
|
|
||||||
@Getter
|
public static class NoClipData implements SWPlayer.Component {
|
||||||
private static final List<Player> NOCLIPS = new ArrayList<>();
|
private long lastTick = -1;
|
||||||
private static final Map<Player, Long> LAST_TICKS = new HashMap<>();
|
|
||||||
|
@Override
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
player.setGameMode(GameMode.CREATIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public NoClipCommand() {
|
public NoClipCommand() {
|
||||||
super("noclip", "nc");
|
super("noclip", "nc");
|
||||||
|
|
||||||
BiFunction<Player, Object, Object> first = (player, o) -> {
|
BiFunction<Player, Object, Object> first = (player, o) -> {
|
||||||
if (NOCLIPS.contains(player)) {
|
NoClipData noClipData = SWPlayer.of(player).getComponent(NoClipData.class).orElse(null);
|
||||||
if (LAST_TICKS.getOrDefault(player, -1L).equals(TPSUtils.currentTick.get())) return o;
|
if (noClipData == null) return o;
|
||||||
NMSWrapper.impl.setInternalGameMode(player, GameMode.SPECTATOR);
|
if (noClipData.lastTick == TPSUtils.currentTick.get()) return o;
|
||||||
LAST_TICKS.put(player, TPSUtils.currentTick.get());
|
NMSWrapper.impl.setInternalGameMode(player, GameMode.SPECTATOR);
|
||||||
}
|
noClipData.lastTick = TPSUtils.currentTick.get();
|
||||||
return o;
|
return o;
|
||||||
};
|
};
|
||||||
TinyProtocol.instance.addFilter(position, first);
|
TinyProtocol.instance.addFilter(position, first);
|
||||||
TinyProtocol.instance.addFilter(positionLook, first);
|
TinyProtocol.instance.addFilter(positionLook, first);
|
||||||
|
|
||||||
BiFunction<Player, Object, Object> second = (player, o) -> {
|
BiFunction<Player, Object, Object> second = (player, o) -> {
|
||||||
if (NOCLIPS.contains(player)) {
|
NoClipData noClipData = SWPlayer.of(player).getComponent(NoClipData.class).orElse(null);
|
||||||
NMSWrapper.impl.setInternalGameMode(player, GameMode.CREATIVE);
|
if (noClipData == null) return o;
|
||||||
LAST_TICKS.put(player, TPSUtils.currentTick.get());
|
NMSWrapper.impl.setInternalGameMode(player, GameMode.CREATIVE);
|
||||||
}
|
noClipData.lastTick = TPSUtils.currentTick.get();
|
||||||
return o;
|
return o;
|
||||||
};
|
};
|
||||||
TinyProtocol.instance.addFilter(useItem, second);
|
TinyProtocol.instance.addFilter(useItem, second);
|
||||||
@@ -89,7 +90,7 @@ public class NoClipCommand extends SWCommand implements Listener {
|
|||||||
TinyProtocol.instance.addFilter(windowClick, second);
|
TinyProtocol.instance.addFilter(windowClick, second);
|
||||||
|
|
||||||
BiFunction<Player, Object, Object> third = (player, o) -> {
|
BiFunction<Player, Object, Object> third = (player, o) -> {
|
||||||
if (NOCLIPS.contains(player)) {
|
if (SWPlayer.of(player).hasComponent(NoClipData.class)) {
|
||||||
NMSWrapper.impl.setSlotToItemStack(player, o);
|
NMSWrapper.impl.setSlotToItemStack(player, o);
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
@@ -99,9 +100,9 @@ public class NoClipCommand extends SWCommand implements Listener {
|
|||||||
|
|
||||||
@Register(help = true)
|
@Register(help = true)
|
||||||
public void genericCommand(@Validator Player player) {
|
public void genericCommand(@Validator Player player) {
|
||||||
if (NOCLIPS.contains(player)) {
|
SWPlayer swPlayer = SWPlayer.of(player);
|
||||||
NOCLIPS.remove(player);
|
if (swPlayer.hasComponent(NoClipData.class)) {
|
||||||
player.setGameMode(GameMode.CREATIVE);
|
swPlayer.removeComponent(NoClipData.class);
|
||||||
} else {
|
} else {
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
player.setGameMode(GameMode.SPECTATOR);
|
||||||
NMSWrapper.impl.setPlayerBuildAbilities(player);
|
NMSWrapper.impl.setPlayerBuildAbilities(player);
|
||||||
@@ -109,8 +110,8 @@ public class NoClipCommand extends SWCommand implements Listener {
|
|||||||
Object gameStateChangeObject = Reflection.newInstance(gameStateChange);
|
Object gameStateChangeObject = Reflection.newInstance(gameStateChange);
|
||||||
NMSWrapper.impl.setGameStateChangeReason(gameStateChangeObject);
|
NMSWrapper.impl.setGameStateChangeReason(gameStateChangeObject);
|
||||||
floatFieldAccessor.set(gameStateChangeObject, 1F);
|
floatFieldAccessor.set(gameStateChangeObject, 1F);
|
||||||
|
|
||||||
NOCLIPS.add(player);
|
swPlayer.setComponent(new NoClipData());
|
||||||
BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player);
|
BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player);
|
||||||
TinyProtocol.instance.sendPacket(player, gameStateChangeObject);
|
TinyProtocol.instance.sendPacket(player, gameStateChangeObject);
|
||||||
pseudoGameMode(player, GameMode.SPECTATOR);
|
pseudoGameMode(player, GameMode.SPECTATOR);
|
||||||
@@ -120,30 +121,27 @@ public class NoClipCommand extends SWCommand implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
||||||
event.getNewSpectator().forEach(player -> {
|
event.getNewSpectator().forEach(player -> {
|
||||||
if (NOCLIPS.contains(player)) {
|
SWPlayer.of(player).removeComponent(NoClipData.class);
|
||||||
NOCLIPS.remove(player);
|
|
||||||
player.setGameMode(GameMode.CREATIVE);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
|
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
|
||||||
if (NOCLIPS.contains(event.getPlayer())) {
|
if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onBlock(BlockCanBuildEvent event) {
|
public void onBlock(BlockCanBuildEvent event) {
|
||||||
if (NOCLIPS.contains(event.getPlayer())) {
|
if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
|
||||||
event.setBuildable(true);
|
event.setBuildable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerToggleFlight(PlayerToggleFlightEvent event) {
|
public void onPlayerToggleFlight(PlayerToggleFlightEvent event) {
|
||||||
if (NOCLIPS.contains(event.getPlayer())) {
|
if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
event.getPlayer().setFlying(true);
|
event.getPlayer().setFlying(true);
|
||||||
}
|
}
|
||||||
@@ -154,7 +152,7 @@ public class NoClipCommand extends SWCommand implements Listener {
|
|||||||
if (event.getCause() != PlayerTeleportEvent.TeleportCause.SPECTATE) {
|
if (event.getCause() != PlayerTeleportEvent.TeleportCause.SPECTATE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (NOCLIPS.contains(event.getPlayer())) {
|
if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||||
event.getPlayer().setSpectatorTarget(null);
|
event.getPlayer().setSpectatorTarget(null);
|
||||||
|
|||||||
+5
-8
@@ -24,6 +24,7 @@ import de.steamwar.bausystem.Permission;
|
|||||||
import de.steamwar.bausystem.linkage.BauGuiItem;
|
import de.steamwar.bausystem.linkage.BauGuiItem;
|
||||||
import de.steamwar.bausystem.region.utils.RegionExtensionType;
|
import de.steamwar.bausystem.region.utils.RegionExtensionType;
|
||||||
import de.steamwar.bausystem.region.utils.RegionType;
|
import de.steamwar.bausystem.region.utils.RegionType;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.inventory.SWInventory;
|
import de.steamwar.inventory.SWInventory;
|
||||||
import de.steamwar.inventory.SWItem;
|
import de.steamwar.inventory.SWItem;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
@@ -35,15 +36,11 @@ import org.bukkit.event.inventory.ClickType;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Linked
|
@Linked
|
||||||
public class SelectBauGuiItem extends BauGuiItem {
|
public class SelectBauGuiItem extends BauGuiItem {
|
||||||
|
|
||||||
private static final Map<Player, LastSelect> LAST_SELECT_MAP = new HashMap<>();
|
|
||||||
|
|
||||||
public SelectBauGuiItem() {
|
public SelectBauGuiItem() {
|
||||||
super(13);
|
super(13);
|
||||||
}
|
}
|
||||||
@@ -58,13 +55,13 @@ public class SelectBauGuiItem extends BauGuiItem {
|
|||||||
|
|
||||||
private static void selectFinish(Player p, RegionType type, RegionExtensionType extensionType) {
|
private static void selectFinish(Player p, RegionType type, RegionExtensionType extensionType) {
|
||||||
p.closeInventory();
|
p.closeInventory();
|
||||||
LAST_SELECT_MAP.put(p, new LastSelect(type, extensionType));
|
SWPlayer.of(p).setComponent(new LastSelect(type, extensionType));
|
||||||
p.performCommand("select " + type.name() + " " + extensionType.toString());
|
p.performCommand("select " + type.name() + " " + extensionType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItem(Player player) {
|
public ItemStack getItem(Player player) {
|
||||||
LastSelect last = LAST_SELECT_MAP.getOrDefault(player, new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL));
|
LastSelect last = SWPlayer.of(player).getComponentOrDefault(LastSelect.class, () -> new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL));
|
||||||
return new SWItem(Material.SCAFFOLDING, BauSystem.MESSAGE.parse("SELECT_ITEM_SELECT", player), Arrays.asList(BauSystem.MESSAGE.parse("SELECT_ITEM_AUSWAHL", player, BauSystem.MESSAGE.parse(last.type.getChatValue(), player), last.extensionType.name()), BauSystem.MESSAGE.parse("SELECT_ITEM_RIGHT_CLICK", player)), false, clickType -> {
|
return new SWItem(Material.SCAFFOLDING, BauSystem.MESSAGE.parse("SELECT_ITEM_SELECT", player), Arrays.asList(BauSystem.MESSAGE.parse("SELECT_ITEM_AUSWAHL", player, BauSystem.MESSAGE.parse(last.type.getChatValue(), player), last.extensionType.name()), BauSystem.MESSAGE.parse("SELECT_ITEM_RIGHT_CLICK", player)), false, clickType -> {
|
||||||
}).getItemStack();
|
}).getItemStack();
|
||||||
}
|
}
|
||||||
@@ -80,7 +77,7 @@ public class SelectBauGuiItem extends BauGuiItem {
|
|||||||
inv.open();
|
inv.open();
|
||||||
} else {
|
} else {
|
||||||
p.closeInventory();
|
p.closeInventory();
|
||||||
LastSelect last = LAST_SELECT_MAP.getOrDefault(p, new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL));
|
LastSelect last = SWPlayer.of(p).getComponentOrDefault(LastSelect.class, () -> new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL));
|
||||||
p.performCommand("select " + last.getType().name() + " " + last.getExtensionType().toString());
|
p.performCommand("select " + last.getType().name() + " " + last.getExtensionType().toString());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -92,7 +89,7 @@ public class SelectBauGuiItem extends BauGuiItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
private static class LastSelect {
|
private static class LastSelect implements SWPlayer.Component {
|
||||||
@Getter
|
@Getter
|
||||||
private final RegionType type;
|
private final RegionType type;
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
+32
-42
@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.warp;
|
|||||||
|
|
||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
import de.steamwar.core.Core;
|
import de.steamwar.core.Core;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.entity.RArmorStand;
|
import de.steamwar.entity.RArmorStand;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
@@ -30,7 +31,10 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.player.*;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||||
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
@@ -42,8 +46,21 @@ import java.util.Map;
|
|||||||
@Linked
|
@Linked
|
||||||
public class WarpListener implements Listener {
|
public class WarpListener implements Listener {
|
||||||
|
|
||||||
private Map<Player, REntityServer> warpEntityServer = new HashMap<>();
|
public static class WarpComponent implements SWPlayer.Component {
|
||||||
private Map<Player, List<Location>> selected = new HashMap<>();
|
private REntityServer server;
|
||||||
|
private List<Location> selected = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMount(SWPlayer player) {
|
||||||
|
server = new REntityServer();
|
||||||
|
server.addPlayer(player.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
server.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerItemHeld(PlayerItemHeldEvent e) {
|
public void onPlayerItemHeld(PlayerItemHeldEvent e) {
|
||||||
@@ -65,20 +82,11 @@ public class WarpListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reshow(Player p, Material material, boolean sneaking) {
|
private void reshow(Player p, Material material, boolean sneaking) {
|
||||||
REntityServer entityServer = warpEntityServer.get(p);
|
SWPlayer swPlayer = SWPlayer.of(p);
|
||||||
if (entityServer != null) {
|
swPlayer.removeComponent(WarpComponent.class);
|
||||||
entityServer.close();
|
if (material != Material.COMPASS) return;
|
||||||
}
|
|
||||||
if (material != Material.COMPASS) {
|
|
||||||
warpEntityServer.remove(p);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
selected.remove(p);
|
|
||||||
entityServer = new REntityServer();
|
|
||||||
entityServer.addPlayer(p);
|
|
||||||
warpEntityServer.put(p, entityServer);
|
|
||||||
|
|
||||||
|
WarpComponent warpComponent = swPlayer.getComponentOrDefault(WarpComponent.class, WarpComponent::new);
|
||||||
Vector current = p.getLocation().clone().add(p.getLocation().getDirection().multiply(5)).toVector();
|
Vector current = p.getLocation().clone().add(p.getLocation().getDirection().multiply(5)).toVector();
|
||||||
|
|
||||||
Map<String, Location> locations = new HashMap<>();
|
Map<String, Location> locations = new HashMap<>();
|
||||||
@@ -99,12 +107,9 @@ public class WarpListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
REntityServer finalEntityServer = entityServer;
|
|
||||||
locations.forEach((name, location) -> {
|
locations.forEach((name, location) -> {
|
||||||
Vector vector = location.toVector().subtract(p.getLocation().toVector());
|
Vector vector = location.toVector().subtract(p.getLocation().toVector());
|
||||||
if (vector.getX() * vector.getX() + vector.getZ() * vector.getZ() < 25) {
|
if (vector.getX() * vector.getX() + vector.getZ() * vector.getZ() < 25) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
vector.setY(0);
|
vector.setY(0);
|
||||||
|
|
||||||
Vector position = p.getLocation().toVector().clone().add(vector.normalize().multiply(5));
|
Vector position = p.getLocation().toVector().clone().add(vector.normalize().multiply(5));
|
||||||
@@ -112,9 +117,9 @@ public class WarpListener implements Listener {
|
|||||||
|
|
||||||
if ((position.getX() - current.getX()) * (position.getX() - current.getX()) + (position.getZ() - current.getZ()) * (position.getZ() - current.getZ()) < 0.1) {
|
if ((position.getX() - current.getX()) * (position.getX() - current.getX()) + (position.getZ() - current.getZ()) * (position.getZ() - current.getZ()) < 0.1) {
|
||||||
name = "§a§l" + name;
|
name = "§a§l" + name;
|
||||||
selected.computeIfAbsent(p, player -> new ArrayList<>()).add(location);
|
warpComponent.selected.add(location);
|
||||||
}
|
}
|
||||||
RArmorStand armorStand = new RArmorStand(finalEntityServer, position.toLocation(p.getWorld()), RArmorStand.Size.MARKER);
|
RArmorStand armorStand = new RArmorStand(warpComponent.server, position.toLocation(p.getWorld()), RArmorStand.Size.MARKER);
|
||||||
armorStand.setDisplayName(name);
|
armorStand.setDisplayName(name);
|
||||||
armorStand.setNoGravity(true);
|
armorStand.setNoGravity(true);
|
||||||
armorStand.setInvisible(true);
|
armorStand.setInvisible(true);
|
||||||
@@ -123,28 +128,13 @@ public class WarpListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
if (event.getPlayer().getInventory().getItemInMainHand().getType() != Material.COMPASS) {
|
if (event.getPlayer().getInventory().getItemInMainHand().getType() != Material.COMPASS) return;
|
||||||
return;
|
if (event.getAction() != Action.RIGHT_CLICK_AIR) return;
|
||||||
}
|
WarpComponent warpComponent = SWPlayer.of(event.getPlayer()).getComponent(WarpComponent.class).orElse(null);
|
||||||
if (event.getAction() != Action.RIGHT_CLICK_AIR) {
|
if (warpComponent == null || warpComponent.selected.size() != 1) return;
|
||||||
return;
|
Location location = warpComponent.selected.get(0);
|
||||||
}
|
|
||||||
List<Location> locations = selected.getOrDefault(event.getPlayer(), new ArrayList<>());
|
|
||||||
if (locations.size() != 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Location location = locations.get(0);
|
|
||||||
event.getPlayer().teleport(location);
|
event.getPlayer().teleport(location);
|
||||||
event.getPlayer().playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
event.getPlayer().playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
warpEntityServer.computeIfPresent(event.getPlayer(), (player, rEntityServer) -> {
|
|
||||||
rEntityServer.close();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
selected.remove(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ public class AntiBauAddMemberFix implements Listener {
|
|||||||
}
|
}
|
||||||
if (BauweltMember.getBauMember(BauServer.getInstance().getOwner(), event.getPlayer().getUniqueId()) == null) {
|
if (BauweltMember.getBauMember(BauServer.getInstance().getOwner(), event.getPlayer().getUniqueId()) == null) {
|
||||||
event.getPlayer().kickPlayer("");
|
event.getPlayer().kickPlayer("");
|
||||||
throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.get(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!");
|
throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.byId(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-5
@@ -59,18 +59,14 @@ public class BauMemberUpdate extends PacketHandler implements Listener {
|
|||||||
Set<Player> newSpectator = new HashSet<>();
|
Set<Player> newSpectator = new HashSet<>();
|
||||||
Set<Player> newBuilder = new HashSet<>();
|
Set<Player> newBuilder = new HashSet<>();
|
||||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||||
if (Permission.REAL_SPECTATOR.hasPermission(player)) {
|
if (Permission.SPECTATOR.hasPermission(player)) {
|
||||||
if (!SPECTATORS.contains(player)) {
|
if (!SPECTATORS.contains(player)) {
|
||||||
SPECTATORS.add(player);
|
SPECTATORS.add(player);
|
||||||
Permission.removeForceOnlySpectator(player);
|
|
||||||
newSpectator.add(player);
|
newSpectator.add(player);
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, -1, 1, false,false, false));
|
player.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, -1, 1, false,false, false));
|
||||||
showSpectatorNotice(player);
|
showSpectatorNotice(player);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Permission.SUPERVISOR.hasPermission(player)) {
|
|
||||||
Permission.removeForceOnlySpectator(player);
|
|
||||||
}
|
|
||||||
if (SPECTATORS.contains(player)) {
|
if (SPECTATORS.contains(player)) {
|
||||||
SPECTATORS.remove(player);
|
SPECTATORS.remove(player);
|
||||||
newBuilder.add(player);
|
newBuilder.add(player);
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.world;
|
|
||||||
|
|
||||||
import de.steamwar.linkage.Linked;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
|
||||||
|
|
||||||
@Linked
|
|
||||||
public class OtherTNTListener implements Listener {
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
|
||||||
public void onExplosion(EntityExplodeEvent e) {
|
|
||||||
e.blockList().removeIf(block -> {
|
|
||||||
if(block.getType() == Material.TNT) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
block.setType(Material.AIR);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+18
-4
@@ -49,6 +49,7 @@ import java.util.Set;
|
|||||||
@Linked
|
@Linked
|
||||||
public class SpectatorListener implements Listener {
|
public class SpectatorListener implements Listener {
|
||||||
|
|
||||||
|
private static final TechHider techHider;
|
||||||
private static final Set<Player> NO_TECHHIDER = new HashSet<>();
|
private static final Set<Player> NO_TECHHIDER = new HashSet<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -100,10 +101,20 @@ public class SpectatorListener implements Listener {
|
|||||||
materials.add(Material.WATER);
|
materials.add(Material.WATER);
|
||||||
materials.remove(Material.BARRIER);
|
materials.remove(Material.BARRIER);
|
||||||
materials.remove(Material.STONE);
|
materials.remove(Material.STONE);
|
||||||
TechHider techHider = new TechHider((TechHider.LocationEvaluator) (player, i, i1) -> {
|
techHider = new TechHider((TechHider.LocationEvaluator) (player, i, i1) -> {
|
||||||
return Permission.BUILD.hasPermission(player) || Permission.isTempOnlySpectator(player) || NO_TECHHIDER.contains(player);
|
return Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player);
|
||||||
}, Material.END_STONE, materials, new HashSet<>());
|
}, Material.END_STONE, materials, new HashSet<>());
|
||||||
techHider.enable();
|
}
|
||||||
|
|
||||||
|
private static void enableOrDisableTechhider() {
|
||||||
|
boolean enable = Bukkit.getOnlinePlayers()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(player -> !(Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player)));
|
||||||
|
if (enable) {
|
||||||
|
techHider.enable();
|
||||||
|
} else {
|
||||||
|
techHider.disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void toggleNoTechHider(Player player) {
|
public static void toggleNoTechHider(Player player) {
|
||||||
@@ -113,6 +124,7 @@ public class SpectatorListener implements Listener {
|
|||||||
NO_TECHHIDER.add(player);
|
NO_TECHHIDER.add(player);
|
||||||
}
|
}
|
||||||
resendChunks(player);
|
resendChunks(player);
|
||||||
|
enableOrDisableTechhider();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void resendChunks(Player player) {
|
private static void resendChunks(Player player) {
|
||||||
@@ -131,6 +143,7 @@ public class SpectatorListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
enableOrDisableTechhider();
|
||||||
if (BauSystem.DEV_SERVER) return;
|
if (BauSystem.DEV_SERVER) return;
|
||||||
if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) {
|
if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) {
|
||||||
return;
|
return;
|
||||||
@@ -152,6 +165,7 @@ public class SpectatorListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
||||||
|
enableOrDisableTechhider();
|
||||||
if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) {
|
if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) {
|
||||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||||
player.kickPlayer("");
|
player.kickPlayer("");
|
||||||
@@ -161,7 +175,6 @@ public class SpectatorListener implements Listener {
|
|||||||
|
|
||||||
event.getChanged().forEach(player -> {
|
event.getChanged().forEach(player -> {
|
||||||
NO_TECHHIDER.remove(player);
|
NO_TECHHIDER.remove(player);
|
||||||
if (Permission.isTempOnlySpectator(player)) return;
|
|
||||||
resendChunks(player);
|
resendChunks(player);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -169,6 +182,7 @@ public class SpectatorListener implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
NO_TECHHIDER.remove(event.getPlayer());
|
NO_TECHHIDER.remove(event.getPlayer());
|
||||||
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), SpectatorListener::enableOrDisableTechhider, 1);
|
||||||
if (BauSystem.DEV_SERVER) return;
|
if (BauSystem.DEV_SERVER) return;
|
||||||
if (!anySupervisorOnline(event.getPlayer())) {
|
if (!anySupervisorOnline(event.getPlayer())) {
|
||||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||||
|
|||||||
+10
-15
@@ -23,6 +23,7 @@ import de.steamwar.bausystem.BauSystem;
|
|||||||
import de.steamwar.bausystem.region.Point;
|
import de.steamwar.bausystem.region.Point;
|
||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
import de.steamwar.core.WorldEditRenderer;
|
import de.steamwar.core.WorldEditRenderer;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.linkage.MinVersion;
|
import de.steamwar.linkage.MinVersion;
|
||||||
@@ -35,13 +36,10 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
@@ -71,32 +69,23 @@ public class SelectAdjacent implements Listener {
|
|||||||
new Vector(0, -1, -1),
|
new Vector(0, -1, -1),
|
||||||
};
|
};
|
||||||
|
|
||||||
private Map<Player, Selector> selectors = new HashMap<>();
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
if (!event.hasItem()) return;
|
if (!event.hasItem()) return;
|
||||||
if (event.getItem().getType() != Material.WOODEN_AXE) return;
|
if (event.getItem().getType() != Material.WOODEN_AXE) return;
|
||||||
Selector selector = selectors.get(event.getPlayer());
|
|
||||||
if (selector != null) selector.cancel();
|
|
||||||
if (!event.getPlayer().isSneaking()) return;
|
if (!event.getPlayer().isSneaking()) return;
|
||||||
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
|
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
|
||||||
Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
|
Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
|
||||||
|
Selector selector;
|
||||||
if (material.isAir()) {
|
if (material.isAir()) {
|
||||||
selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
|
selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
|
||||||
} else {
|
} else {
|
||||||
selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
|
selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
|
||||||
}
|
}
|
||||||
selectors.put(event.getPlayer(), selector);
|
SWPlayer.of(event.getPlayer()).setComponent(selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
private class Selector implements SWPlayer.Component {
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
Selector selector = selectors.remove(event.getPlayer());
|
|
||||||
if (selector != null) selector.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Selector {
|
|
||||||
|
|
||||||
private static final int MAX_BLOCKS = 500_000;
|
private static final int MAX_BLOCKS = 500_000;
|
||||||
|
|
||||||
@@ -154,6 +143,7 @@ public class SelectAdjacent implements Listener {
|
|||||||
if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
|
if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
|
||||||
bukkitTask.cancel();
|
bukkitTask.cancel();
|
||||||
player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
|
player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
|
||||||
|
SWPlayer.of(player).removeComponent(Selector.class);
|
||||||
}
|
}
|
||||||
}, 1, 1);
|
}, 1, 1);
|
||||||
}
|
}
|
||||||
@@ -190,5 +180,10 @@ public class SelectAdjacent implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen
|
|||||||
if (hidden.containsKey(region) && hidden.get(region).contains(player)) {
|
if (hidden.containsKey(region) && hidden.get(region).contains(player)) {
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||||
PlayerMovementWrapper.impl.setPosition(player, o);
|
PlayerMovementWrapper.impl.setPosition(player, o);
|
||||||
}, 1L);
|
}, 0);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
|
|||||||
@@ -50,5 +50,6 @@ tasks.register<DevServer>("DevBau21") {
|
|||||||
description = "Run a 1.21 Dev Bau"
|
description = "Run a 1.21 Dev Bau"
|
||||||
dependsOn(":SpigotCore:shadowJar")
|
dependsOn(":SpigotCore:shadowJar")
|
||||||
dependsOn(":BauSystem:shadowJar")
|
dependsOn(":BauSystem:shadowJar")
|
||||||
|
dependsOn(":SchematicSystem:shadowJar")
|
||||||
template = "Bau21"
|
template = "Bau21"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
steamwar.java
|
steamwar.kotlin
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvmToolchain(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(libs.sqlite)
|
compileOnly(libs.sqlite)
|
||||||
|
|
||||||
implementation("org.yaml:snakeyaml:2.2")
|
implementation("org.yaml:snakeyaml:2.2")
|
||||||
}
|
|
||||||
|
compileOnlyApi("org.jetbrains.kotlin:kotlin-stdlib:2.2.21")
|
||||||
|
compileOnlyApi(libs.exposedCore)
|
||||||
|
compileOnlyApi(libs.exposedDao)
|
||||||
|
compileOnlyApi(libs.exposedJdbc)
|
||||||
|
compileOnlyApi(libs.exposedTime)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SqlTypeMapper;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NonNull;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class AuditLog {
|
|
||||||
|
|
||||||
static {
|
|
||||||
SqlTypeMapper.nameEnumMapper(AuditLog.Type.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String SERVER_NAME_VELOCITY = "Velocity";
|
|
||||||
|
|
||||||
private static final Table<AuditLog> table = new Table<>(AuditLog.class);
|
|
||||||
|
|
||||||
private static final Statement create = table.insertFields(true, "time", "serverName", "serverOwner", "actor", "actionType", "actionText");
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp time;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final String serverName;
|
|
||||||
|
|
||||||
@Field(nullable = true)
|
|
||||||
private final int serverOwner;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private final int actor;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Type actionType;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final String actionText;
|
|
||||||
|
|
||||||
public enum Type {
|
|
||||||
JOIN,
|
|
||||||
LEAVE,
|
|
||||||
COMMAND,
|
|
||||||
SENSITIVE_COMMAND,
|
|
||||||
|
|
||||||
CHAT,
|
|
||||||
GUI_OPEN,
|
|
||||||
GUI_CLOSE,
|
|
||||||
GUI_CLICK,
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void create(String serverName, SteamwarUser serverOwner, SteamwarUser actor, Type actionType, String text) {
|
|
||||||
create.insertGetKey(Timestamp.from(Instant.now()), serverName, serverOwner, actor, actionType, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createJoin(@NonNull String jointServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) {
|
|
||||||
create(jointServerName, serverOwner, joinedPlayer, Type.JOIN, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createLeave(@NonNull String leftServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) {
|
|
||||||
create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) {
|
|
||||||
if (player == null) return;
|
|
||||||
create(serverName, serverOwner, player, Type.COMMAND, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createSensitiveCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) {
|
|
||||||
if (player == null) return;
|
|
||||||
create(serverName, serverOwner, player, Type.SENSITIVE_COMMAND, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createChat(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser chatter, @NonNull String chat) {
|
|
||||||
create(serverName, serverOwner, chatter, Type.CHAT, chat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createGuiOpen(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) {
|
|
||||||
create(serverName, serverOwner, player, Type.GUI_OPEN, guiName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createGuiClick(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName, @NonNull String clickType, int slot, @NonNull String itemName) {
|
|
||||||
create(serverName, serverOwner, player, Type.GUI_CLICK, "Gui: " + guiName + "\nSlot: " + slot + "\nClickType: " + clickType + "\nItemName: " + itemName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createGuiClose(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) {
|
|
||||||
create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SteamwarUser getServerOwner() {
|
|
||||||
return SteamwarUser.get(serverOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SteamwarUser getActor() {
|
|
||||||
return SteamwarUser.get(actor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
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 java.time.Instant
|
||||||
|
|
||||||
|
object AuditLogTable: IntIdTable("AuditLog", "AuditLogId") {
|
||||||
|
val time = timestamp("Time")
|
||||||
|
val server = varchar("ServerName", 255)
|
||||||
|
val serverOwner = reference("ServerOwner", SteamwarUserTable).nullable()
|
||||||
|
val actor = reference("Actor", SteamwarUserTable)
|
||||||
|
val action = enumerationByName("ActionType", 255, AuditLog.Type::class)
|
||||||
|
val actionText = text("ActionText")
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuditLog(id: EntityID<Int>): IntEntity(id) {
|
||||||
|
companion object: IntEntityClass<AuditLog>(AuditLogTable) {
|
||||||
|
const val SERVER_NAME_VELOCITY: String = "Velocity"
|
||||||
|
|
||||||
|
private fun create(
|
||||||
|
serverName: String,
|
||||||
|
serverOwner: SteamwarUser?,
|
||||||
|
actor: SteamwarUser,
|
||||||
|
actionType: Type,
|
||||||
|
text: String = ""
|
||||||
|
) = useDb {
|
||||||
|
new {
|
||||||
|
this.time = Instant.now()
|
||||||
|
this.server = serverName
|
||||||
|
this.serverOwner = serverOwner?.id
|
||||||
|
this.actor = actor.id
|
||||||
|
this.action = actionType
|
||||||
|
this.actionText = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createJoin(jointServerName: String, serverOwner: SteamwarUser?, joinedPlayer: SteamwarUser) = create(jointServerName, serverOwner, joinedPlayer, Type.JOIN)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createLeave(leftServerName: String, serverOwner: SteamwarUser?, joinedPlayer: SteamwarUser) = create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createCommand(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser?, command: String) = player?.let { create(serverName, serverOwner, it, Type.COMMAND, command) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createSensitiveCommand(
|
||||||
|
serverName: String,
|
||||||
|
serverOwner: SteamwarUser?,
|
||||||
|
player: SteamwarUser?,
|
||||||
|
command: String
|
||||||
|
) = player?.let { create(serverName, serverOwner, it, Type.SENSITIVE_COMMAND, command) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createChat(serverName: String, serverOwner: SteamwarUser?, chatter: SteamwarUser, chat: String) = create(serverName, serverOwner, chatter, Type.CHAT, chat)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createGuiOpen(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser, guiName: String) = create(serverName, serverOwner, player, Type.GUI_OPEN, guiName)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createGuiClick(
|
||||||
|
serverName: String,
|
||||||
|
serverOwner: SteamwarUser?,
|
||||||
|
player: SteamwarUser,
|
||||||
|
guiName: String,
|
||||||
|
clickType: String,
|
||||||
|
slot: Int,
|
||||||
|
itemName: String
|
||||||
|
) = create(
|
||||||
|
serverName,
|
||||||
|
serverOwner,
|
||||||
|
player,
|
||||||
|
Type.GUI_CLICK,
|
||||||
|
"Gui: $guiName\nSlot: $slot\nClickType: $clickType\nItemName: $itemName"
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createGuiClose(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser, guiName: String) = create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName)
|
||||||
|
}
|
||||||
|
|
||||||
|
var time by AuditLogTable.time
|
||||||
|
var server by AuditLogTable.server
|
||||||
|
var serverOwner by AuditLogTable.serverOwner
|
||||||
|
var actor by AuditLogTable.actor
|
||||||
|
var action by AuditLogTable.action
|
||||||
|
var actionText by AuditLogTable.actionText
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
JOIN,
|
||||||
|
LEAVE,
|
||||||
|
COMMAND,
|
||||||
|
SENSITIVE_COMMAND,
|
||||||
|
CHAT,
|
||||||
|
GUI_OPEN,
|
||||||
|
GUI_CLOSE,
|
||||||
|
GUI_CLICK,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class BannedUserIPs {
|
|
||||||
|
|
||||||
private static final Table<BannedUserIPs> table = new Table<>(BannedUserIPs.class);
|
|
||||||
|
|
||||||
private static final SelectStatement<BannedUserIPs> getByID = table.selectFields("UserID");
|
|
||||||
private static final SelectStatement<BannedUserIPs> getByIP = new SelectStatement<>(table, "SELECT * FROM BannedUserIPs WHERE IP = ? ORDER BY Timestamp DESC");
|
|
||||||
private static final Statement banIP = table.insertAll();
|
|
||||||
private static final Statement unbanIPs = table.deleteFields("UserID");
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int userID;
|
|
||||||
@Getter
|
|
||||||
@Field(def = "CURRENT_TIMESTAMP")
|
|
||||||
private final Timestamp timestamp;
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final String ip;
|
|
||||||
|
|
||||||
public static List<BannedUserIPs> get(int userID) {
|
|
||||||
return getByID.listSelect(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<BannedUserIPs> get(String ip) {
|
|
||||||
return getByIP.listSelect(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void banIP(int userID, String ip){
|
|
||||||
banIP.update(userID, Timestamp.from(Instant.now()), ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void unbanIPs(int userID) {
|
|
||||||
unbanIPs.update(userID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.deleteWhere
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||||
|
import java.sql.Timestamp
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
object BannedUserIPsTable: CompositeIdTable("BannedUserIPs") {
|
||||||
|
val userId = reference("UserID", SteamwarUserTable)
|
||||||
|
val timestamp = timestamp("Timestamp")
|
||||||
|
val ip = varchar("IP", 45)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(userId, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BannedUserIPs(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
companion object: CompositeEntityClass<BannedUserIPs>(BannedUserIPsTable) {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(userId: Int) = useDb {
|
||||||
|
find { BannedUserIPsTable.userId eq userId }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(ip: String) = useDb {
|
||||||
|
find { BannedUserIPsTable.ip eq ip }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun banIP(userId: Int, ip: String) = useDb {
|
||||||
|
BannedUserIPsTable.insertIgnore {
|
||||||
|
it[BannedUserIPsTable.userId] = userId
|
||||||
|
it[BannedUserIPsTable.ip] = ip
|
||||||
|
it[BannedUserIPsTable.timestamp] = Instant.now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun unbanIPs(userId: Int) = useDb {
|
||||||
|
BannedUserIPsTable.deleteWhere { BannedUserIPsTable.userId eq userId }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val userID by BannedUserIPsTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
val timestamp: Timestamp by BannedUserIPsTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
val ip by BannedUserIPsTable.ip
|
||||||
|
|
||||||
|
fun remove() = useDb {
|
||||||
|
delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class BauweltMember {
|
|
||||||
private static final Map<Integer, BauweltMember> memberCache = new HashMap<>();
|
|
||||||
|
|
||||||
public static void clear() {
|
|
||||||
memberCache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<BauweltMember> table = new Table<>(BauweltMember.class);
|
|
||||||
private static final SelectStatement<BauweltMember> getMember = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<BauweltMember> getMembers = table.selectFields("BauweltID");
|
|
||||||
private static final Statement update = table.insertAll();
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
public static void addMember(UUID ownerID, UUID memberID) {
|
|
||||||
new BauweltMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId(), false, false).updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BauweltMember getBauMember(UUID ownerID, UUID memberID){
|
|
||||||
return getBauMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BauweltMember getBauMember(int ownerID, int memberID){
|
|
||||||
BauweltMember member = memberCache.get(memberID);
|
|
||||||
if(member != null && member.bauweltID == ownerID)
|
|
||||||
return member;
|
|
||||||
return getMember.select(ownerID, memberID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<BauweltMember> getMembers(UUID bauweltID){
|
|
||||||
return getMembers(SteamwarUser.get(bauweltID).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<BauweltMember> getMembers(int bauweltID){
|
|
||||||
return getMembers.listSelect(bauweltID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int bauweltID;
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int memberID;
|
|
||||||
@Getter
|
|
||||||
@Field(def = "0")
|
|
||||||
private boolean worldEdit;
|
|
||||||
@Getter
|
|
||||||
@Field(def = "0")
|
|
||||||
private boolean world;
|
|
||||||
|
|
||||||
public BauweltMember(int bauweltID, int memberID, boolean worldEdit, boolean world) {
|
|
||||||
this.bauweltID = bauweltID;
|
|
||||||
this.memberID = memberID;
|
|
||||||
this.worldEdit = worldEdit;
|
|
||||||
this.world = world;
|
|
||||||
memberCache.put(memberID, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWorldEdit(boolean worldEdit) {
|
|
||||||
this.worldEdit = worldEdit;
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWorld(boolean world) {
|
|
||||||
this.world = world;
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDB(){
|
|
||||||
update.update(bauweltID, memberID, worldEdit, world);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(){
|
|
||||||
delete.update(bauweltID, memberID);
|
|
||||||
memberCache.remove(memberID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBuild() {
|
|
||||||
return worldEdit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSupervisor() {
|
|
||||||
return world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBuild(boolean build) {
|
|
||||||
this.worldEdit = build;
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSupervisor(boolean supervisor) {
|
|
||||||
this.world = supervisor;
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.BauweltMemberTable.bauweltId
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object BauweltMemberTable: CompositeIdTable("BauweltMember") {
|
||||||
|
val bauweltId = reference("BauweltID", SteamwarUserTable)
|
||||||
|
val memberId = reference("MemberID", SteamwarUserTable)
|
||||||
|
val build = bool("Build")
|
||||||
|
val worldEdit = bool("WorldEdit")
|
||||||
|
val world = bool("World")
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(bauweltId, memberId)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(bauweltId)
|
||||||
|
addIdColumn(memberId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BauweltMember(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
companion object: CompositeEntityClass<BauweltMember>(BauweltMemberTable) {
|
||||||
|
private val cache = mutableMapOf<Int, BauweltMember>()
|
||||||
|
|
||||||
|
private fun cache(member: BauweltMember) = cache.put(member.memberID, member)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun clear() = cache.clear()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Deprecated("Use addMember(ownerId: Int, newMemberId: Int)")
|
||||||
|
fun addMember(ownerId: UUID, newMemberId: UUID) = addMember(SteamwarUser.get(ownerId)!!.id, SteamwarUser.get(newMemberId)!!.id)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun addMember(ownerId: Int, newMemberId: Int) = addMember(EntityID(ownerId, SteamwarUserTable), EntityID(newMemberId, SteamwarUserTable))
|
||||||
|
|
||||||
|
fun addMember(ownerId: EntityID<Int>, newMemberId: EntityID<Int>) = useDb {
|
||||||
|
BauweltMemberTable.insertIgnore {
|
||||||
|
it[bauweltId] = ownerId
|
||||||
|
it[memberId] = newMemberId
|
||||||
|
it[build] = false
|
||||||
|
it[worldEdit] = false
|
||||||
|
it[world] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Deprecated("Use getBauMember(bauwelt: Int, member: Int)")
|
||||||
|
fun getBauMember(bauwelt: UUID, member: UUID) = useDb {
|
||||||
|
find { (bauweltId eq SteamwarUser.get(bauwelt)!!.id) and (BauweltMemberTable.memberId eq SteamwarUser.get(member)!!.id) }.firstOrNull()?.also { cache(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getBauMember(bauwelt: Int, member: Int) = useDb {
|
||||||
|
find { (bauweltId eq bauwelt) and (BauweltMemberTable.memberId eq member) }.firstOrNull()?.also { cache(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Deprecated("Use getMembers(bauwelt: Int)")
|
||||||
|
fun getMembers(bauwelt: UUID) = getMembers(SteamwarUser.get(bauwelt)!!.id.value)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getMembers(bauwelt: Int) = useDb {
|
||||||
|
find { bauweltId eq bauwelt }.toList().also { it.forEach { cache(it) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val bauweltID by BauweltMemberTable.bauweltId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
val memberID by BauweltMemberTable.memberId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
private var worldEditInternal by BauweltMemberTable.worldEdit
|
||||||
|
var worldEdit: Boolean
|
||||||
|
get() = worldEditInternal
|
||||||
|
set(value) = useDb {
|
||||||
|
worldEditInternal = value
|
||||||
|
}
|
||||||
|
private var buildInternal by BauweltMemberTable.build
|
||||||
|
var build: Boolean
|
||||||
|
get() = buildInternal
|
||||||
|
set(value) = useDb {
|
||||||
|
buildInternal = value
|
||||||
|
}
|
||||||
|
private var worldInternal by BauweltMemberTable.world
|
||||||
|
var world: Boolean
|
||||||
|
get() = worldInternal
|
||||||
|
set(value) = useDb {
|
||||||
|
worldInternal = value
|
||||||
|
}
|
||||||
|
var supervisor: Boolean
|
||||||
|
get() = world
|
||||||
|
set(value) = useDb {
|
||||||
|
world = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isBuild() = build
|
||||||
|
fun isSupervisor() = world
|
||||||
|
fun isWorldEdit() = build
|
||||||
|
fun isWorld() = world
|
||||||
|
|
||||||
|
fun remove() = useDb {
|
||||||
|
delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class CheckedSchematic {
|
|
||||||
|
|
||||||
private static final Table<CheckedSchematic> table = new Table<>(CheckedSchematic.class);
|
|
||||||
private static final SelectStatement<CheckedSchematic> statusOfNode = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC");
|
|
||||||
private static final SelectStatement<CheckedSchematic> nodeHistory = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC");
|
|
||||||
private static final Statement insert = table.insertAll();
|
|
||||||
|
|
||||||
private static final SelectStatement<CheckedSchematic> getUnseen = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE Seen = 0 AND NodeOwner = ? ORDER BY StartTime DESC");
|
|
||||||
private static final Statement updateSeen = new Statement("UPDATE CheckedSchematic SET Seen = ? WHERE StartTime = ? AND EndTime = ? AND NodeName = ?");
|
|
||||||
|
|
||||||
public static void create(SchematicNode node, int validator, Timestamp startTime, Timestamp endTime, String reason, boolean seen) {
|
|
||||||
insert.update(node.getId(), node.getOwner(), node.getName(), validator, startTime, endTime, reason, seen, node.getSchemtype().toDB().substring(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<CheckedSchematic> getLastDeclinedOfNode(int node) {
|
|
||||||
return statusOfNode.listSelect(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<CheckedSchematic> previousChecks(SchematicNode node) {
|
|
||||||
return nodeHistory.listSelect(node.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<CheckedSchematic> getUnseen(SteamwarUser owner) {
|
|
||||||
return getUnseen.listSelect(owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(nullable = true)
|
|
||||||
private final Integer nodeId;
|
|
||||||
@Field
|
|
||||||
private final int nodeOwner;
|
|
||||||
@Field
|
|
||||||
private final String nodeName;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final int validator;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp startTime;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp endTime;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final String declineReason;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private boolean seen;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final String nodeType;
|
|
||||||
|
|
||||||
public int getNode() {
|
|
||||||
return nodeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSchemName() {
|
|
||||||
return nodeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSchemOwner() {
|
|
||||||
return nodeOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeen(boolean seen) {
|
|
||||||
this.seen = seen;
|
|
||||||
updateSeen.update(seen, startTime, endTime, nodeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.SortOrder
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.neq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||||
|
import java.sql.Timestamp
|
||||||
|
|
||||||
|
object CheckedSchematicTable: CompositeIdTable("CheckedSchematic") {
|
||||||
|
val nodeId = optReference("NodeId", SchematicNodeTable)
|
||||||
|
val nodeOwner = reference("NodeOwner", SteamwarUserTable)
|
||||||
|
val nodeName = varchar("NodeName", 64).entityId()
|
||||||
|
val validator = reference("Validator", SteamwarUserTable)
|
||||||
|
val startTime = timestamp("StartTime").entityId()
|
||||||
|
val endTime = timestamp("EndTime")
|
||||||
|
val declineReason = text("DeclineReason")
|
||||||
|
val seen = bool("Seen")
|
||||||
|
val nodeType = varchar("NodeType", 16)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(nodeOwner)
|
||||||
|
addIdColumn(nodeName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CheckedSchematic(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
companion object: CompositeEntityClass<CheckedSchematic>(CheckedSchematicTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun create(node: SchematicNode, validator: Int, startTime: Timestamp, endTime: Timestamp, reason: String, seen: Boolean) = useDb {
|
||||||
|
CheckedSchematicTable.insertIgnore {
|
||||||
|
it[this.nodeId] = node.id
|
||||||
|
it[this.nodeOwner] = EntityID(node.owner, SteamwarUserTable)
|
||||||
|
it[this.nodeName] = node.name
|
||||||
|
it[this.validator] = EntityID(validator, SteamwarUserTable)
|
||||||
|
it[this.startTime] = startTime.toInstant()
|
||||||
|
it[this.endTime] = endTime.toInstant()
|
||||||
|
it[this.declineReason] = reason
|
||||||
|
it[this.seen] = seen
|
||||||
|
it[this.nodeType] = node.schemtype.toDB().substring(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getLastDeclinedOfNode(node: Int) = useDb {
|
||||||
|
find { (CheckedSchematicTable.nodeId eq node) and (CheckedSchematicTable.declineReason neq "Prüfvorgang abgebrochen") }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun previousChecks(node: SchematicNode) = useDb {
|
||||||
|
find { (CheckedSchematicTable.nodeId eq node.id) and (CheckedSchematicTable.declineReason neq "") and (CheckedSchematicTable.declineReason neq "Prüfvorgang abgebrochen") }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getUnseen(owner: SteamwarUser) = useDb {
|
||||||
|
find { (CheckedSchematicTable.nodeOwner eq owner.id) and (CheckedSchematicTable.seen eq false) }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val node by CheckedSchematicTable.nodeId.transform({ it?.let { EntityID(it, SchematicNodeTable) } }, { it?.value })
|
||||||
|
val schemOwner by CheckedSchematicTable.nodeOwner.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
val nodeName by CheckedSchematicTable.nodeName
|
||||||
|
val schemName get() = nodeName.value
|
||||||
|
val validator by CheckedSchematicTable.validator.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
val startTimeId by CheckedSchematicTable.startTime
|
||||||
|
val startTime get() = Timestamp.from(startTimeId.value)
|
||||||
|
val endTime by CheckedSchematicTable.endTime.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
val declineReason by CheckedSchematicTable.declineReason
|
||||||
|
private var wasSeen by CheckedSchematicTable.seen
|
||||||
|
var seen: Boolean
|
||||||
|
get() = wasSeen
|
||||||
|
set(value) = useDb { wasSeen = value }
|
||||||
|
val nodeType by CheckedSchematicTable.nodeType
|
||||||
|
}
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class Event {
|
|
||||||
|
|
||||||
static {
|
|
||||||
SchematicType.Normal.name(); // Ensure SchematicType is loaded.
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<Event> table = new Table<>(Event.class);
|
|
||||||
|
|
||||||
private static final SelectStatement<Event> byCurrent = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start < now() AND End > now()");
|
|
||||||
private static final SelectStatement<Event> byId = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<Event> byName = table.select("eventName");
|
|
||||||
private static final SelectStatement<Event> byComing = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start > now()");
|
|
||||||
private static final SelectStatement<Event> all = new SelectStatement<>(table, "SELECT * FROM Event");
|
|
||||||
|
|
||||||
private static final Statement create = table.insertFields(true, "eventName", "deadline", "start", "end", "maximumTeamMembers", "publicSchemsOnly");
|
|
||||||
private static final Statement update = table.update(Table.PRIMARY, "eventName", "deadline", "start", "end", "schemType", "maximumTeamMembers", "publicSchemsOnly");
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
private static Event current = null;
|
|
||||||
|
|
||||||
public static Event get(){
|
|
||||||
if(current != null && current.now())
|
|
||||||
return current;
|
|
||||||
|
|
||||||
current = byCurrent.select();
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Event> getAll(){
|
|
||||||
return all.listSelect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Event create(String eventName, Timestamp start, Timestamp end){
|
|
||||||
return get(create.insertGetKey(eventName, start, start, end, 5, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Event get(int eventID){
|
|
||||||
return byId.select(eventID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Event get(String eventName) {
|
|
||||||
return byName.select(eventName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Event> getComing() {
|
|
||||||
return byComing.listSelect();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
|
||||||
private final int eventID;
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {"eventName"})
|
|
||||||
private final String eventName;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp deadline;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp start;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp end;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final int maximumTeamMembers;
|
|
||||||
@Field(nullable = true)
|
|
||||||
private final SchematicType schemType;
|
|
||||||
@Field
|
|
||||||
private final boolean publicSchemsOnly;
|
|
||||||
|
|
||||||
public boolean publicSchemsOnly() {
|
|
||||||
return publicSchemsOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SchematicType getSchematicType() {
|
|
||||||
return schemType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean now() {
|
|
||||||
Instant now = Instant.now();
|
|
||||||
return now.isAfter(start.toInstant()) && now.isBefore(end.toInstant());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(String eventName, Timestamp deadline, Timestamp start, Timestamp end, SchematicType schemType, int maximumTeamMembers, boolean publicSchemsOnly) {
|
|
||||||
update.update(eventName, deadline, start, end, schemType, maximumTeamMembers, publicSchemsOnly, eventID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(eventID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.greater
|
||||||
|
import org.jetbrains.exposed.v1.core.lessEq
|
||||||
|
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.time.Instant
|
||||||
|
|
||||||
|
object EventTable : IntIdTable("Event", "EventId") {
|
||||||
|
val name = varchar("EventName", 100).uniqueIndex()
|
||||||
|
val deadline = timestamp("Deadline")
|
||||||
|
val start = timestamp("Start")
|
||||||
|
val end = timestamp("End")
|
||||||
|
val maxPlayers = integer("MaximumTeamMembers")
|
||||||
|
val schemType = varchar("SchemType", 16).nullable()
|
||||||
|
val publicsOnly = bool("PublicSchemsOnly")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Event(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Event>(EventTable) {
|
||||||
|
private var current: Event? = null
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(): Event? = if (current?.now() == true) {
|
||||||
|
current
|
||||||
|
} else useDb {
|
||||||
|
find { EventTable.start.lessEq(Instant.now()) and EventTable.end.greater(Instant.now()) }.firstOrNull()
|
||||||
|
?.also { current == it }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getAll() = useDb { all().toList() }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(name: String, start: Timestamp, end: Timestamp) = useDb {
|
||||||
|
EventTable.insertAndGetId {
|
||||||
|
it[this.name] = name
|
||||||
|
it[this.deadline] = start.toInstant()
|
||||||
|
it[this.start] = start.toInstant()
|
||||||
|
it[this.end] = end.toInstant()
|
||||||
|
it[this.maxPlayers] = 5
|
||||||
|
it[this.publicsOnly] = false
|
||||||
|
}.let { get(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun byId(id: Int) = useDb { findById(id) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(name: String) = useDb { find { EventTable.name eq name }.firstOrNull() }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getComing() = useDb { find { EventTable.start greater Instant.now() }.toList() }
|
||||||
|
}
|
||||||
|
|
||||||
|
val eventID by EventTable.id.transform({ EntityID(it, EventTable) }, { it.value })
|
||||||
|
var eventName by EventTable.name
|
||||||
|
private set
|
||||||
|
var deadline: Timestamp by EventTable.deadline.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
private set
|
||||||
|
var start: Timestamp by EventTable.start.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
private set
|
||||||
|
var end: Timestamp by EventTable.end.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
private set
|
||||||
|
var maximumTeamMembers by EventTable.maxPlayers
|
||||||
|
private set
|
||||||
|
var schematicType by EventTable.schemType.transform({ it?.toDB() }, { it?.let { SchematicType.fromDB(it) } })
|
||||||
|
private set
|
||||||
|
var publicSchemsOnly by EventTable.publicsOnly
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun publicSchemsOnly() = publicSchemsOnly
|
||||||
|
fun now() = Instant.now().let { it.isAfter(start.toInstant()) && it.isBefore(end.toInstant()) }
|
||||||
|
|
||||||
|
fun update(
|
||||||
|
name: String,
|
||||||
|
deadline: Timestamp,
|
||||||
|
start: Timestamp,
|
||||||
|
end: Timestamp,
|
||||||
|
schematicType: SchematicType?,
|
||||||
|
maxPlayers: Int,
|
||||||
|
publicSchemsOnly: Boolean
|
||||||
|
) = useDb {
|
||||||
|
this@Event.eventName = name
|
||||||
|
this@Event.deadline = deadline
|
||||||
|
this@Event.start = start
|
||||||
|
this@Event.end = end
|
||||||
|
this@Event.maximumTeamMembers = maxPlayers
|
||||||
|
this@Event.schematicType = schematicType
|
||||||
|
this@Event.publicSchemsOnly = publicSchemsOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() = useDb { super.delete() }
|
||||||
|
}
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static java.time.temporal.ChronoUnit.SECONDS;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class EventFight implements Comparable<EventFight> {
|
|
||||||
|
|
||||||
private static final Table<EventFight> table = new Table<>(EventFight.class);
|
|
||||||
private static final SelectStatement<EventFight> byId = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<EventFight> byGroup = new SelectStatement<EventFight>(table, "SELECT * FROM EventFight WHERE GroupID = ? ORDER BY StartTime ASC");
|
|
||||||
private static final SelectStatement<EventFight> byGroupLast = new SelectStatement<EventFight>(table, "SELECT * FROM EventFight WHERE GroupID = ? ORDER BY StartTime DESC LIMIT 1");
|
|
||||||
private static final SelectStatement<EventFight> allComing = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE StartTime > now() ORDER BY StartTime ASC");
|
|
||||||
private static final SelectStatement<EventFight> event = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID = ? ORDER BY StartTime ASC");
|
|
||||||
private static final SelectStatement<EventFight> activeFights = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID IN (SELECT EventID FROM Event WHERE Start < now() and End > now()) AND Fight IS NULL AND StartTime < now()");
|
|
||||||
private static final Statement reschedule = table.update(Table.PRIMARY, "StartTime");
|
|
||||||
private static final Statement setResult = table.update(Table.PRIMARY, "Ergebnis");
|
|
||||||
private static final Statement setFight = table.update(Table.PRIMARY, "Fight");
|
|
||||||
|
|
||||||
private static final Statement create = table.insertFields(true, "eventID", "startTime", "spielmodus", "map", "teamBlue", "teamRed", "spectatePort");
|
|
||||||
private static final Statement update = table.update(Table.PRIMARY, "startTime", "spielModus", "map", "teamBlue", "teamRed", "spectatePort");
|
|
||||||
private static final Statement setGroup = table.update(Table.PRIMARY, "GroupID");
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private static final Queue<EventFight> fights = new PriorityQueue<>();
|
|
||||||
|
|
||||||
public static EventFight get(int fightID) {
|
|
||||||
return byId.select(fightID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<EventFight> get(EventGroup group) {
|
|
||||||
return byGroup.listSelect(group.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Optional<EventFight> getLast(EventGroup group) {
|
|
||||||
return Optional.ofNullable(byGroupLast.select(group.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadAllComingFights() {
|
|
||||||
fights.clear();
|
|
||||||
fights.addAll(allComing.listSelect());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<EventFight> getEvent(int eventID) {
|
|
||||||
return event.listSelect(eventID);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<EventFight> activeFightsCache = null;
|
|
||||||
|
|
||||||
public static void clearActiveFightsCache() {
|
|
||||||
activeFightsCache = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<EventFight> getActiveFights() {
|
|
||||||
if (activeFightsCache == null) {
|
|
||||||
activeFightsCache = activeFights.listSelect();
|
|
||||||
}
|
|
||||||
return activeFightsCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EventFight create(int event, Timestamp from, String spielmodus, String map, int blueTeam, int redTeam, Integer spectatePort) {
|
|
||||||
return get(create.insertGetKey(event, from, spielmodus, map, blueTeam, redTeam, spectatePort));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final int eventID;
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
|
||||||
private final int fightID;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field(nullable = true, def = "null")
|
|
||||||
private Integer groupId;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field
|
|
||||||
private Timestamp startTime;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field
|
|
||||||
private String spielmodus;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field
|
|
||||||
private String map;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field
|
|
||||||
private int teamBlue;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field
|
|
||||||
private int teamRed;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field(nullable = true)
|
|
||||||
private Integer spectatePort;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Field(def = "1")
|
|
||||||
private int bestOf;
|
|
||||||
@Getter
|
|
||||||
@Field(def = "0")
|
|
||||||
private int ergebnis;
|
|
||||||
@Field(nullable = true)
|
|
||||||
private int fight;
|
|
||||||
|
|
||||||
public Optional<EventGroup> getGroup() {
|
|
||||||
return Optional.ofNullable(groupId).flatMap(EventGroup::get);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Team> getWinner() {
|
|
||||||
if(ergebnis == 0)
|
|
||||||
return Optional.empty();
|
|
||||||
return Optional.ofNullable(ergebnis == 1 ? Team.get(teamBlue) : Team.get(teamRed));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Team> getLosser() {
|
|
||||||
if(ergebnis == 0)
|
|
||||||
return Optional.empty();
|
|
||||||
return Optional.ofNullable(ergebnis == 1 ? Team.get(teamRed) : Team.get(teamBlue));
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<EventRelation> getDependents() {
|
|
||||||
return EventRelation.getFightRelations(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setErgebnis(int winner) {
|
|
||||||
this.ergebnis = winner;
|
|
||||||
setResult.update(winner, fightID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFight(int fight) {
|
|
||||||
//Fight.FightID, not EventFight.FightID
|
|
||||||
this.fight = fight;
|
|
||||||
setFight.update(fight, fightID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGroup(Integer group) {
|
|
||||||
setGroup.update(group, fightID);
|
|
||||||
this.groupId = group;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasFinished() {
|
|
||||||
return fight != 0 || ergebnis != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reschedule() {
|
|
||||||
startTime = Timestamp.from(new Date().toInstant().plus(30, SECONDS));
|
|
||||||
reschedule.update(startTime, fightID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode(){
|
|
||||||
return fightID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o){
|
|
||||||
if(o == null)
|
|
||||||
return false;
|
|
||||||
if(!(o instanceof EventFight))
|
|
||||||
return false;
|
|
||||||
return fightID == ((EventFight) o).fightID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(EventFight o) {
|
|
||||||
return startTime.compareTo(o.startTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(Timestamp startTime, String spielmodus, String map, int teamBlue, int teamRed, Integer spectatePort) {
|
|
||||||
update.update(startTime, spielmodus, map, teamBlue, teamRed, spectatePort, fightID);
|
|
||||||
this.startTime = startTime;
|
|
||||||
this.spielmodus = spielmodus;
|
|
||||||
this.map = map;
|
|
||||||
this.teamBlue = teamBlue;
|
|
||||||
this.teamRed = teamRed;
|
|
||||||
this.spectatePort = spectatePort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(fightID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
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 org.jetbrains.exposed.v1.jdbc.select
|
||||||
|
import java.sql.Timestamp
|
||||||
|
import java.time.Instant
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object EventFightTable : IntIdTable("EventFight", "FightID") {
|
||||||
|
val eventId = reference("EventID", EventTable)
|
||||||
|
val startTime = timestamp("StartTime")
|
||||||
|
val gamemode = text("Spielmodus")
|
||||||
|
val map = text("Map")
|
||||||
|
val groupId = optReference("GroupId", EventGroupTable)
|
||||||
|
val teamBlue = reference("TeamBlue", TeamTable)
|
||||||
|
val teamRed = reference("TeamRed", TeamTable)
|
||||||
|
val spectatePort = integer("SpectatePort").nullable()
|
||||||
|
val bestOf = integer("BestOf")
|
||||||
|
val ergebnis = integer("Ergebnis")
|
||||||
|
val fight = optReference("Fight", FightTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventFight(id: EntityID<Int>) : IntEntity(id), Comparable<EventFight> {
|
||||||
|
companion object : IntEntityClass<EventFight>(EventFightTable) {
|
||||||
|
val fights: Queue<EventFight> = PriorityQueue()
|
||||||
|
@JvmStatic get
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun byId(fightId: Int) = useDb { findById(fightId) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun byId(group: EventGroup) = useDb {
|
||||||
|
find { EventFightTable.groupId eq group.id }.orderBy(EventFightTable.startTime to SortOrder.DESC).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getLast(group: EventGroup) = useDb {
|
||||||
|
Optional.ofNullable(
|
||||||
|
find { EventFightTable.groupId eq group.id }.orderBy(EventFightTable.startTime to SortOrder.DESC)
|
||||||
|
.firstOrNull()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun loadAllComingFights() = useDb {
|
||||||
|
fights.clear()
|
||||||
|
fights.addAll(find { EventFightTable.startTime greaterEq Instant.now() }.orderBy(EventFightTable.startTime to SortOrder.ASC))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getEvent(eventId: Int) = useDb {
|
||||||
|
find { EventFightTable.eventId eq eventId }.orderBy(EventFightTable.startTime to SortOrder.ASC).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var activeFightsCache: List<EventFight>? = null
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun clearActiveFightsCache() {
|
||||||
|
activeFightsCache = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getActiveFights(): List<EventFight> {
|
||||||
|
if (activeFightsCache == null) {
|
||||||
|
activeFightsCache = useDb {
|
||||||
|
find {
|
||||||
|
EventFightTable.fight.isNull() and (EventFightTable.startTime less Instant.now()) and (EventFightTable.eventId.inSubQuery(
|
||||||
|
EventTable.select(
|
||||||
|
EventTable.id
|
||||||
|
)
|
||||||
|
.where { (EventTable.start less Instant.now()) and (EventTable.end greater Instant.now()) }))
|
||||||
|
}.orderBy(EventFightTable.startTime to SortOrder.ASC).toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeFightsCache!!
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(
|
||||||
|
event: Int,
|
||||||
|
from: Timestamp,
|
||||||
|
spielmodus: String,
|
||||||
|
map: String,
|
||||||
|
blueTeam: Int,
|
||||||
|
redTeam: Int,
|
||||||
|
spectatePort: Int?
|
||||||
|
) = useDb {
|
||||||
|
get(
|
||||||
|
EventFightTable.insertAndGetId {
|
||||||
|
it[eventId] = EntityID(event, EventTable)
|
||||||
|
it[startTime] = from.toInstant()
|
||||||
|
it[gamemode] = spielmodus
|
||||||
|
it[EventFightTable.map] = map
|
||||||
|
it[teamBlue] = EntityID(blueTeam, TeamTable)
|
||||||
|
it[teamRed] = EntityID(redTeam, TeamTable)
|
||||||
|
it[EventFightTable.spectatePort] = spectatePort
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val fightID by EventFightTable.id.transform({ EntityID(it, EventFightTable) }, { it.value })
|
||||||
|
var teamBlue by EventFightTable.teamBlue.transform({ EntityID(it, TeamTable) }, { it.value })
|
||||||
|
var teamRed by EventFightTable.teamRed.transform({ EntityID(it, TeamTable) }, { it.value })
|
||||||
|
private var fightErgebnis by EventFightTable.ergebnis
|
||||||
|
var ergebnis: Int
|
||||||
|
get() = fightErgebnis
|
||||||
|
set(value) = useDb {
|
||||||
|
fightErgebnis = value
|
||||||
|
}
|
||||||
|
var eventID by EventFightTable.eventId.transform({ EntityID(it, EventTable) }, { it.value })
|
||||||
|
var startTime by EventFightTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
var spielmodus by EventFightTable.gamemode
|
||||||
|
var map by EventFightTable.map
|
||||||
|
var groupId by EventFightTable.groupId
|
||||||
|
val group by lazy { useDb { Optional.ofNullable(groupId).map { EventGroup[it] } } }
|
||||||
|
var spectatePort by EventFightTable.spectatePort
|
||||||
|
private var fightStat by EventFightTable.fight.transform({ it?.let { EntityID(it, EventFightTable) } }, { it?.value })
|
||||||
|
var fight: Int?
|
||||||
|
get() = fightStat
|
||||||
|
set(value) = useDb {
|
||||||
|
fightStat = value
|
||||||
|
}
|
||||||
|
val dependents by lazy { useDb { EventRelation.getFightRelations(this@EventFight).toList() } }
|
||||||
|
|
||||||
|
val winner: Team?
|
||||||
|
get() = useDb { if (ergebnis == 1) Team[teamBlue] else if (ergebnis == 2) Team[teamRed] else null }
|
||||||
|
val losser: Team?
|
||||||
|
get() = useDb { if (ergebnis == 1) Team[teamRed] else if (ergebnis == 2) Team[teamBlue] else null }
|
||||||
|
|
||||||
|
fun setGroup(group: Int?) = useDb { groupId = group?.let { EntityID(it, EventGroupTable) } }
|
||||||
|
fun hasFinished() = fight != null || ergebnis != 0
|
||||||
|
|
||||||
|
fun reschedule() = useDb {
|
||||||
|
startTime = Timestamp.from(Instant.now().plusSeconds(30))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode() = fightID
|
||||||
|
override fun equals(other: Any?) = other is EventFight && other.fightID == fightID
|
||||||
|
override fun compareTo(other: EventFight): Int = startTime.compareTo(other.startTime)
|
||||||
|
|
||||||
|
fun update(
|
||||||
|
startTime: Timestamp,
|
||||||
|
spielmodus: String,
|
||||||
|
map: String,
|
||||||
|
teamBlue: Int,
|
||||||
|
teamRed: Int,
|
||||||
|
spectatePort: Int?
|
||||||
|
) = useDb {
|
||||||
|
this@EventFight.startTime = startTime
|
||||||
|
this@EventFight.spielmodus = spielmodus
|
||||||
|
this@EventFight.map = map
|
||||||
|
this@EventFight.teamBlue = teamBlue
|
||||||
|
this@EventFight.teamRed = teamRed
|
||||||
|
this@EventFight.spectatePort = spectatePort
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() = useDb {
|
||||||
|
super.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class EventGroup {
|
|
||||||
static {
|
|
||||||
SqlTypeMapper.ordinalEnumMapper(EventGroupType.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<EventGroup> table = new Table<>(EventGroup.class);
|
|
||||||
|
|
||||||
private static final SelectStatement<EventGroup> get = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<EventGroup> byEvent = new SelectStatement<>(table, "SELECT * FROM EventGroup WHERE EventID = ?");
|
|
||||||
|
|
||||||
private static final Statement insert = table.insertFields(true, "EventID", "Name", "Type");
|
|
||||||
private static final Statement update = table.update(Table.PRIMARY, "Name", "Type", "PointsPerWin", "PointsPerLoss", "PointsPerDraw");
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
public static List<EventGroup> get(Event eventID) {
|
|
||||||
return byEvent.listSelect(eventID.getEventID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EventGroup create(Event event, String name, EventGroupType type) {
|
|
||||||
int key = insert.insertGetKey(event.getEventID(), name, type);
|
|
||||||
return EventGroup.get(key).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Optional<EventGroup> get(int id) {
|
|
||||||
return Optional.ofNullable(get.select(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = Table.PRIMARY)
|
|
||||||
private final int id;
|
|
||||||
|
|
||||||
@Field(keys = "EVENT_NAME")
|
|
||||||
private int eventID;
|
|
||||||
|
|
||||||
@Field(keys = "EVENT_NAME")
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private EventGroupType type;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private int pointsPerWin;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private int pointsPerLoss;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private int pointsPerDraw;
|
|
||||||
|
|
||||||
public EventGroup(int id, int eventID, String name, EventGroupType type, int pointsPerWin, int pointsPerLoss, int pointsPerDraw) {
|
|
||||||
this.id = id;
|
|
||||||
this.eventID = eventID;
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.pointsPerWin = pointsPerWin;
|
|
||||||
this.pointsPerLoss = pointsPerLoss;
|
|
||||||
this.pointsPerDraw = pointsPerDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<Team, Integer> points;
|
|
||||||
|
|
||||||
public List<EventFight> getFights() {
|
|
||||||
return EventFight.get(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getTeamsId() {
|
|
||||||
return getFights().stream().flatMap(fight -> Stream.of(fight.getTeamBlue(), fight.getTeamRed()))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Team> getTeams() {
|
|
||||||
return getTeamsId().stream().map(Team::get).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<EventFight> getLastFight() {
|
|
||||||
return EventFight.getLast(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<EventRelation> getDependents() {
|
|
||||||
return EventRelation.getGroupRelations(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Team, Integer> calculatePoints() {
|
|
||||||
if (points == null) {
|
|
||||||
Map<Integer, Integer> p = getTeamsId().stream().collect(Collectors.toMap(team -> team, team -> 0));
|
|
||||||
|
|
||||||
for (EventFight fight : getFights()) {
|
|
||||||
int blueTeamAdd = 0;
|
|
||||||
int redTeamAdd = 0;
|
|
||||||
|
|
||||||
if (!fight.hasFinished()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fight.getErgebnis()) {
|
|
||||||
case 1:
|
|
||||||
blueTeamAdd += pointsPerWin;
|
|
||||||
redTeamAdd += pointsPerLoss;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
blueTeamAdd += pointsPerLoss;
|
|
||||||
redTeamAdd += pointsPerWin;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
if (fight.getFightID() != 0) {
|
|
||||||
blueTeamAdd += pointsPerDraw;
|
|
||||||
redTeamAdd += pointsPerDraw;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.put(fight.getTeamBlue(), p.get(fight.getTeamBlue()) + blueTeamAdd);
|
|
||||||
p.put(fight.getTeamRed(), p.get(fight.getTeamRed()) + redTeamAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
points = p.entrySet().stream().collect(Collectors.toMap(integerIntegerEntry -> Team.get(integerIntegerEntry.getKey()), Map.Entry::getValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
return points;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(String name, EventGroupType type, int pointsPerWin, int pointsPerLoss, int pointsPerDraw) {
|
|
||||||
update.update(name, type, pointsPerWin, pointsPerLoss, pointsPerDraw, id);
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.pointsPerWin = pointsPerWin;
|
|
||||||
this.pointsPerLoss = pointsPerLoss;
|
|
||||||
this.pointsPerDraw = pointsPerDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean needsTieBreak() {
|
|
||||||
return calculatePoints().values().stream().sorted().limit(2).distinct().count() < 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum EventGroupType {
|
|
||||||
GROUP_STAGE,
|
|
||||||
ELIMINATION_STAGE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntityClass
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object EventGroupTable : IntIdTable("EventGroup", "Id") {
|
||||||
|
val event = reference("EventID", EventTable)
|
||||||
|
val name = varchar("Name", 64)
|
||||||
|
val type = enumeration("Type", EventGroup.EventGroupType::class)
|
||||||
|
val pointsPerWin = integer("PointsPerWin").default(3)
|
||||||
|
val pointsPerLoss = integer("PointsPerLoss").default(0)
|
||||||
|
val pointsPerDraw = integer("PointsPerDraw").default(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventGroup(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<EventGroup>(EventGroupTable) {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(event: Event) = useDb { find { EventGroupTable.event eq event.id }.toList() }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun byId(groupId: Int) = useDb { Optional.ofNullable(findById(groupId)) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(event: Event, name: String, type: EventGroupType) = useDb {
|
||||||
|
new {
|
||||||
|
this.eventID = event.id.value
|
||||||
|
this.groupName = name
|
||||||
|
this.groupType = type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventID by EventGroupTable.event.transform({ EntityID(it, EventTable) }, { it.value })
|
||||||
|
private set
|
||||||
|
private var groupName by EventGroupTable.name
|
||||||
|
private var groupType by EventGroupTable.type
|
||||||
|
private var groupPointsPerWin by EventGroupTable.pointsPerWin
|
||||||
|
private var groupPointsPerLoss by EventGroupTable.pointsPerLoss
|
||||||
|
private var groupPointsPerDraw by EventGroupTable.pointsPerDraw
|
||||||
|
val fights by lazy { useDb { EventFight.find { EventFightTable.groupId eq id }.toList() } }
|
||||||
|
val teamsId by lazy { fights.flatMap { listOf(it.teamBlue, it.teamRed) }.toSet() }
|
||||||
|
|
||||||
|
var name: String
|
||||||
|
get() = groupName
|
||||||
|
set(value) {
|
||||||
|
groupName = value
|
||||||
|
}
|
||||||
|
var type: EventGroupType
|
||||||
|
get() = groupType
|
||||||
|
set(value) {
|
||||||
|
groupType = value
|
||||||
|
}
|
||||||
|
var pointsPerWin: Int
|
||||||
|
get() = groupPointsPerWin
|
||||||
|
set(value) {
|
||||||
|
groupPointsPerWin = value
|
||||||
|
}
|
||||||
|
var pointsPerLoss: Int
|
||||||
|
get() = groupPointsPerLoss
|
||||||
|
set(value) {
|
||||||
|
groupPointsPerLoss = value
|
||||||
|
}
|
||||||
|
var pointsPerDraw: Int
|
||||||
|
get() = groupPointsPerDraw
|
||||||
|
set(value) {
|
||||||
|
groupPointsPerDraw = value
|
||||||
|
}
|
||||||
|
val dependents by lazy { EventRelation.getGroupRelations(this).toList() }
|
||||||
|
val lastFight by lazy { Optional.ofNullable(fights.maxByOrNull { it.startTime }) }
|
||||||
|
|
||||||
|
fun getId() = id.value
|
||||||
|
|
||||||
|
private var points: Map<Team, Int>? = null
|
||||||
|
|
||||||
|
fun calculatePoints(): Map<Team, Int> {
|
||||||
|
if (points == null) {
|
||||||
|
val p: MutableMap<Int, Int> = teamsId.associateWith { 0 }.toMutableMap()
|
||||||
|
|
||||||
|
for (fight in fights) {
|
||||||
|
var blueTeamAdd = 0
|
||||||
|
var redTeamAdd = 0
|
||||||
|
|
||||||
|
if (!fight.hasFinished()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
when (fight.ergebnis) {
|
||||||
|
1 -> {
|
||||||
|
blueTeamAdd += pointsPerWin
|
||||||
|
redTeamAdd += pointsPerLoss
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
blueTeamAdd += pointsPerLoss
|
||||||
|
redTeamAdd += pointsPerWin
|
||||||
|
}
|
||||||
|
0 -> if (fight.fight != null) {
|
||||||
|
blueTeamAdd += pointsPerDraw
|
||||||
|
redTeamAdd += pointsPerDraw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p[fight.teamBlue] = p[fight.teamBlue]?.plus(blueTeamAdd) ?: blueTeamAdd
|
||||||
|
p[fight.teamRed] = p[fight.teamRed]?.plus(redTeamAdd) ?: redTeamAdd
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.mapKeys { Team.byId(it.key) }.also { points = it }
|
||||||
|
} else {
|
||||||
|
return points!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun needsTieBreak() = calculatePoints().values.let { it.size == it.toSet().size }
|
||||||
|
|
||||||
|
fun update(name: String, type: EventGroupType, pointsPerWin: Int, pointsPerLoss: Int, pointsPerDraw: Int) = useDb {
|
||||||
|
this@EventGroup.name = name
|
||||||
|
this@EventGroup.type = type
|
||||||
|
this@EventGroup.pointsPerWin = pointsPerWin
|
||||||
|
this@EventGroup.pointsPerLoss = pointsPerLoss
|
||||||
|
this@EventGroup.pointsPerDraw = pointsPerDraw
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() = useDb { super.delete() }
|
||||||
|
|
||||||
|
enum class EventGroupType {
|
||||||
|
GROUP_STAGE,
|
||||||
|
ELIMINATION_STAGE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class EventRelation {
|
|
||||||
|
|
||||||
static {
|
|
||||||
SqlTypeMapper.ordinalEnumMapper(FightTeam.class);
|
|
||||||
SqlTypeMapper.ordinalEnumMapper(FromType.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<EventRelation> table = new Table<>(EventRelation.class);
|
|
||||||
|
|
||||||
private static final SelectStatement<EventRelation> get = new SelectStatement<>(table, "SELECT * FROM EventRelation WHERE FromType = ? AND FromId = ?");
|
|
||||||
private static final SelectStatement<EventRelation> byId = new SelectStatement<>(table, "SELECT * FROM EventRelation WHERE id = ?");
|
|
||||||
private static final SelectStatement<EventRelation> byEvent = new SelectStatement<>(table, "SELECT ER.* FROM EventRelation ER JOIN EventFight EF ON EF.fightId = ER.fightId WHERE EF.EventID = ?");
|
|
||||||
private static final Statement insert = table.insertFields(true, "fightId", "fightTeam", "fromType", "fromId", "fromPlace");
|
|
||||||
private static final Statement update = table.update(Table.PRIMARY, "fromType", "fromId", "fromPlace");
|
|
||||||
private static final Statement updateTeam = table.update(Table.PRIMARY, "fightTeam");
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
public static List<EventRelation> get(Event event) {
|
|
||||||
return byEvent.listSelect(event.getEventID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EventRelation get(int id) {
|
|
||||||
return byId.select(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<EventRelation> getFightRelations(EventFight fight) {
|
|
||||||
return get.listSelect(FromType.FIGHT, fight.getFightID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<EventRelation> getGroupRelations(EventGroup group) {
|
|
||||||
return get.listSelect(FromType.GROUP, group.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EventRelation create(EventFight fight, FightTeam fightTeam, FromType fromType, int fromId, int fromPlace) {
|
|
||||||
int id = insert.insertGetKey(fight.getFightID(), fightTeam, fromType, fromId, fromPlace);
|
|
||||||
return get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = Table.PRIMARY)
|
|
||||||
private final int id;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private int fightId;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private FightTeam fightTeam;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private FromType fromType;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private int fromId;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private int fromPlace;
|
|
||||||
|
|
||||||
public EventFight getFight() {
|
|
||||||
return EventFight.get(fightId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<EventFight> getFromFight() {
|
|
||||||
if(fromType == FromType.FIGHT) {
|
|
||||||
return Optional.of(EventFight.get(fromId));
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<EventGroup> getFromGroup() {
|
|
||||||
if(fromType == FromType.GROUP) {
|
|
||||||
return EventGroup.get(fromId);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateTeam(FightTeam team) {
|
|
||||||
updateTeam.update(id, team);
|
|
||||||
this.fightTeam = team;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFromFight(EventFight fight, int place) {
|
|
||||||
setFrom(fight.getFightID(), place, FromType.FIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFromGroup(EventGroup group, int place) {
|
|
||||||
setFrom(group.getId(), place, FromType.GROUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setFrom(int fightId, int place, FromType type) {
|
|
||||||
update.update(type, fightId, place, id);
|
|
||||||
this.fromType = type;
|
|
||||||
this.fromId = fightId;
|
|
||||||
this.fromPlace = place;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Team> getAdvancingTeam() {
|
|
||||||
if (fromType == FromType.FIGHT) {
|
|
||||||
if (fromPlace == 0) {
|
|
||||||
return getFromFight().flatMap(EventFight::getWinner);
|
|
||||||
} else {
|
|
||||||
return getFromFight().flatMap(EventFight::getLosser);
|
|
||||||
}
|
|
||||||
} else if (fromType == FromType.GROUP) {
|
|
||||||
return getFromGroup().map(EventGroup::calculatePoints)
|
|
||||||
.flatMap(points -> points.entrySet().stream()
|
|
||||||
.sorted(Map.Entry.<Team, Integer>comparingByValue().reversed())
|
|
||||||
.skip(fromPlace)
|
|
||||||
.findFirst()
|
|
||||||
.map(Map.Entry::getKey));
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean apply() {
|
|
||||||
Optional<Integer> team = getAdvancingTeam().map(Team::getTeamId);
|
|
||||||
if(!team.isPresent())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
EventFight fight = getFight();
|
|
||||||
if(fightTeam == FightTeam.RED) {
|
|
||||||
fight.update(
|
|
||||||
fight.getStartTime(),
|
|
||||||
fight.getSpielmodus(),
|
|
||||||
fight.getMap(),
|
|
||||||
fight.getTeamBlue(),
|
|
||||||
team.get(),
|
|
||||||
fight.getSpectatePort()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fight.update(
|
|
||||||
fight.getStartTime(),
|
|
||||||
fight.getSpielmodus(),
|
|
||||||
fight.getMap(),
|
|
||||||
team.get(),
|
|
||||||
fight.getTeamRed(),
|
|
||||||
fight.getSpectatePort()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum FightTeam {
|
|
||||||
BLUE,
|
|
||||||
RED
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum FromType {
|
|
||||||
FIGHT,
|
|
||||||
GROUP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.select
|
||||||
|
|
||||||
|
object EventRelationTable : IntIdTable("EventRelation") {
|
||||||
|
val fightId = reference("FightId", EventFightTable)
|
||||||
|
val fightTeam = enumeration("FightTeam", EventRelation.FightTeam::class)
|
||||||
|
val fromType = enumeration("FromType", EventRelation.FromType::class)
|
||||||
|
val fromId = integer("FromId")
|
||||||
|
val fromPlace = integer("FromPlace")
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventRelation(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<EventRelation>(EventRelationTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun get(event: Event) = useDb {
|
||||||
|
EventRelationTable.innerJoin(EventFightTable)
|
||||||
|
.select(EventRelationTable.columns)
|
||||||
|
.where { EventFightTable.eventId eq event.id }
|
||||||
|
.map { wrapRow(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun byId(id: Int) = useDb { findById(id) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getFightRelations(fight: EventFight) =
|
||||||
|
useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) } }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getGroupRelations(group: EventGroup) =
|
||||||
|
useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) } }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb {
|
||||||
|
new {
|
||||||
|
this.fightEntityId = fight.id
|
||||||
|
this.fightTeam = fightTeam
|
||||||
|
this.fromType = fromType
|
||||||
|
this.fromId = fromId
|
||||||
|
this.fromPlace = fromPlace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fightEntityId by EventRelationTable.fightId
|
||||||
|
var fightId: Int
|
||||||
|
get() = fightEntityId.value
|
||||||
|
set(value) = useDb { fightEntityId = EntityID(value, EventFightTable) }
|
||||||
|
val fight by lazy { useDb { EventFight[fightEntityId] } }
|
||||||
|
var fightTeam by EventRelationTable.fightTeam
|
||||||
|
private set
|
||||||
|
var fromType by EventRelationTable.fromType
|
||||||
|
private set
|
||||||
|
var fromId by EventRelationTable.fromId
|
||||||
|
private set
|
||||||
|
|
||||||
|
var fromFightId: Int?
|
||||||
|
get() = if (fromType == FromType.FIGHT) fromId else null
|
||||||
|
set(value) = useDb {
|
||||||
|
fromType = FromType.FIGHT
|
||||||
|
fromId = value!!
|
||||||
|
}
|
||||||
|
val fromFight: EventFight?
|
||||||
|
get() = fromFightId?.let { useDb { EventFight[it] } }
|
||||||
|
var fromGroupId: Int?
|
||||||
|
get() = if (fromType == FromType.GROUP) fromId else null
|
||||||
|
set(value) = useDb {
|
||||||
|
fromType = FromType.GROUP
|
||||||
|
fromId = value!!
|
||||||
|
}
|
||||||
|
val fromGroup: EventGroup?
|
||||||
|
get() = fromGroupId?.let { useDb { EventGroup[it] } }
|
||||||
|
var fromPlace by EventRelationTable.fromPlace
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun getId() = id.value
|
||||||
|
fun setUpdateTeam(team: FightTeam) = useDb {
|
||||||
|
fightTeam = team
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFromFight(fight: EventFight, place: Int) = useDb {
|
||||||
|
fromType = FromType.FIGHT
|
||||||
|
fromId = fight.id.value
|
||||||
|
fromPlace = place
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFromGroup(group: EventGroup, place: Int) = useDb {
|
||||||
|
fromType = FromType.GROUP
|
||||||
|
fromId = group.id.value
|
||||||
|
fromPlace = place
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAdvancingTeam(): Team? = useDb { when(fromType) {
|
||||||
|
FromType.FIGHT -> if (fromPlace == 0) fromFight?.winner else fromFight?.losser
|
||||||
|
FromType.GROUP -> fromGroup?.calculatePoints()?.toList()?.sortedBy { (_, v) -> v }?.reversed()?.elementAt(fromPlace)?.first
|
||||||
|
} }
|
||||||
|
|
||||||
|
fun apply(): Boolean {
|
||||||
|
val team = getAdvancingTeam() ?: return false
|
||||||
|
|
||||||
|
useDb {
|
||||||
|
when(fightTeam) {
|
||||||
|
FightTeam.BLUE -> fight.teamBlue = team.teamId
|
||||||
|
FightTeam.RED -> fight.teamRed = team.teamId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() = useDb {
|
||||||
|
super.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class FightTeam {
|
||||||
|
BLUE, RED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class FromType {
|
||||||
|
FIGHT, GROUP
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class Fight {
|
|
||||||
|
|
||||||
private static final Table<Fight> table = new Table<>(Fight.class);
|
|
||||||
private static final SelectStatement<Fight> getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?");
|
|
||||||
private static final SelectStatement<Fight> getById = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId WHERE FightId = ?");
|
|
||||||
private static final Statement insert = table.insertFields(true, "GameMode", "Server", "StartTime", "Duration", "BlueLeader", "RedLeader", "BlueSchem", "RedSchem", "Win", "WinCondition");
|
|
||||||
private static final Statement updateReplayAvailable = table.update(Table.PRIMARY, "ReplayAvailable");
|
|
||||||
|
|
||||||
public static List<Fight> getPage(int page, int elementsPerPage) {
|
|
||||||
List<Fight> fights = getPage.listSelect(page * elementsPerPage, elementsPerPage);
|
|
||||||
|
|
||||||
List<FightPlayer> fightPlayers = FightPlayer.batchGet(fights.stream().map(f -> f.fightID));
|
|
||||||
for(Fight fight : fights) {
|
|
||||||
fight.initPlayers(fightPlayers);
|
|
||||||
}
|
|
||||||
|
|
||||||
SteamwarUser.batchCache(fightPlayers.stream().map(FightPlayer::getUserID).collect(Collectors.toSet()));
|
|
||||||
return fights;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Fight getById(int fightID) {
|
|
||||||
return getById.select(fightID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int create(String gamemode, String server, Timestamp starttime, int duration, int blueleader, int redleader, Integer blueschem, Integer redschem, int win, String wincondition){
|
|
||||||
return insert.insertGetKey(gamemode, server, starttime, duration, blueleader, redleader, blueschem, redschem, win, wincondition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void markReplayAvailable(int fightID) {
|
|
||||||
updateReplayAvailable.update(true, fightID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
|
||||||
private final int fightID;
|
|
||||||
@Field
|
|
||||||
private final String gameMode;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final String server;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final Timestamp startTime;
|
|
||||||
@Field
|
|
||||||
private final int duration;
|
|
||||||
@Field
|
|
||||||
private final int blueLeader;
|
|
||||||
@Field
|
|
||||||
private final int redLeader;
|
|
||||||
@Field(nullable = true)
|
|
||||||
private final Integer blueSchem;
|
|
||||||
@Field(nullable = true)
|
|
||||||
private final Integer redSchem;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final int win;
|
|
||||||
@Field
|
|
||||||
private final String wincondition;
|
|
||||||
@Field
|
|
||||||
private final boolean replayAvailable;
|
|
||||||
@Field // Virtual field for easy select
|
|
||||||
private final boolean replayAllowed;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final List<FightPlayer> bluePlayers = new ArrayList<>();
|
|
||||||
@Getter
|
|
||||||
private final List<FightPlayer> redPlayers = new ArrayList<>();
|
|
||||||
|
|
||||||
public SchematicType getSchemType() {
|
|
||||||
return SchematicType.fromDB(gameMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SteamwarUser getBlueLeader() {
|
|
||||||
return SteamwarUser.get(blueLeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SteamwarUser getRedLeader() {
|
|
||||||
return SteamwarUser.get(redLeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean replayAllowed() {
|
|
||||||
return replayExists() && replayAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean replayExists() {
|
|
||||||
return getSchemType() != null && replayAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initPlayers(List<FightPlayer> fightPlayers) {
|
|
||||||
for(FightPlayer fp : fightPlayers) {
|
|
||||||
if(fp.getFightID() != fightID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(fp.getTeam() == 1)
|
|
||||||
bluePlayers.add(fp);
|
|
||||||
else
|
|
||||||
redPlayers.add(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.IntegerColumnType
|
||||||
|
import org.jetbrains.exposed.v1.core.ReferenceOption
|
||||||
|
import org.jetbrains.exposed.v1.core.SortOrder
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
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 org.jetbrains.exposed.v1.jdbc.update
|
||||||
|
import java.sql.Timestamp
|
||||||
|
|
||||||
|
object FightTable : IntIdTable("Fight", "FightId") {
|
||||||
|
val gamemode = varchar("Gamemode", 30)
|
||||||
|
val server = text("Server")
|
||||||
|
val startTime = timestamp("StartTime")
|
||||||
|
val duration = integer("Duration")
|
||||||
|
val blueLeader = reference("BlueLeader", SteamwarUserTable)
|
||||||
|
val redLeader = reference("RedLeader", SteamwarUserTable)
|
||||||
|
val blueSchem = optReference("BlueSchem", SchematicNodeTable, onDelete = ReferenceOption.SET_NULL)
|
||||||
|
val redSchem = optReference("RedSchem", SchematicNodeTable, onDelete = ReferenceOption.SET_NULL)
|
||||||
|
val win = enumeration("Win", Fight.WinningTeam::class)
|
||||||
|
val winCondition = varchar("WinCondition", 100)
|
||||||
|
val replayAvailable = bool("ReplayAvailable")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fight(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Fight>(FightTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun getById(id: Int) = useDb { get(id) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(
|
||||||
|
gamemode: String,
|
||||||
|
server: String,
|
||||||
|
starttime: Timestamp,
|
||||||
|
duration: Int,
|
||||||
|
blueleader: Int,
|
||||||
|
redleader: Int,
|
||||||
|
blueschem: Int?,
|
||||||
|
redschem: Int?,
|
||||||
|
win: Int,
|
||||||
|
wincondition: String
|
||||||
|
): Int = useDb {
|
||||||
|
FightTable.insertAndGetId {
|
||||||
|
it[FightTable.gamemode] = gamemode
|
||||||
|
it[FightTable.server] = server
|
||||||
|
it[FightTable.startTime] = starttime.toInstant()
|
||||||
|
it[FightTable.duration] = duration
|
||||||
|
it[FightTable.blueLeader] = EntityID(blueleader, SteamwarUserTable)
|
||||||
|
it[FightTable.redLeader] = EntityID(redleader, SteamwarUserTable)
|
||||||
|
it[FightTable.blueSchem] = blueschem?.let { EntityID(it, SchematicNodeTable) }
|
||||||
|
it[FightTable.redSchem] = redschem?.let { EntityID(it, SchematicNodeTable) }
|
||||||
|
it[FightTable.win] = WinningTeam.entries[win]
|
||||||
|
it[FightTable.winCondition] = wincondition
|
||||||
|
}.value
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getPage(page: Int, pageSize: Int): List<Fight> = useDb {
|
||||||
|
val fights = all().orderBy(FightTable.startTime to SortOrder.DESC).limit(pageSize).offset((pageSize * page).toLong())
|
||||||
|
|
||||||
|
val fightPlayer = FightPlayer.batchGet(fights.map { it.id.value })
|
||||||
|
for (fight in fights) {
|
||||||
|
fight.initPlayers(fightPlayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamwarUser.batchCache(fightPlayer.map { it.userID }.toMutableSet())
|
||||||
|
fights.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun markReplayAvailable(id: Int) = useDb {
|
||||||
|
FightTable.update({ FightTable.id eq id }) {
|
||||||
|
it[replayAvailable] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val fightID by FightTable.id.transform({ EntityID(it, FightTable) }, { it.value })
|
||||||
|
val gameMode by FightTable.gamemode
|
||||||
|
val server by FightTable.server
|
||||||
|
val startTime by FightTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
val duration by FightTable.duration
|
||||||
|
val blueLeaderId by FightTable.blueLeader
|
||||||
|
val blueLeader by lazy { useDb { SteamwarUser[blueLeaderId] } }
|
||||||
|
val redLeaderId by FightTable.redLeader
|
||||||
|
val redLeader by lazy { useDb { SteamwarUser[redLeaderId] } }
|
||||||
|
val blueSchem by FightTable.blueSchem
|
||||||
|
val redSchem by FightTable.redSchem
|
||||||
|
val winner by FightTable.win
|
||||||
|
val win: Int
|
||||||
|
get() = winner.ordinal
|
||||||
|
val winCondition by FightTable.winCondition
|
||||||
|
val replayAvailable by FightTable.replayAvailable
|
||||||
|
|
||||||
|
val schemType: SchematicType?
|
||||||
|
get() = SchematicType.fromDB(gameMode)
|
||||||
|
|
||||||
|
val replayAllowed by lazy {
|
||||||
|
replayExists() && useDb {
|
||||||
|
exec(
|
||||||
|
"SELECT (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId WHERE FightId = ?",
|
||||||
|
args = listOf(IntegerColumnType() to this@Fight.id.value)
|
||||||
|
) {
|
||||||
|
if (it.next()) {
|
||||||
|
it.getBoolean("ReplayAllowed")
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun replayExists() = schemType != null && replayAvailable
|
||||||
|
fun replayAllowed() = replayAllowed
|
||||||
|
|
||||||
|
lateinit var bluePlayers: List<FightPlayer>
|
||||||
|
lateinit var redPlayers: List<FightPlayer>
|
||||||
|
|
||||||
|
private fun initPlayers(fightPlayers: List<FightPlayer>) {
|
||||||
|
val blue = mutableListOf<FightPlayer>()
|
||||||
|
val red = mutableListOf<FightPlayer>()
|
||||||
|
|
||||||
|
for (player in fightPlayers.filter { it.fightID == id.value }) {
|
||||||
|
if (player.team == 1)
|
||||||
|
blue.add(player)
|
||||||
|
else
|
||||||
|
red.add(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
bluePlayers = blue
|
||||||
|
redPlayers = red
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class WinningTeam {
|
||||||
|
NONE, BLUE, RED;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class FightPlayer {
|
|
||||||
|
|
||||||
private static final Table<FightPlayer> table = new Table<>(FightPlayer.class);
|
|
||||||
private static final Statement create = table.insertAll();
|
|
||||||
private static final SelectStatement<FightPlayer> batchGet = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN ?");
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int fightID;
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int userID;
|
|
||||||
@Getter
|
|
||||||
@Field
|
|
||||||
private final int team;
|
|
||||||
@Field
|
|
||||||
private final String kit;
|
|
||||||
@Field
|
|
||||||
private final int kills;
|
|
||||||
@Field
|
|
||||||
private final boolean isOut;
|
|
||||||
|
|
||||||
public static void create(int fightID, int userID, boolean blue, String kit, int kills, boolean isOut) {
|
|
||||||
create.update(fightID, userID, blue ? 1 : 2, kit, kills, isOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<FightPlayer> batchGet(Stream<Integer> fightIds) {
|
|
||||||
try (SelectStatement<FightPlayer> batch = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN (" + fightIds.map(Object::toString).collect(Collectors.joining(", ")) + ")")) {
|
|
||||||
return batch.listSelect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.inList
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||||
|
|
||||||
|
object FightPlayerTable : CompositeIdTable("FightPlayer") {
|
||||||
|
val fightId = reference("FightId", FightTable)
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val team = integer("Team")
|
||||||
|
val kit = varchar("Kit", 64)
|
||||||
|
val kills = integer("Kills")
|
||||||
|
val out = bool("IsOut")
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(fightId)
|
||||||
|
addIdColumn(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FightPlayer(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||||
|
companion object : CompositeEntityClass<FightPlayer>(FightPlayerTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun create(
|
||||||
|
fightId: Int,
|
||||||
|
userId: Int,
|
||||||
|
blue: Boolean,
|
||||||
|
kit: String,
|
||||||
|
kills: Int,
|
||||||
|
out: Boolean
|
||||||
|
) = useDb {
|
||||||
|
FightPlayerTable.insertIgnore {
|
||||||
|
it[this.fightId] = fightId
|
||||||
|
it[this.userId] = userId
|
||||||
|
it[this.team] = if (blue) 1 else 2
|
||||||
|
it[this.kit] = kit
|
||||||
|
it[this.kills] = kills
|
||||||
|
it[this.out] = out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun batchGet(fightIds: List<Int>) = useDb {
|
||||||
|
find { FightPlayerTable.fightId inList fightIds.toList() }.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val fightID by FightPlayerTable.fightId.transform({ EntityID(it, FightTable) }, { it.value })
|
||||||
|
val userID by FightPlayerTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
val team by FightPlayerTable.team
|
||||||
|
val kit by FightPlayerTable.kit
|
||||||
|
val kills by FightPlayerTable.kills
|
||||||
|
val out by FightPlayerTable.out
|
||||||
|
|
||||||
|
fun isOut() = out
|
||||||
|
}
|
||||||
@@ -35,11 +35,19 @@ import java.util.stream.Collectors;
|
|||||||
public final class GameModeConfig<M, W> {
|
public final class GameModeConfig<M, W> {
|
||||||
|
|
||||||
public static final Function<String, String> ToString = Function.identity();
|
public static final Function<String, String> ToString = Function.identity();
|
||||||
public static final Function<File, String> ToStaticWarGear = __ -> "WarGear";
|
public static final Function<File, String> ToStaticWarGear = GameModeConfig::constWarGear;
|
||||||
public static final Function<File, String> ToInternalName = file -> file != null ? file.getName().replace(".yml", "") : "WarGear";
|
public static final Function<File, String> ToInternalName = GameModeConfig::internalName;
|
||||||
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
|
|
||||||
|
private static String constWarGear(File f) {
|
||||||
|
return "WarGear";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String internalName(File f) {
|
||||||
|
return f != null ? f.getName().replace(".yml", "") : constWarGear(null);
|
||||||
|
}
|
||||||
|
|
||||||
private static final Map<String, GameModeConfig<?, String>> byFileName;
|
private static final Map<String, GameModeConfig<?, String>> byFileName;
|
||||||
private static final Map<String, GameModeConfig<?, String>> byGameName;
|
private static final Map<String, GameModeConfig<?, String>> byGameName;
|
||||||
private static final Map<SchematicType, GameModeConfig<?, String>> bySchematicType;
|
private static final Map<SchematicType, GameModeConfig<?, String>> bySchematicType;
|
||||||
@@ -63,11 +71,15 @@ public final class GameModeConfig<M, W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Field Schematic_TypeField;
|
private static final Field Schematic_TypeField;
|
||||||
|
private static final Field Schematic_SubTypesField;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
Schematic_TypeField = SchematicConfig.class.getDeclaredField("Type");
|
Schematic_TypeField = SchematicConfig.class.getDeclaredField("Type");
|
||||||
Schematic_TypeField.setAccessible(true);
|
Schematic_TypeField.setAccessible(true);
|
||||||
|
|
||||||
|
Schematic_SubTypesField = SchematicConfig.class.getDeclaredField("SubTypes");
|
||||||
|
Schematic_SubTypesField.setAccessible(true);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
throw new SecurityException(e.getMessage(), e);
|
throw new SecurityException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -77,6 +89,18 @@ public final class GameModeConfig<M, W> {
|
|||||||
bySchematicType = new HashMap<>();
|
bySchematicType = new HashMap<>();
|
||||||
SchematicType.values();
|
SchematicType.values();
|
||||||
DEFAULTS = SQLWrapper.impl.loadGameModeConfig(null);
|
DEFAULTS = SQLWrapper.impl.loadGameModeConfig(null);
|
||||||
|
|
||||||
|
byFileName.values().forEach(gameModeConfig -> {
|
||||||
|
List<SchematicType> subTypes = Collections.unmodifiableList(gameModeConfig.Schematic.SubTypesStrings.stream()
|
||||||
|
.map(SchematicType::fromDB)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
try {
|
||||||
|
Schematic_SubTypesField.set(gameModeConfig.Schematic, subTypes);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new SecurityException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean loaded;
|
public final boolean loaded;
|
||||||
@@ -516,6 +540,8 @@ public final class GameModeConfig<M, W> {
|
|||||||
*/
|
*/
|
||||||
public final SchematicType Type;
|
public final SchematicType Type;
|
||||||
|
|
||||||
|
private final List<String> SubTypesStrings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The schematic types that are also allowed to be chosen in this arena
|
* The schematic types that are also allowed to be chosen in this arena
|
||||||
*/
|
*/
|
||||||
@@ -605,6 +631,13 @@ public final class GameModeConfig<M, W> {
|
|||||||
*/
|
*/
|
||||||
public final int MaxDispenserItems;
|
public final int MaxDispenserItems;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximal blast resistance for the blocks
|
||||||
|
*
|
||||||
|
* @implSpec {@code Double.MAX_VALUE} by default
|
||||||
|
*/
|
||||||
|
public final double MaxBlastResistance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximal blast resistance for the design blocks
|
* Maximal blast resistance for the design blocks
|
||||||
*
|
*
|
||||||
@@ -623,6 +656,7 @@ public final class GameModeConfig<M, W> {
|
|||||||
Size = new SizeConfig(loader.with("Size"));
|
Size = new SizeConfig(loader.with("Size"));
|
||||||
Inset = new InsetConfig(loader.with("Inset"));
|
Inset = new InsetConfig(loader.with("Inset"));
|
||||||
Type = loader.getSchematicType("Type", "Normal");
|
Type = loader.getSchematicType("Type", "Normal");
|
||||||
|
SubTypesStrings = loader.getStringList("SubTypes");
|
||||||
SubTypes = loader.getSchematicTypeList("SubTypes");
|
SubTypes = loader.getSchematicTypeList("SubTypes");
|
||||||
Shortcut = loader.getString("Shortcut", "");
|
Shortcut = loader.getString("Shortcut", "");
|
||||||
Material = loader.getMaterial("Material", "STONE_BUTTON");
|
Material = loader.getMaterial("Material", "STONE_BUTTON");
|
||||||
@@ -636,6 +670,7 @@ public final class GameModeConfig<M, W> {
|
|||||||
UnlimitedPrepare = loader.getBoolean("UnlimitedPrepare", false);
|
UnlimitedPrepare = loader.getBoolean("UnlimitedPrepare", false);
|
||||||
MaxBlocks = loader.getInt("MaxBlocks", 0);
|
MaxBlocks = loader.getInt("MaxBlocks", 0);
|
||||||
MaxDispenserItems = loader.getInt("MaxDispenserItems", 128);
|
MaxDispenserItems = loader.getInt("MaxDispenserItems", 128);
|
||||||
|
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
|
||||||
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", Double.MAX_VALUE);
|
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", Double.MAX_VALUE);
|
||||||
|
|
||||||
Map<Set<M>, Integer> Limited = new HashMap<>();
|
Map<Set<M>, Integer> Limited = new HashMap<>();
|
||||||
@@ -650,6 +685,10 @@ public final class GameModeConfig<M, W> {
|
|||||||
Limited.put(Collections.unmodifiableSet(materials.stream().map(String::toUpperCase).map(loader.materialMapper).collect(Collectors.toSet())), amount);
|
Limited.put(Collections.unmodifiableSet(materials.stream().map(String::toUpperCase).map(loader.materialMapper).collect(Collectors.toSet())), amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SQLWrapper.impl.getMaterialWithGreaterBlastResistance(MaxBlastResistance).forEach(material -> {
|
||||||
|
if (Limited.entrySet().stream().anyMatch(entry -> entry.getKey().contains(material))) return;
|
||||||
|
Limited.put(Collections.singleton((M) material), 0);
|
||||||
|
});
|
||||||
this.Limited = Collections.unmodifiableMap(Limited);
|
this.Limited = Collections.unmodifiableMap(Limited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class IgnoreSystem {
|
|
||||||
|
|
||||||
private static final Table<IgnoreSystem> table = new Table<>(IgnoreSystem.class, "IgnoredPlayers");
|
|
||||||
private static final SelectStatement<IgnoreSystem> select = table.select(Table.PRIMARY);
|
|
||||||
private static final Statement insert = table.insertAll();
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int ignorer;
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int ignored;
|
|
||||||
|
|
||||||
public static boolean isIgnored(UUID ignorer, UUID ignored){
|
|
||||||
return isIgnored(SteamwarUser.get(ignorer), SteamwarUser.get(ignored));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isIgnored(SteamwarUser ignorer, SteamwarUser ignored) {
|
|
||||||
return select.select(ResultSet::next, ignorer.getId(), ignored.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ignore(SteamwarUser ignorer, SteamwarUser ignored) {
|
|
||||||
insert.update(ignorer.getId(), ignored.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void unIgnore(SteamwarUser ignorer, SteamwarUser ignored) {
|
|
||||||
delete.update(ignorer.getId(), ignored.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object IgnoreSystemTable: CompositeIdTable("IgnoredPlayers") {
|
||||||
|
val ignorer = reference("Ignorer", SteamwarUserTable)
|
||||||
|
val ignored = reference("Ignored", SteamwarUserTable)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(ignorer, ignored)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(ignorer)
|
||||||
|
addIdColumn(ignored)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IgnoreSystem(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||||
|
var ignorer by IgnoreSystemTable.ignorer
|
||||||
|
var ignored by IgnoreSystemTable.ignored
|
||||||
|
|
||||||
|
companion object : CompositeEntityClass<IgnoreSystem>(IgnoreSystemTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun isIgnored(ignorer: UUID, ignored: UUID) = useDb { isIgnored(SteamwarUser.get(ignorer)!!, SteamwarUser.get(ignored)!!) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isIgnored(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
|
||||||
|
find {
|
||||||
|
(IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id)
|
||||||
|
}.firstOrNull() != null
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun ignore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
|
||||||
|
new {
|
||||||
|
this.ignorer = ignorer.id
|
||||||
|
this.ignored = ignored.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun unIgnore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
|
||||||
|
find {
|
||||||
|
(IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id)
|
||||||
|
}.firstOrNull()?.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.SortOrder
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.count
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.lessSubQuery
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.dao.flushCache
|
||||||
|
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.select
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.upsert
|
||||||
|
|
||||||
|
object LeaderboardTable : CompositeIdTable("Leaderboard") {
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val name = varchar("LeaderboardName", 64).entityId()
|
||||||
|
val time = long("Time")
|
||||||
|
val updatedAt = timestamp("UpdatedAt").defaultExpression(CurrentTimestamp)
|
||||||
|
val bestTime = bool("BestTime")
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(userId, name)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Leaderboard(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||||
|
companion object : CompositeEntityClass<Leaderboard>(LeaderboardTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun getLeaderboard(name: String) = useDb {
|
||||||
|
find { LeaderboardTable.name eq name }.orderBy(LeaderboardTable.time to SortOrder.ASC).limit(5).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getPlayerTime(user: SteamwarUser, name: String) = useDb {
|
||||||
|
find { (LeaderboardTable.userId eq user.id.value) and (LeaderboardTable.name eq name) }.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getPlayerPlacement(user: SteamwarUser, name: String) = useDb {
|
||||||
|
LeaderboardTable.select(LeaderboardTable.time.count())
|
||||||
|
.where {
|
||||||
|
(LeaderboardTable.name eq name) and (LeaderboardTable.time lessSubQuery LeaderboardTable.select(
|
||||||
|
LeaderboardTable.time
|
||||||
|
).where { (LeaderboardTable.userId eq user.id.value) and (LeaderboardTable.name eq name) })
|
||||||
|
}
|
||||||
|
.firstOrNull()?.get(LeaderboardTable.time.count())?.toInt() ?: Int.MAX_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun upsert(userId: Int, name: String, time: Long, bestTime: Boolean) = useDb {
|
||||||
|
LeaderboardTable.upsert(
|
||||||
|
onUpdateExclude = listOf(LeaderboardTable.updatedAt, LeaderboardTable.userId, LeaderboardTable.name)
|
||||||
|
) {
|
||||||
|
it[LeaderboardTable.userId] = userId
|
||||||
|
it[LeaderboardTable.name] = name
|
||||||
|
it[LeaderboardTable.time] = time
|
||||||
|
it[LeaderboardTable.bestTime] = bestTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val user by LeaderboardTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
val name by LeaderboardTable.name
|
||||||
|
var time by LeaderboardTable.time
|
||||||
|
var updatedAt by LeaderboardTable.updatedAt
|
||||||
|
var bestTime by LeaderboardTable.bestTime
|
||||||
|
}
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class Mod {
|
|
||||||
|
|
||||||
static {
|
|
||||||
SqlTypeMapper.ordinalEnumMapper(Platform.class);
|
|
||||||
SqlTypeMapper.ordinalEnumMapper(ModType.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<Mod> table = new Table<>(Mod.class, "Mods");
|
|
||||||
private static final SelectStatement<Mod> get = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<Mod> findFirst = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = 0 LIMIT 1");
|
|
||||||
private static final SelectStatement<Mod> getPageOfType = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = ? ORDER BY ModName DESC LIMIT ?, ?");
|
|
||||||
private static final Statement insert = table.insert(Table.PRIMARY);
|
|
||||||
private static final Statement set = table.update(Table.PRIMARY, "ModType");
|
|
||||||
|
|
||||||
public static Mod get(String name, Platform platform) {
|
|
||||||
return get.select(platform, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Mod getOrCreate(String name, Platform platform) {
|
|
||||||
Mod mod = get(name, platform);
|
|
||||||
if(mod != null)
|
|
||||||
return mod;
|
|
||||||
|
|
||||||
insert.update(platform, name);
|
|
||||||
return new Mod(platform, name, ModType.UNKLASSIFIED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Mod> getAllModsFiltered(int page, int elementsPerPage, ModType filter) {
|
|
||||||
return Mod.getPageOfType.listSelect(filter, page * elementsPerPage, elementsPerPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Mod findFirstMod() {
|
|
||||||
return findFirst.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final Platform platform;
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final String modName;
|
|
||||||
@Getter
|
|
||||||
@Field(def = "0")
|
|
||||||
private ModType modType;
|
|
||||||
|
|
||||||
public void setModType(ModType modType) {
|
|
||||||
set.update(modType, platform, modName);
|
|
||||||
this.modType = modType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Platform {
|
|
||||||
FORGE,
|
|
||||||
LABYMOD,
|
|
||||||
FABRIC
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ModType {
|
|
||||||
UNKLASSIFIED("7"),
|
|
||||||
GREEN("a"),
|
|
||||||
YELLOW("e"),
|
|
||||||
RED("c"),
|
|
||||||
YOUTUBER_ONLY("6");
|
|
||||||
|
|
||||||
ModType(String colorcode) {
|
|
||||||
this.colorcode = colorcode;
|
|
||||||
}
|
|
||||||
private final String colorcode;
|
|
||||||
|
|
||||||
public String getColorCode() {
|
|
||||||
return colorcode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.SortOrder
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
|
||||||
|
object ModTable : CompositeIdTable("Mods") {
|
||||||
|
val platform = enumeration("Platform", Mod.Platform::class)
|
||||||
|
val modName = varchar("ModName", 100)
|
||||||
|
val modeType = enumerationByName("ModType", 10, Mod.ModType::class)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mod(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||||
|
companion object : CompositeEntityClass<Mod>(ModTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun get(modName: String, platform: Platform) = useDb {
|
||||||
|
find { ModTable.platform eq platform and (ModTable.modName eq modName) }.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getOrCreate(modName: String, platform: Platform) = useDb {
|
||||||
|
get(modName, platform) ?: new {
|
||||||
|
this.platform = platform
|
||||||
|
this.modName = modName
|
||||||
|
this.type = ModType.UNKLASSIFIED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getAllModsFiltered(page: Int, elementsPerPage: Int, filter: ModType) = useDb {
|
||||||
|
find { ModTable.modeType eq filter }.limit(elementsPerPage).offset((elementsPerPage * page).toLong())
|
||||||
|
.orderBy(
|
||||||
|
ModTable.modName to SortOrder.DESC
|
||||||
|
).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun findFirstMod() = useDb {
|
||||||
|
find { ModTable.modeType eq ModType.UNKLASSIFIED }.limit(1).firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var platform by ModTable.platform
|
||||||
|
var modName by ModTable.modName
|
||||||
|
private var type by ModTable.modeType
|
||||||
|
var modType: ModType
|
||||||
|
get() = type
|
||||||
|
set(value) = useDb { type = value }
|
||||||
|
|
||||||
|
enum class Platform {
|
||||||
|
FORGE,
|
||||||
|
LABYMOD,
|
||||||
|
FABRIC
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ModType(val colorCode: String) {
|
||||||
|
UNKLASSIFIED("7"),
|
||||||
|
GREEN("a"),
|
||||||
|
YELLOW("e"),
|
||||||
|
RED("c"),
|
||||||
|
YOUTUBER_ONLY("6");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.swing.plaf.nimbus.State;
|
|
||||||
import java.io.*;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.zip.GZIPInputStream;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class NodeData {
|
|
||||||
static {
|
|
||||||
new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
|
|
||||||
new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
|
|
||||||
new SqlTypeMapper<>(BufferedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("BufferedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
|
|
||||||
|
|
||||||
SqlTypeMapper.ordinalEnumMapper(SchematicFormat.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<NodeData> table = new Table<>(NodeData.class);
|
|
||||||
|
|
||||||
private static final Statement updateDatabase = new Statement("INSERT INTO NodeData(NodeId, NodeFormat, SchemData) VALUES (?, ?, ?)", true);
|
|
||||||
private static final Statement selSchemData = new Statement("SELECT SchemData FROM NodeData WHERE NodeId = ? AND CreatedAt = ?");
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
private static final SelectStatement<NodeData> get = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt ");
|
|
||||||
private static final Statement getRevisions = new Statement("SELECT COUNT(DISTINCT CreatedAt) as CNT FROM NodeData WHERE NodeId = ?");
|
|
||||||
private static final SelectStatement<NodeData> getLatest = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt DESC LIMIT 1");
|
|
||||||
|
|
||||||
public static NodeData getLatest(SchematicNode node) {
|
|
||||||
if (node.isDir()) throw new IllegalArgumentException("Node is dir");
|
|
||||||
return Optional.ofNullable(getLatest.select(node)).orElseGet(() -> new NodeData(node.getId(), Timestamp.from(Instant.now()), SchematicFormat.MCEDIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<NodeData> get(SchematicNode node) {
|
|
||||||
return get.listSelect(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NodeData get(SchematicNode node, int revision) {
|
|
||||||
return get.listSelect(node).get(revision - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getRevisions(SchematicNode node) {
|
|
||||||
return getRevisions.select(rs -> {
|
|
||||||
if (rs.next()) {
|
|
||||||
return rs.getInt("CNT");
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveFromStream(SchematicNode node, InputStream blob, SchematicFormat format) {
|
|
||||||
updateDatabase.update(node.getId(), format, blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int nodeId;
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private Timestamp createdAt;
|
|
||||||
|
|
||||||
@Field
|
|
||||||
private SchematicFormat nodeFormat;
|
|
||||||
|
|
||||||
public InputStream schemData() throws IOException {
|
|
||||||
return schemData(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream schemData(boolean decompress) throws IOException {
|
|
||||||
try {
|
|
||||||
return selSchemData.select(rs -> {
|
|
||||||
rs.next();
|
|
||||||
InputStream schemData = rs.getBinaryStream("SchemData");
|
|
||||||
try {
|
|
||||||
if(rs.wasNull() || schemData.available() == 0) {
|
|
||||||
throw new SecurityException("SchemData is null");
|
|
||||||
}
|
|
||||||
if (decompress) {
|
|
||||||
return new GZIPInputStream(schemData);
|
|
||||||
} else {
|
|
||||||
return schemData;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new SecurityException("SchemData is wrong", e);
|
|
||||||
}
|
|
||||||
}, nodeId, createdAt);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void saveFromStream(InputStream blob, SchematicFormat newFormat) {
|
|
||||||
saveFromStream(SchematicNode.getSchematicNode(nodeId), blob, newFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(nodeId, createdAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public enum SchematicFormat {
|
|
||||||
MCEDIT(".schematic"),
|
|
||||||
SPONGE_V2(".schem"),
|
|
||||||
SPONGE_V3(".schem");
|
|
||||||
|
|
||||||
private final String fileEnding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.SortOrder
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.statements.api.ExposedBlob
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.zip.GZIPInputStream
|
||||||
|
|
||||||
|
object NodeDataTable: CompositeIdTable("NodeData") {
|
||||||
|
val nodeId = reference("NodeId", SchematicNodeTable)
|
||||||
|
val createdAt = timestamp("CreatedAt").defaultExpression(CurrentTimestamp).entityId()
|
||||||
|
val nodeFormat = enumeration("NodeFormat", NodeData.SchematicFormat::class)
|
||||||
|
val schemData = blob("SchemData")
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(nodeId, createdAt)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(nodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NodeData(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
val nodeId by NodeDataTable.nodeId
|
||||||
|
val createdAt by NodeDataTable.createdAt
|
||||||
|
val nodeFormat by NodeDataTable.nodeFormat
|
||||||
|
val schemData by NodeDataTable.schemData
|
||||||
|
|
||||||
|
companion object: CompositeEntityClass<NodeData>(NodeDataTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun getLatest(node: SchematicNode) = useDb {
|
||||||
|
find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.DESC).firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(node: SchematicNode) = useDb {
|
||||||
|
find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(node: SchematicNode, revision: Int) = useDb {
|
||||||
|
find { NodeDataTable.nodeId eq node.nodeId }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList().get(revision - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getRevisions(node: SchematicNode) = useDb {
|
||||||
|
count(NodeDataTable.nodeId eq node.nodeId).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun saveFromStream(node: SchematicNode, blob: InputStream, format: SchematicFormat) = useDb {
|
||||||
|
NodeDataTable.insert {
|
||||||
|
it[NodeDataTable.nodeId] = EntityID(node.getId(), SchematicNodeTable)
|
||||||
|
it[NodeDataTable.nodeFormat] = format
|
||||||
|
it[NodeDataTable.schemData] = ExposedBlob(blob.readBytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun schemData(decompress: Boolean) = useDb {
|
||||||
|
schemData.inputStream.let { if(decompress) GZIPInputStream(it) else it }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun schemData() = schemData(true)
|
||||||
|
|
||||||
|
override fun delete() = useDb { super.delete() }
|
||||||
|
|
||||||
|
enum class SchematicFormat(val fileEnding: String) {
|
||||||
|
MCEDIT(".schematic"),
|
||||||
|
SPONGE_V2(".schem"),
|
||||||
|
SPONGE_V3(".schem");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class NodeDownload {
|
|
||||||
|
|
||||||
private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
||||||
private static final String LINK_BASE = "https://api.steamwar.de/download/";
|
|
||||||
|
|
||||||
private static final Table<NodeDownload> table = new Table<>(NodeDownload.class);
|
|
||||||
private static final Statement insert = table.insertFields("NodeId", "Link");
|
|
||||||
|
|
||||||
private static final SelectStatement<NodeDownload> select = table.selectFields("link");
|
|
||||||
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
public static NodeDownload get(String link) {
|
|
||||||
return select.select(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int nodeId;
|
|
||||||
@Field
|
|
||||||
private final String link;
|
|
||||||
@Field(def = "CURRENT_TIMESTAMP")
|
|
||||||
@Getter
|
|
||||||
private final Timestamp timestamp;
|
|
||||||
|
|
||||||
public static String getLink(SchematicNode schem){
|
|
||||||
if(schem.isDir())
|
|
||||||
throw new SecurityException("Can not Download Directorys");
|
|
||||||
MessageDigest digest;
|
|
||||||
try {
|
|
||||||
digest = MessageDigest.getInstance("SHA-1");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new SecurityException(e);
|
|
||||||
}
|
|
||||||
digest.reset();
|
|
||||||
digest.update((Instant.now().toString() + schem.getOwner() + schem.getId()).getBytes());
|
|
||||||
String hash = base16encode(digest.digest());
|
|
||||||
insert.update(schem.getId(), hash);
|
|
||||||
return LINK_BASE + hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String base16encode(byte[] byteArray) {
|
|
||||||
StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2);
|
|
||||||
for (byte b : byteArray)
|
|
||||||
hexBuffer.append(HEX[(b >>> 4) & 0xF]).append(HEX[b & 0xF]);
|
|
||||||
return hexBuffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(nodeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.sql.Timestamp
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
object NodeDownloadTable: IdTable<Int>("NodeDownload") {
|
||||||
|
override val id = reference("NodeId", SchematicNodeTable).uniqueIndex()
|
||||||
|
val link = varchar("Link", 255)
|
||||||
|
val timestamp = timestamp("Timestamp").defaultExpression(CurrentTimestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
class NodeDownload(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<NodeDownload>(NodeDownloadTable) {
|
||||||
|
const val LINK_BASE = "https://api.steamwar.de/download/"
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getLink(schem: SchematicNode): String {
|
||||||
|
if (schem.isDir())
|
||||||
|
throw IllegalArgumentException("Cannot get link for directory")
|
||||||
|
|
||||||
|
val digest = MessageDigest.getInstance("SHA-1")
|
||||||
|
digest.update("${Instant.now()}${schem.owner}${schem.nodeId}".toByteArray())
|
||||||
|
val hash = digest.digest().joinToString("") { "%02x".format(it) }
|
||||||
|
useDb {
|
||||||
|
findByIdAndUpdate(schem.id.value) {
|
||||||
|
it.link = hash
|
||||||
|
} ?: new {
|
||||||
|
nodeId = schem.id.value
|
||||||
|
link = hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "${LINK_BASE}${hash}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(link: String) = useDb {
|
||||||
|
find { NodeDownloadTable.link eq link }.firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeId by NodeDownloadTable.id.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
|
||||||
|
var link by NodeDownloadTable.link
|
||||||
|
var timestamp by NodeDownloadTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
|
||||||
|
override fun delete() = useDb {
|
||||||
|
super.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class NodeMember {
|
|
||||||
|
|
||||||
public static void init() {
|
|
||||||
// enforce class initialization
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<NodeMember> table = new Table<>(NodeMember.class);
|
|
||||||
private static final SelectStatement<NodeMember> getNodeMember = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<NodeMember> getNodeMembers = table.selectFields("NodeId");
|
|
||||||
private static final SelectStatement<NodeMember> getSchematics = table.selectFields("UserId");
|
|
||||||
private static final Statement create = table.insert(Table.PRIMARY);
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
private static final Statement updateParent = table.update(Table.PRIMARY, "ParentId");
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int nodeId;
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int userId;
|
|
||||||
@Field(nullable = true, def = "null")
|
|
||||||
private Integer parentId;
|
|
||||||
|
|
||||||
public int getNode() {
|
|
||||||
return nodeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMember() {
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Integer> getParent() {
|
|
||||||
return Optional.ofNullable(parentId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(nodeId, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NodeMember createNodeMember(int node, int member) {
|
|
||||||
create.update(node, member);
|
|
||||||
return new NodeMember(node, member, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NodeMember getNodeMember(int node, SteamwarUser member) {
|
|
||||||
return getNodeMember(node, member.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NodeMember getNodeMember(int node, int member) {
|
|
||||||
return getNodeMember.select(node, member);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<NodeMember> getNodeMembers(int node) {
|
|
||||||
return new HashSet<>(getNodeMembers.listSelect(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<NodeMember> getSchematics(int member) {
|
|
||||||
return new HashSet<>(getSchematics.listSelect(member));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParentId(Integer parentId) {
|
|
||||||
this.parentId = parentId;
|
|
||||||
updateParent.update(this.parentId, nodeId, userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.jvm.optionals.getOrNull
|
||||||
|
|
||||||
|
object NodeMemberTable : CompositeIdTable("NodeMember") {
|
||||||
|
val node = reference("NodeId", SchematicNodeTable)
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val parentNode = optReference("ParentId", SchematicNodeTable)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(node, userId)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(node)
|
||||||
|
addIdColumn(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NodeMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||||
|
companion object : CompositeEntityClass<NodeMember>(NodeMemberTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun createNodeMember(node: Int, member: Int): NodeMember = useDb {
|
||||||
|
NodeMemberTable.insertIgnore {
|
||||||
|
it[this.node] = EntityID(node, SchematicNodeTable)
|
||||||
|
it[this.userId] = EntityID(member, SteamwarUserTable)
|
||||||
|
}
|
||||||
|
getNodeMember(node, member) ?: throw IllegalStateException("NodeMember not created")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createNodeMember(node: Int, member: Int, parent: SchematicNode): NodeMember = useDb {
|
||||||
|
if (!parent.isDir()) throw IllegalStateException("Parent must be a directory")
|
||||||
|
NodeMemberTable.insertIgnore {
|
||||||
|
it[this.node] = EntityID(node, SchematicNodeTable)
|
||||||
|
it[this.userId] = EntityID(member, SteamwarUserTable)
|
||||||
|
it[NodeMemberTable.parentNode] = parent.getId()
|
||||||
|
}
|
||||||
|
getNodeMember(node, member) ?: throw IllegalStateException("NodeMember not created")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createNodeMember(node: Int, member: SteamwarUser) = createNodeMember(node, member.id.value)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getNodeMember(node: Int, member: Int) = useDb {
|
||||||
|
find { (NodeMemberTable.node eq node) and (NodeMemberTable.userId eq member) }.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getNodeMember(node: Int, member: SteamwarUser) = getNodeMember(node, member.id.value)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getNodeMembers(node: Int) = useDb { find { NodeMemberTable.node eq node }.toSet() }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getSchematics(member: Int) = useDb { find { NodeMemberTable.userId eq member }.toSet() }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun init() = Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
val node by NodeMemberTable.node.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
|
||||||
|
val member by NodeMemberTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
var parent by NodeMemberTable.parentNode.transform(
|
||||||
|
{ it.map { EntityID(it, SchematicNodeTable) }.getOrNull() },
|
||||||
|
{ Optional.ofNullable(it?.value) })
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun setParentId(id: Int?) {
|
||||||
|
parent = Optional.ofNullable(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() = useDb {
|
||||||
|
super.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
|
||||||
|
object PersonalKitTable: CompositeIdTable("PersonalKit") {
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val gamemode = varchar("Gamemode", 64).entityId()
|
||||||
|
val kitName = varchar("Name", 64).entityId()
|
||||||
|
val inventory = text("Inventory")
|
||||||
|
val armor = text("Armor")
|
||||||
|
val inUse = bool("InUse")
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(userId, gamemode, kitName)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalKit(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
companion object: CompositeEntityClass<InternalKit>(PersonalKitTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun get(userId: Int, gamemode: String) = useDb {
|
||||||
|
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.inUse eq true) }
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(userId: Int, gamemode: String, kitName: String) = useDb {
|
||||||
|
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.kitName eq kitName) and (PersonalKitTable.inUse eq true) }
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(userId: Int, gamemode: String, kitName: String, rawInventory: String, rawArmor: String) = useDb {
|
||||||
|
new(
|
||||||
|
CompositeID {
|
||||||
|
it[PersonalKitTable.userId] = EntityID(userId, SteamwarUserTable)
|
||||||
|
it[PersonalKitTable.gamemode] = gamemode
|
||||||
|
it[PersonalKitTable.kitName] = kitName
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
this.inventory = rawInventory
|
||||||
|
this.armor = rawArmor
|
||||||
|
this.inUse = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getKitInUse(userId: Int, gamemode: String) = useDb {
|
||||||
|
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.inUse eq true) }
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var userID by PersonalKitTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
private set
|
||||||
|
private var gameMode by PersonalKitTable.gamemode
|
||||||
|
val gamemode: String
|
||||||
|
get() = gameMode.value
|
||||||
|
|
||||||
|
var kitName by PersonalKitTable.kitName
|
||||||
|
private set
|
||||||
|
val name: String
|
||||||
|
get() = kitName.value
|
||||||
|
|
||||||
|
var rawInventory by PersonalKitTable.inventory
|
||||||
|
private set
|
||||||
|
var rawArmor by PersonalKitTable.armor
|
||||||
|
private set
|
||||||
|
var inUse by PersonalKitTable.inUse
|
||||||
|
private set
|
||||||
|
|
||||||
|
var inventory: String
|
||||||
|
get() = rawInventory
|
||||||
|
set(value) = useDb { rawInventory = value }
|
||||||
|
var armor: String
|
||||||
|
get() = rawArmor
|
||||||
|
set(value) = useDb { rawArmor = value }
|
||||||
|
|
||||||
|
fun setDefault() = useDb {
|
||||||
|
find { PersonalKitTable.userId eq userID and (PersonalKitTable.gamemode eq gameMode) and (PersonalKitTable.inUse eq true) }
|
||||||
|
.forEach { it.inUse = false }
|
||||||
|
inUse = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() = useDb {
|
||||||
|
super.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class PollAnswer {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private static String currentPoll;
|
|
||||||
|
|
||||||
private static final Table<PollAnswer> table = new Table<>(PollAnswer.class);
|
|
||||||
|
|
||||||
private static final SelectStatement<PollAnswer> get = table.select(Table.PRIMARY);
|
|
||||||
private static final Statement getResults = new Statement("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC");
|
|
||||||
private static final Statement insert = table.insertAll();
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int userID;
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final String question;
|
|
||||||
@Field(def = "0")
|
|
||||||
private int answer;
|
|
||||||
|
|
||||||
public static PollAnswer get(int userID) {
|
|
||||||
PollAnswer answer = get.select(userID, currentPoll);
|
|
||||||
if(answer == null)
|
|
||||||
return new PollAnswer(userID, currentPoll, 0);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<Integer, Integer> getCurrentResults() {
|
|
||||||
return getResults.select(rs -> {
|
|
||||||
Map<Integer, Integer> retMap = new HashMap<>();
|
|
||||||
while (rs.next())
|
|
||||||
retMap.put(rs.getInt("Answer")-1, rs.getInt("Times"));
|
|
||||||
return retMap;
|
|
||||||
}, currentPoll);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasAnswered(){
|
|
||||||
return answer != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnswer(int answer){
|
|
||||||
this.answer = answer;
|
|
||||||
insert.update(userID, question, answer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class Punishment {
|
|
||||||
|
|
||||||
static {
|
|
||||||
SqlTypeMapper.nameEnumMapper(PunishmentType.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Timestamp PERMA_TIME = Timestamp.from(Instant.ofEpochSecond(946674800));
|
|
||||||
|
|
||||||
private static final Table<Punishment> table = new Table<>(Punishment.class, "Punishments");
|
|
||||||
private static final SelectStatement<Punishment> getPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)");
|
|
||||||
private static final SelectStatement<Punishment> getPunishment = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1");
|
|
||||||
private static final SelectStatement<Punishment> getAllPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC");
|
|
||||||
private static final Statement insert = table.insertFields(true, "UserId", "Punisher", "Type", "EndTime", "Perma", "Reason");
|
|
||||||
|
|
||||||
public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) {
|
|
||||||
return getPunishment.select(user, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<PunishmentType, Punishment> getPunishmentsOfPlayer(int user) {
|
|
||||||
return getPunishments.listSelect(user).stream().collect(Collectors.toMap(Punishment::getType, punishment -> punishment));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Punishment> getAllPunishmentsOfPlayer(int user) {
|
|
||||||
return getAllPunishments.listSelect(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPunished(SteamwarUser user, PunishmentType type, Consumer<Punishment> callback) {
|
|
||||||
Punishment punishment = Punishment.getPunishmentOfPlayer(user.getId(), type);
|
|
||||||
if(punishment == null || !punishment.isCurrent()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
callback.accept(punishment);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) {
|
|
||||||
if(perma && !endTime.equals(PERMA_TIME)) {
|
|
||||||
throw new IllegalArgumentException("Permanent punishments must have an end time of `Punishment.PERMA_TIME`");
|
|
||||||
}
|
|
||||||
int punishmentId = insert.insertGetKey(user, executor, type.name(), endTime, perma, reason);
|
|
||||||
return new Punishment(punishmentId, user, executor, type, Timestamp.from(Instant.now()), endTime, perma, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
|
||||||
private final int punishmentId;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final int userId;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final int punisher;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final PunishmentType type;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final Timestamp startTime;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final Timestamp endTime;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final boolean perma;
|
|
||||||
@Field
|
|
||||||
@Getter
|
|
||||||
private final String reason;
|
|
||||||
|
|
||||||
@Deprecated // Not multiling, misleading title
|
|
||||||
public String getBantime(Timestamp endTime, boolean perma) {
|
|
||||||
if (perma) {
|
|
||||||
return "permanent";
|
|
||||||
} else {
|
|
||||||
return endTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCurrent() {
|
|
||||||
return isPerma() || getEndTime().after(new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public enum PunishmentType {
|
|
||||||
Ban(UserPerm.TEAM, "BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN"),
|
|
||||||
Mute( UserPerm.TEAM, "MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE"),
|
|
||||||
NoSchemReceiving(UserPerm.MODERATION, "NOSCHEMRECEIVING_TEAM", "NOSCHEMRECEIVING_PERMA", "NOSCHEMRECEIVING_UNTIL", "UNNOSCHEMRECEIVING_ERROR", "UNNOSCHEMRECEIVING"),
|
|
||||||
NoSchemSharing(UserPerm.MODERATION, "NOSCHEMSHARING_TEAM", "NOSCHEMSHARING_PERMA", "NOSCHEMSHARING_UNTIL", "UNNOSCHEMSHARING_ERROR", "UNNOSCHEMSHARING"),
|
|
||||||
NoSchemSubmitting(UserPerm.TEAM, "NOSCHEMSUBMITTING_TEAM", "NOSCHEMSUBMITTING_PERMA", "NOSCHEMSUBMITTING_UNTIL", "UNNOSCHEMSUBMITTING_ERROR", "UNNOSCHEMSUBMITTING"),
|
|
||||||
NoDevServer(UserPerm.PREFIX_DEVELOPER, "NODEVSERVER_TEAM", "NODEVSERVER_PERMA", "NODEVSERVER_UNTIL", "UNNODEVSERVER_ERROR", "UNNODEVSERVER"),
|
|
||||||
NoFightServer(UserPerm.MODERATION, "NOFIGHTSERVER_TEAM", "NOFIGHTSERVER_PERMA", "NOFIGHTSERVER_UNTIL", "UNNOFIGHTSERVER_ERROR", "UNNOFIGHTSERVER"),
|
|
||||||
NoTeamServer(UserPerm.MODERATION, "NOTEAMSERVER_TEAM", "NOTEAMSERVER_PERMA", "NOTEAMSERVER_UNTIL", "UNNOTEAMSERVER_ERROR", "UNNOTEAMSERVER"),
|
|
||||||
Note(UserPerm.TEAM, "NOTE_TEAM", null, null, null, null, true);
|
|
||||||
|
|
||||||
private final UserPerm userPerm;
|
|
||||||
private final String teamMessage;
|
|
||||||
private final String playerMessagePerma;
|
|
||||||
private final String playerMessageUntil;
|
|
||||||
private final String usageNotPunished;
|
|
||||||
private final String unpunishmentMessage;
|
|
||||||
private boolean multi = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
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.select
|
||||||
|
import java.sql.Timestamp
|
||||||
|
import java.time.Instant
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
object PunishmentTable : IntIdTable("Punishments", "PunishmentId") {
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val punisher = reference("Punisher", SteamwarUserTable)
|
||||||
|
val type = enumerationByName("Type", 32, Punishment.PunishmentType::class)
|
||||||
|
val startTime = timestamp("StartTime")
|
||||||
|
val endTime = timestamp("EndTime")
|
||||||
|
val perma = bool("Perma")
|
||||||
|
val reason = text("Reason")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Punishment(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Punishment>(PunishmentTable) {
|
||||||
|
@JvmField
|
||||||
|
val PERMA_TIME: Timestamp = Timestamp.from(Instant.ofEpochSecond(946674800))
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getPunsihmentOfPlayer(user: Int, type: PunishmentType) = useDb {
|
||||||
|
find { (PunishmentTable.userId eq user) and (PunishmentTable.type eq type) }.orderBy(PunishmentTable.id to SortOrder.DESC)
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getPunishmentsOfPlayer(user: Int) = useDb {
|
||||||
|
find {
|
||||||
|
PunishmentTable.id inSubQuery PunishmentTable.select(PunishmentTable.id.max())
|
||||||
|
.where { PunishmentTable.userId eq user }.groupBy(
|
||||||
|
PunishmentTable.type
|
||||||
|
)
|
||||||
|
}.associateBy { it.type }.toMutableMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getAllPunishmentsOfPlayer(user: Int) = useDb {
|
||||||
|
find { PunishmentTable.userId eq user }.orderBy(PunishmentTable.id to SortOrder.DESC).toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isPunished(user: SteamwarUser, type: PunishmentType, callback: Consumer<Punishment>): Boolean = useDb {
|
||||||
|
val punishment = getPunsihmentOfPlayer(user.id.value, type) ?: return@useDb false
|
||||||
|
|
||||||
|
if (punishment.isCurrent()) {
|
||||||
|
callback.accept(punishment)
|
||||||
|
return@useDb true
|
||||||
|
}
|
||||||
|
|
||||||
|
return@useDb false
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createPunishment(
|
||||||
|
user: Int,
|
||||||
|
executor: Int,
|
||||||
|
type: PunishmentType,
|
||||||
|
reason: String,
|
||||||
|
endTime: Timestamp,
|
||||||
|
perma: Boolean
|
||||||
|
) = useDb {
|
||||||
|
new {
|
||||||
|
this.userId = user
|
||||||
|
this.punisher = executor
|
||||||
|
this.type = type
|
||||||
|
this.startTime = Timestamp.from(Instant.now())
|
||||||
|
this.endTime = endTime
|
||||||
|
this.perma = perma
|
||||||
|
this.reason = reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var userId by PunishmentTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
private set
|
||||||
|
var punisher by PunishmentTable.punisher.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
private set
|
||||||
|
var type by PunishmentTable.type
|
||||||
|
private set
|
||||||
|
var startTime by PunishmentTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
private set
|
||||||
|
var endTime by PunishmentTable.endTime.transform({ it.toInstant() }, { Timestamp.from(it) })
|
||||||
|
private set
|
||||||
|
var perma by PunishmentTable.perma
|
||||||
|
private set
|
||||||
|
var reason by PunishmentTable.reason
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun isPerma() = perma
|
||||||
|
|
||||||
|
fun isCurrent() = perma || endTime.after(Date())
|
||||||
|
|
||||||
|
enum class PunishmentType(
|
||||||
|
val teamMessage: String?,
|
||||||
|
val playerMessagePerma: String?,
|
||||||
|
val playerMessageUntil: String?,
|
||||||
|
val usageNotPunished: String?,
|
||||||
|
val unpunishmentMessage: String?,
|
||||||
|
val userPerm: UserPerm,
|
||||||
|
val multi: Boolean = false
|
||||||
|
) {
|
||||||
|
Ban("BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN", UserPerm.PUNISHMENTS),
|
||||||
|
Mute("MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE", UserPerm.PUNISHMENTS),
|
||||||
|
NoSchemReceiving(
|
||||||
|
"NOSCHEMRECEIVING_TEAM",
|
||||||
|
"NOSCHEMRECEIVING_PERMA",
|
||||||
|
"NOSCHEMRECEIVING_UNTIL",
|
||||||
|
"UNNOSCHEMRECEIVING_ERROR",
|
||||||
|
"UNNOSCHEMRECEIVING",
|
||||||
|
UserPerm.MODERATION
|
||||||
|
),
|
||||||
|
NoSchemSharing(
|
||||||
|
"NOSCHEMSHARING_TEAM",
|
||||||
|
"NOSCHEMSHARING_PERMA",
|
||||||
|
"NOSCHEMSHARING_UNTIL",
|
||||||
|
"UNNOSCHEMSHARING_ERROR",
|
||||||
|
"UNNOSCHEMSHARING",
|
||||||
|
UserPerm.MODERATION
|
||||||
|
),
|
||||||
|
NoSchemSubmitting(
|
||||||
|
"NOSCHEMSUBMITTING_TEAM",
|
||||||
|
"NOSCHEMSUBMITTING_PERMA",
|
||||||
|
"NOSCHEMSUBMITTING_UNTIL",
|
||||||
|
"UNNOSCHEMSUBMITTING_ERROR",
|
||||||
|
"UNNOSCHEMSUBMITTING",
|
||||||
|
UserPerm.CHECK
|
||||||
|
),
|
||||||
|
NoDevServer(
|
||||||
|
"NODEVSERVER_TEAM",
|
||||||
|
"NODEVSERVER_PERMA",
|
||||||
|
"NODEVSERVER_UNTIL",
|
||||||
|
"UNNODEVSERVER_ERROR",
|
||||||
|
"UNNODEVSERVER",
|
||||||
|
UserPerm.PREFIX_DEVELOPER
|
||||||
|
),
|
||||||
|
NoFightServer(
|
||||||
|
"NOFIGHTSERVER_TEAM",
|
||||||
|
"NOFIGHTSERVER_PERMA",
|
||||||
|
"NOFIGHTSERVER_UNTIL",
|
||||||
|
"UNNOFIGHTSERVER_ERROR",
|
||||||
|
"UNNOFIGHTSERVER",
|
||||||
|
UserPerm.MODERATION
|
||||||
|
),
|
||||||
|
NoTeamServer(
|
||||||
|
"NOTEAMSERVER_TEAM",
|
||||||
|
"NOTEAMSERVER_PERMA",
|
||||||
|
"NOTEAMSERVER_UNTIL",
|
||||||
|
"UNNOTEAMSERVER_ERROR",
|
||||||
|
"UNNOTEAMSERVER",
|
||||||
|
UserPerm.MODERATION
|
||||||
|
),
|
||||||
|
Note("NOTE_TEAM", null, null, null, null, UserPerm.PUNISHMENTS, true);
|
||||||
|
|
||||||
|
fun isMulti() = multi
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class Referee {
|
|
||||||
|
|
||||||
private static final Table<Referee> table = new Table<>(Referee.class);
|
|
||||||
private static final SelectStatement<Referee> byEvent = table.selectFields("eventID");
|
|
||||||
|
|
||||||
private static final Statement insert = table.insertAll();
|
|
||||||
private static final Statement delete = table.delete("eventReferee");
|
|
||||||
|
|
||||||
public static void add(int eventID, int userID) {
|
|
||||||
insert.update(eventID, userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void remove(int eventID, int userID) {
|
|
||||||
delete.update(eventID, userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<Integer> get(int eventID) {
|
|
||||||
return byEvent.listSelect(eventID).stream().map(referee -> referee.userID).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = {"eventReferee"})
|
|
||||||
private final int eventID;
|
|
||||||
@Field(keys = {"eventReferee"})
|
|
||||||
private final int userID;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
|
||||||
|
object RefereeTable: CompositeIdTable("Referee") {
|
||||||
|
val eventId = reference("EventId", EventTable)
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(eventId, userId)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(eventId)
|
||||||
|
addIdColumn(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Referee(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
companion object: CompositeEntityClass<Referee>(RefereeTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun add(eventId: Int, userId: Int) = useDb {
|
||||||
|
new {
|
||||||
|
this.eventID = eventId
|
||||||
|
this.userID = userId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun remove(eventId: Int, userId: Int) = useDb {
|
||||||
|
find { (RefereeTable.eventId eq eventId) and (RefereeTable.userId eq userId) }.firstOrNull()?.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(event: Int) = useDb {
|
||||||
|
find { RefereeTable.eventId eq event }.map { it.userID }.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventID by RefereeTable.eventId.transform({ EntityID(it, EventTable) }, { it.value })
|
||||||
|
var userID by RefereeTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@ package de.steamwar.sql;
|
|||||||
import de.steamwar.ImplementationProvider;
|
import de.steamwar.ImplementationProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface SQLWrapper<M> {
|
public interface SQLWrapper<M> {
|
||||||
SQLWrapper<?> impl = ImplementationProvider.getImpl("de.steamwar.sql.SQLWrapperImpl");
|
SQLWrapper<?> impl = ImplementationProvider.getImpl("de.steamwar.sql.SQLWrapperImpl");
|
||||||
@@ -30,6 +32,10 @@ public interface SQLWrapper<M> {
|
|||||||
|
|
||||||
GameModeConfig<M, String> loadGameModeConfig(File file);
|
GameModeConfig<M, String> loadGameModeConfig(File file);
|
||||||
|
|
||||||
|
default List<M> getMaterialWithGreaterBlastResistance(double maxBlastResistance) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
default void processSchematicType(GameModeConfig<?, String> gameModeConfig) {
|
default void processSchematicType(GameModeConfig<?, String> gameModeConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class SWException {
|
|
||||||
|
|
||||||
public static void init() {
|
|
||||||
// force class initialialisation
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String CWD = System.getProperty("user.dir");
|
|
||||||
private static final String SERVER_NAME = new File(CWD).getName();
|
|
||||||
|
|
||||||
private static final Table<SWException> table = new Table<>(SWException.class, "Exception");
|
|
||||||
private static final Statement insert = table.insertFields(true, "server", "message", "stacktrace");
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
|
||||||
private final int id;
|
|
||||||
@Field(def = "CURRENT_TIMESTAMP")
|
|
||||||
private final Timestamp time;
|
|
||||||
@Field
|
|
||||||
private final String server;
|
|
||||||
@Field
|
|
||||||
private final String message;
|
|
||||||
@Field
|
|
||||||
private final String stacktrace;
|
|
||||||
|
|
||||||
public static void log(String message, String stacktrace){
|
|
||||||
insert.update(SERVER_NAME, generateMessage(message), stacktrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int logGetId(String message, String stacktrace) {
|
|
||||||
return insert.insertGetKey(SERVER_NAME, generateMessage(message), stacktrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String generateMessage(String message) {
|
|
||||||
StringBuilder msgBuilder = new StringBuilder(message);
|
|
||||||
SQLWrapper.impl.additionalExceptionMetadata(msgBuilder);
|
|
||||||
msgBuilder.append("\nCWD: ").append(CWD);
|
|
||||||
return msgBuilder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object ExceptionTable: IntIdTable("Exception") {
|
||||||
|
val time = timestamp("Time").defaultExpression(CurrentTimestamp)
|
||||||
|
val server = text("Server")
|
||||||
|
val message = text("Message")
|
||||||
|
val stackTrace = text("StackTrace")
|
||||||
|
}
|
||||||
|
|
||||||
|
class SWException {
|
||||||
|
companion object {
|
||||||
|
val cwd = System.getProperty("user.dir")
|
||||||
|
val serverName = File(cwd).name
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun init() = Unit
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun log(message: String, stacktrace: String) = useDb {
|
||||||
|
ExceptionTable.insert {
|
||||||
|
it[ExceptionTable.server] = serverName
|
||||||
|
it[ExceptionTable.message] = generateMessage(message)
|
||||||
|
it[ExceptionTable.stackTrace] = stacktrace
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun logGetId(message: String, stacktrace: String) = useDb {
|
||||||
|
ExceptionTable.insertAndGetId {
|
||||||
|
it[ExceptionTable.server] = serverName
|
||||||
|
it[ExceptionTable.message] = generateMessage(message)
|
||||||
|
it[ExceptionTable.stackTrace] = stacktrace
|
||||||
|
}.value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateMessage(message: String): String {
|
||||||
|
val msgBuilder = StringBuilder(message)
|
||||||
|
SQLWrapper.impl.additionalExceptionMetadata(msgBuilder)
|
||||||
|
msgBuilder.append("\nCWD: ").append(cwd)
|
||||||
|
return msgBuilder.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class SchemElo {
|
|
||||||
private static final int ELO_DEFAULT = 1000;
|
|
||||||
|
|
||||||
private static final Table<SchemElo> table = new Table<>(SchemElo.class);
|
|
||||||
private static final SelectStatement<SchemElo> select = table.select(Table.PRIMARY);
|
|
||||||
private static final Statement setElo = table.insertAll();
|
|
||||||
|
|
||||||
public static int getElo(SchematicNode node, int season) {
|
|
||||||
SchemElo elo = select.select(node, season);
|
|
||||||
return elo != null ? elo.elo : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getCurrentElo(int schemID) {
|
|
||||||
SchemElo elo = select.select(schemID, Season.getSeason());
|
|
||||||
return elo != null ? elo.elo : ELO_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setElo(int schemID, int elo) {
|
|
||||||
setElo.update(schemID, elo, Season.getSeason());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int schemId;
|
|
||||||
@Field
|
|
||||||
private final int elo;
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private final int season;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||||
|
|
||||||
|
object SchemEloTable: CompositeIdTable("SchemElo") {
|
||||||
|
val schemId = reference("SchemId", SchematicNodeTable)
|
||||||
|
val season = integer("Season").entityId()
|
||||||
|
val elo = integer("Elo")
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(schemId, season)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addIdColumn(schemId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SchemElo(id: EntityID<CompositeID>): CompositeEntity(id) {
|
||||||
|
companion object: CompositeEntityClass<SchemElo>(SchemEloTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun getElo(node: SchematicNode, season: Int, defaultElo: Int = 0) = useDb {
|
||||||
|
find { (SchemEloTable.schemId eq node.id) and (SchemEloTable.season eq season) }.firstOrNull()?.elo ?: defaultElo
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getCurrentElo(schemId: Int) = getElo(SchematicNode.byId(schemId)!!, Season.getSeason())
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setElo(node: Int, elo: Int) = useDb {
|
||||||
|
findByIdAndUpdate(CompositeID {
|
||||||
|
it[SchemEloTable.schemId] = node
|
||||||
|
it[SchemEloTable.season] = Season.getSeason()
|
||||||
|
}) {
|
||||||
|
it.elo = elo
|
||||||
|
} ?: SchemEloTable.insertIgnore {
|
||||||
|
it[SchemEloTable.schemId] = node
|
||||||
|
it[SchemEloTable.season] = Season.getSeason()
|
||||||
|
it[SchemEloTable.elo] = elo
|
||||||
|
}
|
||||||
|
|
||||||
|
return@useDb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var node by SchemEloTable.schemId
|
||||||
|
var season by SchemEloTable.season
|
||||||
|
var elo by SchemEloTable.elo
|
||||||
|
}
|
||||||
@@ -1,634 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Integer, Map<String, List<String>>> TAB_CACHE = new HashMap<>();
|
|
||||||
|
|
||||||
public static void clear() {
|
|
||||||
TAB_CACHE.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode ";
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
static {
|
|
||||||
NodeMember.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
private String brCache;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<SchematicNode> getAll(SteamwarUser user) {
|
|
||||||
return all.listSelect(user, user, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<Integer, List<SchematicNode>> getAllMap(SteamwarUser user) {
|
|
||||||
return map(getAll(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SchematicNode createSchematic(int owner, String name, Integer parent) {
|
|
||||||
return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) {
|
|
||||||
return createSchematicNode(owner, name, parent, null, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.get(owner), SchematicType.fromDB(schemType), parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<SchematicNode> getAllAccessibleSchematicsOfType(int user, String schemType) {
|
|
||||||
return accessibleByUserType(SteamwarUser.get(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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return finalList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static List<SchematicNode> getSchematicsAccessibleByUser(int user, Integer parent) {
|
|
||||||
return list(SteamwarUser.get(user), parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static List<SchematicNode> getAllSchematicsAccessibleByUser(int user) {
|
|
||||||
return getAll(SteamwarUser.get(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);
|
|
||||||
}
|
|
||||||
if (s.endsWith("/")) {
|
|
||||||
s = s.substring(0, s.length() - 1);
|
|
||||||
}
|
|
||||||
if (s.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
} else {
|
|
||||||
if (filter.test(node))
|
|
||||||
finalList.add(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setItem(String item) {
|
|
||||||
this.nodeItem = item;
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public String getType() {
|
|
||||||
return nodeType.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void setType(String type) {
|
|
||||||
if (isDir())
|
|
||||||
throw new SecurityException("Node is Directory");
|
|
||||||
this.nodeType = SchematicType.fromDB(type);
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDir() {
|
|
||||||
return nodeType == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
} else {
|
|
||||||
config &= ~(1 << flag.ordinal());
|
|
||||||
}
|
|
||||||
updateDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SchematicNode getParentNode() {
|
|
||||||
if (parentNode == null)
|
|
||||||
return null;
|
|
||||||
return SchematicNode.getSchematicNode(parentNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getElo(int season) {
|
|
||||||
return SchemElo.getElo(this, season);
|
|
||||||
}
|
|
||||||
|
|
||||||
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("/");
|
|
||||||
}
|
|
||||||
return brCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
while (currentNode.isPresent()) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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()) {
|
|
||||||
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<String> FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public"));
|
|
||||||
|
|
||||||
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 {
|
|
||||||
REPLACE_COLOR,
|
|
||||||
ALLOW_REPLAY,
|
|
||||||
IS_PREPARED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
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.CurrentTimestamp
|
||||||
|
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
|
||||||
|
|
||||||
|
object SchematicNodeTable : IntIdTable("SchematicNode", "NodeId") {
|
||||||
|
val owner = reference("NodeOwner", SteamwarUserTable)
|
||||||
|
val name = varchar("NodeName", 64)
|
||||||
|
val parent = optReference("ParentNode", SchematicNodeTable)
|
||||||
|
val lastUpdate = timestamp("LastUpdate").defaultExpression(CurrentTimestamp)
|
||||||
|
val item = text("NodeItem")
|
||||||
|
val type = varchar("NodeType", 16).nullable()
|
||||||
|
val config = integer("Config")
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
private val FORBIDDEN_NAMES = listOf("public")
|
||||||
|
private val FORBIDDEN_CHARS = listOf('/', '\\', '<', '>', '^', '°', '\'', '"', ' ')
|
||||||
|
|
||||||
|
val tabCache = mutableMapOf<Int, MutableMap<String, List<String>>>()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun clear() = tabCache.clear()
|
||||||
|
|
||||||
|
private fun List<SchematicNode>.mapToIds(): Map<Int, SchematicNode> = this.associateBy { it.nodeId }
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getAllMap(user: SteamwarUser) = getAll(user).mapToIds()
|
||||||
|
|
||||||
|
@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, 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 schematicId,
|
||||||
|
IntegerColumnType() to user.getId(),
|
||||||
|
IntegerColumnType() to schematicId,
|
||||||
|
IntegerColumnType() to schematicId,
|
||||||
|
), fieldIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
@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, 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 schematicId,
|
||||||
|
IntegerColumnType() to user.getId(),
|
||||||
|
IntegerColumnType() to schematicId,
|
||||||
|
IntegerColumnType() to schematicId,
|
||||||
|
VarCharColumnType() to name,
|
||||||
|
), fieldIndex
|
||||||
|
).firstOrNull()
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun accessibleByUserTypeMap(user: SteamwarUser, type: SchematicType) =
|
||||||
|
accessibleByUserType(user, type).mapToIds()
|
||||||
|
|
||||||
|
@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()
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Deprecated("Use byId")
|
||||||
|
fun byIdAndUser(ignored: SteamwarUser, id: Int) = useDb {
|
||||||
|
findById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun parentsOfNode(user: SteamwarUser, id: Int) = fromSql(
|
||||||
|
"WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.Config FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId",
|
||||||
|
listOf(
|
||||||
|
IntegerColumnType() to id,
|
||||||
|
IntegerColumnType() to user.getId()
|
||||||
|
), fieldIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createSchematic(owner: Int, name: String, parent: Int?) = createSchematicNode(
|
||||||
|
owner, name, parent,
|
||||||
|
SchematicType.Normal.toDB(), ""
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createSchematicDirectory(owner: Int, name: String, parent: Int?) =
|
||||||
|
createSchematicNode(owner, name, parent, null, "")
|
||||||
|
|
||||||
|
@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@useDb findById(id) ?: throw IllegalStateException("SchematicNode $id not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
@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()
|
||||||
|
}
|
||||||
|
|
||||||
|
@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()
|
||||||
|
}
|
||||||
|
|
||||||
|
@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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
return byParentName(user, null, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.toMutableList() }
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() = useDb { 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!!) ?: SchematicType.Normal }
|
||||||
|
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 a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
return block()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun replaceColor() = getConfig(ConfigFlags.REPLACE_COLOR)
|
||||||
|
fun setReplaceColor(value: Boolean) = setConfig(ConfigFlags.REPLACE_COLOR, value)
|
||||||
|
|
||||||
|
fun allowReplay() = getConfig(ConfigFlags.ALLOW_REPLAY)
|
||||||
|
fun setAllowReplay(value: Boolean) = setConfig(ConfigFlags.ALLOW_REPLAY, value)
|
||||||
|
|
||||||
|
fun isPrepared() = getConfig(ConfigFlags.IS_PREPARED)
|
||||||
|
fun setPrepared(value: Boolean) = setConfig(ConfigFlags.IS_PREPARED, value)
|
||||||
|
|
||||||
|
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 and (1 shl flag.ordinal).inv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getElo(season: Int) = SchemElo.getElo(this, season)
|
||||||
|
|
||||||
|
override fun delete() = useDb {
|
||||||
|
super.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode() = nodeId
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is SchematicNode) return false
|
||||||
|
return nodeId == other.nodeId
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateBreadcrumbs(user: SteamwarUser): String {
|
||||||
|
if (!this::breadcrumbs.isInitialized) {
|
||||||
|
breadcrumbs = generateBreadcrumbs("/", user)
|
||||||
|
}
|
||||||
|
return breadcrumbs
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateBreadcrumbs(split: String, user: SteamwarUser): String = useDb {
|
||||||
|
val builder: StringBuilder = StringBuilder(name)
|
||||||
|
if (isDir()) {
|
||||||
|
builder.append(split)
|
||||||
|
}
|
||||||
|
var currentNode: SchematicNode? = this@SchematicNode
|
||||||
|
while (currentNode != null) {
|
||||||
|
currentNode = currentNode
|
||||||
|
.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@useDb builder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateBreadcrumbsMap(user: SteamwarUser): List<Pair<String, Int>> = useDb {
|
||||||
|
val map = mutableListOf<Pair<String, Int>>()
|
||||||
|
var currentNode: SchematicNode? = this@SchematicNode
|
||||||
|
while (currentNode != null) {
|
||||||
|
currentNode = currentNode
|
||||||
|
.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@useDb map
|
||||||
|
}
|
||||||
|
|
||||||
|
fun accessibleByUser(user: SteamwarUser) = schematicAccessibleForUser(user, nodeId)
|
||||||
|
|
||||||
|
enum class ConfigFlags {
|
||||||
|
REPLACE_COLOR,
|
||||||
|
ALLOW_REPLAY,
|
||||||
|
IS_PREPARED
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Removed")
|
||||||
|
var rank = 0
|
||||||
|
}
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.SqlTypeMapper;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class SchematicType {
|
|
||||||
|
|
||||||
public static final SchematicType Normal = new SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false);
|
|
||||||
|
|
||||||
private static final Map<String, SchematicType> fromDB;
|
|
||||||
private static final List<SchematicType> types;
|
|
||||||
|
|
||||||
static {
|
|
||||||
List<SchematicType> tmpTypes = new LinkedList<>();
|
|
||||||
Map<String, SchematicType> tmpFromDB = new HashMap<>();
|
|
||||||
|
|
||||||
tmpTypes.add(Normal);
|
|
||||||
tmpFromDB.put(Normal.name().toLowerCase(), Normal);
|
|
||||||
|
|
||||||
File folder = SQLWrapper.impl.getSchemTypesFolder();
|
|
||||||
if (folder.exists()) {
|
|
||||||
for (File configFile : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().collect(Collectors.toList())) {
|
|
||||||
GameModeConfig<?, String> gameModeConfig = SQLWrapper.impl.loadGameModeConfig(configFile);
|
|
||||||
if (gameModeConfig.Schematic.Type == null) continue;
|
|
||||||
if (tmpFromDB.containsKey(gameModeConfig.Schematic.Type.toDB())) continue;
|
|
||||||
SchematicType current = gameModeConfig.Schematic.Type;
|
|
||||||
if (!gameModeConfig.CheckQuestions.isEmpty()) {
|
|
||||||
SchematicType checkType = current.checkType;
|
|
||||||
tmpTypes.add(checkType);
|
|
||||||
tmpFromDB.put(checkType.toDB(), checkType);
|
|
||||||
}
|
|
||||||
tmpTypes.add(current);
|
|
||||||
tmpFromDB.put(current.toDB(), current);
|
|
||||||
SQLWrapper.impl.processSchematicType(gameModeConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fromDB = Collections.unmodifiableMap(tmpFromDB);
|
|
||||||
types = Collections.unmodifiableList(tmpTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
new SqlTypeMapper<>(SchematicType.class, "VARCHAR(16)", (rs, identifier) -> {
|
|
||||||
String t = rs.getString(identifier);
|
|
||||||
return t != null ? fromDB.get(t) : null;
|
|
||||||
}, (st, index, value) -> st.setString(index, value.toDB()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
@Getter
|
|
||||||
private final String kuerzel;
|
|
||||||
private final Type type;
|
|
||||||
private final SchematicType checkType;
|
|
||||||
@Getter
|
|
||||||
private final String material;
|
|
||||||
@Getter
|
|
||||||
private final Date deadline;
|
|
||||||
@Getter
|
|
||||||
private final boolean manualCheck;
|
|
||||||
|
|
||||||
SchematicType(String name, String kuerzel, Type type, SchematicType checkType, String material, boolean manualCheck){
|
|
||||||
this(name, kuerzel, type, checkType, material, null, manualCheck);
|
|
||||||
}
|
|
||||||
|
|
||||||
SchematicType(String name, String kuerzel, Type type, SchematicType checkType, String material, Date deadline, boolean manualCheck){
|
|
||||||
this.name = name;
|
|
||||||
this.kuerzel = kuerzel;
|
|
||||||
this.type = type;
|
|
||||||
this.checkType = checkType;
|
|
||||||
this.material = material;
|
|
||||||
this.deadline = deadline;
|
|
||||||
this.manualCheck = manualCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAssignable(){
|
|
||||||
return type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SchematicType checkType(){
|
|
||||||
if (!manualCheck) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return checkType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean check(){
|
|
||||||
return type == Type.CHECK_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean fightType(){
|
|
||||||
return type == Type.FIGHT_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean writeable(){
|
|
||||||
return type == Type.NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String name(){
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toDB(){
|
|
||||||
return name.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SchematicType fromDB(String input) {
|
|
||||||
if (fromDB == null) return null;
|
|
||||||
return fromDB.get(input.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<SchematicType> values(){
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Type{
|
|
||||||
NORMAL,
|
|
||||||
CHECK_TYPE,
|
|
||||||
FIGHT_TYPE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.Locale.getDefault
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
|
data class SchematicType(
|
||||||
|
val name: String,
|
||||||
|
val kuerzel: String,
|
||||||
|
val type: Type,
|
||||||
|
val checkType: SchematicType?,
|
||||||
|
val material: String,
|
||||||
|
val deadline: Date?,
|
||||||
|
val manualCheck: Boolean,
|
||||||
|
) {
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
kuerzel: String,
|
||||||
|
type: Type,
|
||||||
|
checkType: SchematicType?,
|
||||||
|
material: String,
|
||||||
|
manualCheck: Boolean
|
||||||
|
) : this(name, kuerzel, type, checkType, material, null, manualCheck)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmField
|
||||||
|
val Normal = SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false)
|
||||||
|
|
||||||
|
private val types: List<SchematicType>
|
||||||
|
private val fromDB: Map<String, SchematicType>?
|
||||||
|
|
||||||
|
init {
|
||||||
|
val tmpTypes = mutableListOf<SchematicType>()
|
||||||
|
val tmpFromDB = mutableMapOf<String, SchematicType>()
|
||||||
|
|
||||||
|
tmpTypes.add(Normal)
|
||||||
|
tmpFromDB[Normal.toDB()] = Normal
|
||||||
|
|
||||||
|
val folder = SQLWrapper.impl.schemTypesFolder
|
||||||
|
if (folder.exists()) {
|
||||||
|
for (configFile in Arrays.stream<File?>(folder.listFiles { _, name ->
|
||||||
|
name.endsWith(
|
||||||
|
".yml"
|
||||||
|
) && !name.endsWith(".kits.yml")
|
||||||
|
}).sorted().collect(Collectors.toList())) {
|
||||||
|
val gameModeConfig = SQLWrapper.impl.loadGameModeConfig(configFile)
|
||||||
|
if (gameModeConfig.Schematic.Type == null) continue
|
||||||
|
if (tmpFromDB.containsKey(gameModeConfig.Schematic.Type.toDB())) continue
|
||||||
|
val current = gameModeConfig.Schematic.Type
|
||||||
|
if (gameModeConfig.CheckQuestions.isNotEmpty()) {
|
||||||
|
val checkType = current.checkType
|
||||||
|
tmpTypes.add(checkType!!)
|
||||||
|
tmpFromDB[checkType.toDB()] = checkType
|
||||||
|
}
|
||||||
|
tmpTypes.add(current)
|
||||||
|
tmpFromDB[current.toDB()] = current
|
||||||
|
SQLWrapper.impl.processSchematicType(gameModeConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
types = tmpTypes.toList()
|
||||||
|
fromDB = tmpFromDB.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun values() = types
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun fromDB(value: String) = fromDB?.let { it[value.lowercase()] }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun name() = name
|
||||||
|
fun toDB() = name.lowercase()
|
||||||
|
|
||||||
|
fun check() = type == Type.CHECK_TYPE
|
||||||
|
fun fightType() = type == Type.FIGHT_TYPE
|
||||||
|
fun writeable() = type == Type.NORMAL
|
||||||
|
|
||||||
|
fun checkType() = if (manualCheck) checkType else this
|
||||||
|
fun isAssignable() = type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
NORMAL,
|
||||||
|
CHECK_TYPE,
|
||||||
|
FIGHT_TYPE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class Script {
|
|
||||||
|
|
||||||
private static final Table<Script> table = new Table<>(Script.class);
|
|
||||||
|
|
||||||
private static final SelectStatement<Script> byId = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<Script> byUserName = table.select("nameUser");
|
|
||||||
private static final SelectStatement<Script> byUser = table.selectFields("userId");
|
|
||||||
|
|
||||||
private static final Statement insert = table.insertFields(true, "userId", "name", "code");
|
|
||||||
private static final Statement updateName = table.update(Table.PRIMARY, "name");
|
|
||||||
private static final Statement updateCode = table.update(Table.PRIMARY, "code");
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
public static Script get(int id) {
|
|
||||||
return byId.select(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Script get(SteamwarUser user, String name) {
|
|
||||||
return byUserName.select(user, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Script create(SteamwarUser user, String name, String code) {
|
|
||||||
return new Script(insert.insertGetKey(user, name, code), user.getId(), name, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Script> list(SteamwarUser user) {
|
|
||||||
return byUser.listSelect(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = Table.PRIMARY, autoincrement = true)
|
|
||||||
private final int id;
|
|
||||||
@Field(keys = "nameUser")
|
|
||||||
private final int userId;
|
|
||||||
@Field(keys = "nameUser")
|
|
||||||
private String name;
|
|
||||||
@Field
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
updateName.update(name, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCode(String code) {
|
|
||||||
this.code = code;
|
|
||||||
updateCode.update(code, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
delete.update(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.v1.dao.IntEntityClass
|
||||||
|
|
||||||
|
object ScriptTable: IntIdTable("Script") {
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val name = varchar("Name", 64)
|
||||||
|
val code = text("Code")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Script(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Script>(ScriptTable) {
|
||||||
|
@JvmStatic
|
||||||
|
fun byId(id: Int) = useDb { findById(id) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun get(user: SteamwarUser, name: String) = useDb {
|
||||||
|
find { ScriptTable.userId eq user.id and (ScriptTable.name eq name) }.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun create(user: SteamwarUser, name: String, code: String) = useDb {
|
||||||
|
new {
|
||||||
|
this.userId = user.id.value
|
||||||
|
this.scriptName = name
|
||||||
|
this.scriptCode = code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun list(user: SteamwarUser) = useDb {
|
||||||
|
find { ScriptTable.userId eq user.id }.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getId() = id.value
|
||||||
|
var userId by ScriptTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
|
||||||
|
private var scriptName by ScriptTable.name
|
||||||
|
private var scriptCode by ScriptTable.code
|
||||||
|
|
||||||
|
var name: String
|
||||||
|
get() = scriptName
|
||||||
|
set(value) = useDb { scriptName = value }
|
||||||
|
|
||||||
|
var code: String
|
||||||
|
get() = scriptCode
|
||||||
|
set(value) = useDb { scriptCode = value }
|
||||||
|
|
||||||
|
override fun delete() = useDb { super.delete() }
|
||||||
|
}
|
||||||
@@ -46,14 +46,14 @@ public class Season {
|
|||||||
if (season == -1) return "";
|
if (season == -1) return "";
|
||||||
int yearSeason = season % 3;
|
int yearSeason = season % 3;
|
||||||
int year = (season - yearSeason) / 3;
|
int year = (season - yearSeason) / 3;
|
||||||
return String.format("%d-%d", year, yearSeason);
|
return String.format("%d-%d", year, yearSeason + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int convertSeasonToNumber(String season){
|
public static int convertSeasonToNumber(String season){
|
||||||
if (season.isEmpty()) return -1;
|
if (season.isEmpty()) return -1;
|
||||||
String[] split = season.split("-");
|
String[] split = season.split("-");
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(split[0]) * 3 + Integer.parseInt(split[1]);
|
return Integer.parseInt(split[0]) * 3 + Integer.parseInt(split[1]) - 1;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.sql;
|
|
||||||
|
|
||||||
import de.steamwar.sql.internal.Field;
|
|
||||||
import de.steamwar.sql.internal.Statement;
|
|
||||||
import de.steamwar.sql.internal.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class Session {
|
|
||||||
|
|
||||||
private static final Table<Session> table = new Table<>(Session.class);
|
|
||||||
private static final Statement insert = table.insert(Table.PRIMARY);
|
|
||||||
|
|
||||||
public static void insertSession(int userID, Timestamp startTime){
|
|
||||||
insert.update(userID, startTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private int userId;
|
|
||||||
@Field(keys = {Table.PRIMARY})
|
|
||||||
private Timestamp startTime;
|
|
||||||
@Field(def = "CURRENT_TIMESTAMP")
|
|
||||||
private Timestamp endTime;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql
|
||||||
|
|
||||||
|
import de.steamwar.sql.internal.useDb
|
||||||
|
import org.jetbrains.exposed.v1.core.Table
|
||||||
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.javatime.timestamp
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import java.sql.Timestamp
|
||||||
|
|
||||||
|
object SessionTable: Table("Session") {
|
||||||
|
val userId = reference("UserId", SteamwarUserTable)
|
||||||
|
val startTime = timestamp("StartTime")
|
||||||
|
val endTime = timestamp("EndTime").defaultExpression(CurrentTimestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Session {
|
||||||
|
@JvmStatic
|
||||||
|
fun insertSession(userId: Int, startTime: Timestamp) = useDb {
|
||||||
|
SessionTable.insert {
|
||||||
|
it[SessionTable.userId] = EntityID(userId, SteamwarUserTable)
|
||||||
|
it[SessionTable.startTime] = startTime.toInstant()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user