From 55adb1a05249fb81bd8441e2cf7e099f39e8e20c Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 22 Dec 2024 23:16:19 +0100 Subject: [PATCH 001/112] Improve SendCommand --- .../velocitycore/commands/SendCommand.java | 72 ++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java index a0435983..ef8131ea 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java @@ -20,6 +20,7 @@ package de.steamwar.velocitycore.commands; import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; import de.steamwar.command.PreviousArguments; @@ -33,23 +34,46 @@ import de.steamwar.velocitycore.VelocityCore; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class SendCommand extends SWCommand { + // /send from to [only ] + // /send to only [] + // can also be current + public SendCommand() { super("send", UserPerm.TEAM); } @Register - public void sendToServer(Chatter sender, Player send, RegisteredServer server) { - send.createConnectionRequest(server).fireAndForget(); + public void sendCommand(Chatter sender, @StaticValue("from") String from, RegisteredServer fromServer, @StaticValue("to") String to, RegisteredServer toServer) { + sendPlayers(toServer, fromServer.getPlayersConnected()); + } + + @Register + public void sendCommand(Chatter sender, @StaticValue("from") String from, RegisteredServer fromServer, @StaticValue("to") String to, RegisteredServer toServer, @StaticValue("only") String only, @ArrayLength(min = 1) Player... players) { + sendPlayers(toServer, List.of(players)); + } + + @Register + public void sendCommand(Chatter sender, @StaticValue("to") String to, RegisteredServer toServer, @StaticValue("only") String only, @ArrayLength(min = 1) Player... players) { + sendPlayers(toServer, List.of(players)); + } + + private void sendPlayers(RegisteredServer toServer, Collection players) { + for (Player player : players) { + player.createConnectionRequest(toServer).fireAndForget(); + } } @ClassMapper(value = RegisteredServer.class, local = true) public TypeMapper subserverTypeMapper() { return new TypeMapper<>() { private boolean check(SteamwarUser user, RegisteredServer registeredServer) { + if (registeredServer == null) return false; ServerInfo serverInfo = registeredServer.getServerInfo(); String name = serverInfo.getName(); if (name.contains(" ")) return false; @@ -66,20 +90,64 @@ public class SendCommand extends SWCommand { return registeredServer; } } + + RegisteredServer currentServer = sender.getPlayer().getCurrentServer().map(ServerConnection::getServer).orElse(null); + if (s.equals("current") && check(user, currentServer)) { + return currentServer; + } return null; } @Override public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { SteamwarUser user = sender.user(); + List previous = previousArguments.getAll(RegisteredServer.class); + List tabCompletes = new ArrayList<>(); for (RegisteredServer registeredServer : VelocityCore.getProxy().getAllServers()) { + if (previous.contains(registeredServer)) continue; if (check(user, registeredServer)) { tabCompletes.add(registeredServer.getServerInfo().getName()); } } + + Player player = sender.getPlayer(); + if (player != null) { + RegisteredServer currentServer = player.getCurrentServer().map(ServerConnection::getServer).orElse(null); + if (currentServer != null && !previous.contains(currentServer) && check(user, currentServer)) { + tabCompletes.add("current"); + } + } + return tabCompletes; } }; } + + @ClassMapper(value = Player.class, local = true) + public TypeMapper playerTypeMapper() { + return new TypeMapper<>() { + @Override + public Player map(Chatter sender, PreviousArguments previousArguments, String s) { + return VelocityCore.getProxy().getPlayer(s).orElse(null); + } + + @Override + public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { + List previous = previousArguments.getAll(RegisteredServer.class); + if (previous.isEmpty()) { + return VelocityCore.getProxy().getAllPlayers().stream().map(Player::getUsername).collect(Collectors.toList()); + } + if (previous.size() == 1) { + Collection players = previous.get(0).getPlayersConnected(); + return VelocityCore.getProxy().getAllPlayers().stream().filter(player -> !players.contains(player)).map(Player::getUsername).collect(Collectors.toList()); + } + if (previous.size() == 2) { + Collection players = previous.get(0).getPlayersConnected(); + return players.stream().map(Player::getUsername).collect(Collectors.toList()); + } + return Collections.emptyList(); + } + }; + } } From 9a8cb543e9978829e25a8988dc57afbaec48bd2f Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Tue, 7 Jan 2025 14:27:57 +0100 Subject: [PATCH 002/112] Update SendCommand --- .../velocitycore/commands/SendCommand.java | 35 +++---------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java index ef8131ea..77cd2193 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java @@ -34,13 +34,11 @@ import de.steamwar.velocitycore.VelocityCore; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; public class SendCommand extends SWCommand { - // /send from to [only ] // /send to only [] // can also be current @@ -48,22 +46,8 @@ public class SendCommand extends SWCommand { super("send", UserPerm.TEAM); } - @Register - public void sendCommand(Chatter sender, @StaticValue("from") String from, RegisteredServer fromServer, @StaticValue("to") String to, RegisteredServer toServer) { - sendPlayers(toServer, fromServer.getPlayersConnected()); - } - - @Register - public void sendCommand(Chatter sender, @StaticValue("from") String from, RegisteredServer fromServer, @StaticValue("to") String to, RegisteredServer toServer, @StaticValue("only") String only, @ArrayLength(min = 1) Player... players) { - sendPlayers(toServer, List.of(players)); - } - - @Register - public void sendCommand(Chatter sender, @StaticValue("to") String to, RegisteredServer toServer, @StaticValue("only") String only, @ArrayLength(min = 1) Player... players) { - sendPlayers(toServer, List.of(players)); - } - - private void sendPlayers(RegisteredServer toServer, Collection players) { + @Register("to") + public void sendCommand(Chatter sender, RegisteredServer toServer, @ArrayLength(min = 1) Player... players) { for (Player player : players) { player.createConnectionRequest(toServer).fireAndForget(); } @@ -135,18 +119,9 @@ public class SendCommand extends SWCommand { @Override public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { List previous = previousArguments.getAll(RegisteredServer.class); - if (previous.isEmpty()) { - return VelocityCore.getProxy().getAllPlayers().stream().map(Player::getUsername).collect(Collectors.toList()); - } - if (previous.size() == 1) { - Collection players = previous.get(0).getPlayersConnected(); - return VelocityCore.getProxy().getAllPlayers().stream().filter(player -> !players.contains(player)).map(Player::getUsername).collect(Collectors.toList()); - } - if (previous.size() == 2) { - Collection players = previous.get(0).getPlayersConnected(); - return players.stream().map(Player::getUsername).collect(Collectors.toList()); - } - return Collections.emptyList(); + if (previous.isEmpty()) return null; + Collection players = previous.get(0).getPlayersConnected(); + return VelocityCore.getProxy().getAllPlayers().stream().filter(player -> !players.contains(player)).map(Player::getUsername).collect(Collectors.toList()); } }; } From 1350be9b80e7ee82b09afcaaa164c5cd65c519f7 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Wed, 8 Jan 2025 12:02:11 +0100 Subject: [PATCH 003/112] Add new roughlyenoughitems plugin channel --- .../de/steamwar/velocitycore/listeners/PluginMessage.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java index 05e91edb..af208aed 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java @@ -137,7 +137,6 @@ public class PluginMessage extends BasicListener { "itemswapper:enableshulker", "itemswapper:enablerefill", //https://github.com/tr7zw/ItemSwapper/tree/main (Easier inventory item swapping) "jade:show_overlay", "jade:receive_data", "jade:server_ping", "jade:server_ping_v1", //https://github.com/Snownee/Jade (Information over block/entity under crosshair) "bclib:hello_client", "bclib:request_files", "bclib:send_files", "bclib:chunker", //https://github.com/quiqueck/BCLib (Library for additional dimensions) - "roughlyenoughitems:ci_msg", "roughlyenoughitems:request_tags_s2c", "roughlyenoughitems:og_not_enough", //https://github.com/shedaniel/RoughlyEnoughItems (Crafting recipe helper) "essentialclient:chunkdebug", "essentialclient:clientscript", "essentialclient:gamerule", //https://github.com/senseiwells/EssentialClient (Carpet mod extension) "couplings:server_config", //https://github.com/ChloeDawn/Couplings (Opens/closes double doors/gates simultaneously) "yigd:grave_overview_s2c", "yigd:grave_selection_s2c", "yigd:player_selection_s2c", //https://github.com/B1n-ry/Youre-in-grave-danger (Adds new block - graves) @@ -190,6 +189,10 @@ public class PluginMessage extends BasicListener { "better-suggestions:entity_scores_response", "better-suggestions:entity_tags_response", //https://github.com/shurik204/better-suggestions (Better command tab completion) "farmingforblockheads:chicken_nest_effect", "farmingforblockheads:market_categories", //https://github.com/TwelveIterationMods/FarmingForBlockheads (Improved farming with new blocks) + //https://github.com/shedaniel/RoughlyEnoughItems (Crafting recipe helper) + "roughlyenoughitems:ci_msg", "roughlyenoughitems:request_tags_s2c", "roughlyenoughitems:og_not_enough", + "roughlyenoughitems:sync_displays", + //https://modrinth.com/mod/servux "servux:structures", "servux:entity_data", "servux:hud_metadata", "servux:debug_service", "servux:tweaks", From a39f172a34ca2205291bab54ff2a6b3defe2e86b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 8 Jan 2025 12:56:51 +0100 Subject: [PATCH 004/112] Fix Schem Upload --- .../discord/listeners/DiscordSchemUpload.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordSchemUpload.java b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordSchemUpload.java index 68b8d360..4a202368 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordSchemUpload.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordSchemUpload.java @@ -31,13 +31,12 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import java.util.zip.GZIPInputStream; public class DiscordSchemUpload extends ListenerAdapter { @@ -84,7 +83,8 @@ public class DiscordSchemUpload extends ListenerAdapter { node = SchematicNode.createSchematic(user.getId(), name, null); try (InputStream in = attachment.getProxy().download().get()) { - CompoundTag tags = NBT.fromStream(new DataInputStream(in)); + byte[] bytes = in.readAllBytes(); + CompoundTag tags = NBT.fromStream(new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(bytes)))); NodeData.SchematicFormat version = NodeData.SchematicFormat.SPONGE_V2; @@ -94,7 +94,7 @@ public class DiscordSchemUpload extends ListenerAdapter { version = NodeData.SchematicFormat.MCEDIT; } - NodeData.get(node).saveFromStream(in, version); + NodeData.get(node).saveFromStream(new ByteArrayInputStream(bytes), version); sender.system("DC_SCHEMUPLOAD_SUCCESS", name); } catch (InterruptedException e) { Thread.currentThread().interrupt(); From 0f1fbc4b88d0b69c16a1420b731ef9e85d631710 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 14 Jan 2025 23:44:30 +0100 Subject: [PATCH 005/112] Test Webhook --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index b0fb3f72..ccd23880 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * Copyright (C) 2024 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 From f7c9c6d796e410495a43282c1b947438afd15fd0 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Tue, 14 Jan 2025 16:11:13 +0100 Subject: [PATCH 006/112] Fix tablist --- .../src/de/steamwar/velocitycore/tablist/Tablist.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java b/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java index 2c380a90..f15bc79c 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java +++ b/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java @@ -142,8 +142,14 @@ public class Tablist extends ChannelInboundHandlerAdapter { } public void onServerPostSwitch() { - if(player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20)) + if(player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20)) { + if(player.getProtocolVersion().greaterThan(ProtocolVersion.MINECRAFT_1_20)) { + sendTabPacket(current, null); + current.clear(); + } + sendPacket(player, createTeamPacket); + } } private void injection() { From 91d4a2dac35c049189a3d0608898ae0c3085a73d Mon Sep 17 00:00:00 2001 From: Lixfel Date: Wed, 15 Jan 2025 10:01:23 +0100 Subject: [PATCH 007/112] Changes for new Server --- VelocityCore/src/de/steamwar/velocitycore/Node.java | 6 +++--- .../src/de/steamwar/velocitycore/ServerStarter.java | 6 +++--- .../src/de/steamwar/velocitycore/ServerVersion.java | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/Node.java b/VelocityCore/src/de/steamwar/velocitycore/Node.java index 23cf808a..9c717886 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/Node.java +++ b/VelocityCore/src/de/steamwar/velocitycore/Node.java @@ -97,9 +97,9 @@ public abstract class Node { protected void constructServerstart(File directory, List cmd, String serverJar, String worldDir, String levelName, int port, String... dParams) { if (JAVA_8.contains(serverJar)) - cmd.add("/usr/lib/jvm/java-8-openj9-amd64/bin/java"); + cmd.add("/usr/lib/jvm/openj9-8/bin/java"); else - cmd.add("/usr/lib/jvm/java-21-openj9-amd64/bin/java"); + cmd.add("/usr/lib/jvm/openj9-21/bin/java"); for(String param : dParams){ cmd.add("-D" + param); @@ -113,7 +113,7 @@ public abstract class Node { cmd.add("-XX:-CRIUSecProvider"); } cmd.add("-jar"); - cmd.add("/binarys/" + serverJar); + cmd.add("/jars/" + serverJar); cmd.add("--log-strip-color"); cmd.add("--world-dir"); cmd.add(worldDir); diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index 0fbdf696..ce3b5240 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -49,10 +49,10 @@ public class ServerStarter { private static final String USER_HOME = System.getProperty("user.home") + "/"; private static final String EVENT_PATH = USER_HOME + "event/"; public static final String TEMP_WORLD_PATH = USER_HOME + "arenaserver/"; - public static final String TUTORIAL_PATH = USER_HOME + "tutorials/"; - public static final String WORLDS_BASE_PATH = USER_HOME + "userworlds"; - public static final String BUILDER_BASE_PATH = USER_HOME + "builder"; + public static final String TUTORIAL_PATH = "/worlds/tutorials/"; + public static final String WORLDS_BASE_PATH = "/worlds/userworlds"; + public static final String BUILDER_BASE_PATH = "/worlds/builder"; private File directory = null; private String worldDir = null; diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java index fd505e77..093933bc 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java @@ -41,11 +41,10 @@ public enum ServerVersion { PAPER_8("paper-1.8.8.jar", 8, ProtocolVersion.MINECRAFT_1_8), PAPER_10("paper-1.10.2.jar", 10, ProtocolVersion.MINECRAFT_1_10), PAPER_12("paper-1.12.2.jar", 12, ProtocolVersion.MINECRAFT_1_12_2), - PAPER_15("paper-1.15.2.jar", 15, ProtocolVersion.MINECRAFT_1_15_2), PAPER_18("paper-1.18.2.jar", 15, ProtocolVersion.MINECRAFT_1_18_2), PAPER_19("paper-1.19.3.jar", 19, ProtocolVersion.MINECRAFT_1_19_3), PAPER_20("paper-1.20.1.jar", 20, ProtocolVersion.MINECRAFT_1_20), - PAPER_21("paper-1.21.jar", 21, ProtocolVersion.MINECRAFT_1_21_2); + PAPER_21("paper-1.21.3.jar", 21, ProtocolVersion.MINECRAFT_1_21_2); private static final Map chatMap = new HashMap<>(); @@ -66,7 +65,7 @@ public enum ServerVersion { chatMap.put("mwg", ServerVersion.PAPER_20); chatMap.put("miniwargear", ServerVersion.PAPER_20); - chatMap.put("19", ServerVersion.PAPER_19); + /*chatMap.put("19", ServerVersion.PAPER_19); chatMap.put("1.19", ServerVersion.PAPER_19); chatMap.put("1.19.2", ServerVersion.PAPER_19); @@ -76,7 +75,7 @@ public enum ServerVersion { chatMap.put("12", ServerVersion.SPIGOT_12); chatMap.put("1.12", ServerVersion.SPIGOT_12); - chatMap.put("1.12.2", ServerVersion.SPIGOT_12); + chatMap.put("1.12.2", ServerVersion.SPIGOT_12);*/ } public static ServerVersion get(String chat) { From 2564227ec7347c3a42d6edf4596adadc6797216e Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 18:18:11 +0100 Subject: [PATCH 008/112] CI Test --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 21b9838c..011b3e37 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 From 12c2ae435deb9191139c34d6d4abb7f5bed6da8b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 18:21:44 +0100 Subject: [PATCH 009/112] CI Test --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index ccd23880..7b474b73 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 From 8e7a6a56caf9e450f3fecc4cec71388dab46423b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 18:23:57 +0100 Subject: [PATCH 010/112] buildSrc/build.gradle aktualisiert --- buildSrc/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index ff9b2587..5aa2e416 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 From 82e6aff4bb0b32cb1c51276a954b1409c0aeab7e Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 18:32:49 +0100 Subject: [PATCH 011/112] buildSrc/src/steamwar.java.gradle aktualisiert --- buildSrc/src/steamwar.java.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/steamwar.java.gradle b/buildSrc/src/steamwar.java.gradle index e68f9fda..a0da4a5f 100644 --- a/buildSrc/src/steamwar.java.gradle +++ b/buildSrc/src/steamwar.java.gradle @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 From ceff8e9cd5dc95a159bf6e346468fddd1de42865 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 21:51:09 +0100 Subject: [PATCH 012/112] BauSystem/build.gradle.kts aktualisiert --- BauSystem/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BauSystem/build.gradle.kts b/BauSystem/build.gradle.kts index 7a02ffa7..712238c8 100644 --- a/BauSystem/build.gradle.kts +++ b/BauSystem/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * Copyright (C) 2024 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 From 2d84cc8ca71609a0e380bc5cdf178a45995ed0c2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 21:54:30 +0100 Subject: [PATCH 013/112] KotlinCore/build.gradle.kts aktualisiert --- KotlinCore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KotlinCore/build.gradle.kts b/KotlinCore/build.gradle.kts index 0c610074..c3bb85b5 100644 --- a/KotlinCore/build.gradle.kts +++ b/KotlinCore/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * Copyright (C) 2024 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 From 60968283947d361b478372104653b29558ff76b2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 22:00:12 +0100 Subject: [PATCH 014/112] SchematicSystem/build.gradle.kts aktualisiert --- SchematicSystem/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SchematicSystem/build.gradle.kts b/SchematicSystem/build.gradle.kts index 2c9ef365..f9871adc 100644 --- a/SchematicSystem/build.gradle.kts +++ b/SchematicSystem/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * Copyright (C) 2024 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 From 349e36fb6b1fbb0eecc707b30a9d8883bb5f03dc Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 22:12:55 +0100 Subject: [PATCH 015/112] CommandFramework/build.gradle.kts aktualisiert --- CommandFramework/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommandFramework/build.gradle.kts b/CommandFramework/build.gradle.kts index 61fbf34e..7fcb7845 100644 --- a/CommandFramework/build.gradle.kts +++ b/CommandFramework/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * Copyright (C) 2024 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 From 393f840507e9d8463020d4d135abe02a93765129 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 22:14:39 +0100 Subject: [PATCH 016/112] BauSystem/build.gradle.kts aktualisiert --- BauSystem/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BauSystem/build.gradle.kts b/BauSystem/build.gradle.kts index 712238c8..fd4e9a56 100644 --- a/BauSystem/build.gradle.kts +++ b/BauSystem/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 From 79a0fcb3aa670bc766e040a73b17b1eca1a137c5 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 15 Jan 2025 22:20:50 +0100 Subject: [PATCH 017/112] BauSystem/build.gradle.kts aktualisiert --- BauSystem/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BauSystem/build.gradle.kts b/BauSystem/build.gradle.kts index fd4e9a56..712238c8 100644 --- a/BauSystem/build.gradle.kts +++ b/BauSystem/build.gradle.kts @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2025 SteamWar.de-Serverteam + * Copyright (C) 2024 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 From fe4e486d413009d066933c31e58d2f4c505e121e Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 16 Jan 2025 15:07:22 +0100 Subject: [PATCH 018/112] Test CI --- steamwarci.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/steamwarci.yml b/steamwarci.yml index 9e5f7f8e..8a038b62 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -2,35 +2,35 @@ build: - "./gradlew build --no-daemon" artifacts: - "/binarys/bausystem2.0.jar": "BauSystem/build/libs/BauSystem-all.jar" + "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" - "/binarys/fightsystem.jar": "FightSystem/build/libs/FightSystem-all.jar" - "/binarys/FightSystem_Standalone.jar": "FightSystem/FightSystem_Standalone/build/libs/FightSystem_Standalone-all.jar" + "/jars/FightSystem.jar": "FightSystem/build/libs/FightSystem-all.jar" + #"/binarys/FightSystem_Standalone.jar": "FightSystem/FightSystem_Standalone/build/libs/FightSystem_Standalone-all.jar" - "/binarys/kotlincore.jar": "KotlinCore/build/libs/KotlinCore-all.jar" - "/binarys/tntleague.jar": "TNTLeague/build/libs/TNTLeague.jar" + "/jars/KotlinCore.jar": "KotlinCore/build/libs/KotlinCore-all.jar" + "/jars/TNTLeague.jar": "TNTLeague/build/libs/TNTLeague.jar" - "/binarys/lobbysystem2.0.jar": "LobbySystem/build/libs/LobbySystem.jar" + "/jars/LobbySystem.jar": "LobbySystem/build/libs/LobbySystem.jar" - "/binarys/missilewars.jar": "MissileWars/build/libs/MissileWars.jar" + "/jars/MissileWars.jar": "MissileWars/build/libs/MissileWars.jar" - "/binarys/realtime.jar": "Realtime/build/libs/Realtime.jar" + "/jars/RealTime.jar": "Realtime/build/libs/Realtime.jar" - "/binarys/schematicsystem.jar": "SchematicSystem/build/libs/SchematicSystem-all.jar" + "/jars/SchematicSystem.jar": "SchematicSystem/build/libs/SchematicSystem-all.jar" - "/binarys/spigotcore.jar": "SpigotCore/build/libs/SpigotCore-all.jar" + "/jars/SpigotCore.jar": "SpigotCore/build/libs/SpigotCore-all.jar" - "/binarys/Builder.jar": "Teamserver/build/libs/Teamserver.jar" + "/jars/Builder.jar": "Teamserver/build/libs/Teamserver.jar" - "/binarys/towerrun.jar": "TowerRun/build/libs/TowerRun.jar" + "/jars/TowerRun.jar": "TowerRun/build/libs/TowerRun.jar" - "/binarys/tutorialsystem.jar": "TutorialSystem/build/libs/TutorialSystem.jar" + "/jars/TutorialSystem.jar": "TutorialSystem/build/libs/TutorialSystem.jar" - "/binarys/PersistentVelocityCore.jar": "VelocityCore/Persistent/build/libs/Persistent.jar" - "/binarys/VelocityCore.jar": "VelocityCore/build/libs/VelocityCore-all.jar" - "/binarys/deployarena.py": "VelocityCore/deployarena.py" + "/jars/PersistentVelocityCore.jar": "VelocityCore/Persistent/build/libs/Persistent.jar" + "/jars/VelocityCore.jar": "VelocityCore/build/libs/VelocityCore-all.jar" + "/usr/local/bin/deployarena.py": "VelocityCore/deployarena.py" - "/binarys/website-api.jar": "WebsiteBackend/build/libs/WebsiteBackend-all.jar" + "/jars/website-api.jar": "WebsiteBackend/build/libs/WebsiteBackend-all.jar" release: - "sudo systemctl restart api.service" From 4012426e26256d40fc224a39d5e1977fd9e70c96 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 16 Jan 2025 15:19:44 +0100 Subject: [PATCH 019/112] Test CI --- steamwarci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/steamwarci.yml b/steamwarci.yml index 8a038b62..4f4703dc 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -1,4 +1,5 @@ build: + - "printenv" - "./gradlew build --no-daemon" artifacts: From fba7fe5008d719a7c2430112d64ad7be1fc6b486 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 16 Jan 2025 15:23:17 +0100 Subject: [PATCH 020/112] Test CI --- steamwarci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/steamwarci.yml b/steamwarci.yml index 4f4703dc..1e2f6eed 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -2,6 +2,7 @@ build: - "printenv" - "./gradlew build --no-daemon" + artifacts: "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" From 429f938f1ca3ed8cf9e2c570b146c092c7847737 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 16 Jan 2025 16:26:57 +0100 Subject: [PATCH 021/112] Test CI --- steamwarci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/steamwarci.yml b/steamwarci.yml index 1e2f6eed..4f4703dc 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -2,7 +2,6 @@ build: - "printenv" - "./gradlew build --no-daemon" - artifacts: "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" From 0c815ee1d5a917874b39a9b00450b166b4653f71 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 16 Jan 2025 16:37:50 +0100 Subject: [PATCH 022/112] Test CI --- steamwarci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/steamwarci.yml b/steamwarci.yml index 4f4703dc..1e2f6eed 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -2,6 +2,7 @@ build: - "printenv" - "./gradlew build --no-daemon" + artifacts: "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" From eaae2f4009a116d8e3cc030db9e068deb8862ba5 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Fri, 17 Jan 2025 13:28:57 +0100 Subject: [PATCH 023/112] Adapt to new server, unlock old versions again --- .../de/steamwar/providers/BauServerInfo.java | 9 +----- VelocityCore/deployarena.py | 4 +-- .../steamwar/velocitycore/ServerStarter.java | 28 +++++++++++++------ .../steamwar/velocitycore/ServerVersion.java | 4 +-- .../velocitycore/commands/BauCommand.java | 2 +- .../commands/BuilderCloudCommand.java | 2 +- steamwarci.yml | 1 - 7 files changed, 26 insertions(+), 24 deletions(-) diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java index b7de60b1..ddc7839e 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java @@ -19,22 +19,15 @@ package de.steamwar.providers; -import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; -import java.util.UUID; - public class BauServerInfo { private static Integer bauOwner = null; static { try { bauOwner = Integer.parseInt(Bukkit.getWorlds().get(0).getName()); - } catch (NumberFormatException e) { - try { - bauOwner = SteamwarUser.get(UUID.fromString(Bukkit.getWorlds().get(0).getName())).getId(); - } catch (IllegalArgumentException ignored) {} - } + } catch (NumberFormatException ignored) {} } public static Integer getOwnerId() { diff --git a/VelocityCore/deployarena.py b/VelocityCore/deployarena.py index d058b8e4..2195e264 100755 --- a/VelocityCore/deployarena.py +++ b/VelocityCore/deployarena.py @@ -37,11 +37,11 @@ if __name__ == "__main__": with open(configfile, 'r') as file: gamemode = yaml.load(file) - builderworld = path.expanduser(f'~/builder{version}/{worldname}') + builderworld = path.expanduser(f'/worlds/builder{version}/{worldname}') arenaworld = f'/servers/{gamemode["Server"]["Folder"]}/arenas/{worldname}' if path.exists(arenaworld): - backupworld = path.expanduser(f'~/backup/arenas/{datetime.datetime.now()}-{worldname}-{version}.tar.xz') + backupworld = path.expanduser(f'/mnt/storage/backup/arenas/{datetime.datetime.now()}-{worldname}-{version}.tar.xz') with tarfile.open(backupworld, 'w:xz') as tar: tar.add(arenaworld, arcname=worldname) diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index ce3b5240..67567ae9 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -46,13 +46,17 @@ public class ServerStarter { private static final Portrange ARENA_PORTS = VelocityCore.MAIN_SERVER ? new Portrange(3000, 3100) : (VelocityCore.get().getConfig().isEventmode() ? new Portrange(4000, 5000) : BAU_PORTS); public static final String SERVER_PATH = "/servers/"; - private static final String USER_HOME = System.getProperty("user.home") + "/"; - private static final String EVENT_PATH = USER_HOME + "event/"; - public static final String TEMP_WORLD_PATH = USER_HOME + "arenaserver/"; - public static final String TUTORIAL_PATH = "/worlds/tutorials/"; - public static final String WORLDS_BASE_PATH = "/worlds/userworlds"; - public static final String BUILDER_BASE_PATH = "/worlds/builder"; + private static final String TMP_DATA = System.getProperty("user.home") + "/"; + private static final String EVENT_PATH = TMP_DATA + "event/"; + public static final String TEMP_WORLD_PATH = TMP_DATA + "arenaserver/"; + + private static final String WORLDS_FOLDER = "/worlds"; + public static final String TUTORIAL_PATH = WORLDS_FOLDER + "/tutorials/"; + public static final String WORLDS_BASE_PATH = WORLDS_FOLDER + "/userworlds"; + public static final String BUILDER_BASE_PATH = WORLDS_FOLDER + "/builder"; + + private static final String WORLDS_STORAGE_BASE_PATH = "/mnt/storage/worlds/userworlds"; private File directory = null; private String worldDir = null; @@ -149,15 +153,21 @@ public class ServerStarter { this.version = version; directory = version.getServerDirectory("Bau"); worldDir = version.getWorldFolder(WORLDS_BASE_PATH); - worldName = version != ServerVersion.SPIGOT_12 ? String.valueOf(SteamwarUser.get(owner).getId()) : owner.toString(); + worldName = String.valueOf(SteamwarUser.get(owner).getId()); checkpoint = true; build(owner); worldSetup = () -> { File world = new File(worldDir, worldName); - if (!world.exists()) - copyWorld(node, new File(directory, "Bauwelt").getPath(), world.getPath()); + if (!world.exists()) { + File storage = new File(version.getWorldFolder(WORLDS_STORAGE_BASE_PATH), worldName); + + if(storage.exists()) + node.execute("mv", storage.getPath(), world.getPath()); + else + copyWorld(node, new File(directory, "Bauwelt").getPath(), world.getPath()); + } }; // Send players to existing server diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java index 093933bc..cc7c9d38 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java @@ -65,7 +65,7 @@ public enum ServerVersion { chatMap.put("mwg", ServerVersion.PAPER_20); chatMap.put("miniwargear", ServerVersion.PAPER_20); - /*chatMap.put("19", ServerVersion.PAPER_19); + chatMap.put("19", ServerVersion.PAPER_19); chatMap.put("1.19", ServerVersion.PAPER_19); chatMap.put("1.19.2", ServerVersion.PAPER_19); @@ -75,7 +75,7 @@ public enum ServerVersion { chatMap.put("12", ServerVersion.SPIGOT_12); chatMap.put("1.12", ServerVersion.SPIGOT_12); - chatMap.put("1.12.2", ServerVersion.SPIGOT_12);*/ + chatMap.put("1.12.2", ServerVersion.SPIGOT_12); } public static ServerVersion get(String chat) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java index 150df3fd..710bb1be 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/BauCommand.java @@ -214,7 +214,7 @@ public class BauCommand extends SWCommand { public void delete(PlayerChatter sender, @OptionalValue(value = "", onlyUINIG = true) ServerVersion version) { SWInventory inventory = new SWInventory(sender, 9, new Message("BAU_DELETE_GUI_NAME")); inventory.addItem(0, new SWItem(new Message("BAU_DELETE_GUI_DELETE"), 10), click -> { - String world = version.getWorldFolder(ServerStarter.WORLDS_BASE_PATH) + (version != ServerVersion.SPIGOT_12 ? sender.user().getId() : sender.user().getUUID().toString()); + String world = version.getWorldFolder(ServerStarter.WORLDS_BASE_PATH) + sender.user().getId(); VelocityCore.schedule(() -> { Bauserver subserver = Bauserver.get(sender.user().getUUID()); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/BuilderCloudCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/BuilderCloudCommand.java index 4c5c115d..51c0f1bf 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/BuilderCloudCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/BuilderCloudCommand.java @@ -90,7 +90,7 @@ public class BuilderCloudCommand extends SWCommand { } VelocityCore.schedule(() -> { - VelocityCore.local.execute("/binarys/deployarena.py", arenaMode.getConfig(), Integer.toString(version.getVersionSuffix()), map); + VelocityCore.local.execute("deployarena.py", arenaMode.getConfig(), Integer.toString(version.getVersionSuffix()), map); ArenaMode.init(); sender.system("BUILDERCLOUD_DEPLOY_FINISHED"); }).schedule(); diff --git a/steamwarci.yml b/steamwarci.yml index 1e2f6eed..0fa07cde 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -1,5 +1,4 @@ build: - - "printenv" - "./gradlew build --no-daemon" From afd054103966276217285cdc28d7d5109cefe7e8 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Fri, 17 Jan 2025 13:46:02 +0100 Subject: [PATCH 024/112] Move Replays to File system --- CommonCore/SQL/src/de/steamwar/sql/Fight.java | 11 ++- .../SQL/src/de/steamwar/sql/Replay.java | 74 ------------------- .../fightsystem/record/FileSource.java | 11 ++- .../fightsystem/utils/FightStatistics.java | 9 ++- 4 files changed, 22 insertions(+), 83 deletions(-) delete mode 100644 CommonCore/SQL/src/de/steamwar/sql/Replay.java diff --git a/CommonCore/SQL/src/de/steamwar/sql/Fight.java b/CommonCore/SQL/src/de/steamwar/sql/Fight.java index efa230d2..66efbef9 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/Fight.java +++ b/CommonCore/SQL/src/de/steamwar/sql/Fight.java @@ -35,8 +35,9 @@ import java.util.stream.Collectors; public class Fight { private static final Table table = new Table<>(Fight.class); - private static final SelectStatement getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed, (SELECT COUNT(1) FROM Replay WHERE Replay.FightID = f.FightID) as ReplayAvailable 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 getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) 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 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 getPage(int page, int elementsPerPage) { List fights = getPage.listSelect(page * elementsPerPage, elementsPerPage); @@ -54,6 +55,10 @@ public class Fight { 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; @@ -80,10 +85,10 @@ public class Fight { private final int win; @Field private final String wincondition; + @Field + private final boolean replayAvailable; @Field // Virtual field for easy select private final boolean replayAllowed; - @Field // Virtual field for easy select - private final boolean replayAvailable; @Getter private final List bluePlayers = new ArrayList<>(); diff --git a/CommonCore/SQL/src/de/steamwar/sql/Replay.java b/CommonCore/SQL/src/de/steamwar/sql/Replay.java deleted file mode 100644 index a90e2392..00000000 --- a/CommonCore/SQL/src/de/steamwar/sql/Replay.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2022 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.*; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.sql.SQLException; - -@AllArgsConstructor -public class Replay { - - static { - new SqlTypeMapper<>(File.class, "BLOB", (rs, identifier) -> { - try { - File file = File.createTempFile("replay", ".replay"); - file.deleteOnExit(); - Files.copy(rs.getBinaryStream(identifier), file.toPath(), StandardCopyOption.REPLACE_EXISTING); - return file; - } catch (IOException e) { - throw new SQLException(e); - } - }, (st, index, value) -> { - try { - st.setBinaryStream(index, new FileInputStream(value)); - } catch (FileNotFoundException e) { - throw new SQLException(e); - } - }); - } - - private static final Table table = new Table<>(Replay.class); - private static final SelectStatement get = table.select(Table.PRIMARY); - - public static final Statement insert = table.insertAll(); - - public static Replay get(int fightID) { - return get.select(fightID); - } - - public static void save(int fightID, File file) { - insert.update(fightID, file); - } - - @Field(keys = {Table.PRIMARY}) - private final int fightID; - @Getter - @Field - private final File replay; -} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java index 2fcaa59e..9e1a05ea 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/FileSource.java @@ -20,15 +20,18 @@ package de.steamwar.fightsystem.record; import de.steamwar.fightsystem.Config; -import de.steamwar.sql.Replay; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.zip.GZIPInputStream; public class FileSource extends PacketSource { + public static File replayFile(int fightId) { + return new File("/mnt/storage/replays", fightId + ".replay"); + } + public static void startReplay() { if(Config.replayserver()) { try { @@ -41,7 +44,7 @@ public class FileSource extends PacketSource { if(Config.ReplayID > 0) { try { - new FileSource(Replay.get(Config.ReplayID).getReplay()); + new FileSource(replayFile(Config.ReplayID)); } catch (IOException e) { throw new SecurityException("Could not start replay", e); } @@ -49,7 +52,7 @@ public class FileSource extends PacketSource { } public FileSource(File fightFile) throws IOException { - super(new GZIPInputStream(new FileInputStream(fightFile))); + super(new GZIPInputStream(Files.newInputStream(fightFile.toPath()))); new PacketProcessor(this); } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java index 1f46a3a8..35e0fc80 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java @@ -27,23 +27,25 @@ import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightPlayer; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.record.FileRecorder; +import de.steamwar.fightsystem.record.FileSource; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.winconditions.Wincondition; import de.steamwar.network.NetworkSender; import de.steamwar.network.packets.common.FightEndsPacket; -import de.steamwar.sql.Replay; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; import lombok.Getter; import org.bukkit.Bukkit; +import java.io.IOException; import java.sql.Timestamp; import java.time.Instant; import java.util.logging.Level; import java.util.stream.Collectors; import static de.steamwar.sql.Fight.create; +import static de.steamwar.sql.Fight.markReplayAvailable; public class FightStatistics { @@ -125,7 +127,10 @@ public class FightStatistics { } try { - Replay.save(fightId, FileRecorder.getFile()); + if(!FileRecorder.getFile().renameTo(FileSource.replayFile(fightId))) + throw new IOException("Failed to move replay"); + + markReplayAvailable(fightId); } catch (Exception e) { Bukkit.getLogger().log(Level.INFO, "Failed to save replay", e); } From d42da4c90310b3a8633c5a4ba9f040e8f7412e28 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Fri, 17 Jan 2025 17:40:49 +0100 Subject: [PATCH 025/112] gradle.properties aktualisiert --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9d0945b1..e1095f30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # # This file is a part of the SteamWar software. # -# Copyright (C) 2024 SteamWar.de-Serverteam +# Copyright (C) 2024 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 From 07185d096033879d765a7ba4efb48ce08f82385a Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Fri, 17 Jan 2025 17:42:32 +0100 Subject: [PATCH 026/112] Test CI --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e1095f30..91f3a83a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # # This file is a part of the SteamWar software. # -# Copyright (C) 2024 SteamWar.de-Serverteam +# 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 From 3d78a23af18f63746765a0e2bcb0417b3043b69f Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Fri, 17 Jan 2025 17:44:07 +0100 Subject: [PATCH 027/112] Test CI --- buildSrc/src/steamwar.kotlin.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/steamwar.kotlin.gradle b/buildSrc/src/steamwar.kotlin.gradle index 03b0a99d..72e6d640 100644 --- a/buildSrc/src/steamwar.kotlin.gradle +++ b/buildSrc/src/steamwar.kotlin.gradle @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 From 21b389a99327d1dab925d81e25c2fc3e0eb20547 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Fri, 17 Jan 2025 22:28:46 +0100 Subject: [PATCH 028/112] Update Schematic Download and /webpw to new Website --- .../SQL/src/de/steamwar/sql/NodeDownload.java | 2 +- .../SQL/src/de/steamwar/sql/SteamwarUser.java | 7 ++-- .../core/events/PlayerJoinedEvent.java | 2 +- .../commands/PunishmentCommand.java | 2 +- .../commands/WebpasswordCommand.java | 35 +++++-------------- .../listeners/ConnectionListener.java | 3 +- 6 files changed, 18 insertions(+), 33 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java index b3792b63..030dbf38 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java @@ -35,7 +35,7 @@ import java.time.Instant; 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://steamwar.de/download.php?schem="; + private static final String LINK_BASE = "https://steamwar.de/schematic?code="; private static final Table table = new Table<>(NodeDownload.class); private static final Statement insert = table.insertFields("NodeId", "Link"); diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java index d5b87b6e..9906d149 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java +++ b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java @@ -122,13 +122,12 @@ public class SteamwarUser { return byDiscord.select(discordId); } - public static SteamwarUser getOrCreate(UUID uuid, String name, Consumer newPlayer, BiConsumer nameUpdate) { + public static SteamwarUser getOrCreate(UUID uuid, String name, Consumer newPlayer) { SteamwarUser user = get(uuid); if (user != null) { if (!user.userName.equals(name)) { updateName.update(name, user.id); - nameUpdate.accept(user.userName, name); user.userName = name; } @@ -359,6 +358,10 @@ public class SteamwarUser { } } + public boolean hasPassword() { + return this.password == null; + } + private byte[] generateHash(String password, byte[] salt) throws InvalidKeySpecException { PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 512); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java index 8936de9a..29b0ffd8 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java @@ -35,7 +35,7 @@ public class PlayerJoinedEvent implements Listener{ @EventHandler(priority = EventPriority.LOWEST) private void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - SteamwarUser user = Statement.productionDatabase() ? SteamwarUser.get(player.getUniqueId()) : SteamwarUser.getOrCreate(player.getUniqueId(), player.getName(), uuid -> {}, (oldName, newName) -> {}); + SteamwarUser user = Statement.productionDatabase() ? SteamwarUser.get(player.getUniqueId()) : SteamwarUser.getOrCreate(player.getUniqueId(), player.getName(), uuid -> {}); UserPerm.Prefix prefix = user.prefix(); if(prefix != UserPerm.emptyPrefix) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java index da847019..1dc8ebde 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java @@ -61,7 +61,7 @@ public class PunishmentCommand { return null; } - return SteamwarUser.getOrCreate(uuid, name, u -> {}, (o, n) -> {}); + return SteamwarUser.getOrCreate(uuid, name, u -> {}); } private static UUID getUUIDofOfflinePlayer(String playerName) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java index ff3370c8..3ab97ddf 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java @@ -21,10 +21,9 @@ package de.steamwar.velocitycore.commands; import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; +import de.steamwar.sql.SteamwarUser; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; public class WebpasswordCommand extends SWCommand { @@ -40,33 +39,15 @@ public class WebpasswordCommand extends SWCommand { return; } - ProcessBuilder pb = new ProcessBuilder("php", "/var/www/register.php", sender.user().getUserName(), password); - pb.redirectErrorStream(true); - try { - Process regProcess = pb.start(); - BufferedReader reader = new BufferedReader(new InputStreamReader(regProcess.getInputStream())); - String errorLine; - if((errorLine = reader.readLine()) != null) { - if ("updated".equals(errorLine)) { - sender.system("WEB_UPDATED"); - return; - } else { - throw new SecurityException("Could not create webaccount " + errorLine); - } - } + SteamwarUser user = sender.user(); + boolean resetPW = user.hasPassword(); + user.setPassword(password); + + if (resetPW) { + sender.system("WEB_UPDATED"); + } else { sender.system("WEB_CREATED"); - } catch (IOException e) { - throw new SecurityException("Could not create webaccount", e); - } - } - - public static void changeUsername(String oldUsername, String newUsername){ - ProcessBuilder pb = new ProcessBuilder("php", "/var/www/changename.php", oldUsername, newUsername); - try { - pb.start(); - } catch (IOException e) { - throw new SecurityException("Could not change username", e); } } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ConnectionListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ConnectionListener.java index c1a4b51d..95edeabb 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ConnectionListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ConnectionListener.java @@ -39,6 +39,7 @@ import net.kyori.adventure.text.event.ClickEvent; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.function.BiConsumer; public class ConnectionListener extends BasicListener { @@ -56,7 +57,7 @@ public class ConnectionListener extends BasicListener { if(!(subject instanceof Player player)) return perm -> Tristate.TRUE; - Set perms = SteamwarUser.getOrCreate(player.getUniqueId(), player.getUsername(), ConnectionListener::newPlayer, WebpasswordCommand::changeUsername).perms(); + Set perms = SteamwarUser.getOrCreate(player.getUniqueId(), player.getUsername(), ConnectionListener::newPlayer).perms(); if(perms.contains(UserPerm.ADMINISTRATION)) return perm -> Tristate.TRUE; else if(perms.contains(UserPerm.TEAM)) From ab4aaf782f44a7c831208829547079ba1a0c2a79 Mon Sep 17 00:00:00 2001 From: TheBreadBeard Date: Mon, 20 Jan 2025 00:42:45 +0100 Subject: [PATCH 029/112] Fix custom NPC Chats color codes for TheBreadBeard --- .../src/de/steamwar/lobby/LobbySystem.properties | 12 ++++++------ .../src/de/steamwar/lobby/LobbySystem_de.properties | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties index 275a99a8..3375de0a 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties @@ -11,12 +11,12 @@ NPC_CHAT_3 = §fBecome a part of our team by applying via our Discord server (ht NPC_CHAT_4 = §fYou can develop your own buildserver features with our Lua script system. NPC_CHAT_5 = §fThere are many secrets to discover in this lobby. ## TheBreadBeard -NPC_CHAT_3266_0 = §fI collect Alts like Infinity Stones. -NPC_CHAT_3266_1 = &fYou want my Bread? You can have it! Just look for it! I've hidden the best bakery in the world somewhere! -NPC_CHAT_3266_2 = &fHey, I am TheBreadBeard, ex- EuropSuchties Player, formerly (un)known as WarGear_Titan. -NPC_CHAT_3266_3 = &fInventor of Lactose Intolerance, the Placeholder and Infinity-Ring. All technical principles no one knows or needs. -NPC_CHAT_3266_4 = &fKnown for the Lobby-Banners, logos, spontaneous Arenas, as well as an Organizer and Moderator of many Events. -NPC_CHAT_3266_5 = &fFrom Supporter to Moderator to Builder ... Maybe the journey takes me to being a Developer next. +NPC_CHAT_3266_0 = §fI collect alts like Infinity Stones. +NPC_CHAT_3266_1 = §fYou want my Bread? You can have it! Just look for it! I've hidden the best bakery in the world somewhere! +NPC_CHAT_3266_2 = §fHey, I am TheBreadBeard, ex- EuropSuchties player, formerly (un)known as WarGear_Titan. +NPC_CHAT_3266_3 = §fInventor of Lactose Intolerance, the Placeholder and Infinity-Ring. All technical principles no one knows or needs. +NPC_CHAT_3266_4 = §fKnown for the lobby-banners, logos, spontaneous arenas, as well as an organizer and moderator of many events. +NPC_CHAT_3266_5 = §fFrom supporter to moderator to builder ... Maybe the journey takes me to being a developer next. # Portal Command PORTAL_COMMAND_LIST_HELP = §8/§7portal §elist §8- §7Lists all portals diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties index bf382639..9823f57c 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties @@ -12,11 +12,11 @@ NPC_CHAT_4 = §fDu kannst mit unserm Lua Script-System deine eigenen Bau Feature NPC_CHAT_5 = §fAuf dieser Lobby sind so einige secrets versteckt. ## TheBreadBeard NPC_CHAT_3266_0 = §fIch sammel Alts wie Infinity Stones. -NPC_CHAT_3266_1 = &fIhr wollt meine Teigwaren? Die könnt ihr haben! Sucht sie doch! Irgendwo hab ich die beste Bäckerei der Welt versteckt! -NPC_CHAT_3266_2 = &fMoin, Ich bin TheBreadBeard, ehemaliger EuropSuchties Spieler, damals (un)bekannt als WarGear_Titan. -NPC_CHAT_3266_3 = &fErfinder der Laktoseintoleranz, des Platzhalters und des Infinity-Rings. Alles Prinzipien, die keiner kennt und keiner braucht. -NPC_CHAT_3266_4 = &fBekannt für die Lobbybanner, Logos, spontane Arenen, sowie als Leiter von so manchem Event. -NPC_CHAT_3266_5 = &fVon Supporter zu Moderator zu Builder ... Vielleicht führt mich die Reise als Nächstes zum Developer. +NPC_CHAT_3266_1 = §fIhr wollt meine Teigwaren? Die könnt ihr haben! Sucht sie doch! Irgendwo hab ich die beste Bäckerei der Welt versteckt! +NPC_CHAT_3266_2 = §fMoin, Ich bin TheBreadBeard, ehemaliger EuropSuchties Spieler, damals (un)bekannt als WarGear_Titan. +NPC_CHAT_3266_3 = §fErfinder der Laktoseintoleranz, des Platzhalters und des Infinity-Rings. Alles Prinzipien, die keiner kennt und keiner braucht. +NPC_CHAT_3266_4 = §fBekannt für die Lobbybanner, Logos, spontane Arenen, sowie als Leiter von so manchem Event. +NPC_CHAT_3266_5 = §fVon Supporter zu Moderator zu Builder ... Vielleicht führt mich die Reise als Nächstes zum Developer. # Portal Command PORTAL_COMMAND_LIST_HELP = §8/§7portal §elist §8- §7Listet alle Portale auf From 658dcd024d3bfe31c1558a3109287fe4dc92499f Mon Sep 17 00:00:00 2001 From: TheBreadBeard Date: Sat, 28 Dec 2024 17:07:00 +0100 Subject: [PATCH 030/112] Add teamsOnSameLine for Arena Monochrome --- .../tntleague/config/TNTLeagueWorldConfig.kt | 3 +++ .../tntleague/events/IngameListener.kt | 20 ++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt index 7fc94826..df2dd34e 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt @@ -29,6 +29,7 @@ import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.entity.WanderingTrader import java.io.File +import kotlin.math.abs import kotlin.properties.Delegates val world by lazy { plugin.server.worlds.first()!! } @@ -56,6 +57,7 @@ object TNTLeagueWorldConfig { lateinit var blueTeam: TeamConfig lateinit var redTeam: TeamConfig lateinit var lobby: Location + var teamsOnSameLine by Delegates.notNull() lateinit var targetMaterial: Material var minHeight by Delegates.notNull() var target by Delegates.notNull() @@ -64,6 +66,7 @@ object TNTLeagueWorldConfig { try { blueTeam = TeamConfig.fromConfig(config.getConfigurationSection("blueTeam")!!) redTeam = TeamConfig.fromConfig(config.getConfigurationSection("redTeam")!!) + teamsOnSameLine = abs(blueTeam.spawnLocation.blockX - redTeam.spawnLocation.blockX) < 20 lobby = config.getWorldLocation("lobby", blueTeam.spawnLocation.clone().add(redTeam.spawnLocation).multiply(0.5)) targetMaterial = Material.matchMaterial(config.getString("targetMaterial", "IRON_BLOCK")!!)!! minHeight = config.getInt("minHeight", 0) diff --git a/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt index e48ea7e6..976e49a3 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt @@ -38,13 +38,13 @@ import org.bukkit.event.player.PlayerInteractEntityEvent import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerMoveEvent -object IngameListener: Listener { +object IngameListener : Listener { @EventHandler fun onEntityInteract(e: PlayerInteractEntityEvent) { if (e.player.gameMode == GameMode.SPECTATOR) return - if(e.rightClicked.type == EntityType.WANDERING_TRADER) { + if (e.rightClicked.type == EntityType.WANDERING_TRADER) { e.isCancelled = true e.player.openInventory(DealerInventory(e.player).getInventory()) } @@ -66,11 +66,12 @@ object IngameListener: Listener { @EventHandler fun onMove(e: PlayerMoveEvent) { - if (TNTLeagueGame.getTeam(e.player) != null) { - if (e.to.blockX >= TNTLeagueWorldConfig.lobby.blockX && e.to.blockX <= TNTLeagueWorldConfig.lobby.blockX + 1 || - e.to.blockZ >= TNTLeagueWorldConfig.lobby.blockZ && e.to.blockZ <= TNTLeagueWorldConfig.lobby.blockZ + 1) { - e.isCancelled = true - } + if (TNTLeagueGame.getTeam(e.player) == null) return + if (e.to.blockZ >= TNTLeagueWorldConfig.lobby.blockZ && e.to.blockZ <= TNTLeagueWorldConfig.lobby.blockZ + 1) { + e.isCancelled = true + } + if (!TNTLeagueWorldConfig.teamsOnSameLine && e.to.blockX >= TNTLeagueWorldConfig.lobby.blockX && e.to.blockX <= TNTLeagueWorldConfig.lobby.blockX + 1) { + e.isCancelled = true } } @@ -84,7 +85,8 @@ object IngameListener: Listener { @EventHandler fun onPickupCoins(e: PlayerAttemptPickupItemEvent) { if (e.item.itemStack.isSimilar(DealerInventory.coins)) { - TNTLeagueGame.getTeam(e.player)?.coins = e.item.itemStack.amount + (TNTLeagueGame.getTeam(e.player)?.coins ?: 0) + TNTLeagueGame.getTeam(e.player)?.coins = + e.item.itemStack.amount + (TNTLeagueGame.getTeam(e.player)?.coins ?: 0) e.item.itemStack.amount = 0 e.isCancelled = true @@ -100,7 +102,7 @@ object IngameListener: Listener { } private fun Map.filterKeysNotNull(destination: MutableMap = mutableMapOf()): Map { - this.forEach { (t, u) -> if(t != null) destination[t] = u } + this.forEach { (t, u) -> if (t != null) destination[t] = u } return destination } } \ No newline at end of file From 2192eddb8bf36e8f9ac7e364a0ed8cf4c83d5088 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 11:19:08 +0100 Subject: [PATCH 031/112] Test CI --- steamwarci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/steamwarci.yml b/steamwarci.yml index 0fa07cde..8a038b62 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -1,7 +1,6 @@ build: - "./gradlew build --no-daemon" - artifacts: "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" From 898f3c785b2e07a87e61906b00e344323ab003e3 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 11:24:56 +0100 Subject: [PATCH 032/112] Test CI --- steamwarci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/steamwarci.yml b/steamwarci.yml index 8a038b62..0fa07cde 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -1,6 +1,7 @@ build: - "./gradlew build --no-daemon" + artifacts: "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" From 3be748b92ea850e7dacbd2227335b9eee56d6123 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 11:30:05 +0100 Subject: [PATCH 033/112] Fix maven repo location --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 7b474b73..cea601bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -44,7 +44,7 @@ dependencyResolutionManagement { maven { if (isInCi) { - url = URI("file:///var/www/html/maven/") + url = URI("file:///var/www/maven/") } else { url = URI("https://steamwar.de/maven/") credentials { From 3d2cba6a286ed860e2c3714572bbe85aa272f581 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 12:19:10 +0100 Subject: [PATCH 034/112] Fix tutorials --- VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index 67567ae9..a6707c45 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -195,6 +195,7 @@ public class ServerStarter { } public ServerStarter tutorial(Player owner, Tutorial tutorial) { + version = ServerVersion.SPIGOT_15; directory = new File(SERVER_PATH, "Tutorial"); buildWithTemp(owner); tempWorld(TUTORIAL_PATH + tutorial.getTutorialId()); From 721723716e291f1cb929aa7eada436c019077230 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 12:25:55 +0100 Subject: [PATCH 035/112] Fix sign --- CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java | 3 +-- .../velocitycore/commands/WebpasswordCommand.java | 8 +------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java index 9906d149..d4bed21c 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java +++ b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java @@ -29,7 +29,6 @@ import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.sql.Timestamp; import java.util.*; -import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.logging.Level; import java.util.stream.Collectors; @@ -359,7 +358,7 @@ public class SteamwarUser { } public boolean hasPassword() { - return this.password == null; + return this.password != null; } private byte[] generateHash(String password, byte[] salt) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java index 3ab97ddf..d19dedd0 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java @@ -23,8 +23,6 @@ import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; import de.steamwar.sql.SteamwarUser; -import java.io.IOException; - public class WebpasswordCommand extends SWCommand { public WebpasswordCommand() { @@ -44,10 +42,6 @@ public class WebpasswordCommand extends SWCommand { user.setPassword(password); - if (resetPW) { - sender.system("WEB_UPDATED"); - } else { - sender.system("WEB_CREATED"); - } + sender.system(resetPW ? "WEB_UPDATED" : "WEB_CREATED"); } } From a13039bce42bf107f55523f992e72537d8fe1cec Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 12:31:27 +0100 Subject: [PATCH 036/112] Fix unignore message --- VelocityCore/src/de/steamwar/messages/BungeeCore.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index 887a73d6..d9ddc86e 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -541,7 +541,7 @@ TP_USAGE_EVENT=§8/§7tp §8[§ePlayer §7or §eteam§8] UNIGNORE_USAGE=§8/§7unignore §8[§eplayer§8] UNIGNORE_NOT_PLAYER=§cThis player does not exist! UNIGNORE_NOT_IGNORED=§cYou are not ignoring this player. -UNIGNORE_UNIGNORED=§7You ignored §e{0}§8. +UNIGNORE_UNIGNORED=§7You unignored §e{0}§8. #WebregisterCommand WEB_USAGE=§8/§7webpassword §8[§epassword§8] From 6519269d74249a00dc6b70fba6c5b054f9293a12 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 20 Jan 2025 16:07:52 +0100 Subject: [PATCH 037/112] Add bust to RatsChannel threads --- .../velocitycore/discord/DiscordBot.java | 3 +- .../velocitycore/discord/DiscordConfig.java | 2 + .../discord/channels/RatsChannel.java | 108 ++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index 10cb773f..20b8d219 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -189,7 +189,8 @@ public class DiscordBot { new DiscordTicketHandler(), new DiscordTeamEvent(), new ChannelListener(), - new DiscordSchemUpload() + new DiscordSchemUpload(), + new RatsChannel() ); commandSetup(jda.retrieveCommands().complete(), jda.updateCommands()); diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java index af930d77..60a13f88 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java @@ -56,6 +56,8 @@ public class DiscordConfig { private String ticketcategory; + private Map ratsRoleToThread; + @NoArgsConstructor public static class DiscordRole { diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java new file mode 100644 index 00000000..315d1839 --- /dev/null +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java @@ -0,0 +1,108 @@ +package de.steamwar.velocitycore.discord.channels; + +import de.steamwar.sql.SteamwarUser; +import de.steamwar.velocitycore.discord.DiscordBot; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.utils.AttachedFile; +import net.dv8tion.jda.api.utils.FileUpload; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.*; +import java.util.stream.Collectors; + +public class RatsChannel extends ListenerAdapter { + + private Map ratsChannel = new HashMap<>(); + + public RatsChannel() { + DiscordBot.getInstance().getConfig().getRatsRoleToThread().forEach((roleId, threadId) -> { + Role role = DiscordBot.getGuild().getRoleById(roleId); + if (role != null) return; + ThreadChannel threadChannel = DiscordBot.getGuild().getThreadChannelById(threadId); + if (threadChannel != null) ratsChannel.put(role, threadChannel); + ratsChannel.put(role, threadChannel); + }); + } + + @Override + public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent event) { + updateRatsChannel(event.getRoles()); + } + + @Override + public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent event) { + updateRatsChannel(event.getRoles()); + } + + private void updateRatsChannel(List roles) { + for (Role role : roles) { + if (!ratsChannel.containsKey(role)) continue; + ThreadChannel channel = ratsChannel.get(role); + + List> ratMembers = loadImages(role) + .entrySet() + .stream() + .sorted(Comparator.comparing(value -> value.getKey().getUserName())) + .collect(Collectors.toList()); + + List messages = new ArrayList<>(channel.getHistory() + .retrievePast(100) + .complete()); + // Need to reverse since they are provided from newest (0) to latest (size() - 1) + Collections.reverse(messages); + + Iterator iterator = messages.iterator(); + if (!iterator.hasNext()) { + channel.sendMessage("# Ratsmitglieder") + .queue(); + } else { + iterator.next(); + } + + for (Map.Entry entry : ratMembers) { + if (iterator.hasNext()) { + Message message = iterator.next(); + if (message.getContentRaw().startsWith("# " + entry.getKey().getUserName())) { + continue; + } + + message.editMessage("## " + entry.getKey().getUserName()) + .setAttachments(AttachedFile.fromData(entry.getValue(), entry.getKey().getUUID().toString() + ".png")) + .queue(); + } else { + channel.sendMessage("## " + entry.getKey().getUserName()) + .addFiles(FileUpload.fromData(entry.getValue(), entry.getKey().getUUID().toString() + ".png")) + .queue(); + } + } + + while (iterator.hasNext()) { + iterator.next().delete().queue(); + } + } + } + + private Map loadImages(Role role) { + Map images = new HashMap<>(); + for (Member member : DiscordBot.getGuild().getMembersWithRoles(role)) { + SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); + if (steamwarUser == null) continue; + + try { + images.put(steamwarUser, new URL("api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()).openStream()); + } catch (IOException e) { + images.put(steamwarUser, null); + } + } + return images; + } +} From 052e549606bb817f5d4355a442bd2740500f6b5c Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 16:09:40 +0100 Subject: [PATCH 038/112] Fix replay saving --- .../steamwar/fightsystem/utils/FightStatistics.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java index 35e0fc80..ae9a56ac 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightStatistics.java @@ -38,7 +38,7 @@ import de.steamwar.sql.SteamwarUser; import lombok.Getter; import org.bukkit.Bukkit; -import java.io.IOException; +import java.nio.file.Files; import java.sql.Timestamp; import java.time.Instant; import java.util.logging.Level; @@ -126,14 +126,9 @@ public class FightStatistics { Config.EventKampf.setFight(fightId); } - try { - if(!FileRecorder.getFile().renameTo(FileSource.replayFile(fightId))) - throw new IOException("Failed to move replay"); + Files.move(FileRecorder.getFile().toPath(), FileSource.replayFile(fightId).toPath()); - markReplayAvailable(fightId); - } catch (Exception e) { - Bukkit.getLogger().log(Level.INFO, "Failed to save replay", e); - } + markReplayAvailable(fightId); } catch (Exception e) { Bukkit.getLogger().log(Level.SEVERE, "Failed to save statistics", e); } From 569d5b033e4067856c3dfa5f45ded9392af76fe1 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 16:14:44 +0100 Subject: [PATCH 039/112] Fix setlocale command --- .../velocitycore/commands/SetLocaleCommand.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SetLocaleCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SetLocaleCommand.java index 689485cf..a2e66b6b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SetLocaleCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SetLocaleCommand.java @@ -19,12 +19,10 @@ package de.steamwar.velocitycore.commands; -import de.steamwar.velocitycore.network.NetworkSender; import de.steamwar.command.SWCommand; -import de.steamwar.messages.Chatter; +import de.steamwar.messages.PlayerChatter; import de.steamwar.network.packets.server.LocaleInvalidationPacket; - -import java.util.Objects; +import de.steamwar.velocitycore.network.NetworkSender; public class SetLocaleCommand extends SWCommand { @@ -33,8 +31,8 @@ public class SetLocaleCommand extends SWCommand { } @Register - public void genericCommand(Chatter sender) { - sender.user().setLocale(Objects.requireNonNull(sender.getLocale()), true); + public void genericCommand(PlayerChatter sender) { + sender.user().setLocale(sender.getPlayer().getPlayerSettings().getLocale(), true); sender.withPlayer(player -> NetworkSender.send(player, new LocaleInvalidationPacket(sender.user().getId()))); sender.system("LOCK_LOCALE_CHANGED"); } From a9660bd3251bbbed445f825997ef356211c8b712 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 16:40:45 +0100 Subject: [PATCH 040/112] Fix TNTLeague --- .../kotlin/inventory/SWInventoryHolder.kt | 60 ------------------- .../src/de/steamwar/tntleague/TNTLeague.kt | 2 + .../tntleague/events/GlobalListener.kt | 9 --- .../tntleague/events/IngameListener.kt | 2 +- .../tntleague/events/LobbyListener.kt | 5 -- .../steamwar/tntleague/game/TNTLeagueTeam.kt | 2 +- .../tntleague/inventory/CategoryInventory.kt | 6 +- .../tntleague/inventory/DealerInventory.kt | 11 ++-- 8 files changed, 14 insertions(+), 83 deletions(-) delete mode 100644 KotlinCore/src/de/steamwar/kotlin/inventory/SWInventoryHolder.kt diff --git a/KotlinCore/src/de/steamwar/kotlin/inventory/SWInventoryHolder.kt b/KotlinCore/src/de/steamwar/kotlin/inventory/SWInventoryHolder.kt deleted file mode 100644 index 3afb3183..00000000 --- a/KotlinCore/src/de/steamwar/kotlin/inventory/SWInventoryHolder.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2024 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.kotlin.inventory - -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.InventoryCloseEvent -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryHolder -import org.bukkit.inventory.ItemStack - -abstract class SWInventoryHolder: InventoryHolder { - - val _inventory: Inventory by lazy { createInventory() } - - private val callbacks = mutableMapOf Unit>() - - override fun getInventory(): Inventory = _inventory - - abstract fun createInventory(): Inventory - - open fun handleInventoryClick(event: InventoryClickEvent) { - callbacks[event.slot]?.invoke(event) - } - - fun addItem(item: ItemStack, slot: Int, callback: (event: InventoryClickEvent) -> Unit) { - _inventory.setItem(slot, item) - addCallback(slot, callback) - } - - fun addCallback(slot: Int, callback: (event: InventoryClickEvent) -> Unit) { - callbacks[slot] = callback - } - - open fun handleClose(event: InventoryCloseEvent) { } - - operator fun set(slot: Int, item: Pair Unit>) { - addItem(item.first, slot, item.second) - } - - operator fun set(slot: Int, item: ItemStack) { - addItem(item, slot) { } - } -} \ No newline at end of file diff --git a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt index 378dbfc7..fb98840a 100644 --- a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt +++ b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt @@ -19,6 +19,7 @@ package de.steamwar.tntleague +import de.steamwar.kotlin.inventory.SWInventoryHolder import de.steamwar.message.Message import de.steamwar.tntleague.command.AcceptCommand import de.steamwar.tntleague.command.InviteCommand @@ -42,6 +43,7 @@ class TNTLeague : JavaPlugin() { server.pluginManager.registerEvents(LobbyListener, this) server.pluginManager.registerEvents(GlobalListener, this) + server.pluginManager.registerEvents(SWInventoryHolder.InventoryListener, this) logger.info("TNTLeague enabled") diff --git a/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt index b01dffd9..1fbadd5a 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt @@ -66,15 +66,6 @@ object GlobalListener: Listener { e.isCancelled = true } - @EventHandler(priority = EventPriority.LOWEST) - fun onPlayerClick(e: InventoryClickEvent) { - val holder = e.inventory.getHolder(false) - if (holder is SWInventoryHolder && e.clickedInventory == holder._inventory) { - e.isCancelled = true - holder.handleInventoryClick(e) - } - } - @EventHandler(priority = EventPriority.LOWEST) fun onPlayerMove(e: PlayerMoveEvent) { if (e.to.blockY < TNTLeagueWorldConfig.minHeight) { diff --git a/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt index ca379821..95b700ef 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt @@ -44,7 +44,7 @@ object IngameListener: Listener { if(e.rightClicked.type == EntityType.WANDERING_TRADER) { e.isCancelled = true - e.player.openInventory(DealerInventory(e.player).getInventory()) + DealerInventory(e.player).open() } } diff --git a/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt index 586b0e79..bb570498 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt @@ -39,11 +39,6 @@ object LobbyListener: Listener { } } - @EventHandler(priority = EventPriority.LOWEST) - fun onPlayerQuit(e: PlayerQuitEvent) { - TNTLeagueGame.playerLeave(e.player) - } - @EventHandler fun onPlayerDamage(e: EntityDamageEvent) { e.isCancelled = true diff --git a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt index 3828d9e8..200f457e 100644 --- a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt +++ b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt @@ -128,7 +128,7 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va fun leave(player: Player) { members.remove(player) - if (TNTLeagueGame.state != TNTLeagueGame.GameState.RUNNING) { + if (TNTLeagueGame.state == TNTLeagueGame.GameState.LOBBY) { if (members.isEmpty()) { plugin.server.onlinePlayers.firstOrNull { it != player && TNTLeagueGame.getTeam(it) == null }?.run { members.add(this) diff --git a/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt b/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt index 3a23812f..dcf1d690 100644 --- a/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt +++ b/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt @@ -19,7 +19,7 @@ package de.steamwar.tntleague.inventory -import de.steamwar.kotlin.inventory.SWInventoryHolder +import de.steamwar.kotlin.KotlinInventory import de.steamwar.tntleague.config.TNTLeagueConfig import de.steamwar.tntleague.inventory.DealerInventory.Companion.buyItem import de.steamwar.tntleague.inventory.DealerInventory.Companion.itemsByCategory @@ -29,8 +29,8 @@ import org.bukkit.Bukkit import org.bukkit.entity.Player import org.bukkit.inventory.Inventory -class CategoryInventory(val player: Player, category: TNTLeagueConfig.ItemCategory): SWInventoryHolder() { - override fun createInventory(): Inventory = Bukkit.createInventory(this, 9 * 6, Component.text(message.parse("DEALER", player))) +class CategoryInventory(player: Player, category: TNTLeagueConfig.ItemCategory): KotlinInventory(player) { + override fun createInventory(): Inventory = Bukkit.createInventory(null, 9 * 6, Component.text(message.parse("DEALER", player))) init { itemsByCategory[category]!!.forEachIndexed { index, item -> diff --git a/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt b/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt index d0af0ca4..384699d1 100644 --- a/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt +++ b/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt @@ -19,8 +19,9 @@ package de.steamwar.tntleague.inventory +import de.steamwar.inventory.SWInventory import de.steamwar.inventory.SWItem -import de.steamwar.kotlin.inventory.SWInventoryHolder +import de.steamwar.kotlin.KotlinInventory import de.steamwar.tntleague.config.TNTLeagueConfig import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.message @@ -38,7 +39,9 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType import java.util.* -class DealerInventory(val player: Player): SWInventoryHolder() { +class DealerInventory(player: Player): KotlinInventory(player) { + + private val inv: SWInventory = SWInventory(player) { createInventory() } init { this[10] = SWItem(Material.REDSTONE_BLOCK, message.parse("DEALER_REDSTONE", player)).itemStack to openCategory(TNTLeagueConfig.ItemCategory.REDSTONE) @@ -51,9 +54,9 @@ class DealerInventory(val player: Player): SWInventoryHolder() { } } - private fun openCategory(cat: TNTLeagueConfig.ItemCategory): (e: InventoryClickEvent) -> Unit = { player.openInventory(CategoryInventory(player, cat).inventory) } + private fun openCategory(cat: TNTLeagueConfig.ItemCategory): (e: InventoryClickEvent) -> Unit = { CategoryInventory(player, cat).open() } - override fun createInventory(): Inventory = plugin.server.createInventory(this, 6 * 9, Component.text(message.parse("DEALER", player))) + override fun createInventory(): Inventory = plugin.server.createInventory(null, 6 * 9, Component.text(message.parse("DEALER", player))) companion object { private val priceKey = NamespacedKey(plugin, "price") From 18418cca2a54d862ba4e1f00f44f754420d01f7c Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 16:41:30 +0100 Subject: [PATCH 041/112] fixup! Fix TNTLeague --- TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt | 2 -- TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt | 4 ---- 2 files changed, 6 deletions(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt index fb98840a..378dbfc7 100644 --- a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt +++ b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt @@ -19,7 +19,6 @@ package de.steamwar.tntleague -import de.steamwar.kotlin.inventory.SWInventoryHolder import de.steamwar.message.Message import de.steamwar.tntleague.command.AcceptCommand import de.steamwar.tntleague.command.InviteCommand @@ -43,7 +42,6 @@ class TNTLeague : JavaPlugin() { server.pluginManager.registerEvents(LobbyListener, this) server.pluginManager.registerEvents(GlobalListener, this) - server.pluginManager.registerEvents(SWInventoryHolder.InventoryListener, this) logger.info("TNTLeague enabled") diff --git a/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt index 1fbadd5a..77aa9dfb 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt @@ -19,9 +19,7 @@ package de.steamwar.tntleague.events -import de.steamwar.kotlin.inventory.SWInventoryHolder import de.steamwar.message.SubMessage -import de.steamwar.tntleague.colorByTeam import de.steamwar.tntleague.config.TNTLeagueWorldConfig import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.game.TNTLeagueTeam @@ -34,9 +32,7 @@ import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.entity.PlayerDeathEvent import org.bukkit.event.inventory.CraftItemEvent -import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.player.* -import java.util.logging.Level object GlobalListener: Listener { From 747bb1055deddfb9647abdad2c7fcb60d08a3270 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 16:43:56 +0100 Subject: [PATCH 042/112] Fix TNTLeague --- .../src/de/steamwar/kotlin/KotlinInventory.kt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt diff --git a/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt b/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt new file mode 100644 index 00000000..3c5f0ae2 --- /dev/null +++ b/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt @@ -0,0 +1,43 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.kotlin + +import de.steamwar.inventory.SWInventory +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack + +abstract class KotlinInventory(val player: Player) { + + private val inv: SWInventory by lazy { SWInventory(player) { createInventory() } } + + abstract fun createInventory(): Inventory + + fun open() = inv.open() + + operator fun set(slot: Int, item: Pair Unit>) { + inv.setItemEvent(slot, item.first, item.second) + } + + operator fun set(slot: Int, item: ItemStack) { + inv.setItemEvent(slot, item) { } + } +} \ No newline at end of file From 90ebc93b140e6440e1c6bad167197c38260c34a5 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 20 Jan 2025 16:44:24 +0100 Subject: [PATCH 043/112] Add bust to RatsChannel threads --- .../velocitycore/discord/DiscordBot.java | 11 +- .../discord/channels/DiscordChannel.java | 10 +- .../discord/channels/RatsChannel.java | 123 ++++++------------ .../channels/StaticMessageChannel.java | 12 ++ 4 files changed, 68 insertions(+), 88 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index 20b8d219..1c7bfa4f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -38,6 +38,7 @@ import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.exceptions.ErrorResponseException; @@ -190,9 +191,17 @@ public class DiscordBot { new DiscordTeamEvent(), new ChannelListener(), new DiscordSchemUpload(), - new RatsChannel() + new RatsChannel.RastChannelListener() ); + config.getRatsRoleToThread().forEach((roleId, threadId) -> { + Role role = DiscordBot.getGuild().getRoleById(roleId); + if (role == null) return; + ThreadChannel threadChannel = DiscordBot.getGuild().getThreadChannelById(threadId); + if (threadChannel == null) return; + new RatsChannel(role, threadChannel); + }); + commandSetup(jda.retrieveCommands().complete(), jda.updateCommands()); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java index 35e78714..3440e1f5 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java @@ -19,11 +19,11 @@ package de.steamwar.velocitycore.discord.channels; -import de.steamwar.velocitycore.discord.DiscordBot; -import de.steamwar.velocitycore.discord.listeners.ChannelListener; import de.steamwar.messages.Chatter; import de.steamwar.messages.Message; import de.steamwar.sql.SteamwarUser; +import de.steamwar.velocitycore.discord.DiscordBot; +import de.steamwar.velocitycore.discord.listeners.ChannelListener; import lombok.AllArgsConstructor; import lombok.Getter; import net.dv8tion.jda.api.entities.User; @@ -31,7 +31,6 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; -import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; @@ -57,6 +56,11 @@ public class DiscordChannel extends Chatter.PlayerlessChatter { ChannelListener.getChannels().put(this.channel, this); } + public DiscordChannel(MessageChannel channel) { + this(SteamwarUser.get(-1), channel); + ChannelListener.getChannels().put(this.channel, this); + } + public void send(String message) { send(new MessageCreateBuilder() .setContent(message diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java index 315d1839..7f8e9e44 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java @@ -2,107 +2,62 @@ package de.steamwar.velocitycore.discord.channels; import de.steamwar.sql.SteamwarUser; import de.steamwar.velocitycore.discord.DiscordBot; +import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.AttachedFile; -import net.dv8tion.jda.api.utils.FileUpload; +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import org.jetbrains.annotations.NotNull; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.*; -import java.util.stream.Collectors; +import java.util.HashMap; +import java.util.List; +import java.util.Map; -public class RatsChannel extends ListenerAdapter { +public class RatsChannel extends StaticMessageChannel { - private Map ratsChannel = new HashMap<>(); + private static Map listener = new HashMap<>(); - public RatsChannel() { - DiscordBot.getInstance().getConfig().getRatsRoleToThread().forEach((roleId, threadId) -> { - Role role = DiscordBot.getGuild().getRoleById(roleId); - if (role != null) return; - ThreadChannel threadChannel = DiscordBot.getGuild().getThreadChannelById(threadId); - if (threadChannel != null) ratsChannel.put(role, threadChannel); - ratsChannel.put(role, threadChannel); - }); - } + public RatsChannel(Role role, ThreadChannel threadChannel) { + super(threadChannel, () -> { + MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder(); + messageCreateBuilder.setContent("# Ratsmitglieder"); - @Override - public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent event) { - updateRatsChannel(event.getRoles()); - } + for (Member member : DiscordBot.getGuild().getMembersWithRoles(role)) { + SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); + if (steamwarUser == null) continue; - @Override - public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent event) { - updateRatsChannel(event.getRoles()); - } - - private void updateRatsChannel(List roles) { - for (Role role : roles) { - if (!ratsChannel.containsKey(role)) continue; - ThreadChannel channel = ratsChannel.get(role); - - List> ratMembers = loadImages(role) - .entrySet() - .stream() - .sorted(Comparator.comparing(value -> value.getKey().getUserName())) - .collect(Collectors.toList()); - - List messages = new ArrayList<>(channel.getHistory() - .retrievePast(100) - .complete()); - // Need to reverse since they are provided from newest (0) to latest (size() - 1) - Collections.reverse(messages); - - Iterator iterator = messages.iterator(); - if (!iterator.hasNext()) { - channel.sendMessage("# Ratsmitglieder") - .queue(); - } else { - iterator.next(); + messageCreateBuilder.addEmbeds(new EmbedBuilder() + .setTitle(steamwarUser.getUserName()) + .setImage("api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()) + .build()); } - for (Map.Entry entry : ratMembers) { - if (iterator.hasNext()) { - Message message = iterator.next(); - if (message.getContentRaw().startsWith("# " + entry.getKey().getUserName())) { - continue; - } + return messageCreateBuilder; + }, genericComponentInteractionCreateEvent -> {}); - message.editMessage("## " + entry.getKey().getUserName()) - .setAttachments(AttachedFile.fromData(entry.getValue(), entry.getKey().getUUID().toString() + ".png")) - .queue(); - } else { - channel.sendMessage("## " + entry.getKey().getUserName()) - .addFiles(FileUpload.fromData(entry.getValue(), entry.getKey().getUUID().toString() + ".png")) - .queue(); + listener.put(role, this); + } + + public static class RastChannelListener extends ListenerAdapter { + @Override + public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent event) { + updateRatsChannel(event.getRoles()); + } + + @Override + public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent event) { + updateRatsChannel(event.getRoles()); + } + + private void updateRatsChannel(List roles) { + roles.forEach(role -> { + if (listener.containsKey(role)) { + listener.get(role).update(); } - } - - while (iterator.hasNext()) { - iterator.next().delete().queue(); - } + }); } } - - private Map loadImages(Role role) { - Map images = new HashMap<>(); - for (Member member : DiscordBot.getGuild().getMembersWithRoles(role)) { - SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); - if (steamwarUser == null) continue; - - try { - images.put(steamwarUser, new URL("api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()).openStream()); - } catch (IOException e) { - images.put(steamwarUser, null); - } - } - return images; - } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java index 3a165915..0db34fc8 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java @@ -21,6 +21,7 @@ package de.steamwar.velocitycore.discord.channels; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import net.dv8tion.jda.api.utils.messages.MessageEditData; @@ -55,6 +56,17 @@ public class StaticMessageChannel extends DiscordChannel { update(); } + public StaticMessageChannel(MessageChannel channel, Supplier supplier, Consumer interaction) { + super(channel); + this.supplier = supplier; + this.interaction = interaction; + + if(getChannel().getLatestMessageIdLong() != 0) + message = getChannel().getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null); + + update(); + } + public void update() { if (message == null) { getChannel().sendMessage(supplier.get().build()).queue(m -> message = m); From eacae09e4f94d69601ea345ae643440117a27452 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 16:46:53 +0100 Subject: [PATCH 044/112] Fix TNTLeague --- KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt | 5 ++--- .../src/de/steamwar/tntleague/inventory/CategoryInventory.kt | 3 ++- .../src/de/steamwar/tntleague/inventory/DealerInventory.kt | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt b/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt index 3c5f0ae2..54798c49 100644 --- a/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt +++ b/KotlinCore/src/de/steamwar/kotlin/KotlinInventory.kt @@ -22,14 +22,13 @@ package de.steamwar.kotlin import de.steamwar.inventory.SWInventory import org.bukkit.entity.Player import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack abstract class KotlinInventory(val player: Player) { - private val inv: SWInventory by lazy { SWInventory(player) { createInventory() } } + private val inv: SWInventory by lazy { createInventory() } - abstract fun createInventory(): Inventory + abstract fun createInventory(): SWInventory fun open() = inv.open() diff --git a/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt b/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt index dcf1d690..76200073 100644 --- a/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt +++ b/TNTLeague/src/de/steamwar/tntleague/inventory/CategoryInventory.kt @@ -19,6 +19,7 @@ package de.steamwar.tntleague.inventory +import de.steamwar.inventory.SWInventory import de.steamwar.kotlin.KotlinInventory import de.steamwar.tntleague.config.TNTLeagueConfig import de.steamwar.tntleague.inventory.DealerInventory.Companion.buyItem @@ -30,7 +31,7 @@ import org.bukkit.entity.Player import org.bukkit.inventory.Inventory class CategoryInventory(player: Player, category: TNTLeagueConfig.ItemCategory): KotlinInventory(player) { - override fun createInventory(): Inventory = Bukkit.createInventory(null, 9 * 6, Component.text(message.parse("DEALER", player))) + override fun createInventory() = SWInventory(player, 9 * 6, message.parse("DEALER", player)) init { itemsByCategory[category]!!.forEachIndexed { index, item -> diff --git a/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt b/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt index 384699d1..418c15fb 100644 --- a/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt +++ b/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt @@ -41,8 +41,6 @@ import java.util.* class DealerInventory(player: Player): KotlinInventory(player) { - private val inv: SWInventory = SWInventory(player) { createInventory() } - init { this[10] = SWItem(Material.REDSTONE_BLOCK, message.parse("DEALER_REDSTONE", player)).itemStack to openCategory(TNTLeagueConfig.ItemCategory.REDSTONE) this[12] = SWItem(Material.END_STONE, message.parse("DEALER_BLOCKS", player)).itemStack to openCategory(TNTLeagueConfig.ItemCategory.BLOCKS) @@ -56,7 +54,7 @@ class DealerInventory(player: Player): KotlinInventory(player) { private fun openCategory(cat: TNTLeagueConfig.ItemCategory): (e: InventoryClickEvent) -> Unit = { CategoryInventory(player, cat).open() } - override fun createInventory(): Inventory = plugin.server.createInventory(null, 6 * 9, Component.text(message.parse("DEALER", player))) + override fun createInventory() = SWInventory(player, 9 * 6, message.parse("DEALER", player)) companion object { private val priceKey = NamespacedKey(plugin, "price") From ca076f9ffd4f73b3635fb6f78a55f8746e405d98 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 16:56:10 +0100 Subject: [PATCH 045/112] Fix Schematic Download Link --- CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java index 030dbf38..71cf83f4 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java @@ -35,7 +35,7 @@ import java.time.Instant; 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://steamwar.de/schematic?code="; + private static final String LINK_BASE = "https://api.steamwar.de/download/"; private static final Table table = new Table<>(NodeDownload.class); private static final Statement insert = table.insertFields("NodeId", "Link"); From af79ef544bee2f07f4aa134409dd539f3dc8590b Mon Sep 17 00:00:00 2001 From: Lixfel Date: Mon, 20 Jan 2025 16:56:59 +0100 Subject: [PATCH 046/112] Fixes --- .../velocitycore/discord/DiscordBot.java | 17 +---- .../velocitycore/discord/DiscordConfig.java | 2 +- .../discord/channels/CouncilChannel.java | 68 +++++++++++++++++++ .../discord/channels/DiscordChannel.java | 3 +- .../discord/channels/RatsChannel.java | 63 ----------------- .../channels/StaticMessageChannel.java | 9 ++- .../discord/listeners/RoleListener.java | 38 +++++++++++ 7 files changed, 115 insertions(+), 85 deletions(-) create mode 100644 VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java delete mode 100644 VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java create mode 100644 VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index 1c7bfa4f..89167565 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -24,10 +24,7 @@ import de.steamwar.messages.Chatter; import de.steamwar.sql.Event; import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.discord.channels.*; -import de.steamwar.velocitycore.discord.listeners.ChannelListener; -import de.steamwar.velocitycore.discord.listeners.DiscordSchemUpload; -import de.steamwar.velocitycore.discord.listeners.DiscordTeamEvent; -import de.steamwar.velocitycore.discord.listeners.DiscordTicketHandler; +import de.steamwar.velocitycore.discord.listeners.*; import de.steamwar.velocitycore.discord.util.AuthManager; import lombok.Getter; import net.dv8tion.jda.api.EmbedBuilder; @@ -38,7 +35,6 @@ import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.exceptions.ErrorResponseException; @@ -166,6 +162,7 @@ public class DiscordBot { .setComponents(actionRows), DiscordTicketHandler::openTicket); eventChannel = new StaticMessageChannel(config.channel("events"), EventChannel::get); checklistChannel = new ChecklistChannel(config.channel("checklist")); + config.getCouncilThread().forEach((roleId, threadId) -> new CouncilChannel(DiscordBot.getGuild().getRoleById(roleId), DiscordBot.getGuild().getThreadChannelById(threadId))); announcementChannel = new DiscordChannel(config.channel("announcement")) { @Override @@ -191,17 +188,9 @@ public class DiscordBot { new DiscordTeamEvent(), new ChannelListener(), new DiscordSchemUpload(), - new RatsChannel.RastChannelListener() + new RoleListener() ); - config.getRatsRoleToThread().forEach((roleId, threadId) -> { - Role role = DiscordBot.getGuild().getRoleById(roleId); - if (role == null) return; - ThreadChannel threadChannel = DiscordBot.getGuild().getThreadChannelById(threadId); - if (threadChannel == null) return; - new RatsChannel(role, threadChannel); - }); - commandSetup(jda.retrieveCommands().complete(), jda.updateCommands()); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java index 60a13f88..7f201abb 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordConfig.java @@ -56,7 +56,7 @@ public class DiscordConfig { private String ticketcategory; - private Map ratsRoleToThread; + private Map councilThread; @NoArgsConstructor public static class DiscordRole { diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java new file mode 100644 index 00000000..6a949d0b --- /dev/null +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java @@ -0,0 +1,68 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.velocitycore.discord.channels; + +import de.steamwar.sql.SteamwarUser; +import de.steamwar.velocitycore.discord.DiscordBot; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CouncilChannel extends StaticMessageChannel { + + private static final Map channels = new HashMap<>(); + + public static void update(List roles) { + for(Role role : roles) { + if (channels.containsKey(role)) { + channels.get(role).update(); + } + } + } + + public CouncilChannel(Role role, ThreadChannel threadChannel) { + super(threadChannel, () -> { + MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder(); + messageCreateBuilder.setContent("# Ratsmitglieder"); + + for (Member member : DiscordBot.getGuild().getMembersWithRoles(role)) { + SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); + if (steamwarUser == null) + continue; + + messageCreateBuilder.addEmbeds(new EmbedBuilder() + .setTitle(steamwarUser.getUserName()) + .setImage("api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()) + .build()); + } + + return messageCreateBuilder; + }, event -> {}); + + channels.put(role, this); + } + +} diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java index 3440e1f5..b420f601 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java @@ -52,8 +52,7 @@ public class DiscordChannel extends Chatter.PlayerlessChatter { } public DiscordChannel(String channel) { - this(SteamwarUser.get(-1), DiscordBot.getGuild().getTextChannelById(channel)); - ChannelListener.getChannels().put(this.channel, this); + this(DiscordBot.getGuild().getTextChannelById(channel)); } public DiscordChannel(MessageChannel channel) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java deleted file mode 100644 index 7f8e9e44..00000000 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/RatsChannel.java +++ /dev/null @@ -1,63 +0,0 @@ -package de.steamwar.velocitycore.discord.channels; - -import de.steamwar.sql.SteamwarUser; -import de.steamwar.velocitycore.discord.DiscordBot; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class RatsChannel extends StaticMessageChannel { - - private static Map listener = new HashMap<>(); - - public RatsChannel(Role role, ThreadChannel threadChannel) { - super(threadChannel, () -> { - MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder(); - messageCreateBuilder.setContent("# Ratsmitglieder"); - - for (Member member : DiscordBot.getGuild().getMembersWithRoles(role)) { - SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); - if (steamwarUser == null) continue; - - messageCreateBuilder.addEmbeds(new EmbedBuilder() - .setTitle(steamwarUser.getUserName()) - .setImage("api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()) - .build()); - } - - return messageCreateBuilder; - }, genericComponentInteractionCreateEvent -> {}); - - listener.put(role, this); - } - - public static class RastChannelListener extends ListenerAdapter { - @Override - public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent event) { - updateRatsChannel(event.getRoles()); - } - - @Override - public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent event) { - updateRatsChannel(event.getRoles()); - } - - private void updateRatsChannel(List roles) { - roles.forEach(role -> { - if (listener.containsKey(role)) { - listener.get(role).update(); - } - }); - } - } -} diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java index 0db34fc8..69549d38 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java @@ -49,18 +49,17 @@ public class StaticMessageChannel extends DiscordChannel { super(channel); this.supplier = supplier; this.interaction = interaction; - - if(getChannel().getLatestMessageIdLong() != 0) - message = getChannel().getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null); - - update(); + init(); } public StaticMessageChannel(MessageChannel channel, Supplier supplier, Consumer interaction) { super(channel); this.supplier = supplier; this.interaction = interaction; + init(); + } + private void init() { if(getChannel().getLatestMessageIdLong() != 0) message = getChannel().getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null); diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java new file mode 100644 index 00000000..75063344 --- /dev/null +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java @@ -0,0 +1,38 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.velocitycore.discord.listeners; + +import de.steamwar.velocitycore.discord.channels.CouncilChannel; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.jetbrains.annotations.NotNull; + +public class RoleListener extends ListenerAdapter { + @Override + public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent event) { + CouncilChannel.update(event.getRoles()); + } + + @Override + public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent event) { + CouncilChannel.update(event.getRoles()); + } +} From 35142f108f761770f509137e5b79b4a0024d38cd Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 17:03:18 +0100 Subject: [PATCH 047/112] Update Links to new Website --- .../steamwar/messages/BungeeCore.properties | 24 +++++++++---------- .../messages/BungeeCore_de.properties | 24 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index d9ddc86e..8a9316ee 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -369,23 +369,23 @@ R_USAGE=§8/§7r §8[§eanswer§8] #RegelnCommand REGELN_RULES=§7§lRules REGELN_AS=§eAirShip §7Rules -REGELN_AS_HOVER=§7https://steamwar.de/spielmodi/airship-regelwerk/ -REGELN_AS_URL=https://steamwar.de/spielmodi/airship-regelwerk/ +REGELN_AS_HOVER=§7https://steamwar.de/en/rules/airship +REGELN_AS_URL=https://steamwar.de/en/rules/airship REGELN_MWG=§eMiniWarGear §7Rules -REGELN_MWG_HOVER=§7https://steamwar.de/spielmodi/miniwargear-regelwerk/ -REGELN_MWG_URL=https://steamwar.de/spielmodi/miniwargear-regelwerk/ +REGELN_MWG_HOVER=§7https://steamwar.de/en/rules/miniwargear +REGELN_MWG_URL=https://steamwar.de/en/rules/miniwargear REGELN_WG=§eWarGear §7Rules -REGELN_WG_HOVER=§7https://steamwar.de/spielmodi/wargear-regelwerk/ -REGELN_WG_URL=https://steamwar.de/spielmodi/wargear-regelwerk/ +REGELN_WG_HOVER=§7https://steamwar.de/en/rules/wargear +REGELN_WG_URL=https://steamwar.de/en/rules/wargear REGELN_WS=§eWarShip §7Rules -REGELN_WS_HOVER=§7https://steamwar.de/spielmodi/warship-regelwerk/ -REGELN_WS_URL=https://steamwar.de/spielmodi/warship-regelwerk/ +REGELN_WS_HOVER=§7https://steamwar.de/en/rules/warship +REGELN_WS_URL=https://steamwar.de/en/rules/warship REGELN_QG=§eQuickGear §7Rules -REGELN_QG_HOVER=§7https://steamwar.de/spielmodi/quickgear-regelwerk/ -REGELN_QG_URL=https://steamwar.de/spielmodi/quickgear-regelwerk/ +REGELN_QG_HOVER=§7https://steamwar.de/en/rules/quickgear +REGELN_QG_URL=https://steamwar.de/enrules/quickgear REGELN_CONDUCT=§eCode of conduct -REGELN_CONDUCT_HOVER=§7https://steamwar.de/verhaltensrichtlinien/ -REGELN_CONDUCT_URL=https://steamwar.de/verhaltensrichtlinien/ +REGELN_CONDUCT_HOVER=§7https://steamwar.de/en/code-of-conduct +REGELN_CONDUCT_URL=https://steamwar.de/en/code-of-conduct #ReplayCommand REPLAY_TITLE=Most recent fights diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index 364988e1..416edb77 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -350,23 +350,23 @@ R_USAGE=§8/§7r §8[§eAntwort§8] #RegelnCommand REGELN_RULES=§7§lRegelwerke REGELN_AS=§eAirShip§8-§7Regelwerk -REGELN_AS_HOVER=§7https://steamwar.de/spielmodi/airship-regelwerk/ -REGELN_AS_URL=https://steamwar.de/spielmodi/airship-regelwerk/ +REGELN_AS_HOVER=§7https://steamwar.de/regeln/airship +REGELN_AS_URL=https://steamwar.de/regeln/airship REGELN_MWG=§eMiniWarGear§8-§7Regelwerk -REGELN_MWG_HOVER=§7https://steamwar.de/spielmodi/miniwargear-regelwerk/ -REGELN_MWG_URL=https://steamwar.de/spielmodi/miniwargear-regelwerk/ +REGELN_MWG_HOVER=§7https://steamwar.de/regeln/miniwargear +REGELN_MWG_URL=https://steamwar.de/regeln/miniwargear REGELN_WG=§eWarGear§8-§7Regelwerk -REGELN_WG_HOVER=§7https://steamwar.de/spielmodi/wargear-regelwerk/ -REGELN_WG_URL=https://steamwar.de/spielmodi/wargear-regelwerk/ +REGELN_WG_HOVER=§7https://steamwar.de/regeln/wargear +REGELN_WG_URL=https://steamwar.de/regeln/wargear REGELN_WS=§eWarShip§8-§7Regelwerk -REGELN_WS_HOVER=§7https://steamwar.de/spielmodi/warship-regelwerk/ -REGELN_WS_URL=https://steamwar.de/spielmodi/warship-regelwerk/ +REGELN_WS_HOVER=§7https://steamwar.de/regeln/warship +REGELN_WS_URL=https://steamwar.de/regeln/warship REGELN_QG=§eQuickGear§8-§7Regelwerk -REGELN_QG_HOVER=§7https://steamwar.de/spielmodi/quickgear-regelwerk/ -REGELN_QG_URL=https://steamwar.de/spielmodi/quickgear-regelwerk/ +REGELN_QG_HOVER=§7https://steamwar.de/regeln/quickgear +REGELN_QG_URL=https://steamwar.de/regeln/quickgear REGELN_CONDUCT=§eVerhaltensrichtlinien -REGELN_CONDUCT_HOVER=§7https://steamwar.de/verhaltensrichtlinien/ -REGELN_CONDUCT_URL=https://steamwar.de/verhaltensrichtlinien/ +REGELN_CONDUCT_HOVER=§7https://steamwar.de/verhaltensrichtlinien +REGELN_CONDUCT_URL=https://steamwar.de/verhaltensrichtlinien #ReplayCommand REPLAY_TITLE=Letzte Kämpfe From b4accdf0a1f9e43f70d68940ebeaf4d8f9c57b0c Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 17:08:24 +0100 Subject: [PATCH 048/112] Update Links to new Website --- .../src/de/steamwar/messages/BungeeCore.properties | 9 ++------- .../src/de/steamwar/messages/BungeeCore_de.properties | 6 ------ .../de/steamwar/velocitycore/commands/RulesCommand.java | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index 8a9316ee..c9527253 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -369,23 +369,18 @@ R_USAGE=§8/§7r §8[§eanswer§8] #RegelnCommand REGELN_RULES=§7§lRules REGELN_AS=§eAirShip §7Rules -REGELN_AS_HOVER=§7https://steamwar.de/en/rules/airship REGELN_AS_URL=https://steamwar.de/en/rules/airship REGELN_MWG=§eMiniWarGear §7Rules -REGELN_MWG_HOVER=§7https://steamwar.de/en/rules/miniwargear REGELN_MWG_URL=https://steamwar.de/en/rules/miniwargear REGELN_WG=§eWarGear §7Rules -REGELN_WG_HOVER=§7https://steamwar.de/en/rules/wargear REGELN_WG_URL=https://steamwar.de/en/rules/wargear REGELN_WS=§eWarShip §7Rules -REGELN_WS_HOVER=§7https://steamwar.de/en/rules/warship REGELN_WS_URL=https://steamwar.de/en/rules/warship REGELN_QG=§eQuickGear §7Rules -REGELN_QG_HOVER=§7https://steamwar.de/en/rules/quickgear -REGELN_QG_URL=https://steamwar.de/enrules/quickgear +REGELN_QG_URL=https://steamwar.de/en/rules/quickgear REGELN_CONDUCT=§eCode of conduct -REGELN_CONDUCT_HOVER=§7https://steamwar.de/en/code-of-conduct REGELN_CONDUCT_URL=https://steamwar.de/en/code-of-conduct +URL_FORMAT=§7{0} #ReplayCommand REPLAY_TITLE=Most recent fights diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index 416edb77..c50cf682 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -350,22 +350,16 @@ R_USAGE=§8/§7r §8[§eAntwort§8] #RegelnCommand REGELN_RULES=§7§lRegelwerke REGELN_AS=§eAirShip§8-§7Regelwerk -REGELN_AS_HOVER=§7https://steamwar.de/regeln/airship REGELN_AS_URL=https://steamwar.de/regeln/airship REGELN_MWG=§eMiniWarGear§8-§7Regelwerk -REGELN_MWG_HOVER=§7https://steamwar.de/regeln/miniwargear REGELN_MWG_URL=https://steamwar.de/regeln/miniwargear REGELN_WG=§eWarGear§8-§7Regelwerk -REGELN_WG_HOVER=§7https://steamwar.de/regeln/wargear REGELN_WG_URL=https://steamwar.de/regeln/wargear REGELN_WS=§eWarShip§8-§7Regelwerk -REGELN_WS_HOVER=§7https://steamwar.de/regeln/warship REGELN_WS_URL=https://steamwar.de/regeln/warship REGELN_QG=§eQuickGear§8-§7Regelwerk -REGELN_QG_HOVER=§7https://steamwar.de/regeln/quickgear REGELN_QG_URL=https://steamwar.de/regeln/quickgear REGELN_CONDUCT=§eVerhaltensrichtlinien -REGELN_CONDUCT_HOVER=§7https://steamwar.de/verhaltensrichtlinien REGELN_CONDUCT_URL=https://steamwar.de/verhaltensrichtlinien #ReplayCommand diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/RulesCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/RulesCommand.java index cf403c4d..e379d6b1 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/RulesCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/RulesCommand.java @@ -36,6 +36,6 @@ public class RulesCommand extends SWCommand { sender.system("REGELN_RULES"); for(String ruleset : Arrays.asList("REGELN_AS", "REGELN_MWG", "REGELN_WG", "REGELN_WS", "REGELN_QG", "REGELN_CONDUCT")) - sender.prefixless(ruleset, new Message(ruleset + "_HOVER"), ClickEvent.openUrl(sender.parseToPlain(ruleset + "_URL"))); + sender.prefixless(ruleset, new Message("URL_FORMAT", sender.parseToPlain(ruleset + "_URL")), ClickEvent.openUrl(sender.parseToPlain(ruleset + "_URL"))); } } From 0ce7429151ac2e72b8ce36ddc88aac76074197f8 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 17:31:20 +0100 Subject: [PATCH 049/112] Fix Schematic Upload --- .../src/de/steamwar/routes/Schematic.kt | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index c4d76f80..e0b220de 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -19,14 +19,11 @@ package de.steamwar.routes +import de.steamwar.ResponseError import de.steamwar.plugins.SWAuthPrincipal import de.steamwar.plugins.SWPermissionCheck -import de.steamwar.sql.NodeData +import de.steamwar.sql.* import de.steamwar.sql.NodeData.SchematicFormat -import de.steamwar.sql.NodeDownload -import de.steamwar.sql.NodeMember -import de.steamwar.sql.SWException -import de.steamwar.sql.SchematicNode import dev.dewy.nbt.Nbt import dev.dewy.nbt.tags.collection.CompoundTag import io.ktor.http.* @@ -36,12 +33,15 @@ import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.serialization.Serializable -import kotlinx.serialization.decodeFromByteArray +import java.io.BufferedInputStream +import java.io.ByteArrayInputStream +import java.io.DataInputStream import java.security.MessageDigest import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit import java.util.* +import java.util.zip.GZIPInputStream @Serializable data class ResponseSchematic(val name: String, val id: Int, val type: String?, val owner: Int, val item: String, val lastUpdate: Long, val rank: Int, val replaceColor: Boolean, val allowReplay: Boolean) { @@ -109,10 +109,20 @@ fun Route.configureSchematic() { post { val file = call.receive() val schemName = file.name.substringBeforeLast(".") + + if (SchematicNode.invalidSchemName(arrayOf(schemName))) { + call.respond(HttpStatusCode.BadRequest, ResponseError( + error = "INVALID_NAME" + )) + return@post + } + val schemType = file.name.substringAfterLast(".") if (schemType != "schem" && schemType != "schematic") { - call.respond(HttpStatusCode.BadRequest) + call.respond(HttpStatusCode.BadRequest, ResponseError( + error = "INVALID_SUFFIX" + )) return@post } @@ -126,7 +136,7 @@ fun Route.configureSchematic() { try { val content = Base64.getDecoder().decode(file.content) - var schem = nbt.fromByteArray(content) + var schem = nbt.fromStream(DataInputStream(BufferedInputStream(GZIPInputStream(ByteArrayInputStream(content))))) if (schem.size() == 1) schem = schem.first() as CompoundTag @@ -144,7 +154,9 @@ fun Route.configureSchematic() { call.respond(ResponseSchematic(node)) } catch (e: Exception) { - call.respond(HttpStatusCode.BadRequest) + call.respond(HttpStatusCode.BadRequest, ResponseError( + error = e.message ?: "GENERIC", code = "UPLOAD_ERROR" + )) } } } From 8da9a3cfbb098f30f77c6b8f670d4caa49f0860a Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 17:38:32 +0100 Subject: [PATCH 050/112] Fix Schematic Upload --- WebsiteBackend/src/de/steamwar/routes/Schematic.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index e0b220de..02f12243 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -128,15 +128,15 @@ fun Route.configureSchematic() { val user = call.principal()!!.user - var node = SchematicNode.getSchematicNode(user.id, schemName, 0) + var node = SchematicNode.getSchematicNode(user.id, schemName, null as Int?) if (node == null) { - node = SchematicNode.createSchematic(user.id, schemName, 0) + node = SchematicNode.createSchematic(user.id, schemName, null) } try { val content = Base64.getDecoder().decode(file.content) - var schem = nbt.fromStream(DataInputStream(BufferedInputStream(GZIPInputStream(ByteArrayInputStream(content))))) + var schem = nbt.fromStream(DataInputStream(BufferedInputStream(GZIPInputStream(content.inputStream())))) if (schem.size() == 1) schem = schem.first() as CompoundTag From 3fadeb77519984103fda39073da32bb930a7995b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 20 Jan 2025 19:09:29 +0100 Subject: [PATCH 051/112] Disable Logs --- WebsiteBackend/src/de/steamwar/plugins/Auth.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WebsiteBackend/src/de/steamwar/plugins/Auth.kt b/WebsiteBackend/src/de/steamwar/plugins/Auth.kt index cc5c0822..eeca85ee 100644 --- a/WebsiteBackend/src/de/steamwar/plugins/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/plugins/Auth.kt @@ -104,6 +104,7 @@ Message: ${cause.message} call.response.headers.append("X-Caught", "1") } + /* onCallRespond { call -> if ((call.response.status() ?: HttpStatusCode.OK).isSuccess()) { return@onCallRespond @@ -125,5 +126,5 @@ Message: ${cause.message} """.trimIndent() SWException.log(msg, stack) - } + }*/ } \ No newline at end of file From 7f7f84a4c48757b3fc0fd79f3fc9201464e05a3c Mon Sep 17 00:00:00 2001 From: Lixfel Date: Tue, 21 Jan 2025 00:03:39 +0100 Subject: [PATCH 052/112] Fix CouncilChannel, unloading issues --- .../src/de/steamwar/velocitycore/VelocityCore.java | 12 +++++++++++- .../de/steamwar/velocitycore/discord/DiscordBot.java | 2 +- .../discord/channels/CouncilChannel.java | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java b/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java index 5e6dca1d..3cec098b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java +++ b/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java @@ -252,7 +252,17 @@ public class VelocityCore implements ReloadablePlugin { @Override public void onProxyShutdown(ProxyShutdownEvent event) { try { - DiscordBot.withBot(bot -> bot.getJda().shutdownNow()); + DiscordBot.withBot(bot -> { + bot.getJda().shutdownNow(); + bot.getJda().getHttpClient().connectionPool().evictAll(); + bot.getJda().getHttpClient().dispatcher().executorService().shutdown(); + try { + if(!bot.getJda().awaitShutdown(1, TimeUnit.SECONDS)) + logger.log(Level.SEVERE, "Could not await discord bot shutdown"); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); } catch (Throwable e) { logger.log(Level.SEVERE, "Could not shutdown discord bot", e); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index 89167565..d2f7419a 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -97,7 +97,7 @@ public class DiscordBot { .createDefault(config.getToken()) .setStatus(OnlineStatus.ONLINE) .setMemberCachePolicy(MemberCachePolicy.ONLINE) - .enableIntents(GatewayIntent.MESSAGE_CONTENT) + .enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.MESSAGE_CONTENT) .build(); instance = this; diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java index 6a949d0b..7c86c1b0 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java @@ -48,7 +48,7 @@ public class CouncilChannel extends StaticMessageChannel { MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder(); messageCreateBuilder.setContent("# Ratsmitglieder"); - for (Member member : DiscordBot.getGuild().getMembersWithRoles(role)) { + for (Member member : DiscordBot.getGuild().findMembersWithRoles(role).get()) { SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); if (steamwarUser == null) continue; From 364911e4496e382174132ea910f9a027803aef51 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Tue, 21 Jan 2025 08:09:11 +0100 Subject: [PATCH 053/112] Fix CouncilChannel URL --- .../steamwar/velocitycore/discord/channels/CouncilChannel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java index 7c86c1b0..c4af706f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java @@ -55,7 +55,7 @@ public class CouncilChannel extends StaticMessageChannel { messageCreateBuilder.addEmbeds(new EmbedBuilder() .setTitle(steamwarUser.getUserName()) - .setImage("api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()) + .setImage("https://api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()) .build()); } From 6541c34cc896406af0687f56d382d544a9daa121 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Tue, 21 Jan 2025 16:53:17 +0100 Subject: [PATCH 054/112] Update CouncilChannel --- .../discord/channels/CouncilChannel.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java index c4af706f..7ac28228 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java @@ -21,15 +21,15 @@ package de.steamwar.velocitycore.discord.channels; import de.steamwar.sql.SteamwarUser; import de.steamwar.velocitycore.discord.DiscordBot; +import it.unimi.dsi.fastutil.Pair; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; public class CouncilChannel extends StaticMessageChannel { @@ -48,16 +48,21 @@ public class CouncilChannel extends StaticMessageChannel { MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder(); messageCreateBuilder.setContent("# Ratsmitglieder"); - for (Member member : DiscordBot.getGuild().findMembersWithRoles(role).get()) { - SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); - if (steamwarUser == null) - continue; - - messageCreateBuilder.addEmbeds(new EmbedBuilder() - .setTitle(steamwarUser.getUserName()) - .setImage("https://api.steamwar.de/data/skin/" + steamwarUser.getUUID().toString()) - .build()); - } + DiscordBot.getGuild().findMembersWithRoles(role).get() + .stream() + .map(member -> { + SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); + String name = steamwarUser == null ? member.getEffectiveName() : steamwarUser.getUserName(); + UUID uuid = steamwarUser == null ? null : steamwarUser.getUUID(); + return Pair.of(name, uuid); + }) + .sorted(Comparator.comparing(Pair::key)) + .forEach(pair -> { + messageCreateBuilder.addEmbeds(new EmbedBuilder() + .setTitle(pair.key()) + .setImage(pair.value() == null ? null : "https://api.steamwar.de/data/skin/" + pair.value().toString()) + .build()); + }); return messageCreateBuilder; }, event -> {}); From e83878a49b2ad4df6cd628bd576a430b3e9b745a Mon Sep 17 00:00:00 2001 From: Lixfel Date: Wed, 22 Jan 2025 09:29:20 +0100 Subject: [PATCH 055/112] Remove ViaVersion requirement from dev servers --- .../steamwar/velocitycore/ServerVersion.java | 11 +++++++ .../velocitycore/commands/DevCommand.java | 31 ++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java index cc7c9d38..a5e08b55 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java @@ -86,6 +86,17 @@ public enum ServerVersion { return chatMap.keySet(); } + private static final Map versionMap = new HashMap<>(); + + static { + for(ServerVersion version : values()) + versionMap.put(version.getVersionSuffix(), version); + } + + public static ServerVersion get(int version) { + return versionMap.get(version); + } + private final String serverJar; private final int versionSuffix; private final ProtocolVersion protocolVersion; diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java index e24432cc..71b4427c 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java @@ -21,18 +21,21 @@ package de.steamwar.velocitycore.commands; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; -import de.steamwar.messages.Chatter; -import de.steamwar.messages.Message; -import de.steamwar.sql.UserPerm; -import de.steamwar.velocitycore.ArenaMode; -import de.steamwar.velocitycore.VelocityCore; +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.velocity.platform.VelocityViaConfig; import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommandUtils; import de.steamwar.command.TypeMapper; import de.steamwar.command.TypeValidator; +import de.steamwar.messages.Chatter; +import de.steamwar.messages.Message; import de.steamwar.messages.PlayerChatter; import de.steamwar.sql.Punishment; import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.UserPerm; +import de.steamwar.velocitycore.ArenaMode; +import de.steamwar.velocitycore.ServerVersion; +import de.steamwar.velocitycore.VelocityCore; import lombok.Getter; import java.io.File; @@ -113,28 +116,32 @@ public class DevCommand extends SWCommand { private void updateDevServers() { String[] serverFiles = devServerDir.list(); - Map devServerFiles = new HashMap<>(); + Map devServerPorts = new HashMap<>(); + Map devServerVersions = new HashMap<>(); if (serverFiles != null) { for (String serverFile : serverFiles) { String[] server = serverFile.split("\\."); - devServerFiles.put(server[0], Integer.parseInt(server[1])); + devServerPorts.put(server[0], Integer.parseInt(server[1])); + devServerVersions.put(server[0], Integer.parseInt(server[2])); } } devServers.entrySet().removeIf(entry -> { - if (!devServerFiles.containsKey(entry.getKey())) { + if (!devServerPorts.containsKey(entry.getKey())) { VelocityCore.getProxy().unregisterServer(entry.getValue().getServerInfo()); return true; } return false; }); - devServerFiles.forEach((key, value) -> { - if (devServers.containsKey(key)) + devServerPorts.forEach((username, value) -> { + if (devServers.containsKey(username)) return; - SteamwarUser user = SteamwarUser.get(key); - devServers.put(user.getUserName().toLowerCase(), VelocityCore.getProxy().registerServer(new ServerInfo("Dev " + user.getUserName(), new InetSocketAddress("127.0.0.1", value)))); + SteamwarUser user = SteamwarUser.get(username); + String name = "Dev " + user.getUserName(); + ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols().put(name, ServerVersion.get(devServerVersions.get(username)).getProtocolVersion().getProtocol()); + devServers.put(user.getUserName().toLowerCase(), VelocityCore.getProxy().registerServer(new ServerInfo(name, new InetSocketAddress("127.0.0.1", value)))); }); } } From de591b7a5f7040cc6164fe4dfba20437664478de Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Wed, 22 Jan 2025 09:39:10 +0100 Subject: [PATCH 056/112] Update CouncilChannel --- .../discord/channels/CouncilChannel.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java index 7ac28228..16a42be1 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java @@ -20,6 +20,7 @@ package de.steamwar.velocitycore.discord.channels; import de.steamwar.sql.SteamwarUser; +import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.discord.DiscordBot; import it.unimi.dsi.fastutil.Pair; import net.dv8tion.jda.api.EmbedBuilder; @@ -29,6 +30,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class CouncilChannel extends StaticMessageChannel { @@ -36,11 +38,12 @@ public class CouncilChannel extends StaticMessageChannel { private static final Map channels = new HashMap<>(); public static void update(List roles) { - for(Role role : roles) { - if (channels.containsKey(role)) { - channels.get(role).update(); - } - } + VelocityCore.schedule(() -> { + roles.stream() + .filter(channels::containsKey) + .map(channels::get) + .forEach(CouncilChannel::update); + }).delay(1, TimeUnit.SECONDS); } public CouncilChannel(Role role, ThreadChannel threadChannel) { From aa5fcd38114d8f79fa62cb427d3d94c2700d78a3 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Wed, 22 Jan 2025 19:52:16 +0100 Subject: [PATCH 057/112] Update CouncilChannel every hour --- .../velocitycore/discord/DiscordBot.java | 16 ++++++-- .../discord/channels/CouncilChannel.java | 23 ++++------- .../discord/listeners/RoleListener.java | 38 ------------------- 3 files changed, 21 insertions(+), 56 deletions(-) delete mode 100644 VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index d2f7419a..2dd455ab 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -24,7 +24,10 @@ import de.steamwar.messages.Chatter; import de.steamwar.sql.Event; import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.discord.channels.*; -import de.steamwar.velocitycore.discord.listeners.*; +import de.steamwar.velocitycore.discord.listeners.ChannelListener; +import de.steamwar.velocitycore.discord.listeners.DiscordSchemUpload; +import de.steamwar.velocitycore.discord.listeners.DiscordTeamEvent; +import de.steamwar.velocitycore.discord.listeners.DiscordTicketHandler; import de.steamwar.velocitycore.discord.util.AuthManager; import lombok.Getter; import net.dv8tion.jda.api.EmbedBuilder; @@ -183,12 +186,19 @@ public class DiscordBot { } }).repeat(30, TimeUnit.SECONDS).schedule(); + VelocityCore.schedule(() -> { + try { + CouncilChannel.updateAll(); + } catch (ErrorResponseException e) { + //ignored + } + }).repeat(1, TimeUnit.HOURS).schedule(); + jda.addEventListener( new DiscordTicketHandler(), new DiscordTeamEvent(), new ChannelListener(), - new DiscordSchemUpload(), - new RoleListener() + new DiscordSchemUpload() ); commandSetup(jda.retrieveCommands().complete(), jda.updateCommands()); diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java index 16a42be1..e5129f24 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/CouncilChannel.java @@ -20,30 +20,24 @@ package de.steamwar.velocitycore.discord.channels; import de.steamwar.sql.SteamwarUser; -import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.discord.DiscordBot; import it.unimi.dsi.fastutil.Pair; import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; public class CouncilChannel extends StaticMessageChannel { - private static final Map channels = new HashMap<>(); + private static final Set channels = new HashSet<>(); - public static void update(List roles) { - VelocityCore.schedule(() -> { - roles.stream() - .filter(channels::containsKey) - .map(channels::get) - .forEach(CouncilChannel::update); - }).delay(1, TimeUnit.SECONDS); + public static void updateAll() { + channels.forEach(StaticMessageChannel::update); } public CouncilChannel(Role role, ThreadChannel threadChannel) { @@ -70,7 +64,6 @@ public class CouncilChannel extends StaticMessageChannel { return messageCreateBuilder; }, event -> {}); - channels.put(role, this); + channels.add(this); } - } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java deleted file mode 100644 index 75063344..00000000 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/RoleListener.java +++ /dev/null @@ -1,38 +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 . - */ - -package de.steamwar.velocitycore.discord.listeners; - -import de.steamwar.velocitycore.discord.channels.CouncilChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import org.jetbrains.annotations.NotNull; - -public class RoleListener extends ListenerAdapter { - @Override - public void onGuildMemberRoleAdd(@NotNull GuildMemberRoleAddEvent event) { - CouncilChannel.update(event.getRoles()); - } - - @Override - public void onGuildMemberRoleRemove(@NotNull GuildMemberRoleRemoveEvent event) { - CouncilChannel.update(event.getRoles()); - } -} From aa01fde5a053cbc5c4cc0501caa3938751df71e0 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 23 Jan 2025 18:21:44 +0100 Subject: [PATCH 058/112] Fix locale --- CommonCore/SQL/src/de/steamwar/sql/internal/Statement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/internal/Statement.java b/CommonCore/SQL/src/de/steamwar/sql/internal/Statement.java index 3d6a49b2..2621da6b 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/internal/Statement.java +++ b/CommonCore/SQL/src/de/steamwar/sql/internal/Statement.java @@ -62,7 +62,7 @@ public class Statement implements AutoCloseable { String user = properties.getProperty("user"); String password = properties.getProperty("password"); - PRODUCTION_DATABASE = "core".equals(properties.getProperty("database")); + PRODUCTION_DATABASE = "production".equals(properties.getProperty("database")); MAX_CONNECTIONS = SQLConfig.impl.maxConnections(); conProvider = () -> { try { From 4db5c50b0685c4021d6a7fd496da598c3ef0220f Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Fri, 24 Jan 2025 08:21:47 +0100 Subject: [PATCH 059/112] Fix PR stuff --- .../src/de/steamwar/velocitycore/discord/DiscordBot.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index 2dd455ab..ecdc5a53 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -186,13 +186,7 @@ public class DiscordBot { } }).repeat(30, TimeUnit.SECONDS).schedule(); - VelocityCore.schedule(() -> { - try { - CouncilChannel.updateAll(); - } catch (ErrorResponseException e) { - //ignored - } - }).repeat(1, TimeUnit.HOURS).schedule(); + VelocityCore.schedule(CouncilChannel::updateAll).repeat(1, TimeUnit.HOURS).schedule(); jda.addEventListener( new DiscordTicketHandler(), From 71362bc07916f165475edbd9e6009fd0da37c072 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 26 Jan 2025 00:22:50 +0100 Subject: [PATCH 060/112] Hotfix: API Download is decompressed --- CommonCore/SQL/src/de/steamwar/sql/NodeData.java | 10 +++++++++- WebsiteBackend/src/de/steamwar/routes/Schematic.kt | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java b/CommonCore/SQL/src/de/steamwar/sql/NodeData.java index 0de6c6c5..a8d7c099 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeData.java @@ -65,6 +65,10 @@ public class NodeData { 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(); @@ -73,7 +77,11 @@ public class NodeData { if(rs.wasNull() || schemData.available() == 0) { throw new SecurityException("SchemData is null"); } - return new GZIPInputStream(schemData); + if (decompress) { + return new GZIPInputStream(schemData); + } else { + return schemData; + } } catch (IOException e) { throw new SecurityException("SchemData is wrong", e); } diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index 02f12243..1beb0f29 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -95,7 +95,7 @@ fun Route.configureSchematic() { } call.response.header("Content-Disposition", "attachment; filename=\"${node.name}${data.nodeFormat.fileEnding}\"") - call.respondBytes(data.schemData().readAllBytes(), contentType = ContentType.Application.OctetStream, status = HttpStatusCode.OK) + call.respondBytes(data.schemData(false).readAllBytes(), contentType = ContentType.Application.OctetStream, status = HttpStatusCode.OK) } get("/info") { val node = call.receiveSchematic() ?: return@get From dbf59df173263f6292304b0bb0b832c52e743abf Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 26 Jan 2025 10:13:36 +0100 Subject: [PATCH 061/112] Fix Gitea Backend --- WebsiteBackend/src/de/steamwar/routes/Page.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/Page.kt b/WebsiteBackend/src/de/steamwar/routes/Page.kt index 9b28ddd5..6f9a9fc4 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Page.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Page.kt @@ -108,7 +108,7 @@ fun Route.configurePage() { json() } defaultRequest { - url("https://steamwar.de/devlabs/api/v1/") + url("https://git.steamwar.de/api/v1/") header("Authorization", "token " + config.giteaToken) } } From 02b63687bcf6961dfb7a4e111f2fbf8df8969add Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 29 Jan 2025 18:38:38 +0100 Subject: [PATCH 062/112] Fix Event Create --- CommonCore/SQL/src/de/steamwar/sql/Event.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/Event.java b/CommonCore/SQL/src/de/steamwar/sql/Event.java index a92cc9f2..5a4477bf 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/Event.java +++ b/CommonCore/SQL/src/de/steamwar/sql/Event.java @@ -64,7 +64,7 @@ public class Event { } public static Event create(String eventName, Timestamp start, Timestamp end){ - return get(create.insertGetKey(eventName, start, start, end, 5, false, false)); + return get(create.insertGetKey(eventName, start, start, end, 5, false)); } public static Event get(int eventID){ From b3ddc048303b4870fc8bdac4ce0bfd90133af1e9 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Wed, 29 Jan 2025 19:12:45 +0100 Subject: [PATCH 063/112] Fix Add Referee --- WebsiteBackend/src/de/steamwar/routes/Events.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt index 4b4c6206..d1edcf07 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Events.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt @@ -32,6 +32,7 @@ import kotlinx.serialization.Serializable import java.lang.StringBuilder import java.sql.Timestamp import java.time.Instant +import java.util.* @Serializable data class ShortEvent(val id: Int, val name: String, val start: Long, val end: Long) { @@ -82,8 +83,8 @@ data class UpdateEvent( val maxTeamMembers: Int? = null, val schemType: String? = null, val publicSchemsOnly: Boolean? = null, - val addReferee: Set? = null, - val removeReferee: Set? = null, + val addReferee: Set? = null, + val removeReferee: Set? = null, ) fun Route.configureEventsRoute() { @@ -204,13 +205,13 @@ fun Route.configureEventsRoute() { if (updateEvent.addReferee != null) { updateEvent.addReferee.forEach { - Referee.add(event.eventID, it) + Referee.add(event.eventID, SteamwarUser.get(UUID.fromString(it)).id) } } if (updateEvent.removeReferee != null) { updateEvent.removeReferee.forEach { - Referee.remove(event.eventID, it) + Referee.remove(event.eventID, SteamwarUser.get(UUID.fromString(it)).id) } } event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly) From 3d153d49b52b162fdfacf3d5537d5fe3c433ef8f Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 1 Feb 2025 21:50:36 +0100 Subject: [PATCH 064/112] Make TNTLeague Event System Capable --- .../src/de/steamwar/message/Message.java | 7 +- .../src/de/steamwar/message/SubMessage.java | 29 +++++--- .../tntleague/command/InviteCommand.kt | 7 +- .../tntleague/config/TNTLeagueConfig.kt | 33 +++++++++ .../tntleague/config/TNTLeagueWorldConfig.kt | 41 ++---------- .../steamwar/tntleague/config/TeamConfig.kt | 67 +++++++++++++++++++ .../tntleague/events/GlobalListener.kt | 6 +- .../steamwar/tntleague/game/TNTLeagueGame.kt | 30 +++++++-- .../steamwar/tntleague/game/TNTLeagueTeam.kt | 37 +++++----- .../tntleague/util/TNTLeagueScoreboard.kt | 4 +- 10 files changed, 182 insertions(+), 79 deletions(-) create mode 100644 TNTLeague/src/de/steamwar/tntleague/config/TeamConfig.kt diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java index b9ae84b7..f953ce8d 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java @@ -72,9 +72,12 @@ public class Message { pattern += fromRB(resourceBundle, message); for (int i = 0; i < params.length; i++) { - if (params[i] instanceof SubMessage) { - SubMessage smsg = (SubMessage) params[i]; + if (params[i] instanceof SubMessage.Translatable) { + SubMessage.Translatable smsg = (SubMessage.Translatable) params[i]; params[i] = parse(smsg.getMessage(), sender, smsg.getParams()); + } else if (params[i] instanceof SubMessage.Literal) { + SubMessage.Literal smsg = (SubMessage.Literal) params[i]; + params[i] = smsg.getMessage(); } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java index e40b74a5..4c302689 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java @@ -19,20 +19,33 @@ package de.steamwar.message; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter -public class SubMessage { +@AllArgsConstructor +public abstract class SubMessage { private final String message; - private final Object[] params; - public SubMessage(String message, Object... params) { - this.message = message; - this.params = params; + @Getter + public static class Translatable extends SubMessage { + private final Object[] params; + + public Translatable(String message, Object... params) { + super(message); + this.params = params; + } + + public Translatable(String message) { + super(message); + this.params = new Object[0]; + } } - public SubMessage(String message) { - this.message = message; - this.params = new Object[0]; + @Getter + public static class Literal extends SubMessage { + public Literal(String message) { + super(message); + } } } diff --git a/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt b/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt index 8ecf50cb..e89e3443 100644 --- a/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt +++ b/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt @@ -21,8 +21,8 @@ package de.steamwar.tntleague.command import de.steamwar.command.SWCommand import de.steamwar.command.TypeValidator -import de.steamwar.message.SubMessage import de.steamwar.tntleague.colorByTeam +import de.steamwar.tntleague.config.TNTLeagueConfig import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.message import net.md_5.bungee.api.chat.ClickEvent @@ -32,6 +32,7 @@ object InviteCommand: SWCommand("invite") { @Register fun invitePlayer(@Validator("isLeader") sender: Player, target: Player) { + if (TNTLeagueConfig.isEvent()) return if (TNTLeagueGame.state != TNTLeagueGame.GameState.LOBBY) return if (TNTLeagueGame.getTeam(target) != null) return @@ -39,8 +40,8 @@ object InviteCommand: SWCommand("invite") { team.invites.add(target) message - .send("INVITED", target, message.parse("INVITED_HOVER", target, SubMessage(team.name)), - ClickEvent(ClickEvent.Action.RUN_COMMAND, "/accept " + sender.name), sender.name.colorByTeam(team), SubMessage(team.name), ) + .send("INVITED", target, message.parse("INVITED_HOVER", target, team.name), + ClickEvent(ClickEvent.Action.RUN_COMMAND, "/accept " + sender.name), sender.name.colorByTeam(team), team.name) message.send("INVITED_PLAYER", sender, target.name) } diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index e4677a4e..e5bccb08 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -19,6 +19,10 @@ package de.steamwar.tntleague.config +import de.steamwar.message.SubMessage +import de.steamwar.sql.Event +import de.steamwar.sql.EventFight +import de.steamwar.sql.Team import de.steamwar.tntleague.plugin import org.bukkit.Material import org.bukkit.configuration.ConfigurationSection @@ -36,7 +40,34 @@ data class TNTLeagueConfig( val blueLeader: UUID? = System.getProperty("blueLeader")?.let { UUID.fromString(it) }, val redLeader: UUID? = System.getProperty("redLeader")?.let { UUID.fromString(it) }, + + val eventFightId: Int? = System.getProperty("fightID")?.toInt() ) { + lateinit var eventFight: EventFight + lateinit var event: Event + lateinit var eventTeamBlue: Team + lateinit var eventTeamRed: Team + + val blueTeam: TeamConfig + val redTeam: TeamConfig + + init { + if (eventFightId != null) { + eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") + + event = Event.get(eventFight.eventID) + + eventTeamBlue = Team.get(eventFight.teamBlue) + eventTeamRed = Team.get(eventFight.teamRed) + + blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage.Literal("§${eventTeamBlue.teamColor}${eventTeamBlue.teamName}"), eventTeamBlue.teamColor[0]) + redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage.Literal("§${eventTeamRed.teamColor}${eventTeamRed.teamName}"), eventTeamRed.teamColor[0]) + } else { + blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage.Translatable("BLUE"), '3') + redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage.Translatable("RED"), 'c') + } + } + companion object { val config: TNTLeagueConfig by lazy { loadConfig(plugin.config) } @@ -55,6 +86,8 @@ data class TNTLeagueConfig( ) }.mapKeys { Material.getMaterial(it.key) ?: Material.BARRIER } } + + fun isEvent() = config.eventFightId != null } data class Price( diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt index df2dd34e..01667abd 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueWorldConfig.kt @@ -54,8 +54,8 @@ object TNTLeagueWorldConfig { ) } - lateinit var blueTeam: TeamConfig - lateinit var redTeam: TeamConfig + lateinit var blueTeam: TeamWorldConfig + lateinit var redTeam: TeamWorldConfig lateinit var lobby: Location var teamsOnSameLine by Delegates.notNull() lateinit var targetMaterial: Material @@ -64,8 +64,8 @@ object TNTLeagueWorldConfig { init { try { - blueTeam = TeamConfig.fromConfig(config.getConfigurationSection("blueTeam")!!) - redTeam = TeamConfig.fromConfig(config.getConfigurationSection("redTeam")!!) + blueTeam = TeamWorldConfig.fromConfig(config.getConfigurationSection("blueTeam")!!) + redTeam = TeamWorldConfig.fromConfig(config.getConfigurationSection("redTeam")!!) teamsOnSameLine = abs(blueTeam.spawnLocation.blockX - redTeam.spawnLocation.blockX) < 20 lobby = config.getWorldLocation("lobby", blueTeam.spawnLocation.clone().add(redTeam.spawnLocation).multiply(0.5)) targetMaterial = Material.matchMaterial(config.getString("targetMaterial", "IRON_BLOCK")!!)!! @@ -76,39 +76,6 @@ object TNTLeagueWorldConfig { Bukkit.shutdown() } } - - @JvmRecord - data class TeamConfig( - val spawnLocation: Location, - val dealerSpawn: Location, - val itemSpawn: Location, - val target: Area - ) { - companion object { - fun fromConfig(config: ConfigurationSection): TeamConfig { - val spawnLocation = config.getWorldLocation("spawn") - val dealerSpawn = config.getWorldLocation("dealerSpawn") - val itemSpawn = config.getWorldLocation("itemSpawn") - val targetPos1 = config.getWorldLocation("targetMin") - val targetPos2 = config.getWorldLocation("targetMax") - - spawnDealer(dealerSpawn) - - return TeamConfig(spawnLocation, dealerSpawn, itemSpawn, Area(targetPos1, targetPos2)) - } - - private fun spawnDealer(loc: Location) = world.spawn(loc, WanderingTrader::class.java) - .apply { - customName(Component.text("Shop")) - isCustomNameVisible = false - isInvulnerable = true - isSilent = true - isCollidable = false - isAware = false - setAI(false) - } - } - } } fun ConfigurationSection.getWorldLocation(s: String, default: Location? = null): Location { diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TeamConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TeamConfig.kt new file mode 100644 index 00000000..61cb3431 --- /dev/null +++ b/TNTLeague/src/de/steamwar/tntleague/config/TeamConfig.kt @@ -0,0 +1,67 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.tntleague.config + +import de.steamwar.kotlin.util.Area +import de.steamwar.message.SubMessage +import net.kyori.adventure.text.Component +import org.bukkit.Location +import org.bukkit.configuration.ConfigurationSection +import org.bukkit.entity.WanderingTrader + +data class TeamConfig( + val worldConfig: TeamWorldConfig, + + val name: SubMessage, + val color: Char +) + +@JvmRecord +data class TeamWorldConfig( + val spawnLocation: Location, + val dealerSpawn: Location, + val itemSpawn: Location, + val target: Area +) { + companion object { + fun fromConfig(config: ConfigurationSection): TeamWorldConfig { + val spawnLocation = config.getWorldLocation("spawn") + val dealerSpawn = config.getWorldLocation("dealerSpawn") + val itemSpawn = config.getWorldLocation("itemSpawn") + val targetPos1 = config.getWorldLocation("targetMin") + val targetPos2 = config.getWorldLocation("targetMax") + + spawnDealer(dealerSpawn) + + return TeamWorldConfig(spawnLocation, dealerSpawn, itemSpawn, Area(targetPos1, targetPos2)) + } + + private fun spawnDealer(loc: Location) = world.spawn(loc, WanderingTrader::class.java) + .apply { + customName(Component.text("Shop")) + isCustomNameVisible = false + isInvulnerable = true + isSilent = true + isCollidable = false + isAware = false + setAI(false) + } + } +} diff --git a/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt index 77aa9dfb..60f921fc 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/GlobalListener.kt @@ -66,7 +66,7 @@ object GlobalListener: Listener { fun onPlayerMove(e: PlayerMoveEvent) { if (e.to.blockY < TNTLeagueWorldConfig.minHeight) { when (val team = TNTLeagueGame.getTeam(e.player)) { - is TNTLeagueTeam -> e.player.teleport(team.config.spawnLocation) + is TNTLeagueTeam -> e.player.teleport(team.config.worldConfig.spawnLocation) null -> e.player.teleport(TNTLeagueWorldConfig.blueTeam.spawnLocation) } } @@ -87,7 +87,7 @@ object GlobalListener: Listener { @EventHandler fun onPlayerRespawn(e: PlayerRespawnEvent) { when (val team = TNTLeagueGame.getTeam(e.player)) { - is TNTLeagueTeam -> e.respawnLocation = team.config.spawnLocation + is TNTLeagueTeam -> e.respawnLocation = team.config.worldConfig.spawnLocation null -> e.respawnLocation = TNTLeagueWorldConfig.lobby } } @@ -100,7 +100,7 @@ object GlobalListener: Listener { val fightTeam = TNTLeagueGame.getTeam(player) if (fightTeam != null) { - message.broadcastPrefixless("PARTICIPANT_CHAT", SubMessage(fightTeam.name), player.name, msg) + message.broadcastPrefixless("PARTICIPANT_CHAT", fightTeam.name, player.name, msg) } else { message.broadcastPrefixless("SPECTATOR_CHAT", player.name, msg) } diff --git a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt index e064a350..80c86314 100644 --- a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt +++ b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt @@ -64,8 +64,8 @@ object TNTLeagueGame { var gameTimeRemaining: Int = TNTLeagueConfig.config.gameTime - val blueTeam = TNTLeagueTeam(TNTLeagueWorldConfig.blueTeam, TNTLeagueTeam.Team.BLUE) - val redTeam = TNTLeagueTeam(TNTLeagueWorldConfig.redTeam, TNTLeagueTeam.Team.RED) + val blueTeam = TNTLeagueTeam(TNTLeagueConfig.config.blueTeam) + val redTeam = TNTLeagueTeam(TNTLeagueConfig.config.redTeam) private lateinit var start: Timestamp @@ -156,10 +156,18 @@ object TNTLeagueGame { fun getTeam(player: Player) = if (player in blueTeam.members) blueTeam else if (player in redTeam.members) redTeam else null - fun getFreeTeam(player: Player) = if (blueTeam.leader == null && (TNTLeagueConfig.config.blueLeader == null || player.uniqueId == TNTLeagueConfig.config.blueLeader)) blueTeam + fun getFreeTeam(player: Player) = if (TNTLeagueConfig.isEvent()) getEventFreeTeam(player) else getNormalFreeTeam(player) + + private fun getNormalFreeTeam(player: Player) = if (blueTeam.leader == null && (TNTLeagueConfig.config.blueLeader == null || player.uniqueId == TNTLeagueConfig.config.blueLeader)) blueTeam else if (redTeam.leader == null && TNTLeagueConfig.config.redLeader == null || player.uniqueId == TNTLeagueConfig.config.redLeader) redTeam else null + private fun getEventFreeTeam(player: Player) = SteamwarUser.get(player.uniqueId).let { user -> + if (user.team == TNTLeagueConfig.config.eventTeamBlue.teamId && blueTeam.members.size < TNTLeagueConfig.config.event.maximumTeamMembers) blueTeam + else if (user.team == TNTLeagueConfig.config.eventTeamRed.teamId && redTeam.members.size < TNTLeagueConfig.config.event.maximumTeamMembers) redTeam + else null + } + fun checkStart() { if (blueTeam.isReady && redTeam.isReady) { blueTeam.leader?.inventory?.clear() @@ -209,18 +217,26 @@ object TNTLeagueGame { fun win(tntLeagueTeam: TNTLeagueTeam, reason: WinReason) { if (state != GameState.RUNNING) return end() - plugin.server.onlinePlayers.forEach { message.send("TEAM_WIN", it, SubMessage(tntLeagueTeam.name)) } + plugin.server.onlinePlayers.forEach { message.send("TEAM_WIN", it, tntLeagueTeam.name) } explode(tntLeagueTeam.opposite) + + if (TNTLeagueConfig.isEvent()) { + TNTLeagueConfig.config.eventFight.ergebnis = tntLeagueTeam.ergebnisInt + } } fun draw(reason: WinReason) { if (state != GameState.RUNNING) return end() message.broadcast("DRAW") + + if (TNTLeagueConfig.isEvent()) { + TNTLeagueConfig.config.eventFight.ergebnis = 3 + } } fun explode(team: TNTLeagueTeam) { - Area(team.config.spawnLocation.clone().add(20.0, 30.0, 20.0), team.config.spawnLocation.clone().subtract(20.0, 0.0, 20.0).add(0.0, 30.0, 0.0)) + Area(team.config.worldConfig.spawnLocation.clone().add(20.0, 30.0, 20.0), team.config.worldConfig.spawnLocation.clone().subtract(20.0, 0.0, 20.0).add(0.0, 30.0, 0.0)) .locations .filterIndexed { index, _ -> index % 7 == 0 } .forEachIndexed { index, location -> @@ -235,8 +251,8 @@ object TNTLeagueGame { plugin.server.worlds.first().name, "TNTLeague", "", - blueTeam.name.colorByTeam(blueTeam), - redTeam.name.colorByTeam(redTeam), + blueTeam.name.message.colorByTeam(blueTeam), + redTeam.name.message.colorByTeam(redTeam), state.lobbyName, TNTLeagueConfig.config.gameTime - gameTimeRemaining, blueTeam.leader?.let { SteamwarUser.get(it.uniqueId).id } ?: 0, diff --git a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt index 200f457e..773c4a46 100644 --- a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt +++ b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt @@ -22,6 +22,7 @@ package de.steamwar.tntleague.game import de.steamwar.message.SubMessage import de.steamwar.tntleague.colorByTeam import de.steamwar.tntleague.config.TNTLeagueWorldConfig +import de.steamwar.tntleague.config.TeamConfig import de.steamwar.tntleague.config.targetedBlocks import de.steamwar.tntleague.game.TNTLeagueGame.WinReason import de.steamwar.tntleague.game.TNTLeagueGame.updateFightinfo @@ -32,11 +33,10 @@ import net.kyori.adventure.text.Component import org.bukkit.GameMode import org.bukkit.Material import org.bukkit.Sound -import org.bukkit.enchantments.Enchantment import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private val team: Team) { +data class TNTLeagueTeam(val config: TeamConfig) { var leader: Player? = null set(player) { @@ -52,11 +52,11 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va val members = mutableListOf() val invites = mutableListOf() - val name: String - get() = team.name.uppercase() + val name: SubMessage + get() = config.name val color: Char - get() = team.color + get() = config.color var isReady: Boolean = false set(value) { @@ -64,7 +64,7 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va leader?.inventory?.setItem(4, readyItem()) leader?.let { it.playSound(it.location, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f) } - message.broadcastActionbar(if (value) "IS_READY" else "IS_NOT_READY", SubMessage(name)) + message.broadcastActionbar(if (value) "IS_READY" else "IS_NOT_READY", name) if (value && opposite.isReady) { TNTLeagueGame.checkStart() @@ -82,19 +82,27 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va var coins: Int = 0 val opposite: TNTLeagueTeam - get() = when (team) { - Team.BLUE -> TNTLeagueGame.redTeam - Team.RED -> TNTLeagueGame.blueTeam + get() = when (this) { + TNTLeagueGame.redTeam -> TNTLeagueGame.blueTeam + TNTLeagueGame.blueTeam -> TNTLeagueGame.redTeam + else -> error("Invalid Team") + } + + val ergebnisInt: Int + get() = when (this) { + TNTLeagueGame.redTeam -> 2 + TNTLeagueGame.blueTeam -> 3 + else -> error("Invalid Team") } fun join(player: Player): Boolean { members.add(player) with(player) { - teleport(config.spawnLocation) + teleport(config.worldConfig.spawnLocation) gameMode = GameMode.ADVENTURE inventory.clear() - message.broadcast("JOIN_TEAM", name.colorByTeam(this@TNTLeagueTeam), SubMessage(this@TNTLeagueTeam.name)) + message.broadcast("JOIN_TEAM", name.colorByTeam(this@TNTLeagueTeam), this@TNTLeagueTeam.name) } if (leader == null) { @@ -154,13 +162,8 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va teleport(TNTLeagueWorldConfig.lobby) gameMode = GameMode.SPECTATOR inventory.clear() - message.broadcast("QUIT_TEAM", name.colorByTeam(this@TNTLeagueTeam), SubMessage(this@TNTLeagueTeam.name)) + message.broadcast("QUIT_TEAM", name.colorByTeam(this@TNTLeagueTeam), this@TNTLeagueTeam.name) } updateFightinfo() } - - enum class Team(val color: Char) { - BLUE('3'), - RED('c'); - } } \ No newline at end of file diff --git a/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt b/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt index 77ba1d48..204680d0 100644 --- a/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt +++ b/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt @@ -50,10 +50,10 @@ data class TNTLeagueScoreboard(val p: Player): ScoreboardCallback { lines.add("§3") with(TNTLeagueGame.redTeam) { - lines.add(message.parse("SCOREBOARD_TEAM", p, SubMessage(name), targetedBlocks - damagedBlocks)) + lines.add(message.parse("SCOREBOARD_TEAM", p, name, targetedBlocks - damagedBlocks)) } with(TNTLeagueGame.blueTeam) { - lines.add(message.parse("SCOREBOARD_TEAM", p, SubMessage(name), targetedBlocks - damagedBlocks)) + lines.add(message.parse("SCOREBOARD_TEAM", p, name, targetedBlocks - damagedBlocks)) } lines.add("§4") From 482282f913cceb3011b6e6fd7b258630880d40ef Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 1 Feb 2025 22:00:36 +0100 Subject: [PATCH 065/112] Make TNTLeague Event System Capable --- .../src/de/steamwar/message/Message.java | 7 ++--- .../src/de/steamwar/message/SubMessage.java | 29 +++++-------------- .../steamwar/tntleague/TNTLeague.properties | 1 + .../tntleague/config/TNTLeagueConfig.kt | 8 ++--- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java index f953ce8d..b9ae84b7 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/Message.java @@ -72,12 +72,9 @@ public class Message { pattern += fromRB(resourceBundle, message); for (int i = 0; i < params.length; i++) { - if (params[i] instanceof SubMessage.Translatable) { - SubMessage.Translatable smsg = (SubMessage.Translatable) params[i]; + if (params[i] instanceof SubMessage) { + SubMessage smsg = (SubMessage) params[i]; params[i] = parse(smsg.getMessage(), sender, smsg.getParams()); - } else if (params[i] instanceof SubMessage.Literal) { - SubMessage.Literal smsg = (SubMessage.Literal) params[i]; - params[i] = smsg.getMessage(); } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java index 4c302689..e40b74a5 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/message/SubMessage.java @@ -19,33 +19,20 @@ package de.steamwar.message; -import lombok.AllArgsConstructor; import lombok.Getter; @Getter -@AllArgsConstructor -public abstract class SubMessage { +public class SubMessage { private final String message; + private final Object[] params; - @Getter - public static class Translatable extends SubMessage { - private final Object[] params; - - public Translatable(String message, Object... params) { - super(message); - this.params = params; - } - - public Translatable(String message) { - super(message); - this.params = new Object[0]; - } + public SubMessage(String message, Object... params) { + this.message = message; + this.params = params; } - @Getter - public static class Literal extends SubMessage { - public Literal(String message) { - super(message); - } + public SubMessage(String message) { + this.message = message; + this.params = new Object[0]; } } diff --git a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.properties b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.properties index 05d998e2..73e3b416 100644 --- a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.properties +++ b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.properties @@ -18,6 +18,7 @@ # PREFIX=§eTNT§7League§8» +PLAIN_STRING={0} JOIN=§e{0} §7joined the game! JOIN_TEAM={0} §7joined the {1} §7team! QUIT={0} §7left the game! diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index e5bccb08..7b1e865a 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -60,11 +60,11 @@ data class TNTLeagueConfig( eventTeamBlue = Team.get(eventFight.teamBlue) eventTeamRed = Team.get(eventFight.teamRed) - blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage.Literal("§${eventTeamBlue.teamColor}${eventTeamBlue.teamName}"), eventTeamBlue.teamColor[0]) - redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage.Literal("§${eventTeamRed.teamColor}${eventTeamRed.teamName}"), eventTeamRed.teamColor[0]) + blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage("PLAIN_STRING", "§${eventTeamBlue.teamColor}${eventTeamBlue.teamName}"), eventTeamBlue.teamColor[0]) + redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage("PLAIN_STRING", "§${eventTeamRed.teamColor}${eventTeamRed.teamName}"), eventTeamRed.teamColor[0]) } else { - blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage.Translatable("BLUE"), '3') - redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage.Translatable("RED"), 'c') + blueTeam = TeamConfig(TNTLeagueWorldConfig.blueTeam, SubMessage("BLUE"), '3') + redTeam = TeamConfig(TNTLeagueWorldConfig.redTeam, SubMessage("RED"), 'c') } } From 414bd20eb9eaa6d01c0d1678b89278b3a76b690b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 1 Feb 2025 22:58:49 +0100 Subject: [PATCH 066/112] Make TowerRun Event System Capable --- .../src/de/steamwar/towerrun/TowerRun.java | 1 - .../de/steamwar/towerrun/config/Config.java | 33 +++++++++++++++++++ .../steamwar/towerrun/game/TowerRunGame.java | 11 ++++++- .../towerrun/listener/GlobalListener.java | 5 --- .../towerrun/listener/LobbyListener.java | 22 +++++++++++++ 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/TowerRun/src/de/steamwar/towerrun/TowerRun.java b/TowerRun/src/de/steamwar/towerrun/TowerRun.java index 23f00488..7e6df112 100644 --- a/TowerRun/src/de/steamwar/towerrun/TowerRun.java +++ b/TowerRun/src/de/steamwar/towerrun/TowerRun.java @@ -73,7 +73,6 @@ public class TowerRun extends JavaPlugin { new LobbyListener(); new IngameListener(); new GlobalListener(); - new LobbyListener(); new NotLobbyListener(); final LobbyCountdown lobbyCountdown = new LobbyCountdown(); new EndCountdown(lobbyCountdown); diff --git a/TowerRun/src/de/steamwar/towerrun/config/Config.java b/TowerRun/src/de/steamwar/towerrun/config/Config.java index 91fb02b4..fe6acd07 100644 --- a/TowerRun/src/de/steamwar/towerrun/config/Config.java +++ b/TowerRun/src/de/steamwar/towerrun/config/Config.java @@ -19,6 +19,8 @@ package de.steamwar.towerrun.config; +import de.steamwar.sql.Event; +import de.steamwar.sql.EventFight; import de.steamwar.towerrun.TowerRun; import lombok.experimental.UtilityClass; import org.bukkit.Bukkit; @@ -41,6 +43,12 @@ public class Config { private static final int EVENT_KAMPF_ID; + // Event + public static final EventFight EVENT_FIGHT; + public static final int EVENT_TEAM_BLUE_ID; + public static final int EVENT_TEAM_RED_ID; + public static final int EVENT_MAXIMUM_TEAM_MEMBERS; + static { File configFile = new File(TowerRun.getInstance().getDataFolder(), "config.yml"); if (!configFile.exists()) { @@ -57,9 +65,34 @@ public class Config { DESTROYABLE_BLOCKS = EnumSet.copyOf(config.getStringList("destroyable").stream().map(Material::valueOf).collect(Collectors.toSet())); EVENT_KAMPF_ID = Integer.parseInt(System.getProperty("fightID", "0")); + + if (event()) { + EVENT_FIGHT = EventFight.get(EVENT_KAMPF_ID); + + if (EVENT_FIGHT == null) { + Bukkit.shutdown(); + throw new IllegalStateException("Event not found"); + } + + Event event = Event.get(EVENT_FIGHT.getEventID()); + + EVENT_TEAM_BLUE_ID = EVENT_FIGHT.getTeamBlue(); + EVENT_TEAM_RED_ID = EVENT_FIGHT.getTeamRed(); + EVENT_MAXIMUM_TEAM_MEMBERS = event.getMaximumTeamMembers(); + } else { + EVENT_FIGHT = null; + + EVENT_TEAM_BLUE_ID = 0; + EVENT_TEAM_RED_ID = 0; + EVENT_MAXIMUM_TEAM_MEMBERS = Integer.MAX_VALUE; + } } public static boolean test() { return EVENT_KAMPF_ID == -1; } + + public static boolean event() { + return EVENT_KAMPF_ID > 0; + } } diff --git a/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java b/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java index c83138d4..2c014cb5 100644 --- a/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java +++ b/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java @@ -20,7 +20,9 @@ package de.steamwar.towerrun.game; import de.steamwar.core.CraftbukkitWrapper; +import de.steamwar.sql.SteamwarUser; import de.steamwar.towerrun.TowerRun; +import de.steamwar.towerrun.config.Config; import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.state.GameState; import de.steamwar.towerrun.state.GameStates; @@ -64,7 +66,6 @@ public class TowerRunGame { public static void start() { if (GameState.getCurrentState() == GameStates.GENERATING_TOWER) { - PLAYERS_ALIVE.addAll(TowerRunPlayer.getAll()); PLAYERS_ALIVE.forEach(p -> { p.reset(); p.player().setGameMode(GameMode.SURVIVAL); @@ -108,6 +109,10 @@ public class TowerRunGame { PLAYERS_ALIVE.clear(); Bukkit.getOnlinePlayers().forEach(player -> player.sendTitle(TowerRun.getMessage().parse("GAME_TIE", player), "", 10, 70, 20)); GameState.nextState(); + + if (Config.event()) { + Config.EVENT_FIGHT.setErgebnis(3); + } } public static void win(TowerRunPlayer tPlayer) { @@ -120,6 +125,10 @@ public class TowerRunGame { player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_DEATH, 1, 1); }); GameState.nextState(); + + if (Config.event()) { + Config.EVENT_FIGHT.setErgebnis(SteamwarUser.get(tPlayer.player().getUniqueId()).getTeam() == Config.EVENT_TEAM_BLUE_ID ? 1 : 2); + } } public static void reset() { diff --git a/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java b/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java index 353adc20..b8256d80 100644 --- a/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java +++ b/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java @@ -38,11 +38,6 @@ public class GlobalListener extends GameStateBukkitListener { super(EnumSet.allOf(GameStates.class)); } - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - TowerRunPlayer.get(event.getPlayer()); - } - @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { if (TowerRunGame.isAlive(TowerRunPlayer.get(event.getPlayer()))) { diff --git a/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java b/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java index 52d600ca..c93bc4bb 100644 --- a/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java +++ b/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java @@ -19,8 +19,12 @@ package de.steamwar.towerrun.listener; +import de.steamwar.sql.SteamwarUser; import de.steamwar.towerrun.TowerRun; +import de.steamwar.towerrun.config.Config; import de.steamwar.towerrun.config.WorldConfig; +import de.steamwar.towerrun.game.TowerRunGame; +import de.steamwar.towerrun.game.TowerRunPlayer; import de.steamwar.towerrun.state.GameStateBukkitListener; import de.steamwar.towerrun.state.GameStates; import org.bukkit.GameMode; @@ -34,6 +38,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import java.util.EnumSet; +import java.util.HashMap; public class LobbyListener extends GameStateBukkitListener { public LobbyListener() { @@ -43,6 +48,7 @@ public class LobbyListener extends GameStateBukkitListener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); + if (TowerRun.getTowerGenerator() != null) { player.teleport(TowerRun.getTowerGenerator().getSpawn()); player.setGameMode(GameMode.SPECTATOR); @@ -50,6 +56,22 @@ public class LobbyListener extends GameStateBukkitListener { player.teleport(WorldConfig.SPAWN); player.setGameMode(GameMode.SURVIVAL); } + + if (Config.event()) { + SteamwarUser user = SteamwarUser.get(player.getUniqueId()); + int team = user.getTeam(); + + if (team != Config.EVENT_TEAM_BLUE_ID && team != Config.EVENT_TEAM_RED_ID) { + player.setGameMode(GameMode.SPECTATOR); + return; + } + + if (TowerRunGame.PLAYERS_ALIVE.stream().map(towerRunPlayer -> SteamwarUser.get(towerRunPlayer.player().getUniqueId()).getTeam()).filter(integer -> integer == team).count() < Config.EVENT_MAXIMUM_TEAM_MEMBERS) { + TowerRunGame.PLAYERS_ALIVE.add(TowerRunPlayer.get(player)); + } + } else { + TowerRunGame.PLAYERS_ALIVE.add(TowerRunPlayer.get(player)); + } } @EventHandler From 93ab1a50f32d624dbe90d920b0848dc40d437d2c Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Feb 2025 14:12:25 +0100 Subject: [PATCH 067/112] Fix team auto-assign logic in lobby state Replaced `members.add` with `join` to correctly integrate new players into teams during the lobby phase. This ensures proper team setup and adherence to game mechanics. --- TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt index 773c4a46..8b452fca 100644 --- a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt +++ b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueTeam.kt @@ -139,7 +139,7 @@ data class TNTLeagueTeam(val config: TeamConfig) { if (TNTLeagueGame.state == TNTLeagueGame.GameState.LOBBY) { if (members.isEmpty()) { plugin.server.onlinePlayers.firstOrNull { it != player && TNTLeagueGame.getTeam(it) == null }?.run { - members.add(this) + join(this) } } if (leader == player) { From b4baef321fa5c3069fd08af61019830f5ecd01a3 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 2 Feb 2025 15:28:33 +0100 Subject: [PATCH 068/112] Trigger rebuild --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ad9f4739..65e4bf0e 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ # SteamWar + From e39db5978bd60d6939bb66d6e70a3492cb714541 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Feb 2025 16:06:48 +0100 Subject: [PATCH 069/112] Add server shutdown if less than 2 players after 5 minutes --- TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt | 7 +++++++ .../src/de/steamwar/tntleague/events/LobbyListener.kt | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt index 378dbfc7..d24cdf6f 100644 --- a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt +++ b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt @@ -27,6 +27,8 @@ import de.steamwar.tntleague.command.RemoveCommand import de.steamwar.tntleague.events.GlobalListener import de.steamwar.tntleague.events.LobbyListener import de.steamwar.tntleague.game.TNTLeagueTeam +import net.kyori.adventure.text.Component +import org.bukkit.Bukkit import org.bukkit.plugin.java.JavaPlugin lateinit var plugin: TNTLeague @@ -49,6 +51,11 @@ class TNTLeague : JavaPlugin() { AcceptCommand.register() RemoveCommand.register() LeaveCommand.register() + + plugin.server.scheduler.runTaskLater(plugin, Runnable { + if (server.onlinePlayers.size >= 2) return@Runnable + Bukkit.shutdown() + }, 20 * 60 * 5) } } diff --git a/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt index bb570498..d160498f 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/LobbyListener.kt @@ -23,7 +23,6 @@ import de.steamwar.tntleague.game.TNTLeagueGame import org.bukkit.GameMode import org.bukkit.entity.EntityType import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.entity.EntityDamageEvent import org.bukkit.event.inventory.InventoryClickEvent From 1715fdccdf717a3b56241d8723cf68c9dd7c86d8 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Feb 2025 16:07:24 +0100 Subject: [PATCH 070/112] Remove unused imports in TNTLeague classes --- TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt | 1 - TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt | 2 -- 2 files changed, 3 deletions(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt index d24cdf6f..ef3b8a81 100644 --- a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt +++ b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt @@ -27,7 +27,6 @@ import de.steamwar.tntleague.command.RemoveCommand import de.steamwar.tntleague.events.GlobalListener import de.steamwar.tntleague.events.LobbyListener import de.steamwar.tntleague.game.TNTLeagueTeam -import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.bukkit.plugin.java.JavaPlugin diff --git a/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt b/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt index 204680d0..40fb4138 100644 --- a/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt +++ b/TNTLeague/src/de/steamwar/tntleague/util/TNTLeagueScoreboard.kt @@ -19,9 +19,7 @@ package de.steamwar.tntleague.util -import de.steamwar.message.SubMessage import de.steamwar.scoreboard.ScoreboardCallback -import de.steamwar.tntleague.colorByTeam import de.steamwar.tntleague.config.targetedBlocks import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.game.TNTLeagueTeam From 25cf1ab314dacee4d7479390542b36a2ad5b4720 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Feb 2025 16:11:02 +0100 Subject: [PATCH 071/112] Add ReadyCommand --- .../src/de/steamwar/tntleague/TNTLeague.kt | 6 ++-- .../tntleague/command/ReadyCommand.kt | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 TNTLeague/src/de/steamwar/tntleague/command/ReadyCommand.kt diff --git a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt index 378dbfc7..2c63ae94 100644 --- a/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt +++ b/TNTLeague/src/de/steamwar/tntleague/TNTLeague.kt @@ -20,10 +20,7 @@ package de.steamwar.tntleague import de.steamwar.message.Message -import de.steamwar.tntleague.command.AcceptCommand -import de.steamwar.tntleague.command.InviteCommand -import de.steamwar.tntleague.command.LeaveCommand -import de.steamwar.tntleague.command.RemoveCommand +import de.steamwar.tntleague.command.* import de.steamwar.tntleague.events.GlobalListener import de.steamwar.tntleague.events.LobbyListener import de.steamwar.tntleague.game.TNTLeagueTeam @@ -45,6 +42,7 @@ class TNTLeague : JavaPlugin() { logger.info("TNTLeague enabled") + ReadyCommand.register() InviteCommand.register() AcceptCommand.register() RemoveCommand.register() diff --git a/TNTLeague/src/de/steamwar/tntleague/command/ReadyCommand.kt b/TNTLeague/src/de/steamwar/tntleague/command/ReadyCommand.kt new file mode 100644 index 00000000..e53444ce --- /dev/null +++ b/TNTLeague/src/de/steamwar/tntleague/command/ReadyCommand.kt @@ -0,0 +1,33 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.tntleague.command + +import de.steamwar.command.SWCommand +import de.steamwar.tntleague.game.TNTLeagueGame +import org.bukkit.entity.Player + +object ReadyCommand: SWCommand("ready") { + + @Register + fun invitePlayer(@Validator("isLeader") sender: Player) { + if (TNTLeagueGame.state != TNTLeagueGame.GameState.LOBBY) return + TNTLeagueGame.getTeam(sender)?.also { it.isReady = it.isReady.not() } + } +} \ No newline at end of file From ec43e7eba8d4ffecd4c44f3670486f4cf2bfae2a Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 2 Feb 2025 16:29:10 +0100 Subject: [PATCH 072/112] Trigger rebuild --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 65e4bf0e..ad9f4739 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ # SteamWar - From 6aeecd444e2cdd3bfaf78c05e6ff07ede2db3e6a Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 4 Feb 2025 21:47:29 +0100 Subject: [PATCH 073/112] Authentication v2 --- .../src/de/steamwar/plugins/Plugins.kt | 12 ++ .../src/de/steamwar/routes/Routes.kt | 4 + .../src/de/steamwar/routes/v2/Auth.kt | 151 ++++++++++++++++++ .../src/de/steamwar/util/TokenUtils.kt | 57 +++++++ 4 files changed, 224 insertions(+) create mode 100644 WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt create mode 100644 WebsiteBackend/src/de/steamwar/util/TokenUtils.kt diff --git a/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt b/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt index fc8dde36..0cff0a03 100644 --- a/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt +++ b/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt @@ -20,7 +20,11 @@ package de.steamwar.plugins import de.steamwar.sql.Token +import de.steamwar.util.TokenType +import de.steamwar.util.isValid +import de.steamwar.util.type import io.ktor.http.* +import io.ktor.http.auth.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* import io.ktor.server.auth.* @@ -66,6 +70,14 @@ fun Application.configurePlugins() { if (token == null) { null } else { + if (!token.isValid) { + token.delete() + return@authenticate null + } + if (token.type == TokenType.RESET_PASSWORD || token.type == TokenType.REFRESH_TOKEN) { + token.delete() + } + SWAuthPrincipal(token, token.owner) } } diff --git a/WebsiteBackend/src/de/steamwar/routes/Routes.kt b/WebsiteBackend/src/de/steamwar/routes/Routes.kt index 041d4b31..1da4ed29 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Routes.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Routes.kt @@ -19,6 +19,7 @@ package de.steamwar.routes +import de.steamwar.routes.v2.configureNewAuth import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.routing.* @@ -34,6 +35,9 @@ fun Application.configureRoutes() { configurePage() configureSchematic() configureAuthRoutes() + route("/v2") { + configureNewAuth() + } } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt new file mode 100644 index 00000000..24e5cee6 --- /dev/null +++ b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt @@ -0,0 +1,151 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.routes.v2 + +import de.steamwar.ResponseError +import de.steamwar.plugins.SWAuthPrincipal +import de.steamwar.sql.SWException +import de.steamwar.sql.SteamwarUser +import de.steamwar.sql.Token +import de.steamwar.util.TokenType +import de.steamwar.util.isValid +import de.steamwar.util.lifetime +import de.steamwar.util.type +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.auth.* +import io.ktor.server.http.* +import io.ktor.server.plugins.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import kotlinx.serialization.Serializable +import java.time.LocalDateTime +import kotlin.time.Duration +import kotlin.time.toJavaDuration + +@Serializable +data class UsernamePassword(val name: String, val password: String, val keepLoggedIn: Boolean = false) + +@Serializable +data class ResponseToken(val token: String, val expires: String) { + constructor(token: String, lifetime: Duration) : this(token, LocalDateTime.now().plus(lifetime.toJavaDuration()).toString()) +} + +@Serializable +data class AuthTokenResponse(val accessToken: ResponseToken, val refreshToken: ResponseToken? = null) + +fun SteamwarUser.createAccessAndRefreshToken(keepLoggedIn: Boolean = false): AuthTokenResponse { + val code = System.currentTimeMillis() % 1000 + val accessToken = Token.createToken("AT-${userName}-${code}", this) + val refreshToken = if (keepLoggedIn) Token.createToken("RT-${userName}-${code}", this) else null + + return AuthTokenResponse(ResponseToken(accessToken, TokenType.ACCESS_TOKEN.lifetime), refreshToken?.let { ResponseToken(it, TokenType.REFRESH_TOKEN.lifetime) }) +} + +fun Route.configureNewAuth() { + route("/auth") { + route("/enroll") { + post("/{userId}") { + if (call.request.headers.contains("X-Forwarded-For")) { + SWException.log("Request to /auth/register from", "Invalid IP") + call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid IP", "F_U")) + return@post + } + + val userId = call.parameters["userId"]?.toInt() + if (userId == null) { + call.respond(HttpStatusCode.BadRequest, ResponseError("Missing or invalid userId")) + return@post + } + + val user = SteamwarUser.get(userId) + if (user == null) { + call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid userId")) + return@post + } + + val token = Token.createToken("PT-${user.userName}", user) + + call.respond(HttpStatusCode.OK, ResponseToken(token, TokenType.RESET_PASSWORD.lifetime)) + } + } + + post("/register") { + val requester = call.request.header("X-Forwarded-For") ?: call.request.origin.remoteAddress + + val request = call.receive() + val token = call.principal() + + if (token == null || token.token.type != TokenType.RESET_PASSWORD || !token.token.isValid) { + SWException.log("$requester tried registering with invalid token", "") + call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid token", "invalid")) + return@post + } + + val user = token.user + + if (user.userName != request.name) { + SWException.log("$requester tried registering for invalid User", """ + User: ${user.userName} + Request: ${request.name} + """.trimIndent()) + call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username", "invalid")) + return@post + } + + user.setPassword(request.password) + + call.respond(HttpStatusCode.OK) + } + route("/state") { + post("/create") { + val request = call.receive() + + val user = SteamwarUser.get(request.name) + val valid = user?.verifyPassword(request.password) ?: false + + if (!valid) { + call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username or password", "invalid")) + return@post + } + + call.respond(user.createAccessAndRefreshToken(request.keepLoggedIn)) + } + post("/refresh") { + val token = call.principal() + + if (token == null || token.token.type != TokenType.REFRESH_TOKEN) { + call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid token type", "invalid")) + return@post + } + + val code = token.token.name.substringAfterLast('-') + + Token.listUser(token.user) + .filter { it.type == TokenType.ACCESS_TOKEN } + .filter { it.name.endsWith(code) } + .forEach { it.delete() } + + call.respond(token.user.createAccessAndRefreshToken(true)) + } + } + } +} \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt b/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt new file mode 100644 index 00000000..7a70c2f3 --- /dev/null +++ b/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt @@ -0,0 +1,57 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.util + +import de.steamwar.sql.Token +import java.time.LocalDateTime +import kotlin.time.Duration +import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.minutes +import kotlin.time.toJavaDuration + +val Token.type: TokenType + get() = when (name.substring((0..1))) { + "RT" -> TokenType.REFRESH_TOKEN + "AT" -> TokenType.ACCESS_TOKEN + "PT" -> TokenType.RESET_PASSWORD + else -> TokenType.OLD_TOKEN + } + +val TokenType.lifetime: Duration + get() = when (this) { + TokenType.REFRESH_TOKEN -> 7.days + TokenType.ACCESS_TOKEN -> 1.hours + TokenType.RESET_PASSWORD -> 10.minutes + TokenType.OLD_TOKEN -> 1.days + } + +val Token.lifetime: Duration + get() = type.lifetime + +val Token.isValid: Boolean + get() = created.toLocalDateTime().plus(lifetime.toJavaDuration()).isAfter(LocalDateTime.now()) + +enum class TokenType { + RESET_PASSWORD, + ACCESS_TOKEN, + REFRESH_TOKEN, + OLD_TOKEN +} \ No newline at end of file From dd9467fa36912e8130d78f78bd00d8306a6404fd Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Fri, 14 Feb 2025 16:53:26 +0100 Subject: [PATCH 074/112] Hotfix TeamPlayer.onPlayerInteractEntity --- LobbySystem/src/de/steamwar/lobby/team/TeamPlayer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LobbySystem/src/de/steamwar/lobby/team/TeamPlayer.java b/LobbySystem/src/de/steamwar/lobby/team/TeamPlayer.java index 989fca7a..ce14aa04 100644 --- a/LobbySystem/src/de/steamwar/lobby/team/TeamPlayer.java +++ b/LobbySystem/src/de/steamwar/lobby/team/TeamPlayer.java @@ -148,6 +148,8 @@ public class TeamPlayer extends BasicListener { return; } + event.setCancelled(true); + SteamwarUser target = SteamwarUser.get(event.getRightClicked().getName()); String message; try { From 5420c19b391cc91580a5826346d78e754d6d3986 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Fri, 14 Feb 2025 20:34:49 +0100 Subject: [PATCH 075/112] Add SCRIPT.md and sw.def.lua --- BauSystem/SCRIPT.md | 419 ++++++++++++++++++++++++++++++++++++++++++ BauSystem/sw.def.lua | 428 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 847 insertions(+) create mode 100644 BauSystem/SCRIPT.md create mode 100644 BauSystem/sw.def.lua diff --git a/BauSystem/SCRIPT.md b/BauSystem/SCRIPT.md new file mode 100644 index 00000000..ae9cb181 --- /dev/null +++ b/BauSystem/SCRIPT.md @@ -0,0 +1,419 @@ +# SteamWar.de - Script System + +--- + +* [SteamWar.de - Script System](#steamwarde---script-system) + * [Einleitung](#einleitung) + * [Nutzung mit einer IDE](#nutzung-mit-einer-ide) +* [Basis-Apis](#basis-apis) +* [SteamWar.de-Api](#steamwarde-api) + * [player](#player) + * [random](#random) + * [region](#region) + * [tnt](#tnt) + * [trace](#trace) + * [server](#server) + * [tps](#tps) + * [storage](#storage) + * [inventory](#inventory) +* [SteamWar.de-Global-Api](#steamwarde-global-api) + * [Commands](#commands) + * [Hotkeys](#hotkeys) + * [Eventtypen](#eventtypen) + * [BlockEvent](#blockevent) + * [InteractEvent](#interactevent) + * [Position](#position) +* [Instabile APIs](#instabile-apis) + * [_worldedit](#worldedit) +* [Beispiele](#beispiele) + * [Hello, World!](#hello-world) + * [Code](#code) + * [Ausgabe](#ausgabe) + * [BauGUI on DoubleSwap](#baugui-on-doubleswap) + * [Code](#code-1) + * [SL Command](#sl-command) + * [Code](#code-2) + * [Paste Hotkey](#paste-hotkey) + * [Code](#code-3) + * [Inventory](#inventory-1) + * [Code](#code-4) + + + +## Einleitung +Das Script System auf SteamWar.de basiert auf [Lua](https://www.lua.org/docs.html). +Der Code wird einfach in ein Minecraft Buch geschrieben und kann mit einem Links-Klick ausgeführt werden. + +## Nutzung mit einer IDE +Im Repository liegen [Lua-Definitionen](sw.def.lua) für [Luanalysis](https://plugins.jetbrains.com/plugin/14698-luanalysis). +Diese können in der IDE genutzt werden, um die APIs zu nutzen. + +Einfach die `sw.def.lua` in denselben Ordner wie das Script legen und die IDE sollte die APIs erkennen. + +# Basis-Apis +Es werden folgende Standard-Apis zur Verfügung gestellt: +- [`math`](https://www.lua.org/manual/5.4/manual.html#6.7) +- [`string`](https://www.lua.org/manual/5.4/manual.html#6.4) +- [`table`](https://www.lua.org/manual/5.4/manual.html#6.6) +- [`bit32`](https://www.lua.org/manual/5.2/manual.html#6.7) + +# SteamWar.de-Api +APIs, die mit einem `_` beginnen sind noch nicht stabil und können sich jederzeit ändern. +Sie sollten daher nicht verwendet werden, da sie sich noch in der Entwicklung befinden. +Diese können auch undokumentierte Funktionen enthalten, die nicht in der Dokumentation aufgeführt sind. + +In den Scripten gibt es dazu noch folgende globale Variablen: +- [`player`](#player) +- [`random`](#random) +- [`region`](#region) +- [`server`](#server) +- [`storage`](#storage) +- [`inventory`](#inventory) +- `_worldedit` + +Ohne eine Kategorie sind folgende Funktionen verfügbar, die nicht allgemein sind: + +| Name | Signature | Beschreibung | +|-----------|-----------------------------------|-------------------------------------------------------------------------------------------------------------------| +| `print` | print(String...) | @see chat(String...) | +| `input` | input(String, Function\) | Fragt den User nach einer Eingabe mit der Nachricht und called die zugehörige Funktion nach dieser | +| `delayed` | delayed(Number, Function\) | Wartet die angegebene Anzahl an Ticks und führt danach die zugehörige Funktion aus | +| `pos` | pos(Number, Number, Number) | Erstellt aus drei Zahlen eine Position-Table. Die Koordinaten sind unter den Namen `x`, `y` und `z` abgespeichert | +| `exec` | exec(String...) | Führt den angegebenen Befehl als Spieler aus | +| `length` | length(Any): Int | Gibt die Länge des Objekts zurück | +| `join` | length(String, String...): String | Füge die Texte mit den ersten Parameter zusammen | + +### player +Das `player`-Modul stellt Funktionen zur Verfügung, die den Spieler betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|------------------|--------------------------------|---------------------------------------------------------------------------------------------------------------------------| +| `name` | name(): String | Gibt den `displayName` des Spielers zurück | +| `chat` | chat(String...) | Sendet den Text in den Chat des Spielers | +| `actionbar` | actionbar(String...) | Sendet den Text in die ActionBar des Spielers | +| `x` | x(Number), x(): Number | Setzt oder gibt die X-Koordinate des Spielers | +| `y` | y(Number), y(): Number | Setzt oder gibt die Y-Koordinate des Spielers | +| `z` | z(Number), z(): Number | Setzt oder gibt die Z-Koordinate des Spielers | +| `yaw` | yaw(Number), yaw(): Number | Setzt oder gibt die Gierung des Spielers | +| `pitch` | pitch(Number), pitch(): Number | Setzt oder gibt die Steigung des Spielers | +| `sneaking` | sneaking(): Boolean | Wahr, wenn der Spieler am Sneaken ist | +| `sprinting` | sprinting(): Boolean | Wahr, wenn der Spieler am Sprinten ist | +| `slot` | slot(Number), slot(): Number | Setzt oder gibt den Slot des gehaltenden Items des Spielers [(Wiki)](https://minecraft.fandom.com/wiki/Slot#Java_Edition) | +| `item` | item(): String | Gibt den Itemtyp der Main-Hand zurück | +| `offHandItem` | offHandItem(): String | Gibt den Itemtyp der Off-Hand zurück | +| `closeInventory` | closeInventory() | Schließe das aktuell geöffnete Inventar des Spielers | + +### random +Das `random`-Modul stellt Funktionen zur Verfügung, die Zufallszahlen betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|------------|------------------------------------|-------------------------------------------------------------------------------| +| nextInt | nextInt(): Int | Gibt eine Zufallszahl zurück zwischen Integer.MIN_VALUE und Integer.MAX_VALUE | +| -"- | nextInt(Int): Int | Gibt eine Zufallszahl zurück zischen 0 und dem Argument | +| -"- | nextInt(Int, Int): Int | Gibt eine Zufallszahl zurück zwischen dem ersten und zweiten Argument | +| nextDouble | nextDouble(): Double | Gibt eine Zufallszahl zurück zwischen 0 und 1 | +| -"- | nextDouble(Double): Double | Gibt eine Zufallszahl zurück zwischen 0 und dem Argument | +| -"- | nextDouble(Double, Double): Double | Gibt eine Zufallszahl zurück zwischen ersten und zweiten Argument | +| nextBool | nextBool(): Boolean | Gibt true oder false zurück | + +### region +Das `region`-Modul stellt Funktion zur Verfügung, die die Region des Spielers betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|-----------|---------------------|------------------------------------------------------------------------------------------------------------| +| `name` | name(): String | Gibt den Regionsnamen | +| `type` | type(): String | Gibt den Regionstyp | +| `fire` | fire(): Boolean | Gibt den Fire-Modus der Region zurück | +| `freeze` | freeze(): Boolean | Gibt den Freeze-Modus der Region zurück | +| `protect` | protect(): Boolean | Gibt den Protect-Modus der Region zurück | +| `loader` | loader(): String | Gibt den Status des Loaders des Spielers zurück, die Werte sind: `OFF`, `SETUP`, `RUNNING`, `PAUSE`, `END` | +| `get` | get(String): Region | Gibt die Region mit dem Namen zurück. Die Region ist gleich aufgebaut wie das Regions-Modul | +| `list` | list(): Region[] | Gibt alle Region zurück. Die Region ist gleich aufgebaut wie das Regions-Modul | + +Es gibt folgende weitere Module: + +| Name | Beschreibung | +|---------|-----------------| +| `tnt` | [tnt](#tnt) | +| `trace` | [trace](#trace) | + +#### tnt +Das `tnt`-Modul stellt Funktionen zur Verfügung, die den TNT-Modus in der Region des Spielers betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|-------------|----------------------|-------------------------------------------------------------------------------------| +| `mode` | mode(): String | Gibt den Aktuellen TNT-Modus zurück, die werte sind: `ALLOW`, `DENY` oder `ONLY_TB` | +| `enabled` | enabled(): Boolean | Gibt zurück, ob der TNT-Modus in der Region des Spielers aktiviert ist oder nicht | +| `onlyTb` | onlyTb(): Boolean | Gibt zurück, ob der TNT-Modus auf Only-Tb ist | +| `onlyBuild` | onlyBuild(): Boolean | Gibt zurück, ob der TNT-Modus auf Only-Build ist | + + +#### trace +Das `trace`-Modul stellt Funktionen zur Verfügung, die den Status des Tracers der Region betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|----------|-------------------|--------------------------------------------------------------------------------| +| `active` | active(): Boolean | Gibt zurück, ob der Tracer in der Region des Spielers aktiviert ist oder nicht | +| `auto` | auto(): Boolean | Gibt zurück, ob der Tracer in der Region ein Auto-Tracer ist | +| `status` | status(): String | Gibt den Status des Tracers zurück | +| `time` | time(): String | Gibt die Zeit des Tracers zurück | + +## server +Das `server`-Modul stellt Funktionen zur Verfügung, die den Server betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|--------------|-------------------------|---------------------------------------------------------------------| +| `time` | time(): String | Gibt die aktuelle Zeit im Format `HH:mm:ss` zurück | +| `ticks` | ticks(): Number | Gibt die Ticks seit start des Serverstarts zurück | +| `getBlockAt` | getBlockAt(Pos): String | Gibt das Material an der Position zurück | +| `setBlockAt` | setBlockAt(Pos, String) | Setzt das Material an der angegebenen Stelle (z.B. Stein = `STONE`) | + +Es gibt folgende weitere Module: + +| Name | Beschreibung | +|-------|--------------| +| `tps` | [tps](#tps) | + +#### tps +Das `tps`-Modul stellt Funktionen zur Verfügung, die die TPS des Servers betreffen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|--------------|----------------------|-------------------------------------------------------------------| +| `current` | current(): Number | Gibt die aktuelle TPS zurück (Das selbe wie `oneSecound()`) | +| `oneSecond` | oneSecond(): Number | Gibt die durchschnittliche TPS über die letzte Sekunde zurück | +| `tenSecond` | tenSecond(): Number | Gibt die durchschnittliche TPS über die letzte 10 Sekunden zurück | +| `oneMinute` | oneMinute(): Number | Gibt die durchschnittliche TPS über die letzte Minute zurück | +| `fiveMinute` | fiveMinute(): Number | Gibt die durchschnittliche TPS über die letzte 5 Minuten zurück | +| `tenMinute` | tenMinute(): Number | Gibt die durchschnittliche TPS über die letzte 10 Minuten zurück | +| `limit` | limit(): Number | Gibt das TPS-Limit zurück | + +## storage +Das `storage`-Modul stellt Funktionen zur Verfügung, mit welchen man Werte speichern kann. + +Es gibt folgende Module: + +| Name | Beschreibung | +|----------|---------------------| +| `player` | Spieler abhängig | +| `region` | Region des Spielers | +| `global` | Alle Skripte | + +Alle Module haben folgende Funktionen: + +| Name | Signature | Beschreibung | +|------------|----------------------------|--------------------------------------------------------| +| `get` | get(String): Any | Gibt den Wert des Schlüssels zurück | +| `set` | set(String, Any) | Setzt den Wert des Schlüssels auf den angegebenen Wert | +| `has` | has(String): Boolean | Prüft ob ein Wert vorhanden ist | +| `remove` | remove(String) | Löscht den Schlüssel | +| `accessor` | accessor(String): Accessor | Gibt einen Accessor zurück | + +Ein Accessor ist ein Objekt, womit du direkt auf einen Wert zugreifen kannst und es ändern kannst. +Es geht wie folgt: +```lua +keyAccessor = storage.player.accessor("key") + +keyAccessor("Hello World") -- Setzt den Wert auf "Hello World" +print(keyAccessor()) -- Gibt den Wert zurück +``` + +## inventory +Das `inventory`-Modul stellt Funktionen zur Verfügung, um ein Inventar zu öffnen. +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|----------|-----------------------------------|-------------------------------------------------------------------| +| `create` | create(String, Number): Inventory | Erstellt ein Inventar mit dem Title und der Anzahl an Zeilen | + +Das `Inventory`-Objekt hat folgende Funktionen: + +| Name | Signature | Beschreibung | +|-------------------|--------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `item` | item(Number, String, String, Function\) | Setze ein Item mit dem Typen des ersten Strings an den Slot (Startet bei 0) mit dem Namen des zweiten Strings mit einem Klick-Handler der den Klick-Typen rein gibt (z.B. `LEFT`, `SHIFT_LEFT`, `RIGHT`, `SHIFT_RIGHT`) | +| -"- | item(Number, String, String, Function\, List) | Füge eine Lore an das Item hinzu | +| -"- | item(Number, String, String, Function\, List, Boolean) | Gebe an, ob das Item enchanted sein soll | +| -"- | item(Number, String, String, Function\, List, Boolean, Number) | Gebe die Anzahl der Items an | +| `setCloseHandler` | setCloseHandler(Function\) | Gebe einen Handler an, der beim schließen des Inventares ausgeführt wird | +| `open` | open() | Öffne das Inventar | + +Siehe auch: [Inventory Beispiel](#inventory-1) + +Siehe auch: [Liste an Materials](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html) + +``` +⚠️⚠️⚠️ + +Wenn eine Barrier statt des richtigen Items angezeigt wird, dann ist das angegebene Material nicht gültig. + +⚠️⚠️⚠️ +``` + +# SteamWar.de-Global-Api +Mit `/script` kann man Script-Bücher global abspeichern. Diese haben dann zugrif auf die `global`-Api. +Die `global`-Api stellt Funktionen zur Verfügung um auf Events, Commands und Hotkeys mit einem Script zu reagieren. + +Es gibt folgende Funktionen: + +| Name | Signature | Beschreibung | +|-----------|-----------------------------------|-----------------------------------------------------------------------------| +| `event` | event(EventType, Function(Any)) | Registriere einen Event Listener | +| `command` | command(String, Function(Args)) | Registriere einen Befehl | +| `hotkey` | hotkey(String, Function(Boolean)) | Registriere einen Hotkey, the function gets a boolean if the key is pressed | + +Es gibt folgende Variablen: + +| Name | Beschreibung | +|----------|----------------------------------| +| `events` | Siehe: [Event Type](#eventtypen) | + +## Commands +Der Command Handler kriegt eine Liste aller angegeben argumenten. Die Argumente sind vom Typ `String`. Mit dem Wert gespeichert unter `args.alias` oder `args["alias"]` erhältst du, welcher command eingegeben wurde. Wenn ein handler für mehrere Befehle registriert wurde kannst du es hiermit erkennen. +Du kannst `args.hasShortFlag(String)` um herauszufinden ob eine Flag angegeben wurde wie zum Beispiel `-f`. Mit `args.removeShortFlag(String)` kannst du die Flag entfernen und erhältst ob sie angegeben wurde. + +## Hotkeys + +Hotkeys werden im folgenden Format angegeben: `MODIFIER+KEY`. Bei den Hotkey erstellung ist die Großschreibung egal. Es gibt folgende Modifier: +- `ctrl` +- `shift` +- `alt` +- `meta` + +Es können auch mehrere Modifier angegeben werden, z.B. `ctrl+shift+alt+c`. Die Reihenfolge der Modifier und des Keys ist egal. + +## Eventtypen +Einige Events sind auch abbrechbar, dazu muss die Funktion `setCancelled()` aufgerufen werden. + +| Name | Wenn | Parameter | Abbrechbar | +|---------------------|-----------------------------------------------------|---------------------------------|------------| +| `DoubleSwap` | Beim Doppelten Drücken der Swap-Hands taste | NIL | false | +| `PlaceBlock` | Beim Platzieren von Blöcken | [BlockEvent](#blockevent) | true | +| `BreakBlock` | Beim Zerstören von Blöcken | [BlockEvent](#blockevent) | true | +| `RightClick` | Beim Rechtsklick | [InteractEvent](#interactevent) | true | +| `LeftClick` | Beim Linksklick | [InteractEvent](#interactevent) | true | +| `TNTSpawn` | Wenn ein TNT in der aktuellen Region spawnt | NIL | false | +| `TNTExplode` | Wenn ein TNT in der aktuellen Region explodiert | [Position](#position) | true | +| `TNTExplodeInBuild` | Wenn ein TNT in der aktuellen Bau Region explodiert | [Position](#position) | true | +| `SelfJoin` | Wenn man selbst den Server betritt | NIL | false | +| `SelfLeave` | Wenn man den Server verlässt | NIL | false | +| `DropItem` | Wenn man ein Item droppt | (type: Material) | true | +| `EntityDeath` | Wenn ein Entity stirbt | (type: Entity Type) | false | + +### BlockEvent +Das übergebene Objekt an den Handler hat folgende Variablen: + +| Name | Beschreibung | +|--------|-----------------------------| +| `x` | Die X-Koordinate des Blocks | +| `y` | Die Y-Koordinate des Blocks | +| `z` | Die Z-Koordinate des Blocks | +| `type` | Das Material des Blocks | + +### InteractEvent +Das übergebene Objekt an den Handler hat folgende Variablen: + +| Name | Beschreibung | +|------------|-------------------------------------------------------------------------------------------------------------------------------| +| `action` | Die Action die ausgeführt wurde, Mögliche Werte: `RIGHT_CLICK_BLOCK`, `RIGHT_CLICK_AIR`, `LEFT_CLICK_BLOCK`, `LEFT_CLICK_AIR` | +| `hand` | Die Hand die zum ausführen genutzt wird, Mögliche Werte: `HAND`, `OFF_HAND`, `null` | +| `block` | Der Typ des Items mit dem geklickt wurde | +| `hasBlock` | Wahr, wenn auf einen Block geklickt wurde | + +Wenn `hasBlock` wahr ist, gibt es folgende Variablen: + +| Name | Beschreibung | +|-------------|-----------------------------------------| +| `blockX` | Die X-Koordinate des Blocks | +| `blockY` | Die Y-Koordinate des Blocks | +| `blockZ` | Die Z-Koordinate des Blocks | +| `blockFace` | Die Seite des Blocks die geklickt wurde | + + +### Position +Die Position ist ein Objekt mit folgenden Variablen: + +| Name | Beschreibung | +|------|------------------| +| `x` | Die X-Koordinate | +| `y` | Die Y-Koordinate | +| `z` | Die Z-Koordinate | + +# Instabile APIs +Hier sind einige APIs aufgelistet, die nicht stabil sind und sich jederzeit ändern können. + +## _worldedit + +| Name | Signatur | Beschreibung | +|-------------|-----------------------------------------------------------|-----------------------------------| +| `selection` | selection(Liste\), selection(): {min: Pos, max: Pos} | Die aktuelle auswahl des Spielers | + + + +# Beispiele + +## Hello, World! +Ein einfaches Hello, World!-Script. + +#### Code +```lua +print("Hello, World!") +``` + +#### Ausgabe +``` +Hello, World! +``` + +## BauGUI on DoubleSwap +Das Standardskript für das Öffnen des BauGUIs + +#### Code +```lua +function handler(event) + exec("gui") +end + +event(events.DoubleSwap, handler) +``` + +## SL Command +Ein einfacher Command Redefiner. + +#### Code +```lua +function handler(args) + exec("stoplag") +end + +command("sl", handler) +``` + +## Paste Hotkey +Ein Hotkey zum Pasten des Clipboard-Inhalts. + +#### Code +```lua +function handler(pressed) + if pressed then + exec("/paste -o") + end +end + +hotkey("ctrl+v", handler) +``` + +## Inventory +Ein Beispiel für ein Inventar. + +#### Code +```lua +inv = inventory.create("Test Inv", 3) +inv.item(13, "STONE", "Ich bin ein Stein", function(e) player.chat(e) end, {"Die Lore", "Die Zweite Zeile"}, true) +inv.open() +``` \ No newline at end of file diff --git a/BauSystem/sw.def.lua b/BauSystem/sw.def.lua new file mode 100644 index 00000000..613437a1 --- /dev/null +++ b/BauSystem/sw.def.lua @@ -0,0 +1,428 @@ +-- This file is a part of the SteamWar software. +-- +-- Copyright (C) 2021 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 . + +--- +--- This file contains the definitions for the SteamWar.de script API. +--- It is used by the IDE to provide code completion and type checking. +--- Created by Chaoscaot +--- + +inventory = {} + +---@param title string +---@param size number +---@return Inventory +function inventory.create(title, size) return nil end + +---@alias InventoryClick 'LEFT' | 'SHIFT_LEFT' | 'RIGHT' | 'SHIFT_RIGHT' | 'MIDDLE' | 'NUMBER_KEY' + +---@class Inventory +local Inventory = {} + +---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick)): void +---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick), lore: string[]): void +---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick), lore: string[], enchanted: boolean): void +---@param slot number +---@param material string +---@param name string +---@param handler fun(click: InventoryClick): void +---@param lore string[] +---@param enchanted boolean +---@param amount number +---@return void +function Inventory.item(slot, material, name, handler, lore, enchanted, amount) end + +---@param handler fun(): void +---@return void +function Inventory.setCloseHandler(handler) end + +---@return void +function Inventory.open() end + +player = {} + +---@return string +---Get the name of the player. +function player.name() return "" end + +---@return void +function player.chat(...) end + +---@return void +---Send a message to the actionbar of the player. +function player.actionbar(...) end + +---@overload fun(): number +---@param newX number +function player.x(newX) end + +---@overload fun(): number +---@param newY number +function player.y(newY) end + +---@overload fun(): number +---@param newZ number +function player.z(newZ) end + +---@overload fun(): number +---@param newYaw number +function player.yaw(newYaw) end + +---@overload fun(): number +---@param newPitch number +function player.pitch(newPitch) end + +---@return boolean +function player.sneaking() return nil end + +---@return boolean +function player.sprinting() return nil end + +---@overload fun(): number +---@param newSlot number +function player.slot(newSlot) end + +---@return string +function player.item() return nil end + +---@return string +function player.offHandItem() return nil end + +---@return void +function player.closeInventory() end + +---@field nextBool fun(): boolean +random = {} + +---@overload fun(): number +---@overload fun(bound: number): number +---@param origin number +---@param bound number +---@return number +function random.nextInt(origin, bound) return nil end + +---@overload fun(): number +---@overload fun(bound: number): number +---@param origin number +---@param bound number +---@return number +function random.nextDouble(origin, bound) return nil end + +---@return boolean +function random.nextBool() return nil end + +---@alias RegionType 'wg' | 'mwg' | 'as' | 'ws' | 'ws_inner' | 'ws_rumpf' | 'ws_rahmen' | 'spawn' + +---@class iregion +---@field tnt tnt +---@field trace trace +local iregion = {} + +---@class region: iregion +region = {} + +---@return string +function iregion.name() return nil end + +---@return RegionType +function iregion.type() return nil end + +---@return boolean +function iregion.fire() return nil end + +---@return boolean +function iregion.freeze() return nil end + +---@return boolean +function iregion.protect() return nil end + +---@return string +function iregion.loader() return nil end + +---@return Position +function iregion.copyPoint() return nil end + +---@return Position +function iregion.minPointBuild() return nil end + +---@return Position +function iregion.maxPointBuild() return nil end + +---@return Position +function iregion.minPointBuildExtension() return nil end + +---@return Position +function iregion.maxPointBuildExtension() return nil end + +---@return Position +function iregion.testblockPoint() return nil end + +---@return Position +function iregion.minPointTestblock() return nil end + +---@return Position +function iregion.maxPointTestblock() return nil end + +---@return Position +function iregion.minPointTestblockExtension() return nil end + +---@return Position +function iregion.maxPointTestblockExtension() return nil end + +---@alias TNTMode 'ALLOW' | 'DENY' | 'ONLY_TB' + +---@class tnt +local tnt = {} + +---@return TNTMode +function tnt.mode() return nil end + +---@return boolean +function tnt.enabled() return nil end + +---@return boolean +function tnt.onlyTb() return nil end + +---@return boolean +function tnt.onlyBuild() return nil end + +---@class trace +local trace = {} + +---@return boolean +function trace.active() return nil end + +---@return boolean +function trace.auto() return nil end + +---@return string +function trace.status() return nil end + +---@return number +function trace.time() return nil end + +---@param name string +---@return iregion +function region.get(name) return nil end + +---@return iregion[] +function region.list() return nil end + +---@class Position +---@field x number +---@field y number +---@field z number + +---@class server +---@field tps tps +server = {} + +---@return string +function server.time() return nil end + +---@return number +function server.ticks() return nil end + +---@param position Position +---@return string +function getBlockAt(position) return nil end + +---@param position Position +---@param material string +---@return void +function setBlockAt(position, material) return nil end + +---@class tps +local tps = {} + +---@return number +function tps.oneSecond() return nil end + +---@return number +function tps.tenSecond() return nil end + +---@return number +function tps.oneMinute() return nil end + +---@return number +function tps.fiveMinute() return nil end + +---@return number +function tps.tenMinute() return nil end + +---@return number +function tps.current() return nil end + +---@return number +function tps.limit() return nil end + +---@class storage +---@field global storageLib +---@field player storageLib +---@field region storageLib +storage = {} + +---@class storageLib +---Any Primitive, Array or Table will be saved across restarts, everything else will be discarded +local storageLib = {} + +---@param key string +---@return any +function storageLib.get(key) return nil end + +---@param key string +---@param value any +---@return void +function storageLib.set(key, value) end + +---@param key string +---@return boolean +function storageLib.has(key) return nil end + +---@param key string +---@return void +function storageLib.remove(key) end + +---@param key string +---@return Accessor +function storageLib.accessor(key) return nil end + +---@class Accessor +---@overload fun(): any +---@overload fun(value: any) + +---@class Selection +---@field max Position +---@field min Position + +---@class _worldedit +_worldedit = {} + +---@overload fun(pos: Position[]): void +---@return Selection +function _worldedit.selection() return nil end + +---@param msg string +---@param callback fun(value: string): void +---@return void +function input(msg, callback) end + +---@param ticks number +---@param callback fun(): void +---@return void +function delayed(ticks, callback) end + +---@param x number +---@param y number +---@param z number +---@return Position +function pos(x, y, z) return nil end + +---@return void +function exec(...) end + +---@param obj any +---@return number +function length(obj) return 0 end + +---@param separator string +---@param table any[] +---@return string +function join(separator, table) return "" end + +---@class EventType +---@class events +---@field DoubleSwap EventType +---@field PlaceBlock EventType +---@field BreakBlock EventType +---@field RightClick EventType +---@field LeftClick EventType +---@field TNTSpawn EventType +---@field TNTExplode EventType +---@field TNTExplodeInBuild EventType +---@field SelfJoin EventType +---@field SelfLeave EventType +---@field DropItem EventType +---@field EntityDeath EventType +events = {} + + +---@param id EventType +---@param handler fun(params: any): void +---@return void +function event(id, handler) end + +---@param command string +---@param handler fun(params: string[]): void +---@return void +function command(command, handler) end + +---@param trigger string +---@param handler fun(pressed: boolean): void +---@return void +function hotkey(trigger, handler) end + +---@class bossbar +bossbar = {} + +---@alias BossBarColor 'PINK' | 'BLUE' | 'RED' | 'GREEN' | 'YELLOW' | 'PURPLE' | 'WHITE' +---@alias BossBarStyle 'SEGMENTED_6' | 'SEGMENTED_10' | 'SEGMENTED_12' | 'SEGMENTED_20' | 'SOLID' +---@alias BossBarFlag 'DARKEN_SKY' | 'PLAY_BOSS_MUSIC' | 'CREATE_FOG' + +---@class BossBar +local BossBar = {} + +---@param title string +---@param color BossBarColor +---@param style BossBarStyle +---@return BossBar +function bossbar.create(title, color, style) return nil end + +---@return string +---@overload fun(title: string): void +function BossBar.title() end + +---@return BossBarColor +---@overload fun(color: BossBarColor): void +function BossBar.color() end + +---@return BossBarStyle +---@overload fun(style: BossBarStyle): void +function BossBar.style() end + +---@return number +---@overload fun(progress: number): void +function BossBar.progress() end + +---@return boolean +---@overload fun(visible: boolean): void +function BossBar.visible() end + +---@return boolean +---@param flag BossBarFlag +function BossBar.hasFlag(flag) return nil end + +---@return void +---@param flag BossBarFlag +function BossBar.addFlag(flag) end + +---@return boolean +---@param flag BossBarFlag +function BossBar.removeFlag(flag) return nil end + +---@return void +function BossBar.destroy() end From 56e1abca7e46aed8961a7ead6e3767580a8e885f Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 16 Feb 2025 17:09:27 +0100 Subject: [PATCH 076/112] Kick player on Channel injection failure --- .../comphenix/tinyprotocol/TinyProtocol.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java index 3a0124e0..7cca9c95 100644 --- a/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -22,10 +22,8 @@ package com.comphenix.tinyprotocol; import de.steamwar.Reflection; import de.steamwar.Reflection.Field; import de.steamwar.core.Core; -import io.netty.channel.Channel; -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; +import io.netty.channel.*; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -57,15 +55,14 @@ public class TinyProtocol implements Listener { private static final Class networkManager = Reflection.getClass("net.minecraft.network.NetworkManager"); public static final Field networkManagers = Reflection.getField(serverConnection, List.class, 0, networkManager); + private static final String HANDLER_NAME = "tiny-steamwar"; public static final TinyProtocol instance = new TinyProtocol(Core.getInstance()); - private static int id = 0; public static void init() { //enforce init } private final Plugin plugin; - private final String handlerName; private final List connections; private boolean closed; @@ -74,7 +71,6 @@ public class TinyProtocol implements Listener { private TinyProtocol(final Plugin plugin) { this.plugin = plugin; - this.handlerName = "tiny-" + plugin.getName() + "-" + ++id; this.connections = networkManagers.get(getServerConnection(plugin)); plugin.getServer().getPluginManager().registerEvents(this, plugin); @@ -148,7 +144,7 @@ public class TinyProtocol implements Listener { this.player = player; channel = getChannel.get(connections.stream().filter(connection -> player.getUniqueId().equals(getUUID.get(connection))).findAny().orElseThrow(() -> { - player.kickPlayer("An injection failure happend."); + Bukkit.getScheduler().runTask(plugin, () -> player.kickPlayer("Connection failure.")); return new SecurityException("Could not find channel for player " + player.getName()); })); @@ -159,7 +155,12 @@ public class TinyProtocol implements Listener { playerInterceptors.put(player, this); } - channel.pipeline().addBefore("packet_handler", handlerName, this); + try { + channel.pipeline().addBefore("packet_handler", HANDLER_NAME, this); + } catch (IllegalArgumentException e) { + Bukkit.getScheduler().runTask(plugin, () -> player.kickPlayer("Connection failure.")); + throw new SecurityException(e); + } } private void sendPacket(Object packet) { @@ -174,7 +175,7 @@ public class TinyProtocol implements Listener { if(channel.isActive()) { channel.eventLoop().execute(() -> { try { - channel.pipeline().remove(handlerName); + channel.pipeline().remove(HANDLER_NAME); } catch (NoSuchElementException e) { // ignore } From b516d1d569b7bfc2f0605c24c9cec0814303c514 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 16 Feb 2025 17:14:55 +0100 Subject: [PATCH 077/112] Configurable techhider interaction suppression --- .../fightsystem/utils/TechHiderWrapper.java | 6 ++++++ .../src/de/steamwar/techhider/TechHider.java | 15 ++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index a01e61b4..c45d7ab6 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -32,6 +32,7 @@ import de.steamwar.fightsystem.states.StateDependent; import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.sql.SteamwarUser; import de.steamwar.techhider.TechHider; +import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -114,6 +115,11 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati }); } + @Override + public boolean suppressInteractions(Player player) { + return player.getGameMode() == GameMode.SPECTATOR; + } + @Override public boolean skipChunk(Player player, int chunkX, int chunkZ) { return getHiddenRegion(player).chunkOutside(chunkX, chunkZ); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java index bae5b7be..03063eb8 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java @@ -19,15 +19,16 @@ package de.steamwar.techhider; -import de.steamwar.Reflection; import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.Reflection; import de.steamwar.core.Core; import lombok.Getter; -import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.entity.Player; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.UnaryOperator; @@ -91,9 +92,9 @@ public class TechHider { } if(Core.getVersion() > 8){ - techhiders.put(Reflection.getClass("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket"), (p, packet) -> p.getGameMode() == GameMode.SPECTATOR ? null : packet); + techhiders.put(Reflection.getClass("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket"), (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet); } - techhiders.put(Reflection.getClass("net.minecraft.network.protocol.game.ServerboundInteractPacket"), (p, packet) -> p.getGameMode() == GameMode.SPECTATOR ? null : packet); + techhiders.put(Reflection.getClass("net.minecraft.network.protocol.game.ServerboundInteractPacket"), (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet); } @@ -161,6 +162,10 @@ public class TechHider { } public interface LocationEvaluator { + default boolean suppressInteractions(Player player) { + return false; + } + boolean skipChunk(Player player, int x, int z); default boolean skipChunkSection(Player player, int x, int y, int z) { return skipChunk(player, x, z); From 9f108a7cea8766146c1be1bebba40ec70b4726f9 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 16 Feb 2025 17:25:18 +0100 Subject: [PATCH 078/112] Update VV dependency version --- settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index cea601bf..cd1db040 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -137,8 +137,8 @@ dependencyResolutionManagement { library("velocity", "de.steamwar:velocity:RELEASE") library("velocityapi", "com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") - library("viaapi", "com.viaversion:viaversion-api:4.3.1") - library("viavelocity", "com.viaversion:viaversion-velocity:4.3.1") + library("viaapi", "com.viaversion:viaversion-api:5.2.1") + library("viavelocity", "com.viaversion:viaversion-velocity:5.2.1") library("jda", "net.dv8tion:JDA:5.2.0") library("msgpack", "org.msgpack:msgpack-core:0.9.8") library("apolloprotos", "com.lunarclient:apollo-protos:1.0-SNAPSHOT") From ef029eb420205e2c7d431529523ad07cb26a4307 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 16 Feb 2025 19:40:18 +0100 Subject: [PATCH 079/112] Add LegacyBauSystem with adaptions to current SpigotCore --- LegacyBauSystem/build.gradle.kts | 29 + .../src/de/steamwar/bausystem/BauSystem.java | 197 +++++++ .../bausystem/CraftbukkitWrapper.java | 43 ++ .../bausystem/CraftbukkitWrapper12.java | 80 +++ .../steamwar/bausystem/FlatteningWrapper.java | 53 ++ .../bausystem/FlatteningWrapper12.java | 148 +++++ .../src/de/steamwar/bausystem/Mapper.java | 87 +++ .../src/de/steamwar/bausystem/Permission.java | 26 + .../src/de/steamwar/bausystem/RamUsage.java | 44 ++ .../src/de/steamwar/bausystem/SWUtils.java | 64 +++ .../de/steamwar/bausystem/TraceEntity12.java | 77 +++ .../steamwar/bausystem/WorldeditWrapper.java | 44 ++ .../bausystem/WorldeditWrapper12.java | 114 ++++ .../bausystem/commands/CommandClear.java | 71 +++ .../bausystem/commands/CommandColor.java | 73 +++ .../bausystem/commands/CommandDebugStick.java | 41 ++ .../bausystem/commands/CommandDetonator.java | 114 ++++ .../bausystem/commands/CommandFire.java | 92 +++ .../bausystem/commands/CommandFreeze.java | 148 +++++ .../bausystem/commands/CommandGUI.java | 530 +++++++++++++++++ .../bausystem/commands/CommandGamemode.java | 50 ++ .../bausystem/commands/CommandGills.java | 53 ++ .../bausystem/commands/CommandInfo.java | 80 +++ .../bausystem/commands/CommandKillAll.java | 74 +++ .../bausystem/commands/CommandLoader.java | 134 +++++ .../bausystem/commands/CommandLockschem.java | 67 +++ .../bausystem/commands/CommandNV.java | 54 ++ .../bausystem/commands/CommandProtect.java | 127 ++++ .../commands/CommandRedstoneTester.java | 52 ++ .../bausystem/commands/CommandRegion.java | 132 +++++ .../bausystem/commands/CommandReset.java | 91 +++ .../bausystem/commands/CommandScript.java | 94 +++ .../bausystem/commands/CommandScriptVars.java | 120 ++++ .../bausystem/commands/CommandSelect.java | 124 ++++ .../bausystem/commands/CommandSkull.java | 49 ++ .../bausystem/commands/CommandSpeed.java | 70 +++ .../bausystem/commands/CommandTNT.java | 173 ++++++ .../bausystem/commands/CommandTPSLimiter.java | 176 ++++++ .../bausystem/commands/CommandTeleport.java | 46 ++ .../bausystem/commands/CommandTestblock.java | 128 +++++ .../bausystem/commands/CommandTime.java | 99 ++++ .../bausystem/commands/CommandTrace.java | 132 +++++ .../bausystem/commands/CommandWorldSpawn.java | 45 ++ .../bausystem/commands/RegionUtils.java | 42 ++ .../steamwar/bausystem/gui/GuiTraceShow.java | 133 +++++ .../bausystem/tracer/AbstractTraceEntity.java | 34 ++ .../bausystem/tracer/RoundedTNTPosition.java | 65 +++ .../bausystem/tracer/TNTPosition.java | 63 ++ .../tracer/record/RecordStateMachine.java | 94 +++ .../bausystem/tracer/record/RecordStatus.java | 55 ++ .../bausystem/tracer/record/Recorder.java | 96 ++++ .../tracer/record/TraceAutoHandler.java | 70 +++ .../bausystem/tracer/show/Record.java | 94 +++ .../bausystem/tracer/show/ShowMode.java | 28 + .../tracer/show/ShowModeParameter.java | 57 ++ .../tracer/show/ShowModeParameterType.java | 44 ++ .../bausystem/tracer/show/StoredRecords.java | 45 ++ .../tracer/show/TraceShowManager.java | 59 ++ .../tracer/show/mode/EntityShowMode.java | 120 ++++ .../steamwar/bausystem/world/AFKStopper.java | 56 ++ .../bausystem/world/AbstractAutoLoader.java | 122 ++++ .../steamwar/bausystem/world/AutoLoader.java | 266 +++++++++ .../bausystem/world/BauScoreboard.java | 111 ++++ .../bausystem/world/ClipboardListener.java | 63 ++ .../de/steamwar/bausystem/world/Color.java | 39 ++ .../steamwar/bausystem/world/Detoloader.java | 87 +++ .../steamwar/bausystem/world/Detonator.java | 120 ++++ .../bausystem/world/DetonatorListener.java | 65 +++ .../bausystem/world/ItemFrameListener.java | 52 ++ .../bausystem/world/PredefinedBook.java | 124 ++++ .../bausystem/world/RegionListener.java | 137 +++++ .../bausystem/world/ScriptListener.java | 542 ++++++++++++++++++ .../steamwar/bausystem/world/SizedStack.java | 123 ++++ .../de/steamwar/bausystem/world/TPSUtils.java | 77 +++ .../src/de/steamwar/bausystem/world/Welt.java | 51 ++ .../bausystem/world/regions/GlobalRegion.java | 64 +++ .../bausystem/world/regions/PasteOptions.java | 99 ++++ .../bausystem/world/regions/Point.java | 31 + .../bausystem/world/regions/Prototype.java | 204 +++++++ .../bausystem/world/regions/Region.java | 388 +++++++++++++ .../world/regions/RegionExtensionType.java | 25 + .../world/regions/RegionSelectionType.java | 25 + .../bausystem/world/regions/RegionType.java | 26 + LegacyBauSystem/src/plugin.yml | 9 + settings.gradle.kts | 2 + steamwarci.yml | 1 + 86 files changed, 8253 insertions(+) create mode 100644 LegacyBauSystem/build.gradle.kts create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper12.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper12.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/Permission.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/RamUsage.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/SWUtils.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/TraceEntity12.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper12.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandClear.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandColor.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDebugStick.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDetonator.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFire.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFreeze.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGUI.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGamemode.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGills.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandKillAll.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLoader.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandNV.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandProtect.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRegion.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandReset.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScript.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScriptVars.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSelect.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSkull.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSpeed.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTNT.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTPSLimiter.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTeleport.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTestblock.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTime.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTrace.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandWorldSpawn.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/commands/RegionUtils.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/gui/GuiTraceShow.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/AbstractTraceEntity.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/RoundedTNTPosition.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/TNTPosition.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStateMachine.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStatus.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/Recorder.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/TraceAutoHandler.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/Record.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowMode.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameter.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameterType.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/StoredRecords.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/TraceShowManager.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/mode/EntityShowMode.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/AFKStopper.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/AbstractAutoLoader.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/AutoLoader.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/BauScoreboard.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/ClipboardListener.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/Color.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/Detoloader.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/Detonator.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/DetonatorListener.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/ItemFrameListener.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/PredefinedBook.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/RegionListener.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/ScriptListener.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/SizedStack.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/TPSUtils.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/Welt.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/GlobalRegion.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/PasteOptions.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Point.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Prototype.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Region.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionExtensionType.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionSelectionType.java create mode 100644 LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionType.java create mode 100644 LegacyBauSystem/src/plugin.yml diff --git a/LegacyBauSystem/build.gradle.kts b/LegacyBauSystem/build.gradle.kts new file mode 100644 index 00000000..a3f42811 --- /dev/null +++ b/LegacyBauSystem/build.gradle.kts @@ -0,0 +1,29 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2024 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 . + */ + +plugins { + steamwar.java +} + +dependencies { + compileOnly(project(":SpigotCore", "default")) + + compileOnly(libs.nms12) + compileOnly(libs.worldedit12) +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java b/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java new file mode 100644 index 00000000..56af8fd7 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java @@ -0,0 +1,197 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.commands.*; +import de.steamwar.bausystem.world.*; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.core.Core; +import de.steamwar.providers.BauServerInfo; +import de.steamwar.scoreboard.SWScoreboard; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import java.util.UUID; +import java.util.logging.Level; + +public class BauSystem extends JavaPlugin implements Listener { + + private static BauSystem plugin; + private static Integer owner; + public static final String PREFIX = "§eBauSystem§8» §7"; + + private BukkitTask autoShutdown; + + @Override + public void onEnable() { + plugin = this; + + Mapper.init(); + + new CommandTrace(); + new CommandTPSLimiter(); + new CommandNV(); + new CommandReset(); + new CommandSpeed(); + new CommandTNT(); + new CommandGamemode(); + new CommandClear(); + new CommandTime(); + new CommandTeleport(); + new CommandFire(); + new CommandFreeze(); + new CommandTestblock(); + new CommandInfo(); + new CommandProtect(); + new CommandSkull(); + new CommandLoader(); + new CommandLockschem(); + new CommandDebugStick(); + new CommandGills(); + new CommandDetonator(); + new CommandScript(); + new CommandScriptVars(); + new CommandRedstoneTester(); + new CommandGUI(); + new CommandWorldSpawn(); + new CommandRegion(); + new CommandSelect(); + new CommandKillAll(); + + if (Core.getVersion() > 14 && Region.buildAreaEnabled()) { + new CommandColor(); + } + + Bukkit.getPluginManager().registerEvents(this, this); + Bukkit.getPluginManager().registerEvents(new RegionListener(), this); + Bukkit.getPluginManager().registerEvents(new ScriptListener(), this); + Bukkit.getPluginManager().registerEvents(new BauScoreboard(), this); + Bukkit.getPluginManager().registerEvents(new ClipboardListener(), this); + Bukkit.getPluginManager().registerEvents(new CommandGUI(), this); + Bukkit.getPluginManager().registerEvents(new DetonatorListener(), this); + Bukkit.getPluginManager().registerEvents(new ItemFrameListener(), this); + new AFKStopper(); + + autoShutdown = Bukkit.getScheduler().runTaskLater(this, Bukkit::shutdown, 1200); + TPSUtils.init(); + } + + @Override + public void onDisable() { + Region.save(); + } + + public static BauSystem getPlugin() { + return plugin; + } + + public static UUID getOwner() { + return SteamwarUser.get(getOwnerID()).getUUID(); + } + + public static int getOwnerID() { + //Lazy loading to improve startup time of the server in 1.15 + if (owner == null) { + owner = BauServerInfo.getOwnerId(); + } + return owner; + } + + @EventHandler + public void onDeath(PlayerDeathEvent e) { + e.setDeathMessage(null); + } + + @EventHandler + public void onJoin(PlayerLoginEvent e) { + if (autoShutdown != null) { + autoShutdown.cancel(); + autoShutdown = null; + } + + Player p = e.getPlayer(); + p.setOp(true); + } + + @EventHandler + public void onLeave(PlayerQuitEvent e) { + Player p = e.getPlayer(); + SWScoreboard.impl.removeScoreboard(p); + if (Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().size() == 1 && Bukkit.getOnlinePlayers().contains(p))) { + if (autoShutdown != null) { + autoShutdown.cancel(); + } + CommandTPSLimiter.setTPS(20.0); + autoShutdown = Bukkit.getScheduler().runTaskTimer(this, new Runnable() { + int count = 0; + + @Override + public void run() { + if (count >= 300) { + Bukkit.shutdown(); + return; + } + count++; + try { + if (RamUsage.getUsage() > 0.8) { + Bukkit.shutdown(); + } + } catch (Throwable throwable) { + Bukkit.getLogger().log(Level.WARNING, throwable.getMessage(), throwable); + Bukkit.shutdown(); + } + } + }, 20, 20); + } + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent e) { + ItemStack stack = e.getCursor(); + if (stack == null || !stack.hasItemMeta()) + return; + assert stack.getItemMeta() != null; + if (stack.getItemMeta().hasEnchants()) { + for (Enchantment en : Enchantment.values()) { + if (stack.getEnchantmentLevel(en) > en.getMaxLevel()) + stack.removeEnchantment(en); + } + } + + Material material = stack.getType(); + if (material == Material.POTION || material == Material.SPLASH_POTION || material == Material.LINGERING_POTION) { + stack.setType(Material.MILK_BUCKET); + } + + e.setCurrentItem(stack); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper.java b/LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper.java new file mode 100644 index 00000000..8dca9a27 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper.java @@ -0,0 +1,43 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.tracer.AbstractTraceEntity; +import de.steamwar.core.VersionDependent; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class CraftbukkitWrapper { + private CraftbukkitWrapper() {} + + public static final ICraftbukkitWrapper impl = VersionDependent.getVersionImpl(BauSystem.getPlugin()); + + public interface ICraftbukkitWrapper { + void initTPS(); + void createTickCache(World world); + void sendTickPackets(); + + void openSignEditor(Player player, Location location); + + AbstractTraceEntity create(World world, Vector tntPosition, boolean tnt); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper12.java b/LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper12.java new file mode 100644 index 00000000..46c1dbcb --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/CraftbukkitWrapper12.java @@ -0,0 +1,80 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.tracer.AbstractTraceEntity; +import de.steamwar.bausystem.world.TPSUtils; +import net.minecraft.server.v1_12_R1.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public class CraftbukkitWrapper12 implements CraftbukkitWrapper.ICraftbukkitWrapper { + + private final List> packets = new ArrayList<>(); + + @Override + public void initTPS() { + TPSUtils.disableWarp(); + } + + @Override + public void createTickCache(World world) { + packets.clear(); + world.getEntities().stream().filter(entity -> !(entity instanceof Player)).forEach(entity -> { + packets.add(new PacketPlayOutEntityVelocity(entity.getEntityId(), 0, 0, 0)); + packets.add(new PacketPlayOutEntityTeleport(((CraftEntity) entity).getHandle())); + + if (entity instanceof TNTPrimed) { + net.minecraft.server.v1_12_R1.Entity serverEntity = ((CraftEntity) entity).getHandle(); + packets.add(new PacketPlayOutEntityMetadata(serverEntity.getId(), serverEntity.getDataWatcher(), true)); + } + }); + } + + @Override + public void sendTickPackets() { + Bukkit.getOnlinePlayers().forEach(player -> { + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + for (Packet p : packets) { + connection.sendPacket(p); + } + }); + } + + @Override + public void openSignEditor(Player player, Location location) { + PacketPlayOutOpenSignEditor packet = new PacketPlayOutOpenSignEditor(new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ())); + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + } + + @Override + public AbstractTraceEntity create(World world, Vector tntPosition, boolean tnt) { + return new TraceEntity12(world, tntPosition, tnt); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper.java b/LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper.java new file mode 100644 index 00000000..2fbbcb64 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper.java @@ -0,0 +1,53 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.world.Detoloader; +import de.steamwar.core.VersionDependent; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +public class FlatteningWrapper { + private FlatteningWrapper(){} + + public static final IFlatteningWrapper impl = VersionDependent.getVersionImpl(BauSystem.getPlugin()); + + public interface IFlatteningWrapper { + boolean tntPlaceActionPerform(Location location); + boolean setRedstone(Location location, boolean active); + Detoloader onPlayerInteractLoader(PlayerInteractEvent event); + boolean getLever(Block block); + + boolean isNoBook(ItemStack item); + + boolean inWater(World world, Vector tntPosition); + Material getTraceShowMaterial(); + Material getTraceHideMaterial(); + Material getTraceXZMaterial(); + + void giveStick(Player player); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper12.java b/LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper12.java new file mode 100644 index 00000000..b6cf7359 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/FlatteningWrapper12.java @@ -0,0 +1,148 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.world.Detoloader; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.stream.Collectors; + +public class FlatteningWrapper12 implements FlatteningWrapper.IFlatteningWrapper { + + @Override + public boolean tntPlaceActionPerform(Location location) { + Material m = location.getBlock().getType(); + if (m != Material.AIR && m != Material.STATIONARY_WATER && m != Material.WATER) + return false; + + location.getBlock().setType(Material.TNT); + return true; + } + + @Override + @SuppressWarnings("deprecation") + public boolean setRedstone(Location location, boolean active) { + Block block = location.getBlock(); + Material material = block.getType(); + if (material == Material.LEVER || material == Material.STONE_BUTTON || material == Material.WOOD_BUTTON) { + if (active) + block.setData((byte) (block.getData() | 8)); + else + block.setData((byte) (block.getData() & -9)); + } else if (material == Material.STONE_PLATE || material == Material.WOOD_PLATE) { + if (active) + block.setData((byte) 1); + else + block.setData((byte) 0); + } else if (material == Material.TRIPWIRE) { + if (active) { + ArmorStand armorStand = (ArmorStand) Bukkit.getWorlds().get(0).spawnEntity(location, EntityType.ARMOR_STAND); + armorStand.setVisible(false); + armorStand.setBasePlate(false); + armorStand.addScoreboardTag("detonator-" + location.getBlockX() + location.getBlockY() + location.getBlockZ()); + } else { + List entityList = Bukkit.getWorlds().get(0).getEntitiesByClasses(ArmorStand.class).stream().filter(entity -> + entity.getScoreboardTags().contains("detonator-" + location.getBlockX() + location.getBlockY() + location.getBlockZ())) + .limit(1) + .collect(Collectors.toList()); + if (entityList.isEmpty()) return false; + entityList.get(0).remove(); + } + } else { + return false; + } + block.getState().update(true); + return true; + } + + @Override + @SuppressWarnings("deprecation") + public Detoloader onPlayerInteractLoader(PlayerInteractEvent event) { + Block block = event.getClickedBlock(); + Material material = block.getType(); + if (material == Material.LEVER) { + if ((block.getData() & 8) == 8) { + return new Detoloader("Hebel", 0).setActive(false); + } else { + return new Detoloader("Hebel", 0).setActive(true); + } + } else if (material == Material.STONE_BUTTON) { + return new Detoloader("Knopf", Detoloader.STONE_BUTTON); + } else if (material == Material.WOOD_BUTTON) { + return new Detoloader("Knopf", Detoloader.WOODEN_BUTTON); + } else if (material == Material.NOTE_BLOCK) { + return new Detoloader("Noteblock", Detoloader.NOTE_BLOCK); + } else if (material == Material.STONE_PLATE || material == Material.WOOD_PLATE) { + return new Detoloader("Druckplatte", Detoloader.PRESSURE_PLATE); + } else if (material == Material.TRIPWIRE) { + return new Detoloader("Tripwire", Detoloader.TRIPWIRE); + } + return new Detoloader("§eUnbekannter Block betätigt (nicht aufgenommen)", -1).setAddBack(false); + } + + @Override + @SuppressWarnings("deprecation") + public boolean getLever(Block block) { + return (block.getData() & 8) == 8; + } + + @Override + public boolean isNoBook(ItemStack item) { + return item.getType() != Material.BOOK_AND_QUILL && item.getType() != Material.WRITTEN_BOOK; + } + + @Override + public boolean inWater(World world, Vector tntPosition) { + Material material = world.getBlockAt(tntPosition.getBlockX(), tntPosition.getBlockY(), tntPosition.getBlockZ()).getType(); + return material == Material.WATER || material == Material.STATIONARY_WATER; + } + + @Override + public Material getTraceShowMaterial() { + return Material.CONCRETE; + } + + @Override + public Material getTraceHideMaterial() { + return Material.CONCRETE; + } + + @Override + public Material getTraceXZMaterial() { + return Material.STEP; + } + + @Override + public void giveStick(Player player) { + player.sendMessage(BauSystem.PREFIX + "§cDen Debugstick gibt es nicht in der 1.12."); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java b/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java new file mode 100644 index 00000000..591fdd08 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/Mapper.java @@ -0,0 +1,87 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.tracer.show.ShowModeParameterType; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import de.steamwar.sql.BauweltMember; +import de.steamwar.sql.SteamwarUser; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +public class Mapper { + + private Mapper() { + throw new IllegalStateException("Utility Class"); + } + + public static void init() { + SWCommandUtils.addMapper(ShowModeParameterType.class, showModeParameterTypesTypeMapper()); + SWCommandUtils.addMapper(BauweltMember.class, bauweltMemberTypeMapper()); + } + + private static TypeMapper showModeParameterTypesTypeMapper() { + Map showModeParameterTypesMap = new HashMap<>(); + showModeParameterTypesMap.put("-water", ShowModeParameterType.WATER); + + showModeParameterTypesMap.put("-interpolatey", ShowModeParameterType.INTERPOLATE_Y); + showModeParameterTypesMap.put("-interpolate-y", ShowModeParameterType.INTERPOLATE_Y); + showModeParameterTypesMap.put("-interpolate_y", ShowModeParameterType.INTERPOLATE_Y); + showModeParameterTypesMap.put("-y", ShowModeParameterType.INTERPOLATE_Y); + + showModeParameterTypesMap.put("-interpolatex", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-interpolate-x", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-interpolate_x", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-x", ShowModeParameterType.INTERPOLATE_XZ); + + showModeParameterTypesMap.put("-interpolatez", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-interpolate-z", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-interpolate_z", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-z", ShowModeParameterType.INTERPOLATE_XZ); + + showModeParameterTypesMap.put("-interpolatexz", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-interpolate-xz", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-interpolate_xz", ShowModeParameterType.INTERPOLATE_XZ); + showModeParameterTypesMap.put("-xz", ShowModeParameterType.INTERPOLATE_XZ); + + showModeParameterTypesMap.put("-advanced", ShowModeParameterType.ADVANCED); + showModeParameterTypesMap.put("-a", ShowModeParameterType.ADVANCED); + showModeParameterTypesMap.put("advanced", ShowModeParameterType.ADVANCED); + showModeParameterTypesMap.put("a", ShowModeParameterType.ADVANCED); + + List tabCompletes = new ArrayList<>(showModeParameterTypesMap.keySet()); + return SWCommandUtils.createMapper(s -> showModeParameterTypesMap.getOrDefault(s, null), s -> tabCompletes); + } + + private static TypeMapper bauweltMemberTypeMapper() { + return SWCommandUtils.createMapper(s -> BauweltMember.getMembers(BauSystem.getOwnerID()) + .stream() + .filter(m -> SteamwarUser.get(m.getMemberID()).getUserName().equals(s)).findFirst().orElse(null), + s -> BauweltMember.getMembers(BauSystem.getOwnerID()) + .stream() + .map(m -> SteamwarUser.get(m.getMemberID()).getUserName()) + .collect(Collectors.toList())); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/Permission.java b/LegacyBauSystem/src/de/steamwar/bausystem/Permission.java new file mode 100644 index 00000000..f3e50856 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/Permission.java @@ -0,0 +1,26 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem; + +public enum Permission { + WORLD, + WORLDEDIT, + MEMBER +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/RamUsage.java b/LegacyBauSystem/src/de/steamwar/bausystem/RamUsage.java new file mode 100644 index 00000000..b3fc6fd4 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/RamUsage.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import org.bukkit.Bukkit; + +import java.lang.management.ManagementFactory; +import java.util.logging.Level; + +public class RamUsage { + + private RamUsage() { + throw new IllegalStateException("Utility Class"); + } + + public static double getUsage() { + try { + long memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + long freeMemory = ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getFreePhysicalMemorySize(); + return (memorySize - freeMemory) / (double) memorySize; + } catch (Throwable throwable) { + Bukkit.getLogger().log(Level.WARNING, throwable.getMessage(), throwable); + return 1D; + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/SWUtils.java b/LegacyBauSystem/src/de/steamwar/bausystem/SWUtils.java new file mode 100644 index 00000000..5f22d5be --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/SWUtils.java @@ -0,0 +1,64 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +public class SWUtils { + + public static void giveItemToPlayer(Player player, ItemStack itemStack) { + if (itemStack == null || itemStack.getType() == Material.AIR) { + return; + } + for (int i = 0; i < player.getInventory().getSize(); i++) { + ItemStack current = player.getInventory().getItem(i); + if (current != null && current.isSimilar(itemStack)) { + player.getInventory().setItem(i, null); + itemStack = current; + break; + } + } + ItemStack current = player.getInventory().getItemInMainHand(); + player.getInventory().setItemInMainHand(itemStack); + if (current.getType() != Material.AIR) { + player.getInventory().addItem(current); + } + } + + public static List manageList(List strings, String[] args, int index) { + strings = new ArrayList<>(strings); + for (int i = strings.size() - 1; i >= 0; i--) { + if (!strings.get(i).startsWith(args[index])) { + strings.remove(i); + } + } + return strings; + } + + public static List manageList(List strings, String[] args) { + return manageList(strings, args, args.length - 1); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/TraceEntity12.java b/LegacyBauSystem/src/de/steamwar/bausystem/TraceEntity12.java new file mode 100644 index 00000000..b30fc9eb --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/TraceEntity12.java @@ -0,0 +1,77 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import de.steamwar.bausystem.tracer.AbstractTraceEntity; +import net.minecraft.server.v1_12_R1.*; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +class TraceEntity12 extends EntityFallingBlock implements AbstractTraceEntity { + + private boolean exploded; + private int references; + + public TraceEntity12(World world, Vector position, boolean tnt) { + super(((CraftWorld) world).getHandle(), position.getX(), position.getY(), position.getZ(), tnt ? Blocks.TNT.getBlockData() : Blocks.STAINED_GLASS.getBlockData()); + + this.setNoGravity(true); + this.ticksLived = -12000; + } + + @Override + public void display(Player player, boolean exploded) { + if (!this.exploded && exploded) { + this.setCustomNameVisible(true); + this.setCustomName("Bumm"); + this.exploded = true; + if (references++ > 0) + sendDestroy(player); + } else if (references++ > 0) + return; + + PacketPlayOutSpawnEntity packetPlayOutSpawnEntity = new PacketPlayOutSpawnEntity(this, 70, Block.getCombinedId(getBlock())); + PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; + playerConnection.sendPacket(packetPlayOutSpawnEntity); + + PacketPlayOutEntityMetadata packetPlayOutEntityMetadata = new PacketPlayOutEntityMetadata(getId(), datawatcher, true); + playerConnection.sendPacket(packetPlayOutEntityMetadata); + + } + + @Override + public boolean hide(Player player, boolean force) { + if (!force && --references > 0) + return false; + + sendDestroy(player); + die(); + return true; + } + + private void sendDestroy(Player player) { + PacketPlayOutEntityDestroy packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(getId()); + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packetPlayOutEntityDestroy); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper.java b/LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper.java new file mode 100644 index 00000000..8ba9bcc7 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import de.steamwar.bausystem.world.regions.PasteOptions; +import de.steamwar.bausystem.world.regions.Point; +import de.steamwar.core.VersionDependent; +import org.bukkit.entity.Player; + +import java.io.File; + +public class WorldeditWrapper { + private WorldeditWrapper() {} + + public static final IWorldeditWrapper impl = VersionDependent.getVersionImpl(BauSystem.getPlugin()); + + public interface IWorldeditWrapper { + void setSelection(Player p, Point minPoint, Point maxPoint); + + EditSession paste(File file, int x, int y, int z, PasteOptions pasteOptions); + EditSession paste(Clipboard clipboard, int x, int y, int z, PasteOptions pasteOptions); + + boolean isWorldEditCommand(String command); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper12.java b/LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper12.java new file mode 100644 index 00000000..8fdf94ac --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/WorldeditWrapper12.java @@ -0,0 +1,114 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.transform.AffineTransform; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; +import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.world.World; +import de.steamwar.bausystem.world.regions.PasteOptions; +import de.steamwar.bausystem.world.regions.Point; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Objects; + +public class WorldeditWrapper12 implements WorldeditWrapper.IWorldeditWrapper { + + private final WorldEditPlugin WORLDEDIT_PLUGIN = ((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit")); + private final World BUKKITWORLD = new BukkitWorld(Bukkit.getWorlds().get(0)); + + @Override + public void setSelection(Player p, Point minPoint, Point maxPoint) { + WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, toVector(minPoint), toVector(maxPoint))); + } + + @Override + public EditSession paste(File file, int x, int y, int z, PasteOptions pasteOptions) { + World w = new BukkitWorld(Bukkit.getWorlds().get(0)); + Clipboard clipboard; + try { + clipboard = Objects.requireNonNull(ClipboardFormat.findByFile(file)).getReader(new FileInputStream(file)).read(w.getWorldData()); + } catch (NullPointerException | IOException e) { + throw new SecurityException("Bausystem schematic not found", e); + } + + return paste(clipboard, x, y, z, pasteOptions); + } + + @Override + public EditSession paste(Clipboard clipboard, int x, int y, int z, PasteOptions pasteOptions) { + World w = new BukkitWorld(Bukkit.getWorlds().get(0)); + + Vector dimensions = clipboard.getDimensions(); + Vector v = new Vector(x, y, z); + Vector offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); + AffineTransform aT = new AffineTransform(); + if (pasteOptions.isRotate()) { + aT = aT.rotateY(180); + v = v.add(dimensions.getX() / 2 + dimensions.getX() % 2, 0, dimensions.getZ() / 2 + dimensions.getZ() % 2).subtract(offset.multiply(-1, 1, -1)).subtract(1, 0, 1); + } else { + v = v.subtract(dimensions.getX() / 2 - dimensions.getX() % 2, 0, dimensions.getZ() / 2 - dimensions.getZ() % 2).subtract(offset); + } + + EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1); + ClipboardHolder ch = new ClipboardHolder(clipboard, w.getWorldData()); + ch.setTransform(aT); + + if (pasteOptions.isReset()) { + try { + e.setBlocks(new CuboidRegion(toVector(pasteOptions.getMinPoint()), toVector(pasteOptions.getMaxPoint())), new BaseBlock(BlockID.AIR)); + } catch (MaxChangedBlocksException ex) { + throw new SecurityException("Max blocks changed?", ex); + } + } + Operations.completeBlindly(ch.createPaste(e, w.getWorldData()).to(v).ignoreAirBlocks(pasteOptions.isIgnoreAir()).build()); + return e; + } + + @Override + public boolean isWorldEditCommand(String command) { + if (command.startsWith("/")) { + command = command.replaceFirst("/", ""); + } + command = command.toLowerCase(); + return ((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit")).getWorldEdit().getPlatformManager() + .getCommandManager().getDispatcher().get(command) != null; + } + + private Vector toVector(Point point) { + return Vector.toBlockPoint(point.getX(), point.getY(), point.getZ()); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandClear.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandClear.java new file mode 100644 index 00000000..195d0f35 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandClear.java @@ -0,0 +1,71 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class CommandClear extends SWCommand { + + public CommandClear() { + super("clear"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eclear §8- §7Leere dein Inventar"); + p.sendMessage("§8/§ebau clear §8[§7Player§8] §8- §7Leere ein Spieler Inventar"); + } + + @Register + public void genericClearCommand(Player p) { + clear(p); + p.sendMessage(BauSystem.PREFIX + "Dein Inventar wurde geleert."); + } + + @Register + public void clearPlayerCommand(Player p, Player target) { + if (!permissionCheck(p)) return; + clear(target); + target.sendMessage(BauSystem.PREFIX + "Dein Inventar wurde von " + p.getDisplayName() + " §7geleert."); + p.sendMessage(BauSystem.PREFIX + "Das Inventar von " + target.getDisplayName() + " §7wurde geleert."); + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier keine fremden Inventare leeren."); + return false; + } + return true; + } + + private void clear(Player player) { + player.getInventory().clear(); + player.getInventory().setHelmet(new ItemStack(Material.AIR)); + player.getInventory().setChestplate(new ItemStack(Material.AIR)); + player.getInventory().setLeggings(new ItemStack(Material.AIR)); + player.getInventory().setBoots(new ItemStack(Material.AIR)); + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandColor.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandColor.java new file mode 100644 index 00000000..ddd04fe9 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandColor.java @@ -0,0 +1,73 @@ +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.world.Color; +import de.steamwar.bausystem.world.regions.GlobalRegion; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + + +public class CommandColor extends SWCommand { + + private static CommandColor instance = null; + + public CommandColor() { + super("color"); + instance = this; + } + + public static CommandColor getInstance() { + return instance; + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§ecolor §8[§7Color§8] §8- §7Setze die Farbe der Region"); + p.sendMessage("§8/§ecolor §8[§7Color§8] §8[§7Type§8] §8- §7Setze die Farbe der Region oder Global"); + } + + @Register + public void genericColor(Player p, Color color) { + genericColorSet(p, color, ColorizationType.LOCAL); + } + + @Register + public void genericColorSet(Player p, Color color, ColorizationType colorizationType) { + if (!permissionCheck(p)) { + return; + } + if (colorizationType == ColorizationType.GLOBAL) { + Region.setGlobalColor(color); + p.sendMessage(BauSystem.PREFIX + "Alle Regions farben auf §e" + color.name().toLowerCase() + "§7 gesetzt"); + return; + } + Region region = Region.getRegion(p.getLocation()); + if (GlobalRegion.isGlobalRegion(region)) { + p.sendMessage(BauSystem.PREFIX + "§cDu befindest dich derzeit in keiner Region"); + return; + } + region.setColor(color); + p.sendMessage(BauSystem.PREFIX + "Regions farben auf §e" + color.name().toLowerCase() + "§7 gesetzt"); + } + + @Register + public void genericColorSet(Player p, ColorizationType colorizationType, Color color) { + genericColorSet(p, color, colorizationType); + } + + private boolean permissionCheck(Player p) { + if (!BauSystem.getOwner().equals(p.getUniqueId())) { + p.sendMessage(BauSystem.PREFIX + "§cDies ist nicht deine Welt!"); + return false; + } else { + return true; + } + } + + public enum ColorizationType { + LOCAL, + GLOBAL + } + +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDebugStick.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDebugStick.java new file mode 100644 index 00000000..33c045a0 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDebugStick.java @@ -0,0 +1,41 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.FlatteningWrapper; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + +public class CommandDebugStick extends SWCommand { + + public CommandDebugStick() { + super("debugstick"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§edebugstick §8- §7Erhalte einen DebugStick"); + } + + @Register + public void genericCommand(Player p) { + FlatteningWrapper.impl.giveStick(p); + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDetonator.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDetonator.java new file mode 100644 index 00000000..ca2bb9c7 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandDetonator.java @@ -0,0 +1,114 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.world.Detonator; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + +public class CommandDetonator extends SWCommand { + + public CommandDetonator() { + super ("detonator", "dt"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§edetonator wand §8- §7Legt den Fernzünder ins Inventar"); + p.sendMessage("§8/§edetonator detonate §8- §7Benutzt den nächst besten Fernzünder"); + p.sendMessage("§8/§edetonator reset §8- §7Löscht alle markierten Positionen"); + p.sendMessage("§8/§edetonator remove §8- §7Entfernt den Fernzünder"); + } + + @Register("wand") + public void wandCommand(Player p) { + if (!permissionCheck(p)) return; + SWUtils.giveItemToPlayer(p, Detonator.WAND); + } + + @Register("detonator") + public void detonatorCommand(Player p) { + if (!permissionCheck(p)) return; + SWUtils.giveItemToPlayer(p, Detonator.WAND); + } + + @Register("item") + public void itemCommand(Player p) { + if (!permissionCheck(p)) return; + SWUtils.giveItemToPlayer(p, Detonator.WAND); + } + + + @Register("remove") + public void removeCommand(Player p) { + if (!permissionCheck(p)) return; + p.getInventory().removeItem(Detonator.WAND); + } + + + @Register("detonate") + public void detonateCommand(Player p) { + if (!permissionCheck(p)) return; + Detonator.execute(p); + } + + @Register("click") + public void clickCommand(Player p) { + if (!permissionCheck(p)) return; + Detonator.execute(p); + } + + @Register("use") + public void useCommand(Player p) { + if (!permissionCheck(p)) return; + Detonator.execute(p); + } + + + @Register("clear") + public void clearCommand(Player p) { + if (!permissionCheck(p)) return; + Detonator.clear(p); + } + + @Register("delete") + public void deleteCommand(Player p) { + if (!permissionCheck(p)) return; + Detonator.clear(p); + } + + @Register("reset") + public void resetCommand(Player p) { + if (!permissionCheck(p)) return; + Detonator.clear(p); + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Detonator nutzen"); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFire.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFire.java new file mode 100644 index 00000000..56b48621 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFire.java @@ -0,0 +1,92 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockSpreadEvent; + +public class CommandFire extends SWCommand implements Listener { + + public CommandFire() { + super("fire"); + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§efire §8- §7Toggle Feuerschaden"); + } + + @Register + public void toggleCommand(Player p) { + if (!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + if (toggle(region)) { + RegionUtils.actionBar(region, getEnableMessage()); + } else { + RegionUtils.actionBar(region, getDisableMessage()); + } + } + + private String getNoPermMessage() { + return "§cDu darfst hier nicht Feuerschaden (de-)aktivieren"; + } + + private String getEnableMessage() { + return "§cRegions Feuerschaden deaktiviert"; + } + + private String getDisableMessage() { + return "§aRegions Feuerschaden aktiviert"; + } + + private boolean toggle(Region region) { + region.setFire(!region.isFire()); + return region.isFire(); + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + getNoPermMessage()); + return false; + } + return true; + } + + @EventHandler + public void onFireDamage(BlockBurnEvent e) { + if (Region.getRegion(e.getBlock().getLocation()).isFire()) e.setCancelled(true); + } + + @EventHandler + public void onFireSpread(BlockSpreadEvent e) { + if (Region.getRegion(e.getBlock().getLocation()).isFire()) e.setCancelled(true); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFreeze.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFreeze.java new file mode 100644 index 00000000..a3460edd --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandFreeze.java @@ -0,0 +1,148 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import de.steamwar.core.Core; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.*; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.inventory.InventoryMoveItemEvent; + +public class CommandFreeze extends SWCommand implements Listener { + + public CommandFreeze() { + super("freeze", "stoplag"); + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§efreeze §8- §7Toggle Freeze"); + } + + @Register + public void toggleCommand(Player p) { + if (!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + if (toggle(region)) { + RegionUtils.actionBar(region, getEnableMessage()); + } else { + RegionUtils.actionBar(region, getDisableMessage()); + } + } + + private String getNoPermMessage() { + return "§cDu darfst diese Welt nicht einfrieren"; + } + + private String getEnableMessage(){ + return "§cRegion eingefroren"; + } + + private String getDisableMessage(){ + return "§aRegion aufgetaut"; + } + + private boolean toggle(Region region) { + region.setFreeze(!region.isFreeze()); + return region.isFreeze(); + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + getNoPermMessage()); + return false; + } + return true; + } + + @EventHandler + public void onEntitySpawn(EntitySpawnEvent e) { + if (!Region.getRegion(e.getLocation()).isFreeze()) return; + e.setCancelled(true); + if (e.getEntityType() == EntityType.PRIMED_TNT) { + Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), () -> { + e.getLocation().getBlock().setType(Material.TNT, false); + }, 1L); + } + } + + @EventHandler + public void onBlockCanBuild(BlockCanBuildEvent e) { + if (Core.getVersion() == 12) return; + if (!e.isBuildable()) return; + if (!Region.getRegion(e.getBlock().getLocation()).isFreeze()) return; + if (e.getMaterial() == Material.TNT) { + e.setBuildable(false); + e.getBlock().setType(Material.TNT, false); + } + } + + @EventHandler + public void onEntityChangeBlock(EntityChangeBlockEvent e) { + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setCancelled(true); + } + + @EventHandler + public void onPhysicsEvent(BlockPhysicsEvent e){ + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setCancelled(true); + } + + @EventHandler + public void onPistonExtend(BlockPistonExtendEvent e){ + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setCancelled(true); + } + + @EventHandler + public void onPistonRetract(BlockPistonRetractEvent e){ + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setCancelled(true); + } + + @EventHandler + public void onBlockGrow(BlockGrowEvent e){ + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setCancelled(true); + } + + @EventHandler + public void onRedstoneEvent(BlockRedstoneEvent e) { + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setNewCurrent(e.getOldCurrent()); + } + + @EventHandler + public void onBlockDispense(BlockDispenseEvent e) { + if (Region.getRegion(e.getBlock().getLocation()).isFreeze()) e.setCancelled(true); + } + + @EventHandler + public void onInventoryMoveEvent(InventoryMoveItemEvent e){ + if (Region.getRegion(e.getDestination().getLocation()).isFreeze()) e.setCancelled(true); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGUI.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGUI.java new file mode 100644 index 00000000..076d7c9d --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGUI.java @@ -0,0 +1,530 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.tracer.record.RecordStateMachine; +import de.steamwar.bausystem.tracer.show.TraceShowManager; +import de.steamwar.bausystem.world.*; +import de.steamwar.bausystem.world.regions.GlobalRegion; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.command.SWCommand; +import de.steamwar.core.Core; +import de.steamwar.inventory.SWAnvilInv; +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; +import de.steamwar.sql.BauweltMember; +import de.steamwar.sql.SteamwarUser; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.potion.PotionEffectType; + +import java.util.*; + +public class CommandGUI extends SWCommand implements Listener { + + private static final Set OPEN_INVS = new HashSet<>(); + private static final Set OPEN_TRACER_INVS = new HashSet<>(); + private static final Set LAST_F_PLAYER = new HashSet<>(); + private static boolean isRefreshing = false; + + public CommandGUI() { + super("gui"); + Bukkit.getScheduler().runTaskTimerAsynchronously(BauSystem.getPlugin(), LAST_F_PLAYER::clear, 0, 20); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§egui §8- §7Öffne die GUI"); + p.sendMessage("§8/§egui item §8- §7Gebe das GUI item"); + } + + @Register + public void genericCommand(Player p) { + openBauGui(p); + OPEN_INVS.add(p); + } + + @Register({"item"}) + public void itemCommand(Player p) { + SWUtils.giveItemToPlayer(p, new ItemStack(Material.NETHER_STAR)); + } + + public static void openBauGui(Player player) { + Region region = Region.getRegion(player.getLocation()); + SWInventory inv = new SWInventory(player, 5 * 9, SteamwarUser.get(BauSystem.getOwner()).getUserName() + "s Bau"); + inv.setCallback(-1, clickType -> { + if (!isRefreshing) + OPEN_INVS.remove(player); + }); + + inv.setItem(43, getMaterial("GLASS_PANE", "THIN_GLASS"), "§7Platzhalter", clickType -> { + }); + inv.setItem(42, Material.NETHER_STAR, "§7Bau GUI Item", Arrays.asList("§7Du kannst dieses Item zum Öffnen der BauGUI nutzen", "§7oder Doppel F (Swap hands) drücken."), false, clickType -> { + player.closeInventory(); + player.performCommand("gui item"); + }); + + ItemStack dtWand = wand(player, Detonator.WAND, "§8/§7dt wand", Permission.WORLD, "§cDu hast keine Worldrechte"); + inv.setItem(39, dtWand, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.closeInventory(); + player.performCommand("dt wand"); + }); + + ItemStack redstoneWand = wand(player, CommandRedstoneTester.WAND, "§8/§7redstonetester", null, ""); + inv.setItem(37, redstoneWand, clickType -> { + player.closeInventory(); + player.performCommand("redstonetester"); + }); + + inv.setItem(40, getMaterial("WOODEN_AXE", "WOOD_AXE"), "§eWorldedit Axt", getNoPermsLore(Arrays.asList("§8//§7wand"), player, "§cDu hast keine Worldeditrechte", Permission.WORLDEDIT), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.closeInventory(); + player.performCommand("/wand"); + }); + inv.setItem(41, getMaterial("DEBUG_STICK", "STICK"), "§eDebugstick", getNoPermsLore(Arrays.asList("§8/§7debugstick"), player, "§cDu hast keine Worldrechte", Permission.WORLD), Core.getVersion() < 13, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.closeInventory(); + player.performCommand("debugstick"); + }); + + inv.setItem(20, Material.COMPASS, "§7TPS Limitieren", getNoPermsLore(Arrays.asList("§7Aktuell: §e" + CommandTPSLimiter.getCurrentTPSLimit(), "§8/§7tpslimit §8[§e0,5 - " + (TPSUtils.isWarpAllowed() ? 40 : 20) + "§8]"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + SWAnvilInv anvilInv = new SWAnvilInv(player, "TPS Limitieren"); + anvilInv.setItem(Material.COMPASS); + anvilInv.setCallback(s -> player.performCommand("tpslimit " + s)); + anvilInv.open(); + }); + inv.setItem(5, Material.FEATHER, "§7Geschwindigkeit", Arrays.asList("§7Aktuell: §e" + player.getFlySpeed() * 10, "§8/§7speed §8[§e1 - 10§8]"), false, clickType -> { + SWAnvilInv anvilInv = new SWAnvilInv(player, "Geschwindigkeit"); + anvilInv.setItem(Material.FEATHER); + anvilInv.setCallback(s -> player.performCommand("speed " + s)); + anvilInv.open(); + }); + + if (player.getUniqueId().equals(BauSystem.getOwner())) { + SWItem skull = SWItem.getPlayerSkull(player.getName()); + skull.setName("§7Bau verwalten"); + List skullLore = new ArrayList<>(); + skullLore.add("§7TNT: §e" + region.getTntMode().getName()); + skullLore.add("§7StopLag: §e" + (region.isFreeze() ? "Eingeschaltet" : "Ausgeschaltet")); + skullLore.add("§7Fire: §e" + (region.isFire() ? "Ausgeschaltet" : "Eingeschaltet")); + skullLore.add("§7Members: §e" + (BauweltMember.getMembers(BauSystem.getOwnerID()).size() - 1)); + skull.setLore(skullLore); + inv.setItem(4, skull); + } + + inv.setItem(6, Material.BOOK, "§7Script Bücher", Arrays.asList("§7Aktuell §e" + PredefinedBook.getBookCount() + " §7Bücher"), true, clickType -> { + player.closeInventory(); + scriptBooksGUI(player); + }); + + inv.setItem(21, Material.OBSERVER, "§7Tracer", getNoPermsLore(Arrays.asList("§7Status: §e" + RecordStateMachine.getRecordStatus().getName()), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.closeInventory(); + OPEN_TRACER_INVS.add(player); + traceGUI(player); + }); + + inv.setItem(22, Material.DISPENSER, "§7Auto-Loader", getNoPermsLore(Arrays.asList("§7Status: " + (AutoLoader.hasLoader(player) ? "§aan" : "§caus")), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.closeInventory(); + autoLoaderGUI(player); + }); + + inv.setItem(17, getMaterial("PLAYER_HEAD", "SKULL_ITEM"), (byte) 3, "§7Spielerkopf geben", Arrays.asList("§8/§7skull §8[§eSpieler§8]"), false, clickType -> { + SWAnvilInv anvilInv = new SWAnvilInv(player, "Spielerköpfe"); + anvilInv.setItem(Material.NAME_TAG); + anvilInv.setCallback(s -> player.performCommand("skull " + s)); + anvilInv.open(); + }); + + if (GlobalRegion.isGlobalRegion(region)) { + inv.setItem(9, Material.BARRIER, "§eKeine Region", clickType -> { + }); + inv.setItem(18, Material.BARRIER, "§eKeine Region", clickType -> { + }); + inv.setItem(27, Material.BARRIER, "§eKeine Region", clickType -> { + }); + } else { + inv.setItem(27, getMaterial("HEAVY_WEIGHTED_PRESSURE_PLATE", "IRON_PLATE"), "§eRegion Reseten", getNoPermsLore(Arrays.asList("§8/§7reset"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + confirmationInventory(player, "Region Reseten?", () -> player.performCommand("reset"), () -> openBauGui(player)); + }); + + if (region.hasProtection()) { + inv.setItem(18, Material.OBSIDIAN, "§eRegion Protecten", getNoPermsLore(Arrays.asList("§8/§7protect"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + confirmationInventory(player, "Region Protecten", () -> player.performCommand("protect"), () -> openBauGui(player)); + }); + } else { + inv.setItem(18, Material.BARRIER, "§eRegion nicht Protect bar", clickType -> { + }); + } + + if (region.hasTestblock()) { + inv.setItem(9, getMaterial("END_STONE", "ENDER_STONE"), "§eTestblock erneuern", getNoPermsLore(Arrays.asList("§8/§7testblock"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + confirmationInventory(player, "Testblock erneuern", () -> player.performCommand("testblock"), () -> openBauGui(player)); + }); + } else { + inv.setItem(9, Material.BARRIER, "§eDie Region hat keinen Testblock", clickType -> { + }); + } + } + + if (player.hasPotionEffect(PotionEffectType.NIGHT_VISION)) { + inv.setItem(26, Material.POTION, "§7Nightvision: §eEingeschaltet", Collections.singletonList("§8/§7nv"), false, clickType -> { + CommandNV.toggleNightvision(player); + openBauGui(player); + }); + } else { + inv.setItem(26, Material.GLASS_BOTTLE, "§7Nightvision: §eAusgeschaltet", Collections.singletonList("§8/§7nv"), false, clickType -> { + CommandNV.toggleNightvision(player); + openBauGui(player); + }); + } + + if (player.hasPotionEffect(PotionEffectType.WATER_BREATHING)) { + inv.setItem(35, Material.WATER_BUCKET, "§7Waterbreathing: §eEingeschaltet", Collections.singletonList("§8/§7wv"), false, clickType -> { + CommandGills.toggleGills(player); + openBauGui(player); + }); + } else { + inv.setItem(35, Material.BUCKET, "§7Waterbreathing: §eAusgeschaltet", Collections.singletonList("§8/§7wv"), false, clickType -> { + CommandGills.toggleGills(player); + openBauGui(player); + }); + } + + boolean isBuildArea = region.hasBuildRegion(); + List tntLore = getNoPermsLore(Arrays.asList("§8/§7tnt §8[" + (isBuildArea ? "§eTB§7, " : "") + "§eOff §7oder §eOn§7]"), player, "§cDu hast keine Worldrechte", Permission.WORLD); + switch (region.getTntMode()) { + case OFF: + inv.setItem(23, Material.MINECART, "§7TNT: §eAusgeschaltet", tntLore, false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("tnt " + (isBuildArea ? "tb" : "on")); + updateInventories(); + }); + break; + case ONLY_TB: + inv.setItem(23, getMaterial("TNT_MINECART", "EXPLOSIVE_MINECART"), "§7TNT: §enur Testblock", tntLore, false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("tnt on"); + updateInventories(); + }); + break; + default: + inv.setItem(23, Material.TNT, "§7TNT: §eEingeschaltet", tntLore, false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("tnt off"); + updateInventories(); + }); + } + + if (region.isFreeze()) { + inv.setItem(24, getMaterial("GUNPOWDER", "SULPHUR"), "§7Freeze: §eEingeschaltet", getNoPermsLore(Arrays.asList("§8/§7freeze"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("freeze"); + updateInventories(); + }); + } else { + inv.setItem(24, Material.REDSTONE, "§7Freeze: §eAusgeschaltet", getNoPermsLore(Arrays.asList("§8/§7freeze"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("freeze"); + updateInventories(); + }); + } + + if (region.isFire()) { + inv.setItem(3, getMaterial("FIREWORK_STAR", "FIREWORK_CHARGE"), "§7Fire: §eAusgeschaltet", getNoPermsLore(Arrays.asList("§8/§7fire"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("fire"); + updateInventories(); + }); + } else { + inv.setItem(3, getMaterial("FIRE_CHARGE", "FIREBALL"), "§7Fire: §eEingeschaltet", getNoPermsLore(Arrays.asList("§8/§7fire"), player, "§cDu hast keine Worldrechte", Permission.WORLD), false, clickType -> { + if (Welt.noPermission(player, Permission.WORLD)) + return; + player.performCommand("fire"); + updateInventories(); + }); + } + + inv.setItem(2, Material.ENDER_PEARL, "§7Teleporter", getNoPermsLore(Arrays.asList("§8/§7tp §8[§eSpieler§8]"), player, "", null), false, clickType -> { + List> playerSWListEntry = new ArrayList<>(); + Bukkit.getOnlinePlayers().forEach(player1 -> { + if (player1.equals(player)) + return; + playerSWListEntry.add(new SWListInv.SWListEntry<>(SWItem.getPlayerSkull(player1.getName()), player1.getName())); + }); + SWListInv playerSWListInv = new SWListInv<>(player, "Teleporter", playerSWListEntry, (clickType1, player1) -> { + player.closeInventory(); + player.performCommand("tp " + player1); + }); + playerSWListInv.open(); + }); + + inv.open(); + } + + private static void traceGUI(Player player) { + SWInventory inv = new SWInventory(player, 9, "Tracer"); + inv.setCallback(-1, clickType -> { + if (!isRefreshing) + OPEN_TRACER_INVS.remove(player); + }); + List stateLore = Arrays.asList("§7Aktuell: §e" + RecordStateMachine.getRecordStatus().getName(), "§8/§7trace §8[§estart§8, stop §8oder §eauto§8]"); + switch (RecordStateMachine.getRecordStatus()) { + case IDLE: + inv.setItem(0, getMaterial("SNOWBALL", "SNOW_BALL"), "§7Tracerstatus", stateLore, false, clickType -> { + RecordStateMachine.commandAuto(); + updateInventories(); + }); + break; + case IDLE_AUTO: + inv.setItem(0, Material.ENDER_PEARL, "§7Tracerstatus", stateLore, false, clickType -> { + RecordStateMachine.commandStart(); + updateInventories(); + }); + break; + case RECORD: + case RECORD_AUTO: + inv.setItem(0, getMaterial("ENDER_EYE", "EYE_OF_ENDER"), "§7Tracerstatus", stateLore, false, clickType -> { + RecordStateMachine.commandStop(); + updateInventories(); + }); + } + if (TraceShowManager.hasActiveShow(player)) { + inv.setItem(2, Material.TNT, "§7Showstatus", Arrays.asList("§7Aktuell: §eGezeigt", "§8/§7trace §8[§eshow§8/§ehide§8]"), false, clickType -> { + player.performCommand("trace hide"); + traceGUI(player); + }); + } else { + inv.setItem(2, Material.GLASS, "§7Showstatus", Arrays.asList("§7Aktuell: §eVersteckt", "§8/§7trace §8[§eshow§8/§ehide§8]"), false, clickType -> { + player.performCommand("trace show"); + traceGUI(player); + }); + } + + inv.setItem(4, getMaterial("TNT_MINECART", "EXPLOSIVE_MINECART"), "§7Trace GUI", Collections.singletonList("§8/§7trace show gui"), false, clickType -> { + player.closeInventory(); + player.performCommand("trace show gui"); + }); + + inv.setItem(6, Material.BARRIER, "§7Trace löschen", Arrays.asList("§8/§7trace delete"), false, clickType -> confirmationInventory(player, "Trace löschen", () -> player.performCommand("trace delete"), () -> { + })); + + inv.setItem(8, Material.ARROW, "§7Zurück", clickType -> { + player.closeInventory(); + openBauGui(player); + OPEN_INVS.add(player); + }); + + inv.open(); + } + + private static void scriptBooksGUI(Player player) { + List> entries = new ArrayList<>(); + List books = PredefinedBook.getBooks(); + books.forEach(predefinedBook -> entries.add(new SWListInv.SWListEntry<>(new SWItem(predefinedBook.getBookMat(), predefinedBook.getName(), predefinedBook.getLore(), false, clickType -> { + }), predefinedBook))); + SWListInv inv = new SWListInv<>(player, "Script Bücher", entries, (clickType, predefinedBook) -> { + player.closeInventory(); + player.getInventory().addItem(predefinedBook.toItemStack()); + }); + inv.open(); + } + + private static void autoLoaderGUI(Player player) { + SWInventory inv = new SWInventory(player, 9, "Autoloader"); + + boolean hasLoader = AutoLoader.hasLoader(player); + + if (hasLoader) { + AutoLoader loader = AutoLoader.getLoader(player); + if (loader.isSetup()) { + inv.setItem(0, Material.DROPPER, "§7Loader Starten", Collections.singletonList("§8/§7loader start"), false, clickType -> { + loader.start(); + autoLoaderGUI(player); + }); + + inv.setItem(2, Material.ARROW, "§7Letzte Aktion entfernen", Collections.singletonList("§8/§7loader undo"), false, clickType -> { + + }); + } else { + inv.setItem(0, Material.BLAZE_ROD, "§7Loader Bearbeiten", Collections.singletonList("§8/§7loader setup"), false, clickType -> { + loader.setup(); + autoLoaderGUI(player); + }); + } + + inv.setItem(4, Material.COMPASS, "§7Schuss Delay", Arrays.asList("§7Aktuell: §e" + loader.getTicksBetweenShots(), "§8/§7loader wait §8[§eTicks§8]"), false, clickType -> { + SWAnvilInv anvilInv = new SWAnvilInv(player, "Schuss Delay", loader.getTicksBetweenShots() + ""); + anvilInv.setItem(Material.STONE); + anvilInv.setCallback(s -> { + player.performCommand("loader wait " + s); + autoLoaderGUI(player); + }); + anvilInv.open(); + }); + + inv.setItem(6, getMaterial("CLOCK", "WATCH"), "§7Block platzier Geschwindigkeit", Arrays.asList("§7Aktuell: §e" + loader.getTicksBetweenBlocks(), "§8/§7loader speed §8[§eTicks§8]"), false, clickType -> { + SWAnvilInv anvilInv = new SWAnvilInv(player, "Platzier Geschwindigkeit", loader.getTicksBetweenBlocks() + ""); + anvilInv.setItem(Material.STONE); + anvilInv.setCallback(s -> { + player.performCommand("loader speed " + s); + autoLoaderGUI(player); + }); + anvilInv.open(); + }); + + inv.setItem(8, Material.BARRIER, "§7Loader löschen", Collections.singletonList("§8/§7loader stop"), false, clickType -> confirmationInventory(player, "Loader löschen?", () -> { + loader.stop(); + autoLoaderGUI(player); + }, () -> autoLoaderGUI(player))); + } else { + inv.setItem(4, Material.GOLD_NUGGET, "§eNeuer Autoloader", clickType -> { + AutoLoader.getLoader(player); + player.closeInventory(); + }); + inv.setItem(8, Material.ARROW, "§7Zurück", clickType -> { + player.closeInventory(); + openBauGui(player); + OPEN_INVS.add(player); + }); + } + + inv.open(); + } + + + private static void confirmChatMessage(Player player, String command) { + player.sendMessage(BauSystem.PREFIX + "§7Klicke auf die Nachricht zum bestätigen"); + TextComponent t = new TextComponent(); + t.setText("[Hier]"); + t.setColor(ChatColor.YELLOW); + t.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command)); + t.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("§7" + command))); + player.spigot().sendMessage(t); + } + + private static List getNoPermsLore(List lore, Player player, String noPerms, Permission perm) { + if (perm != null && Welt.noPermission(player, perm)) { + lore = new ArrayList<>(lore); + lore.add(noPerms); + } + return lore; + } + + private static void updateInventories() { + isRefreshing = true; + OPEN_INVS.forEach(CommandGUI::openBauGui); + OPEN_TRACER_INVS.forEach(CommandGUI::traceGUI); + isRefreshing = false; + } + + private static void confirmationInventory(Player player, String title, Runnable confirm, Runnable decline) { + SWInventory inv = new SWInventory(player, 9, title); + inv.setItem(0, SWItem.getDye(1), (byte) 1, "§cAbbrechen", clickType -> { + player.closeInventory(); + decline.run(); + }); + inv.setItem(8, SWItem.getDye(10), (byte) 10, "§aBestätigen", clickType -> { + player.closeInventory(); + confirm.run(); + }); + inv.open(); + } + + private static Material getMaterial(String... names) { + for (String name : names) { + try { + return Material.valueOf(name); + } catch (IllegalArgumentException ignored) { + //Ignored /\ + } + } + return null; + } + + private static ItemStack wand(Player player, ItemStack base, String command, Permission permission, String noPermissionMessage) { + base = base.clone(); + ItemMeta meta = base.getItemMeta(); + List lore = meta.getLore(); + lore.add(command); + if (permission != null && Welt.noPermission(player, permission)) + lore.add(noPermissionMessage); + meta.setLore(lore); + base.setItemMeta(meta); + return base; + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) + return; + if (event.getItem() == null || event.getItem().getType() != Material.NETHER_STAR) + return; + openBauGui(event.getPlayer()); + OPEN_INVS.add(event.getPlayer()); + } + + @EventHandler + public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { + if (LAST_F_PLAYER.contains(event.getPlayer())) { + openBauGui(event.getPlayer()); + OPEN_INVS.add(event.getPlayer()); + } else { + LAST_F_PLAYER.add(event.getPlayer()); + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGamemode.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGamemode.java new file mode 100644 index 00000000..5ddbfa0d --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGamemode.java @@ -0,0 +1,50 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.command.SWCommand; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; + +public class CommandGamemode extends SWCommand { + + public CommandGamemode() { + super("gamemode", "gm", "g"); + } + + @Register(help = true) + public void gamemodeHelp(Player p, String... args) { + p.sendMessage("§cUnbekannter Spielmodus"); + } + + @Register + public void genericCommand(Player p) { + if (p.getGameMode() == GameMode.CREATIVE) { + p.setGameMode(GameMode.SPECTATOR); + } else { + p.setGameMode(GameMode.CREATIVE); + } + } + + @Register + public void gamemodeCommand(Player p, GameMode gameMode) { + p.setGameMode(gameMode); + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGills.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGills.java new file mode 100644 index 00000000..051ea107 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandGills.java @@ -0,0 +1,53 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class CommandGills extends SWCommand { + + public CommandGills() { + super("watervision", "wv"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§ewatervision §8- §7Toggle WaterBreathing"); + } + + @Register + public void genericCommand(Player p) { + toggleGills(p); + } + + public static void toggleGills(Player player) { + if (player.hasPotionEffect(PotionEffectType.WATER_BREATHING)) { + player.sendMessage(BauSystem.PREFIX + "Wassersicht deaktiviert"); + player.removePotionEffect(PotionEffectType.WATER_BREATHING); + return; + } + player.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 1000000, 255, false, false)); + player.sendMessage(BauSystem.PREFIX + "Wassersicht aktiviert"); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java new file mode 100644 index 00000000..b1831409 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandInfo.java @@ -0,0 +1,80 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.world.TPSUtils; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.command.SWCommand; +import de.steamwar.core.TPSWatcher; +import de.steamwar.sql.BauweltMember; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.entity.Player; + +import java.util.List; + +import static de.steamwar.bausystem.world.TPSUtils.getTps; + +public class CommandInfo extends SWCommand { + + public CommandInfo() { + super("bauinfo"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§ebauinfo §8- §7Gibt Informationen über den Bau"); + } + + @Register + public void genericCommand(Player p) { + CommandInfo.sendBauInfo(p); + } + + public static void sendBauInfo(Player p) { + p.sendMessage(BauSystem.PREFIX + "Besitzer: §e" + SteamwarUser.get(BauSystem.getOwnerID()).getUserName()); + Region region = Region.getRegion(p.getLocation()); + p.sendMessage(BauSystem.PREFIX + "§eTNT§8: " + region.getTntMode().getName() + " §eFire§8: " + (region.isFire() ? "§aAUS" : "§cAN") + " §eFreeze§8: " + (region.isFreeze() ? "§aAN" : "§cAUS")); + if (region.hasProtection()) { + p.sendMessage(BauSystem.PREFIX + "§eProtect§8: " + (region.isProtect() ? "§aAN" : "§cAUS")); + } + + List members = BauweltMember.getMembers(BauSystem.getOwnerID()); + StringBuilder membermessage = new StringBuilder().append(BauSystem.PREFIX).append("Mitglieder: "); + + for (BauweltMember member : members) { + membermessage.append("§e").append(SteamwarUser.get(member.getMemberID()).getUserName()).append("§8["); + membermessage.append(member.isWorldEdit() ? "§a" : "§c").append("WE").append("§8,"); + membermessage.append(member.isWorld() ? "§a" : "§c").append("W").append("§8]").append(" "); + } + p.sendMessage(membermessage.toString()); + + StringBuilder tpsMessage = new StringBuilder(); + tpsMessage.append(BauSystem.PREFIX).append("TPS:§e"); + tpsMessage.append(" ").append(getTps(TPSWatcher.TPSType.ONE_SECOND)); + tpsMessage.append(" ").append(getTps(TPSWatcher.TPSType.TEN_SECONDS)); + if (!TPSUtils.isWarping()) { + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE)); + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES)); + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES)); + } + p.sendMessage(tpsMessage.toString()); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandKillAll.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandKillAll.java new file mode 100644 index 00000000..389a191a --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandKillAll.java @@ -0,0 +1,74 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.world.regions.*; +import de.steamwar.command.SWCommand; +import java.util.concurrent.atomic.AtomicLong; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; + +public class CommandKillAll extends SWCommand { + + private static final World WORLD = Bukkit.getWorlds().get(0); + + public CommandKillAll() { + super("killall", "removeall"); + } + + @Register(help = true) + public void genericHelp(Player player, String... args) { + player.sendMessage("§8/§ekillall §8- §7Entferne alle Entities aus deiner Region"); + player.sendMessage("§8/§ekillall §8[§7Global§8/Local§7] §8- §7Entferne alle Entities aus deiner Region oder global"); + } + + @Register + public void genericCommand(Player player) { + genericCommand(player, RegionSelectionType.LOCAL); + } + + @Register + public void genericCommand(Player player, RegionSelectionType regionSelectionType) { + Region region = Region.getRegion(player.getLocation()); + AtomicLong removedEntities = new AtomicLong(); + if (regionSelectionType == RegionSelectionType.GLOBAL || GlobalRegion.isGlobalRegion(region)) { + WORLD.getEntities() + .stream() + .filter(e -> !(e instanceof Player)) + .forEach(entity -> { + entity.remove(); + removedEntities.getAndIncrement(); + }); + RegionUtils.actionBar(GlobalRegion.getInstance(), "§a" + removedEntities.get() + " Entities aus der Welt entfernt"); + } else { + WORLD.getEntities() + .stream() + .filter(e -> !(e instanceof Player)) + .filter(e -> region.inRegion(e.getLocation(), RegionType.NORMAL, RegionExtensionType.NORMAL)) + .forEach(entity -> { + entity.remove(); + removedEntities.getAndIncrement(); + }); + RegionUtils.actionBar(region, "§a" + removedEntities.get() + " Entities aus der Region entfernt"); + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLoader.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLoader.java new file mode 100644 index 00000000..628db208 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLoader.java @@ -0,0 +1,134 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.AutoLoader; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + +public class CommandLoader extends SWCommand { + + public CommandLoader() { + super("loader"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eloader setup §8- §7Startet die Aufnahme der Aktionen"); + p.sendMessage("§8/§7loader undo §8- §7Entfernt die zuletzt aufgenommene Aktion"); + p.sendMessage("§8/§eloader start §8- §7Spielt die zuvor aufgenommenen Aktionen ab"); + p.sendMessage("§8/§7loader wait §8[§7Ticks§8] - §7Setzt die Wartezeit zwischen Schüssen"); + p.sendMessage("§8/§7loader speed §8[§7Ticks§8] - §7Setzt die Wartezeit zwischen Aktionen"); + p.sendMessage("§8/§eloader stop §8- §7Stoppt die Aufnahme bzw. das Abspielen"); + p.sendMessage("§7Der AutoLader arbeitet mit §eIngame§8-§eTicks §8(20 Ticks pro Sekunde)"); + } + + @Register({"setup"}) + public void setupCommand(Player p) { + setup(p); + } + + @Register({"undo"}) + public void undoCommand(Player p) { + undo(p); + } + + @Register({"start"}) + public void startCommand(Player p) { + start(p); + } + + @Register({"stop"}) + public void stopCommand(Player p) { + stop(p); + } + + @Register({"wait"}) + public void waitCommand(Player p, int time) { + wait(p, time); + } + + @Register({"speed"}) + public void speedCommand(Player p, int time) { + speed(p, time); + } + + private void setup(Player player) { + AutoLoader.getLoader(player).setup(); + } + + private void undo(Player player) { + AutoLoader loader = loader(player); + if (loader == null) + return; + + if (!loader.isSetup()) { + player.sendMessage("§cDer AutoLader wird in den Setup-Zustand versetzt"); + setup(player); + } + + loader.undo(); + } + + private void start(Player player) { + AutoLoader loader = loader(player); + if (loader == null) + return; + + loader.start(); + } + + private void stop(Player player) { + if (!AutoLoader.hasLoader(player)) { + player.sendMessage(BauSystem.PREFIX + "§cDu hast keinen aktiven AutoLader"); + return; + } + AutoLoader.getLoader(player).stop(); + } + + private void wait(Player player, int time) { + AutoLoader loader = loader(player); + if (loader == null) { + loader = AutoLoader.getLoader(player); + } + loader.wait(time); + } + + private void speed(Player player, int time) { + AutoLoader loader = loader(player); + if (loader == null) { + loader = AutoLoader.getLoader(player); + } + loader.blockWait(time); + } + + private AutoLoader loader(Player player) { + if (AutoLoader.hasLoader(player)) { + return AutoLoader.getLoader(player); + } + player.sendMessage(BauSystem.PREFIX + "§cDu hast keinen aktiven AutoLader"); + player.sendMessage(BauSystem.PREFIX + "§7Es wird ein neuer AutoLader gestartet"); + setup(player); + return null; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java new file mode 100644 index 00000000..c5f20eb3 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandLockschem.java @@ -0,0 +1,67 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.command.SWCommand; +import de.steamwar.sql.*; +import org.bukkit.entity.Player; + +public class CommandLockschem extends SWCommand { + + public CommandLockschem() { + super("lockschem"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + if (!SteamwarUser.get(p.getUniqueId()).hasPerm(UserPerm.CHECK)) { + return; + } + + sendHelp(p); + } + + @Register + public void genericCommand(Player p, String owner, String schematicName) { + if (!SteamwarUser.get(p.getUniqueId()).hasPerm(UserPerm.CHECK)) { + return; + } + + SteamwarUser schemOwner = SteamwarUser.get(owner); + if (schemOwner == null) { + p.sendMessage(BauSystem.PREFIX + "Dieser Spieler existiert nicht!"); + return; + } + SchematicNode node = SchematicNode.getNodeFromPath(schemOwner, schematicName); + if (node == null) { + p.sendMessage(BauSystem.PREFIX + "Dieser Spieler besitzt keine Schematic mit diesem Namen!"); + return; + } + p.sendMessage(BauSystem.PREFIX + "Schematic " + node .getName() + " von " + + SteamwarUser.get(node.getOwner()).getUserName() + " von " + node.getSchemtype().toString() + + " auf NORMAL zurückgesetzt!"); + node.setSchemtype(SchematicType.Normal); + } + + private void sendHelp(Player player) { + player.sendMessage("§8/§eschemlock §8[§7Owner§8] §8[§7Schematic§8] §8- §7 Sperre eine Schematic"); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandNV.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandNV.java new file mode 100644 index 00000000..7b232a22 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandNV.java @@ -0,0 +1,54 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class CommandNV extends SWCommand { + + public CommandNV() { + super("nightvision", "nv"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§enightvision §8- §7Toggle NightVision"); + } + + @Register + public void genericCommand(Player p) { + toggleNightvision(p); + } + + public static void toggleNightvision(Player player) { + if (player.hasPotionEffect(PotionEffectType.NIGHT_VISION)) { + player.sendMessage(BauSystem.PREFIX + "Nachtsicht deaktiviert"); + player.removePotionEffect(PotionEffectType.NIGHT_VISION); + return; + } + + player.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, 1000000, 255, false, false)); + player.sendMessage(BauSystem.PREFIX + "Nachtsicht aktiviert"); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandProtect.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandProtect.java new file mode 100644 index 00000000..f97d18e8 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandProtect.java @@ -0,0 +1,127 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.command.SWCommand; +import de.steamwar.sql.SchematicNode; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +import java.io.IOException; +import java.util.logging.Level; + +public class CommandProtect extends SWCommand implements Listener { + + public CommandProtect() { + super("protect"); + if (Region.buildAreaEnabled()) { + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + } + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eprotect §8- §7Schütze die Region"); + p.sendMessage("§8/§eprotect §8[§7Schematic§8] §8- §7Schütze die Region mit einer Schematic"); + } + + @Register + public void genericProtectCommand(Player p) { + if (!permissionCheck(p)) return; + Region region = regionCheck(p); + if (region == null) return; + if (Region.buildAreaEnabled()) { + region.setProtect(!region.isProtect()); + if (region.isProtect()) { + RegionUtils.actionBar(region, "§aBoden geschützt"); + } else { + RegionUtils.actionBar(region, "§cBoden Schutz aufgehoben"); + } + return; + } + try { + region.protect(null); + p.sendMessage(BauSystem.PREFIX + "§7Boden geschützt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Schützen der Region"); + Bukkit.getLogger().log(Level.WARNING, "Failed protect", e); + } + } + + @Register + public void schematicProtectCommand(Player p, String s) { + if (!permissionCheck(p)) return; + if (Region.buildAreaEnabled()) { + genericHelp(p); + return; + } + Region region = regionCheck(p); + if (region == null) return; + SteamwarUser owner = SteamwarUser.get(p.getUniqueId()); + SchematicNode schem = SchematicNode.getNodeFromPath(owner, s); + if (schem == null) { + p.sendMessage(BauSystem.PREFIX + "§cSchematic nicht gefunden"); + return; + } + try { + region.protect(schem); + p.sendMessage(BauSystem.PREFIX + "§7Boden geschützt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Schützen der Region"); + Bukkit.getLogger().log(Level.WARNING, "Failed protect", e); + } + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLDEDIT)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Boden schützen"); + return false; + } + return true; + } + + private Region regionCheck(Player player) { + Region region = Region.getRegion(player.getLocation()); + if (!region.hasProtection()) { + player.sendMessage(BauSystem.PREFIX + "§cDu befindest dich derzeit in keiner (M)WG-Region"); + return null; + } + return region; + } + + @EventHandler + public void onExplode(EntityExplodeEvent event) { + Region region = Region.getRegion(event.getLocation()); + if (!region.isProtect() || !region.hasProtection()) { + return; + } + event.blockList().removeIf(block -> { + return block.getY() < region.getProtectYLevel(); + }); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java new file mode 100644 index 00000000..91a8626a --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java @@ -0,0 +1,52 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.command.SWCommand; +import de.steamwar.inventory.SWItem; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +public class CommandRedstoneTester extends SWCommand { + + public static final ItemStack WAND = new SWItem(Material.BLAZE_ROD, "§eRedstonetester", Arrays.asList("§eLinksklick Block §8- §7Setzt die 1. Position", "§eRechtsklick Block §8- §7Setzt die 2. Position", "§eShift-Rechtsklick Luft §8- §7Zurücksetzten"), false, null).getItemStack(); + + public CommandRedstoneTester() { + super("redstonetester", "rt"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eredstonetester §8- §7Gibt den RedstoneTester"); + } + + @Register + public void genericCommand(Player p) { + p.sendMessage(BauSystem.PREFIX + "Messe die Zeit zwischen der Aktivierung zweier Redstone Komponenten"); + SWUtils.giveItemToPlayer(p, WAND); + } + + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRegion.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRegion.java new file mode 100644 index 00000000..2efb478e --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandRegion.java @@ -0,0 +1,132 @@ +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.Color; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.bausystem.world.regions.GlobalRegion; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.bausystem.world.regions.RegionExtensionType; +import de.steamwar.bausystem.world.regions.RegionType; +import de.steamwar.command.SWCommand; +import de.steamwar.sql.SchematicNode; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.util.logging.Level; + +public class CommandRegion extends SWCommand { + + public CommandRegion() { + super("region", "rg"); + } + + @Register + public void genericCommand(Player player) { + genericHelp(player); + } + + @Register(help = true) + public void genericHelp(Player player, String... args) { + player.sendMessage("§8/§eregion undo §8- §7Mache die letzten 20 /testblock oder /reset rückgängig"); + player.sendMessage("§8/§eregion redo §8- §7Wiederhole die letzten 20 §8/§7rg undo"); + player.sendMessage("§8/§eregion restore §8- §7Setzte die Region zurück, ohne das Gebaute zu löschen"); + player.sendMessage("§8/§eregion §8[§7RegionsTyp§8] §8- §7Wähle einen RegionsTyp aus"); + player.sendMessage("§8/§eregion §8[§7RegionsTyp§8] §8[§7Extension§8] §8- §7Wähle einen RegionsTyp aus mit oder ohne Extension"); + player.sendMessage("§8/§eregion color §8[§7Color§8] §8- §7Ändere die Regions Farbe"); + } + + @Register("undo") + public void undoCommand(Player p) { + if(!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + if(checkGlobalRegion(region, p)) return; + + if (region.undo()) { + p.sendMessage(BauSystem.PREFIX + "Letzte Aktion rückgangig gemacht"); + } else { + p.sendMessage(BauSystem.PREFIX + "§cNichts zum rückgängig machen"); + } + } + + @Register("redo") + public void redoCommand(Player p) { + if (!permissionCheck(p)) { + return; + } + Region region = Region.getRegion(p.getLocation()); + if (checkGlobalRegion(region, p)) { + return; + } + + if (region.redo()) { + p.sendMessage(BauSystem.PREFIX + "Letzte Aktion wiederhohlt"); + } else { + p.sendMessage(BauSystem.PREFIX + "§cNichts zum wiederhohlen"); + } + } + + @Register + public void baurahmenCommand(Player p, RegionType regionType) { + CommandSelect.getInstance().baurahmenCommand(p, regionType, RegionExtensionType.NORMAL); + } + + @Register + public void baurahmenCommand(Player p, RegionType regionType, RegionExtensionType regionExtensionType) { + CommandSelect.getInstance().baurahmenCommand(p, regionType, regionExtensionType); + } + + @Register("restore") + public void genericRestoreCommand(Player p) { + if (!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + if(checkGlobalRegion(region, p)) return; + + if (region == null) return; + try { + region.reset(null, true); + p.sendMessage(BauSystem.PREFIX + "§7Region zurückgesetzt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Zurücksetzen der Region"); + Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); + } + } + + @Register("restore") + public void schematicRestoreCommand(Player p, SchematicNode schem) { + if (!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + if(checkGlobalRegion(region, p)) return; + + if (region == null) return; + try { + region.reset(schem, true); + p.sendMessage(BauSystem.PREFIX + "§7Region zurückgesetzt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Zurücksetzen der Region"); + Bukkit.getLogger().log(Level.WARNING, "Failed reset", e); + } + } + + @Register("color") + public void colorCommand(Player p, Color color) { + CommandColor.getInstance().genericColor(p, color); + } + + static boolean checkGlobalRegion(Region region, Player p) { + if (GlobalRegion.isGlobalRegion(region)) { + p.sendMessage(BauSystem.PREFIX + "§cDu bist in keiner Region"); + return true; + } + return false; + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLDEDIT)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht die Region verändern"); + return false; + } + return true; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandReset.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandReset.java new file mode 100644 index 00000000..4ec404e5 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandReset.java @@ -0,0 +1,91 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.bausystem.world.regions.GlobalRegion; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.command.SWCommand; +import de.steamwar.sql.SchematicNode; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.util.logging.Level; + +public class CommandReset extends SWCommand { + + public CommandReset() { + super("reset"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§ereset §8- §7Setzte die Region zurück"); + p.sendMessage("§8/§ereset §8[§7Schematic§8] §8- §7Setzte die Region mit einer Schematic zurück"); + } + + @Register + public void genericResetCommand(Player p) { + if (!permissionCheck(p)) return; + Region region = regionCheck(p); + if (region == null) return; + try { + region.reset(null, false); + p.sendMessage(BauSystem.PREFIX + "§7Region zurückgesetzt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Zurücksetzen der Region"); + Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); + } + } + + @Register + public void schematicResetCommand(Player p, SchematicNode schem) { + if (!permissionCheck(p)) return; + Region region = regionCheck(p); + if (region == null) return; + try { + region.reset(schem, false); + p.sendMessage(BauSystem.PREFIX + "§7Region zurückgesetzt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Zurücksetzen der Region"); + Bukkit.getLogger().log(Level.WARNING, "Failed reset", e); + } + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht die Region zurücksetzen"); + return false; + } + return true; + } + + private Region regionCheck(Player player) { + Region region = Region.getRegion(player.getLocation()); + if (region == GlobalRegion.getInstance()) { + player.sendMessage(BauSystem.PREFIX + "§cDu befindest dich derzeit in keiner Region"); + return null; + } + return region; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScript.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScript.java new file mode 100644 index 00000000..8e071ea9 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScript.java @@ -0,0 +1,94 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * / + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.SWUtils; +import de.steamwar.command.SWCommand; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; + +import java.util.ArrayList; +import java.util.List; + +public class CommandScript extends SWCommand { + + public CommandScript() { + super("script"); + } + + public static final ItemStack BOOK = new ItemStack(Material.WRITTEN_BOOK, 1); + + static { + List pages = new ArrayList<>(); + pages.add("§6Script System§8\n\n- Commands\n- Kommentare\n- Scriptausführung\n- Sleep\n- Variablen\n- Konstanten\n- Abfragen\n- Schleifen\n- \"echo\"\n- \"input\"\n- Arithmetik\n- Logik"); + pages.add("§6Commands§8\n\nEin minecraft Befehl wird im Scriptbuch so hingeschrieben. Dabei kann man ein '/' weglassen. Um Befehle zu trennen kommen diese in neue Zeilen.\n\nStatt\n/tnt -> tnt\n//pos1 -> /pos1"); + pages.add("§6Kommentare§8\n\nFür ein Kommentar fängt die Zeile mit einem '#' an. Diese Zeilen werden bei dem Ausführen dann ignoriert.\n\nBeispiel:\n§9# TNT an/aus\ntnt"); + pages.add("§6Scriptausführung§8\n\nWenn du mit dem Buch in der Hand links klickst wird dieses ausgeführt."); + pages.add("§6Sleep§8\n\nUm Sachen langsamer zu machen kann man ein 'sleep' in sein Script schreiben. Danach kommt eine Zahl mit der Anzahl der GameTicks die zu schlafen sind.\n\nBeispiel:\n§9# 1 Sekunde schlafen\nsleep 20"); + pages.add("§6Variablen§8\n\nMit Variablen kann man sich Zahlen speichern. Man definiert diese mit 'var '.\n\nBeispiel:\n§9# Setze i zu 0\nvar i 0§8\n\nEs gibt einige spezial values. Dazu zählen"); + pages.add("§8'true', 'yes', 'false' und 'no', welche für 1, 1, 0 und 0 stehen.\n\nMan kann eine Variable auch um einen erhöhen oder verkleinern. Hierfür schreibt man statt einer Zahl '++', 'inc' oder '--', 'dec'.\n\nBeispiel:\n§9var i ++"); + pages.add("§8Variablen kann man referenzieren\ndurch '<' vor dem Variablennamen und '>' nach diesem. Diese kann man in jedem Befehl verwenden.\n\nBeispiel:\n§9# Stacked um 10\nvar stacks 10\n/stack "); + pages.add("§8Man kann auch explizit eine globale, locale, oder konstante variable referenzieren, indem 'global.', 'local.' oder 'const.' vor den Namen in die Klammern zu schreiben."); + pages.add("§8Um Variablen über das Script ausführen zu speichern gibt es 'global' und 'unglobal' als Befehle. Der erste speichert eine locale Variable global und das zweite löscht eine globale wieder."); + pages.add("§8Des weiteren kann man Lokale Variablen mit 'unvar' löschen. Nach dem verlassen einer Welt werden alle Globalen Variablen gelöscht. Globale Variablen kann man mit '/scriptvars' einsehen."); + pages.add("§6Konstanten§8\n\nNeben den variablen gibt es noch 5 Konstante Werte, welche nicht mit dem 'var' Befehl verändert werden können.\n\nDiese sind:\n- trace/autotrace\n- tnt\n- freeze\n- fire"); + pages.add("§8Des weiteren gibt es 3 weitere Variablen, welche explizit Spieler gebunden sind\n\nDiese sind:\n- x\n- y\n- z"); + pages.add("§6Abfragen§8\n\nMit Abfragen kann man nur Gleichheit von 2 Werten überprüft werden. Hierfür verwendet man\n'if '.\nNach den zwei Werten kann man ein oder 2 Jump-Points schreiben\n'if [...] (JP)'."); + pages.add("§8Des weiteren kann man überprüfen, ob eine Variable existiert mit 'if exists' wonach dann wieder 1 oder 2 Jump-Points sein müssen."); + pages.add("§8Ein Jump-Point ist eine Zeile Script, wohin man springen kann. Dieser wird mit einem '.' am Anfang der Zeile beschrieben und direkt danach der Jump-Point Namen ohne Leerzeichen.\n\nBeispiel:\n§9# Jump-Point X\n.X§8"); + pages.add("§8Um zu einem Jump-Point ohne Abfrage zu springen kann man den\n'jump ' Befehl verwenden."); + pages.add("§6Schleifen§8\n\nSchleifen werden mit Jump-Points, if Abfragen und Jumps gebaut.\n\nBeispiel:\n§9var i 0\n.JUMP\nvar i ++\nif i 10 END JUMP\n.END§8"); + pages.add("§6\"echo\"§8\n\nDer echo Befehl ist da um Ausgaben zu tätigen. Hier drin kann man sowohl Variablen ausgeben, als auch Farbcodes verwenden. Es wird alles nach dem Befehl ausgegeben.\n\nBeispiel:\n§9echo &eSteam&8war &7war hier!"); + pages.add("§6\"input\"§8\n\nDer input Befehl ist eine Aufforderung einer Eingabe des Users. Die Argumente sind eine Variable und ein Text als Nachricht.\n\nBeispiel:\n§9input age &eDein Alter?"); + pages.add("§6Arithmetik§8\n\nEs gibt 4 Arithmetische Befehle:\n- add\n- sub\n- mul\n- div\n\nDer erste Parameter ist die Variable welche den ausgerechneten Wert halten soll. Hiernach muss ein"); + pages.add("§8Wert oder Variable kommen welcher verrechnet wird. Hierbei wird das erste Argument als ersten Operand genommen.\n\nBeispiel:\n§9var i 2\nvar j 3\nadd i j\necho $i"); + pages.add("§8Man kann auch 3 Argumente angeben. Dann wird die arithmetische Operation zwischen den letzten beiden Argumenten berechnet und als Variable des ersten Arguments abgespeichert. \n\nBeispiel auf der nächsten Seite -->"); + pages.add("§8Beispiel:\n§9var i 2\nvar j 2\nadd k i j\necho $k"); + pages.add("§6Logik§8\n\nEs gibt 3 Vergleichs Befehle:\n- equal\n- less\n- greater\n\nUnd 3 Logik Befehle:\n- and\n- or\n- not"); + pages.add("§8Der erste Parameter ist die Variable welche den ausgerechneten Wert halten soll. Hiernach muss ein Wert oder Variable kommen welcher verrechnet wird. Hierbei wird das erste Argument als ersten Operand genommen. Dies gilt nicht für den 'not' Befehl, welcher"); + pages.add("§8nur 2 Parameter nimmt. Der erste die Variable und der zweite eine optionale Variable oder ein Wert. Equal vergleicht 2 Werte, less gibt zurück ob der erste kleiner als der zweite Wert ist, greater gibt zurück ob der erste größer als der zweite Wert ist."); + pages.add("§8And vergleicht ob 2 Werte true (1) sind. Or vergleicht ob 1 Wert oder 2 Werte true (1) ist/sind. Not invertiert den Wert von true (1) auf false und anders rum."); + pages.add("§8Beispiel:\n§9var i 1\nvar j 1\n#Ist i und j gleich\nequal k i j\nvar j 0\n#Ist i kleiner j\nless k i j\n#Ist i größer j\ngreater k i j\n#Ist i und j true\nand k i j\n#Beispiel weiter auf nächster Seite"); + pages.add("§9#Ist i oder j true\nor k i j\n#Invertiere i\nnot k i"); + + BookMeta bookMeta = (BookMeta) BOOK.getItemMeta(); + bookMeta.setGeneration(BookMeta.Generation.ORIGINAL); + bookMeta.setAuthor("§eSteam§8war"); + bookMeta.setTitle("§7Script Buch"); + bookMeta.setDisplayName("§7Script Buch"); + bookMeta.setPages(pages); + BOOK.setItemMeta(bookMeta); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§escript §8- §7Gibt das Script Buch"); + } + + @Register + public void giveCommand(Player p) { + SWUtils.giveItemToPlayer(p, BOOK); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScriptVars.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScriptVars.java new file mode 100644 index 00000000..f352fca8 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandScriptVars.java @@ -0,0 +1,120 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.world.ScriptListener; +import de.steamwar.command.SWCommand; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import org.bukkit.entity.Player; + +import java.util.*; + +public class CommandScriptVars extends SWCommand { + + public CommandScriptVars() { + super("scripvars"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§escriptvars §8- §7Zähle alle globalen Variablen auf"); + p.sendMessage("§8/§escriptvars §8[§7Variable§8] §8- §7Gebe den Wert der Variable zurück"); + p.sendMessage("§8/§escriptvars §8[§7Variable§8] §8[§7Value§8] §8- §7Setzte eine Variable auf einen Wert"); + p.sendMessage("§8/§escriptvars §8[§7Variable§8] §8<§7remove§8|§7delete§8|§7clear§8> §8- §7Lösche eine Variable"); + } + + @Register + public void genericCommand(Player p) { + Map globalVariables = ScriptListener.GLOBAL_VARIABLES.get(p); + if (globalVariables == null) { + p.sendMessage(BauSystem.PREFIX + "§cKeine globalen Variablen definiert"); + return; + } + int i = 0; + p.sendMessage(BauSystem.PREFIX + globalVariables.size() + " Variable(n)"); + for (Map.Entry var : globalVariables.entrySet()) { + if (i++ >= 40) break; + p.sendMessage("- " + var.getKey() + "=" + var.getValue()); + } + } + + @Register + public void removeCommand(Player p, String varName) { + Map globalVariables = ScriptListener.GLOBAL_VARIABLES.get(p); + if (globalVariables == null) { + p.sendMessage(BauSystem.PREFIX + "§cKeine globalen Variablen definiert"); + return; + } + if (!globalVariables.containsKey(varName)) { + p.sendMessage(BauSystem.PREFIX + "§cUnbekannte Variable"); + return; + } + p.sendMessage(BauSystem.PREFIX + varName + "=" + globalVariables.get(varName)); + } + + @Register + public void booleanValueCommand(Player p, String varName, int value) { + ScriptListener.GLOBAL_VARIABLES.computeIfAbsent(p, player -> new HashMap<>()).put(varName, value); + p.sendMessage(BauSystem.PREFIX + varName + " auf " + value + " gesetzt"); + } + + @Register + public void removeCommand(Player p, String varName, @Mapper(value = "Delete") String remove) { + if (!ScriptListener.GLOBAL_VARIABLES.containsKey(p)) { + p.sendMessage(BauSystem.PREFIX + "§cKeine globalen Variablen definiert"); + return; + } + ScriptListener.GLOBAL_VARIABLES.get(p).remove(varName); + p.sendMessage(BauSystem.PREFIX + "Variable " + varName + " gelöscht"); + } + + @ClassMapper(value = String.class, local = true) + public TypeMapper stringTypeMapper() { + return SWCommandUtils.createMapper(s -> s, (commandSender, s) -> { + if (commandSender instanceof Player) { + Player player = (Player) commandSender; + return new ArrayList<>(ScriptListener.GLOBAL_VARIABLES.getOrDefault(player, new HashMap<>()).keySet()); + } + return null; + }); + } + + @Mapper(value = "Delete", local = true) + public TypeMapper clearStringTypeMapper() { + List tabCompletes = Arrays.asList("delete", "clear", "remove"); + return SWCommandUtils.createMapper(s -> { + if (s.equalsIgnoreCase("delete") || s.equalsIgnoreCase("clear") || s.equalsIgnoreCase("remove")) { + return s; + } + return null; + }, s -> tabCompletes); + } + + @ClassMapper(value = int.class, local = true) + public TypeMapper integerTypeMapper() { + List tabCompletes = Arrays.asList("true", "false", "yes", "no"); + return SWCommandUtils.createMapper(s -> { + if (s.equalsIgnoreCase("remove") || s.equalsIgnoreCase("clear") || s.equalsIgnoreCase("delete")) return null; + return ScriptListener.parseValue(s); + }, s -> tabCompletes); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSelect.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSelect.java new file mode 100644 index 00000000..96e6105e --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSelect.java @@ -0,0 +1,124 @@ +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.WorldeditWrapper; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.bausystem.world.regions.*; +import de.steamwar.command.SWCommand; +import lombok.Getter; +import org.bukkit.entity.Player; + + +public class CommandSelect extends SWCommand { + + @Getter + private static CommandSelect instance = null; + + public CommandSelect() { + super("select"); + } + + { + instance = this; + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eselect §8[§7RegionsTyp§8] §8- §7Wähle einen RegionsTyp aus"); + p.sendMessage("§8/§eselect §8[§7RegionsTyp§8] §8[§7Extension§8] §8- §7Wähle einen RegionsTyp aus mit oder ohne Extension"); + } + + @Register + public void baurahmenCommand(Player p, RegionType regionType) { + if (!permissionCheck(p)) { + return; + } + + Region region = Region.getRegion(p.getLocation()); + + if (GlobalRegion.isGlobalRegion(region)) { + p.sendMessage(BauSystem.PREFIX + "§cDie globale Region kannst du nicht auswählen"); + return; + } + + if (regionType == RegionType.TESTBLOCK) { + if (!region.hasTestblock()) { + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen Testblock"); + return; + } + setSelection(regionType, RegionExtensionType.NORMAL, region, p); + return; + } + + if (regionType == RegionType.BUILD) { + if (!region.hasBuildRegion()) { + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen BuildArea"); + return; + } + setSelection(regionType, RegionExtensionType.NORMAL, region, p); + return; + } + + setSelection(regionType, RegionExtensionType.NORMAL, region, p); + } + + @Register + public void baurahmenCommand(Player p, RegionType regionType, RegionExtensionType regionExtensionType) { + if (!permissionCheck(p)) { + return; + } + + Region region = Region.getRegion(p.getLocation()); + + if (GlobalRegion.isGlobalRegion(region)) { + p.sendMessage(BauSystem.PREFIX + "§cDie globale Region kannst du nicht auswählen"); + return; + } + + if (regionType == RegionType.TESTBLOCK) { + if (!region.hasTestblock()) { + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen Testblock"); + return; + } + if (regionExtensionType == RegionExtensionType.EXTENSION && !region.hasExtensionArea(regionType)) { + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keine Ausfahrmaße"); + return; + } + setSelection(regionType, regionExtensionType, region, p); + return; + } + + if (regionType == RegionType.BUILD) { + if (!region.hasBuildRegion()) { + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen BuildArea"); + return; + } + if (regionExtensionType == RegionExtensionType.EXTENSION && !region.hasExtensionArea(regionType)) { + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keine Ausfahrmaße"); + return; + } + setSelection(regionType, regionExtensionType, region, p); + return; + } + + setSelection(regionType, regionExtensionType, region, p); + } + + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLDEDIT)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Select verwenden"); + return false; + } + return true; + } + + private void setSelection(RegionType regionType, RegionExtensionType regionExtensionType, Region region, Player p) { + Point minPoint = region.getMinPoint(regionType, regionExtensionType); + Point maxPoint = region.getMaxPoint(regionType, regionExtensionType); + + WorldeditWrapper.impl.setSelection(p, minPoint, maxPoint); + p.sendMessage(BauSystem.PREFIX + "WorldEdit auswahl auf " + minPoint.getX() + ", " + minPoint.getY() + ", " + minPoint.getZ() + " und " + maxPoint.getX() + ", " + maxPoint.getY() + ", " + maxPoint.getZ() + " gesetzt"); + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSkull.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSkull.java new file mode 100644 index 00000000..ca98a7ed --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSkull.java @@ -0,0 +1,49 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.SWUtils; +import de.steamwar.command.SWCommand; +import de.steamwar.inventory.SWItem; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +public class CommandSkull extends SWCommand { + + public CommandSkull() { + super("skull"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eskull §8[§eSpieler§8] §8- §7Gibt einen SpielerKopf"); + } + + @Register + public void giveCommand(Player p, String skull) { + ItemStack is = SWItem.getPlayerSkull(skull).getItemStack(); + SkullMeta sm = (SkullMeta) is.getItemMeta(); + assert sm != null; + sm.setDisplayName("§e" + skull + "§8s Kopf"); + is.setItemMeta(sm); + SWUtils.giveItemToPlayer(p, is); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSpeed.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSpeed.java new file mode 100644 index 00000000..195cefcd --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandSpeed.java @@ -0,0 +1,70 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.command.SWCommand; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.List; + +public class CommandSpeed extends SWCommand { + + public CommandSpeed() { + super("speed"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§espeed §8[§7Geschwindigkeit§8] §8- §7Setzte deine Flug- und Gehgeschwindigkeit"); + } + + @Register({"default"}) + public void defaultCommand(Player p) { + speedCommand(p, 1); + } + + @Register + public void speedCommand(Player p, float speed) { + if (speed < 0 || speed > 10) { + p.sendMessage(BauSystem.PREFIX + "§cBitte gib eine Zahl zwischen 0 und 10 an"); + return; + } + + p.sendMessage("§aGeschwindigkeit wurde auf §6" + speed + " §agesetzt"); + p.setFlySpeed(speed / 10); + p.setWalkSpeed((speed >= 9 ? speed : speed + 1) / 10); + } + + @ClassMapper(value = float.class, local = true) + public TypeMapper doubleTypeMapper() { + List tabCompletes = Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"); + return SWCommandUtils.createMapper(s -> { + try { + return Float.parseFloat(s.replace(',', '.')); + } catch (NumberFormatException e) { + return null; + } + }, s -> tabCompletes); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTNT.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTNT.java new file mode 100644 index 00000000..a96daf31 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTNT.java @@ -0,0 +1,173 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.bausystem.world.regions.RegionExtensionType; +import de.steamwar.bausystem.world.regions.RegionType; +import de.steamwar.command.SWCommand; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CommandTNT extends SWCommand implements Listener { + + public enum TNTMode { + ON("§aan"), + ONLY_TB("§7Kein §eBaurahmen"), + OFF("§caus"); + + private String name; + + TNTMode(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public CommandTNT() { + super("tnt"); + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§etnt §8- §7Ändere das TNT verhalten"); + p.sendMessage("§8/§etnt §8[§7Mode§8] §8- §7Setzte das TNT verhalten auf einen Modus"); + } + + @Register + public void toggleCommand(Player p) { + if (!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + tntToggle(region, null, null); + } + + @Register + public void setCommand(Player p, TNTMode tntMode) { + if (!permissionCheck(p)) return; + Region region = Region.getRegion(p.getLocation()); + + String requestedMessage = null; + switch (tntMode) { + case ON: + requestedMessage = getEnableMessage(); + break; + case OFF: + requestedMessage = getDisableMessage(); + break; + case ONLY_TB: + requestedMessage = getTestblockEnableMessage(); + break; + } + tntToggle(region, tntMode, requestedMessage); + } + + private boolean permissionCheck(Player p) { + if (Welt.noPermission(p, Permission.WORLD)) { + p.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht TNT-Schaden (de-)aktivieren"); + return false; + } + return true; + } + + @ClassMapper(value = TNTMode.class, local = true) + public TypeMapper tntModeTypeMapper() { + Map tntModeMap = new HashMap<>(); + tntModeMap.put("an", TNTMode.ON); + tntModeMap.put("on", TNTMode.ON); + tntModeMap.put("aus", TNTMode.OFF); + tntModeMap.put("off", TNTMode.OFF); + if (Region.buildAreaEnabled()) { + tntModeMap.put("testblock", TNTMode.ONLY_TB); + tntModeMap.put("tb", TNTMode.ONLY_TB); + } + List tabCompletes = new ArrayList<>(tntModeMap.keySet()); + return SWCommandUtils.createMapper(s -> tntModeMap.getOrDefault(s, null), s -> tabCompletes); + } + + private String getEnableMessage() { + return "§aTNT-Schaden aktiviert"; + } + + private String getDisableMessage() { + return "§cTNT-Schaden deaktiviert"; + } + + private String getTestblockEnableMessage() { + return "§aTNT-Schaden außerhalb Baurahmen aktiviert"; + } + + private void tntToggle(Region region, TNTMode requestedMode, String requestedMessage) { + if (requestedMode != null && region.hasTestblock()) { + region.setTntMode(requestedMode); + RegionUtils.actionBar(region, requestedMessage); + return; + } + switch (region.getTntMode()) { + case ON: + case ONLY_TB: + region.setTntMode(TNTMode.OFF); + RegionUtils.actionBar(region, getDisableMessage()); + break; + case OFF: + if (Region.buildAreaEnabled() && region.hasTestblock()) { + region.setTntMode(TNTMode.ONLY_TB); + RegionUtils.actionBar(region, getTestblockEnableMessage()); + } else { + region.setTntMode(TNTMode.ON); + RegionUtils.actionBar(region, getEnableMessage()); + } + break; + } + } + + @EventHandler + public void onExplode(EntityExplodeEvent event) { + event.blockList().removeIf(block -> { + Region region = Region.getRegion(block.getLocation()); + if (region.getTntMode() == TNTMode.ON) return false; + if (region.hasBuildRegion() && region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.NORMAL)) { + RegionUtils.actionBar(region, "§cEine Explosion hätte Blöcke im Baubereich zerstört"); + return true; + } + if (region.hasBuildRegion() && region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.EXTENSION)) { + RegionUtils.actionBar(region, "§cEine Explosion hätte Blöcke im Ausfahrbereich zerstört"); + return true; + } + return region.getTntMode() == TNTMode.OFF; + }); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTPSLimiter.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTPSLimiter.java new file mode 100644 index 00000000..fe73d863 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTPSLimiter.java @@ -0,0 +1,176 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.CraftbukkitWrapper; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.TPSUtils; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CommandTPSLimiter extends SWCommand { + + private static CommandTPSLimiter instance = null; + + { + instance = this; + } + + private static final World WORLD = Bukkit.getWorlds().get(0); + private static double currentTPSLimit = 20; + + private long lastTime = System.nanoTime(); + private long currentTime = System.nanoTime(); + + private double delay = 0; + private int loops = 0; + private long sleepDelay = 0; + + private BukkitTask tpsLimiter = null; + + private List tabCompletions = new ArrayList<>(Arrays.asList("0,5", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20")); + + public CommandTPSLimiter() { + super("tpslimit"); + if (TPSUtils.isWarpAllowed()) { + for (int i = 20; i <= 60; i += 5) { + tabCompletions.add(i + ""); + } + } + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage(BauSystem.PREFIX + "Jetziges TPS limit: " + currentTPSLimit); + p.sendMessage("§8/§etpslimit §8[§7TPS§8|§edefault§8] §8- §7Setzte die TPS auf dem Bau"); + } + + @Register({"default"}) + public void defaultCommand(Player p) { + if (!permissionCheck(p)) return; + currentTPSLimit = 20; + sendNewTPSLimitMessage(); + tpsLimiter(); + } + + @Register + public void valueCommand(Player p, double tpsLimitDouble) { + if (!permissionCheck(p)) return; + if (tpsLimitDouble < 0.5 || tpsLimitDouble > (TPSUtils.isWarpAllowed() ? 60 : 20)) { + sendInvalidArgumentMessage(p); + return; + } + currentTPSLimit = tpsLimitDouble; + sendNewTPSLimitMessage(); + tpsLimiter(); + } + + @ClassMapper(value = double.class, local = true) + public TypeMapper doubleTypeMapper() { + return SWCommandUtils.createMapper(s -> { + try { + return Double.parseDouble(s.replace(',', '.')); + } catch (NumberFormatException e) { + return 0D; + } + }, s -> tabCompletions); + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den TPS-Limiter nutzen"); + return false; + } + return true; + } + + private void sendNewTPSLimitMessage() { + Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("§eTPS limit auf " + currentTPSLimit + " gesetzt."))); + } + + private void sendInvalidArgumentMessage(Player player) { + player.sendMessage(BauSystem.PREFIX + "§cNur Zahlen zwischen 0,5 und " + (TPSUtils.isWarpAllowed() ? 60 : 20) + ", und 'default' erlaubt."); + } + + private void tpsLimiter() { + delay = 20 / currentTPSLimit; + loops = (int) Math.ceil(delay); + sleepDelay = (long) (50 * delay) / loops; + + TPSUtils.setTPS(currentTPSLimit); + if (currentTPSLimit >= 20) { + if (tpsLimiter == null) return; + tpsLimiter.cancel(); + tpsLimiter = null; + } else { + if (tpsLimiter != null) return; + tpsLimiter = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), () -> { + CraftbukkitWrapper.impl.createTickCache(WORLD); + + for (int i = 0; i < loops; i++) { + sleepUntilNextTick(sleepDelay); + CraftbukkitWrapper.impl.sendTickPackets(); + } + }, 0, 1); + } + } + + private void sleepUntilNextTick(long neededDelta) { + lastTime = currentTime; + currentTime = System.nanoTime(); + + long timeDelta = (currentTime - lastTime) / 1000000; + if (neededDelta - timeDelta < 0) return; + + try { + Thread.sleep(neededDelta - timeDelta); + currentTime = System.nanoTime(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + public static double getCurrentTPSLimit() { + return (double) Math.round(currentTPSLimit * 10.0D) / 10.0D; + } + + public static void setTPS(double d) { + if (d < 0.5) d = 0.5; + if (d > (TPSUtils.isWarpAllowed() ? 60 : 20)) d = (TPSUtils.isWarpAllowed() ? 60 : 20); + if (instance != null) { + currentTPSLimit = d; + instance.tpsLimiter(); + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTeleport.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTeleport.java new file mode 100644 index 00000000..04fa8c72 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTeleport.java @@ -0,0 +1,46 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; + +public class CommandTeleport extends SWCommand { + + public CommandTeleport() { + super("teleport", "tp"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§etp §8[§7Player§8] §8- §7Teleportiere dich zu einem Spieler"); + } + + @Register + public void genericCommand(Player p, Player target) { + if (p.getUniqueId().equals(target.getUniqueId())) { + p.sendMessage(BauSystem.PREFIX + "§cSei eins mit dir selbst!"); + return; + } + p.teleport(target, PlayerTeleportEvent.TeleportCause.COMMAND); + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTestblock.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTestblock.java new file mode 100644 index 00000000..ec206fa9 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTestblock.java @@ -0,0 +1,128 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.tracer.show.ShowModeParameterType; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.bausystem.world.regions.RegionExtensionType; +import de.steamwar.command.SWCommand; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import de.steamwar.sql.SchematicNode; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +public class CommandTestblock extends SWCommand { + + public CommandTestblock() { + super("testblock", "tb"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§etestblock §8- §7Setzte den Testblock zurück"); + p.sendMessage("§8/§etestblock §8[§7Schematic§8] §8- §7Setzte den Testblock mit einer Schematic zurück"); + } + + @Register + public void genericTestblockCommand(Player p) { + genericTestblockCommand(p, RegionExtensionType.NORMAL); + } + + @Register + public void genericTestblockCommand(Player p, RegionExtensionType regionExtensionType) { + if (!permissionCheck(p)) return; + Region region = regionCheck(p); + if (region == null) return; + try { + region.resetTestblock(null, regionExtensionType == RegionExtensionType.EXTENSION); + p.sendMessage(BauSystem.PREFIX + "§7Testblock zurückgesetzt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Zurücksetzen des Testblocks"); + Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); + } + } + + + @Register + public void schematicTestblockCommand(Player p, SchematicNode schem) { + schematicTestblockCommand(p, schem, RegionExtensionType.NORMAL); + } + + @Register + public void schematicTestblockCommand(Player p, RegionExtensionType regionExtensionType, SchematicNode schem) { + schematicTestblockCommand(p, schem, regionExtensionType); + } + + @Register + public void schematicTestblockCommand(Player p, SchematicNode schem, RegionExtensionType regionExtensionType) { + if (!permissionCheck(p)) return; + Region region = regionCheck(p); + if (region == null) return; + try { + region.resetTestblock(schem, regionExtensionType == RegionExtensionType.EXTENSION); + p.sendMessage(BauSystem.PREFIX + "§7Testblock zurückgesetzt"); + } catch (IOException e) { + p.sendMessage(BauSystem.PREFIX + "§cFehler beim Zurücksetzen des Testblocks"); + Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e); + } + } + + @ClassMapper(value = RegionExtensionType.class, local = true) + private TypeMapper regionExtensionTypeTypeMapper() { + Map showModeParameterTypesMap = new HashMap<>(); + showModeParameterTypesMap.put("-normal", RegionExtensionType.NORMAL); + showModeParameterTypesMap.put("-n", RegionExtensionType.NORMAL); + showModeParameterTypesMap.put("-extension", RegionExtensionType.EXTENSION); + showModeParameterTypesMap.put("-e", RegionExtensionType.EXTENSION); + + List tabCompletes = new ArrayList<>(showModeParameterTypesMap.keySet()); + return SWCommandUtils.createMapper(s -> showModeParameterTypesMap.getOrDefault(s, null), s -> tabCompletes); + } + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLDEDIT)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Testblock zurücksetzen"); + return false; + } + return true; + } + + private Region regionCheck(Player player) { + Region region = Region.getRegion(player.getLocation()); + if (!region.hasTestblock()) { + player.sendMessage(BauSystem.PREFIX + "§cDu befindest dich derzeit in keiner Region"); + return null; + } + return region; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTime.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTime.java new file mode 100644 index 00000000..8a231052 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTime.java @@ -0,0 +1,99 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.TypeMapper; +import java.util.Arrays; +import java.util.List; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class CommandTime extends SWCommand { + + private static List tabCompletions = Arrays.asList("0", "6000", "12000", "18000"); + + public CommandTime() { + super("time"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§etime §8<§7Zeit 0=Morgen§8, §76000=Mittag§8, §718000=Mitternacht§8> §8- §7Setzt die Zeit auf dem Bau"); + } + + @Register + public void genericCommand(Player p, int time) { + if (Welt.noPermission(p, Permission.WORLD)) { + p.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht die Zeit ändern"); + return; + } + if (time < 0 || time > 24000) { + p.sendMessage(BauSystem.PREFIX + "§cBitte gib eine Zahl zwischen 0 und 24000 an"); + return; + } + Bukkit.getWorlds().get(0).setTime(time); + } + + @Register + public void genericCommand(Player p, Time time) { + if (Welt.noPermission(p, Permission.WORLD)) { + p.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht die Zeit ändern"); + return; + } + Bukkit.getWorlds().get(0).setTime(time.getValue()); + } + + @ClassMapper(value = int.class, local = true) + public TypeMapper doubleTypeMapper() { + return SWCommandUtils.createMapper(s -> { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + return 0; + } + }, s -> tabCompletions); + } + + public enum Time { + NIGHT(18000), + DAY(6000), + DAWN(0), + SUNSET(12000), + NACHT(18000), + TAG(6000), + MORGEN(0), + ABEND(12000); + + private int value; + + private Time(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTrace.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTrace.java new file mode 100644 index 00000000..d1c9e2f0 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandTrace.java @@ -0,0 +1,132 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.gui.GuiTraceShow; +import de.steamwar.bausystem.tracer.record.RecordStateMachine; +import de.steamwar.bausystem.tracer.show.ShowModeParameter; +import de.steamwar.bausystem.tracer.show.ShowModeParameterType; +import de.steamwar.bausystem.tracer.show.StoredRecords; +import de.steamwar.bausystem.tracer.show.TraceShowManager; +import de.steamwar.bausystem.tracer.show.mode.EntityShowMode; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + +public class CommandTrace extends SWCommand { + + public CommandTrace() { + super("trace"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§etrace start §8- §7Startet die Aufnahme aller TNT-Positionen"); + p.sendMessage("§8/§etrace stop §8- §7Stoppt den TNT-Tracer"); + p.sendMessage("§8/§etrace toggleauto §8- §7Automatischer Aufnahmenstart"); + p.sendMessage("§8/§etrace show gui §8- §7Zeigt die Trace show gui"); + p.sendMessage("§8/§etrace show §8<§e-water§8|§e-interpolate-xz§8|§e-interpolate-y§8> §8- §7Zeigt alle TNT-Positionen"); + p.sendMessage("§8/§etrace hide §8- §7Versteckt alle TNT-Positionen"); + p.sendMessage("§8/§etrace delete §8- §7Löscht alle TNT-Positionen"); + // p.sendMessage("§8/§etrace list §8<§7FRAME-ID§8> §8- §7Listet alle TNT auf"); + // p.sendMessage("§8/§etrace gui §8- §7Zeigt die Trace Oberfläche an"); + // p.sendMessage("§7Optionale Parameter mit §8<>§7, Benötigte Parameter mit §8[]"); + } + + @Register({"start"}) + public void startCommand(Player p) { + if (!permissionCheck(p)) return; + RecordStateMachine.commandStart(); + p.sendMessage(BauSystem.PREFIX + "§aTNT-Tracer gestartet"); + } + + @Register({"stop"}) + public void stopCommand(Player p) { + if (!permissionCheck(p)) return; + RecordStateMachine.commandStop(); + p.sendMessage(BauSystem.PREFIX + "§cTNT-Tracer gestoppt"); + } + + @Register({"toggleauto"}) + public void toggleAutoCommand(Player p) { + autoCommand(p); + } + + @Register({"auto"}) + public void autoCommand(Player p) { + if (!permissionCheck(p)) return; + RecordStateMachine.commandAuto(); + p.sendMessage(BauSystem.PREFIX + RecordStateMachine.getRecordStatus().getAutoMessage()); + } + + @Register({"clear"}) + public void clearCommand(Player p) { + deleteCommand(p); + } + + @Register({"delete"}) + public void deleteCommand(Player p) { + if (!permissionCheck(p)) return; + StoredRecords.clear(); + p.sendMessage(BauSystem.PREFIX + "§cAlle TNT-Positionen gelöscht"); + } + + @Register({"show"}) + public void showCommand(Player p) { + if (!permissionCheck(p)) return; + TraceShowManager.show(p, new EntityShowMode(p, new ShowModeParameter())); + p.sendMessage(BauSystem.PREFIX + "§aAlle TNT-Positionen angezeigt"); + } + + @Register({"show"}) + public void showCommand(Player p, ShowModeParameterType... showModeParameterTypes) { + if (!permissionCheck(p)) return; + ShowModeParameter showModeParameter = new ShowModeParameter(); + for (ShowModeParameterType showModeParameterType : showModeParameterTypes) { + showModeParameterType.getShowModeParameterConsumer().accept(showModeParameter); + } + TraceShowManager.show(p, new EntityShowMode(p, showModeParameter)); + p.sendMessage(BauSystem.PREFIX + "§aAlle TNT-Positionen angezeigt"); + } + + @Register({"show", "gui"}) + public void showGuiCommand(Player p) { + if (!permissionCheck(p)) return; + GuiTraceShow.openGui(p); + } + + @Register({"hide"}) + public void hideCommand(Player p) { + if (!permissionCheck(p)) return; + TraceShowManager.hide(p); + p.sendMessage(BauSystem.PREFIX + "§cAlle TNT-Positionen ausgeblendet"); + } + + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den TNT-Tracer nutzen"); + return false; + } + return true; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandWorldSpawn.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandWorldSpawn.java new file mode 100644 index 00000000..2f9c1340 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/CommandWorldSpawn.java @@ -0,0 +1,45 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.command.SWCommand; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; + +public class CommandWorldSpawn extends SWCommand { + + private World world = Bukkit.getWorlds().get(0); + + public CommandWorldSpawn() { + super("worldspawn"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage("§8/§eworldspawn §8- §7Teleportiere dich zum Spawn"); + } + + @Register + public void genericCommand(Player p) { + p.teleport(world.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.COMMAND); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/commands/RegionUtils.java b/LegacyBauSystem/src/de/steamwar/bausystem/commands/RegionUtils.java new file mode 100644 index 00000000..1c783030 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/commands/RegionUtils.java @@ -0,0 +1,42 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.world.regions.GlobalRegion; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.bausystem.world.regions.RegionExtensionType; +import de.steamwar.bausystem.world.regions.RegionType; +import lombok.experimental.UtilityClass; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; + +@UtilityClass +public class RegionUtils { + + public static void actionBar(Region region, String s) { + if (GlobalRegion.isGlobalRegion(region)) { + Bukkit.getOnlinePlayers().forEach(player -> player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(s))); + } else { + Bukkit.getOnlinePlayers().stream().filter(player -> region.inRegion(player.getLocation(), RegionType.NORMAL, RegionExtensionType.NORMAL)).forEach(player -> player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(s))); + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/gui/GuiTraceShow.java b/LegacyBauSystem/src/de/steamwar/bausystem/gui/GuiTraceShow.java new file mode 100644 index 00000000..caa03eb2 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/gui/GuiTraceShow.java @@ -0,0 +1,133 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * / + */ + +package de.steamwar.bausystem.gui; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.FlatteningWrapper; +import de.steamwar.bausystem.tracer.show.ShowModeParameter; +import de.steamwar.bausystem.tracer.show.TraceShowManager; +import de.steamwar.bausystem.tracer.show.mode.EntityShowMode; +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWItem; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class GuiTraceShow { + + private static final Map ShowModeParameterMap = new HashMap<>(); + + private GuiTraceShow() { + + } + + public static void openGui(Player player) { + ShowModeParameter playerShowMode = new ShowModeParameter(); + playerShowMode.setInterpolate_Y(false); + playerShowMode.setInterpolate_XZ(false); + ShowModeParameterMap.put(player, playerShowMode); + + SWInventory swInventory = new SWInventory(player, 9, "Trace Show GUI"); + swInventory.addCloseCallback(clickType -> ShowModeParameterMap.remove(player)); + setActiveShow(player, swInventory); + + SWItem water = new SWItem(Material.TNT, "§eWasser §7Positionen", Arrays.asList("§7Zeigt alles TNT, welches", "§7im Wasser explodiert ist."), false, clickType -> { + }); + swInventory.setItem(5, water); + swInventory.setCallback(5, clickType -> toggleHideTNTinWaterExploded(player, swInventory, water)); + + SWItem interpolateY = new SWItem(Material.QUARTZ_STAIRS, "§eInterpolation §7Y-Achse", Arrays.asList("§7Zeigt die Interpolation", "§7auf der Y-Achse."), false, clickType -> { + }); + swInventory.setItem(6, interpolateY); + swInventory.setCallback(6, clickType -> toggleInterpolateYPosition(player, swInventory, interpolateY)); + + Material xzMaterial = FlatteningWrapper.impl.getTraceXZMaterial(); + SWItem interpolateXZ = new SWItem(xzMaterial, (byte) 7, "§eInterpolation §7XZ-Achse", Arrays.asList("§7Zeigt die Interpolation", "§7auf der XZ-Achse."), false, clickType -> { + }); + swInventory.setItem(7, interpolateXZ); + swInventory.setCallback(7, clickType -> toggleInterpolateXZPosition(player, swInventory, interpolateXZ)); + // Water Bucket (-water) + // TNT (-water-exploded) + // Quartz_Stair (-interpolate-y) + // Quartz_Slab (-interpolate-xz) + swInventory.open(); + } + + private static void setActiveShow(Player player, SWInventory swInventory) { + if (TraceShowManager.hasActiveShow(player)) { + Material showMaterial = FlatteningWrapper.impl.getTraceShowMaterial(); + SWItem shown = new SWItem(showMaterial, (byte) 5, "§aTraces angezeigt", new ArrayList<>(), false, clickType -> { + TraceShowManager.hide(player); + player.sendMessage(BauSystem.PREFIX + "§cAlle TNT-Positionen ausgeblendet"); + setActiveShow(player, swInventory); + }); + swInventory.setItem(1, shown); + } else { + Material hideMaterial = FlatteningWrapper.impl.getTraceHideMaterial(); + SWItem hidden = new SWItem(hideMaterial, (byte) 14, "§cTraces ausgeblendet", new ArrayList<>(), false, clickType -> { + show(player); + player.sendMessage(BauSystem.PREFIX + "§aAlle TNT-Positionen angezeigt"); + setActiveShow(player, swInventory); + }); + swInventory.setItem(1, hidden); + } + } + + private static void toggleHideTNTinWaterExploded(Player player, SWInventory swInventory, SWItem swItem) { + ShowModeParameter showModeParameter = ShowModeParameterMap.get(player); + showModeParameter.setWater(!showModeParameter.isWater()); + show(player); + + swItem.setEnchanted(showModeParameter.isWater()); + swInventory.setItem(5, swItem); + swInventory.setCallback(5, clickType -> toggleHideTNTinWaterExploded(player, swInventory, swItem)); + } + + private static void toggleInterpolateYPosition(Player player, SWInventory swInventory, SWItem swItem) { + ShowModeParameter showModeParameter = ShowModeParameterMap.get(player); + showModeParameter.setInterpolate_Y(!showModeParameter.isInterpolate_Y()); + show(player); + + swItem.setEnchanted(showModeParameter.isInterpolate_Y()); + swInventory.setItem(6, swItem); + swInventory.setCallback(6, clickType -> toggleInterpolateYPosition(player, swInventory, swItem)); + } + + private static void toggleInterpolateXZPosition(Player player, SWInventory swInventory, SWItem swItem) { + ShowModeParameter showModeParameter = ShowModeParameterMap.get(player); + showModeParameter.setInterpolate_XZ(!showModeParameter.isInterpolate_XZ()); + show(player); + + swItem.setEnchanted(showModeParameter.isInterpolate_XZ()); + swInventory.setItem(7, swItem); + swInventory.setCallback(7, clickType -> toggleInterpolateXZPosition(player, swInventory, swItem)); + } + + private static void show(Player player) { + TraceShowManager.show(player, new EntityShowMode(player, ShowModeParameterMap.get(player))); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/AbstractTraceEntity.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/AbstractTraceEntity.java new file mode 100644 index 00000000..1df4d96d --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/AbstractTraceEntity.java @@ -0,0 +1,34 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +public interface AbstractTraceEntity { + + void display(Player player, boolean exploded); + + boolean hide(Player player, boolean always); + + int getId(); + + Entity getBukkitEntity(); +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/RoundedTNTPosition.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/RoundedTNTPosition.java new file mode 100644 index 00000000..73960575 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/RoundedTNTPosition.java @@ -0,0 +1,65 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * / + */ + +package de.steamwar.bausystem.tracer; + +import org.bukkit.util.Vector; + +import java.util.Objects; + +public class RoundedTNTPosition { + + private static final int factor = 10; + + private int x; + private int y; + private int z; + + public RoundedTNTPosition(TNTPosition tntPosition) { + this(tntPosition.getLocation().getX(), tntPosition.getLocation().getY(), tntPosition.getLocation().getZ()); + } + + public RoundedTNTPosition(Vector vector) { + this(vector.getX(), vector.getY(), vector.getZ()); + } + + public RoundedTNTPosition(double x, double y, double z) { + this.x = (int) (x * factor); + this.y = (int) (y * factor); + this.z = (int) (z * factor); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RoundedTNTPosition)) return false; + RoundedTNTPosition that = (RoundedTNTPosition) o; + return x == that.x && + y == that.y && + z == that.z; + } + + @Override + public int hashCode() { + return Objects.hash(x, y, z); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/TNTPosition.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/TNTPosition.java new file mode 100644 index 00000000..d8deae6b --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/TNTPosition.java @@ -0,0 +1,63 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer; + +import de.steamwar.bausystem.tracer.show.Record; +import org.bukkit.entity.Entity; +import org.bukkit.util.Vector; + +public class TNTPosition { + + private final Record.TNTRecord record; + private final Vector location; + private final Vector previousLocation; + private final boolean exploded; + + public TNTPosition(Record.TNTRecord record, Entity entity, Vector previousLocation, boolean exploded) { + this.location = entity.getLocation().toVector(); + this.record = record; + this.previousLocation = previousLocation; + this.exploded = exploded; + } + + public Vector getLocation() { + return location; + } + + public Vector getPreviousLocation() { + return previousLocation; + } + + public boolean isExploded() { + return exploded; + } + + public Record.TNTRecord getRecord() { + return record; + } + + @Override + public String toString() { + return "Position{" + + "location=" + location + + '}'; + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStateMachine.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStateMachine.java new file mode 100644 index 00000000..bd679386 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStateMachine.java @@ -0,0 +1,94 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.record; + +public class RecordStateMachine { + private RecordStateMachine() { + } + + private static final TraceAutoHandler autoHandler = new TraceAutoHandler(); + + private static RecordStatus recordStatus = RecordStatus.IDLE; + private static Recorder recorder = null; + + public static void commandStart() { + autoHandler.disable(); + recordStart(); + recordStatus = RecordStatus.RECORD; + } + + public static void commandStop() { + autoHandler.disable(); + recordStop(); + recordStatus = RecordStatus.IDLE; + } + + public static void commandAuto() { + if (recordStatus.isTracing()) + return; + + if (recordStatus == RecordStatus.IDLE_AUTO) { + recordStatus = RecordStatus.IDLE; + autoHandler.disable(); + } else { + recordStatus = RecordStatus.IDLE_AUTO; + autoHandler.enable(); + } + } + + static void autoRecord() { + recordStart(); + recordStatus = RecordStatus.RECORD_AUTO; + } + + static void autoIdle() { + recordStop(); + recordStatus = RecordStatus.IDLE_AUTO; + } + + private static void recordStart() { + if (recordStatus.isTracing()) return; + recorder = new Recorder(); + } + + private static void recordStop() { + if (!recordStatus.isTracing()) return; + recorder.stopRecording(); + } + + public static RecordStatus getRecordStatus() { + return recordStatus; + } + + public static int size() { + if (recorder == null) return 0; + return recorder.size(); + } + + public static long getStartTime() { + if (recorder == null) return 0; + return recorder.getStartTime(); + } + + public static void postClear() { + if (recorder == null) return; + recorder.postClear(); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStatus.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStatus.java new file mode 100644 index 00000000..b87e740c --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/RecordStatus.java @@ -0,0 +1,55 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.record; + +public enum RecordStatus { + + RECORD("§aan", true, "§cTNT-Tracer muss gestoppt werden"), + RECORD_AUTO("§aan", true, "§cTNT-Tracer darf nicht aufnehmen"), + IDLE("§caus", false, "§cAuto-Tracer gestoppt"), + IDLE_AUTO("§eauto", false, "§aAuto-Tracer gestartet"); + + String name; + boolean tracing; + String autoMessage; + + RecordStatus(String value, boolean tracing, String autoMessage) { + this.name = value; + this.tracing = tracing; + this.autoMessage = autoMessage; + } + + public String getName() { + return name; + } + + public boolean isTracing() { + return tracing; + } + + public boolean isAutoTrace() { + return this == RECORD_AUTO || this == IDLE_AUTO; + } + + public String getAutoMessage() { + return autoMessage; + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/Recorder.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/Recorder.java new file mode 100644 index 00000000..171afd01 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/Recorder.java @@ -0,0 +1,96 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.record; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.tracer.show.Record; +import de.steamwar.bausystem.tracer.show.StoredRecords; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.scheduler.BukkitTask; + +import java.util.HashMap; +import java.util.Map; + +public class Recorder implements Listener { + + private static final World world = Bukkit.getWorlds().get(0); + + private final Map recordMap = new HashMap<>(); + private final BukkitTask task; + private final Record record; + + Recorder() { + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), this::run, 1, 1); + record = new Record(); + + // To trace TNT initial positions with AutoTracer + run(); + } + + void stopRecording() { + HandlerList.unregisterAll(this); + task.cancel(); + } + + int size() { + return record.size(); + } + + long getStartTime() { + return record.getStartTime(); + } + + void postClear() { + record.clear(); + recordMap.clear(); + StoredRecords.add(record); + } + + private void run() { + world.getEntitiesByClass(TNTPrimed.class).forEach(tntPrimed -> get(tntPrimed).add(tntPrimed)); + } + + @EventHandler + public void onEntityExplode(EntityExplodeEvent event) { + if (!(event.getEntity() instanceof TNTPrimed)) + return; + TNTPrimed tntPrimed = (TNTPrimed) event.getEntity(); + + get(tntPrimed).explode(tntPrimed); + recordMap.remove(tntPrimed); + } + + private Record.TNTRecord get(TNTPrimed tntPrimed) { + Record.TNTRecord tntRecord = recordMap.get(tntPrimed); + if (tntRecord != null) + return tntRecord; + + tntRecord = this.record.spawn(); + recordMap.put(tntPrimed, tntRecord); + return tntRecord; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/TraceAutoHandler.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/TraceAutoHandler.java new file mode 100644 index 00000000..58e52e41 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/record/TraceAutoHandler.java @@ -0,0 +1,70 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.record; + +import de.steamwar.bausystem.BauSystem; +import org.bukkit.Bukkit; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.scheduler.BukkitTask; + +public class TraceAutoHandler implements Listener { + /* This listener handles the en- and disabling of the Tracer in AUTO mode */ + + private BukkitTask task; + private int lastExplosion = 0; // Time since the last explosion in ticks + + public void enable() { + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + } + + public void disable() { + HandlerList.unregisterAll(this); + if (task != null) { + task.cancel(); + task = null; + } + } + + @EventHandler + public void onEntityExplode(EntityExplodeEvent event) { + if (!(event.getEntity() instanceof TNTPrimed)) + return; + + lastExplosion = 0; + if (task == null) { + RecordStateMachine.autoRecord(); + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), this::run, 1, 1); + } + } + + private void run() { + lastExplosion++; + + if (lastExplosion > 80) { + RecordStateMachine.autoIdle(); + task.cancel(); + task = null; + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/Record.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/Record.java new file mode 100644 index 00000000..b6ac929c --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/Record.java @@ -0,0 +1,94 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.show; + +import de.steamwar.bausystem.tracer.TNTPosition; +import org.bukkit.entity.TNTPrimed; + +import java.util.ArrayList; +import java.util.List; + +public class Record { + + private final long startTime; + private final List tnt = new ArrayList<>(); + + public int size() { + return tnt.size(); + } + + public long getStartTime() { + return startTime; + } + + public void showAll(ShowMode mode) { + for (TNTRecord record : tnt) + record.showAll(mode); + } + + /* The following methods should only be called by a recorder */ + public Record() { + startTime = System.currentTimeMillis(); + StoredRecords.add(this); + } + + public TNTRecord spawn() { + TNTRecord record = new TNTRecord(); + tnt.add(record); + return record; + } + + public void clear() { + tnt.clear(); + } + + public static class TNTRecord { + private final List positions = new ArrayList<>(41); + + public void showAll(ShowMode mode) { + for (TNTPosition position : positions) + mode.show(position); + } + + /* The following methods should only be called by a recorder */ + public void add(TNTPrimed tntPrimed) { + add(tntPrimed, false); + } + + private void add(TNTPrimed tntPrimed, boolean exploded) { + TNTPosition position; + if (positions.isEmpty()) { + position = new TNTPosition(this, tntPrimed, null, exploded); + } else { + position = new TNTPosition(this, tntPrimed, positions.get(positions.size() - 1).getLocation(), exploded); + } + positions.add(position); + TraceShowManager.show(position); + } + + public void explode(TNTPrimed tntPrimed) { + add(tntPrimed, true); + } + + public List getPositions() { + return positions; + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowMode.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowMode.java new file mode 100644 index 00000000..d313189d --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowMode.java @@ -0,0 +1,28 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.show; + +import de.steamwar.bausystem.tracer.TNTPosition; + +public interface ShowMode { + void show(TNTPosition position); + + void hide(); +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameter.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameter.java new file mode 100644 index 00000000..ba67f716 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameter.java @@ -0,0 +1,57 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * / + */ + +package de.steamwar.bausystem.tracer.show; + +public class ShowModeParameter { + + private boolean water = false; + private boolean interpolate_Y = false; + private boolean interpolate_XZ = false; + + public ShowModeParameter() { + + } + + public boolean isWater() { + return water; + } + + public boolean isInterpolate_Y() { + return interpolate_Y; + } + + public boolean isInterpolate_XZ() { + return interpolate_XZ; + } + + public void setWater(boolean water) { + this.water = water; + } + + public void setInterpolate_Y(boolean interpolate_Y) { + this.interpolate_Y = interpolate_Y; + } + + public void setInterpolate_XZ(boolean interpolate_XZ) { + this.interpolate_XZ = interpolate_XZ; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameterType.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameterType.java new file mode 100644 index 00000000..5cb046cf --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/ShowModeParameterType.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.tracer.show; + +import java.util.function.Consumer; + +public enum ShowModeParameterType { + + WATER(showModeParameter -> showModeParameter.setWater(true)), + INTERPOLATE_Y(showModeParameter -> showModeParameter.setInterpolate_Y(true)), + INTERPOLATE_XZ(showModeParameter -> showModeParameter.setInterpolate_XZ(true)), + ADVANCED(showModeParameter -> { + showModeParameter.setInterpolate_Y(true); + showModeParameter.setInterpolate_XZ(true); + }); + + private final Consumer showModeParameterConsumer; + + public Consumer getShowModeParameterConsumer() { + return showModeParameterConsumer; + } + + ShowModeParameterType(Consumer showModeParameterConsumer) { + this.showModeParameterConsumer = showModeParameterConsumer; + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/StoredRecords.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/StoredRecords.java new file mode 100644 index 00000000..b0a377ee --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/StoredRecords.java @@ -0,0 +1,45 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.tracer.show; + +import de.steamwar.bausystem.tracer.record.RecordStateMachine; + +import java.util.ArrayList; +import java.util.List; + +public class StoredRecords { + + private static final List records = new ArrayList<>(); + + public static void add(Record record) { + records.add(record); + } + + public static void showAll(ShowMode mode) { + for (Record record : records) record.showAll(mode); + } + + public static void clear() { + records.clear(); + TraceShowManager.clear(); + RecordStateMachine.postClear(); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/TraceShowManager.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/TraceShowManager.java new file mode 100644 index 00000000..0c4b88ee --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/TraceShowManager.java @@ -0,0 +1,59 @@ +package de.steamwar.bausystem.tracer.show; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.tracer.TNTPosition; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.HashMap; +import java.util.Map; + +public class TraceShowManager implements Listener { + private TraceShowManager() { + } + + private static final Map showModes = new HashMap<>(); + + public static void show(Player player, ShowMode showMode) { + hide(player); + showModes.put(player, showMode); + StoredRecords.showAll(showMode); + } + + public static void hide(Player player) { + ShowMode showMode = showModes.remove(player); + if (showMode == null) + return; + showMode.hide(); + } + + /* Only to be called by record */ + static void show(TNTPosition tnt) { + for (ShowMode mode : showModes.values()) + mode.show(tnt); + } + + /* Only to be called by StoredRecords */ + static void clear() { + for (ShowMode mode : showModes.values()) + mode.hide(); + } + + /* Internal if player leaves*/ + static { + Bukkit.getPluginManager().registerEvents(new TraceShowManager(), BauSystem.getPlugin()); + } + + @EventHandler + public void onLeave(PlayerQuitEvent event) { + showModes.remove(event.getPlayer()); + } + + public static boolean hasActiveShow(Player player) { + return showModes.containsKey(player); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/mode/EntityShowMode.java b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/mode/EntityShowMode.java new file mode 100644 index 00000000..0e1a27ef --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/tracer/show/mode/EntityShowMode.java @@ -0,0 +1,120 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * / + */ + +package de.steamwar.bausystem.tracer.show.mode; + +import de.steamwar.bausystem.CraftbukkitWrapper; +import de.steamwar.bausystem.FlatteningWrapper; +import de.steamwar.bausystem.tracer.AbstractTraceEntity; +import de.steamwar.bausystem.tracer.RoundedTNTPosition; +import de.steamwar.bausystem.tracer.TNTPosition; +import de.steamwar.bausystem.tracer.show.ShowMode; +import de.steamwar.bausystem.tracer.show.ShowModeParameter; +import org.bukkit.entity.Player; +import org.bukkit.util.Consumer; +import org.bukkit.util.Vector; + +import java.util.HashMap; +import java.util.Map; + +public class EntityShowMode implements ShowMode { + + protected final Player player; + protected final ShowModeParameter showModeParameter; + + private final Map tntEntityMap = new HashMap<>(); + private final Map updateEntityMap = new HashMap<>(); + + public EntityShowMode(Player player, ShowModeParameter showModeParameter) { + this.player = player; + this.showModeParameter = showModeParameter; + } + + @Override + public void show(TNTPosition position) { + if (!showModeParameter.isWater() && position.isExploded() && checkWater(position.getLocation())) { + // Basic + for (TNTPosition pos : position.getRecord().getPositions()) { + RoundedTNTPosition roundedTNTPosition = new RoundedTNTPosition(pos); + tntEntityMap.computeIfPresent(roundedTNTPosition, (p, tnt) -> { + return tnt.hide(player, false) ? null : tnt; + }); + } + // Advanced + for (TNTPosition pos : position.getRecord().getPositions()) { + applyOnPosition(pos, updatePointPosition -> { + updateEntityMap.computeIfPresent(new RoundedTNTPosition(updatePointPosition), (p, point) -> { + return point.hide(player, false) ? null : point; + }); + }); + } + return; + } + + RoundedTNTPosition roundedTNTPosition = new RoundedTNTPosition(position); + AbstractTraceEntity entity = tntEntityMap.computeIfAbsent(roundedTNTPosition, pos -> createEntity(player, position.getLocation(), true)); + entity.display(player, position.isExploded()); + + applyOnPosition(position, updatePointPosition -> { + updateEntityMap.computeIfAbsent(new RoundedTNTPosition(updatePointPosition), pos -> { + return createEntity(player, updatePointPosition, false); + }).display(player, position.isExploded()); + }); + } + + private boolean checkWater(Vector position) { + return FlatteningWrapper.impl.inWater(player.getWorld(), position); + } + + public static AbstractTraceEntity createEntity(Player player, Vector position, boolean tnt) { + return CraftbukkitWrapper.impl.create(player.getWorld(), position, tnt); + } + + private void applyOnPosition(TNTPosition position, Consumer function) { + if (position.getPreviousLocation() == null) return; + + if (showModeParameter.isInterpolate_Y()) { + Vector updatePointY = position.getPreviousLocation().clone().setY(position.getLocation().getY()); + if (!position.getLocation().equals(updatePointY)) { + function.accept(updatePointY); + } + } + + if (showModeParameter.isInterpolate_XZ()) { + Vector movement = position.getLocation().clone().subtract(position.getPreviousLocation()); + Vector updatePointXZ = Math.abs(movement.getX()) > Math.abs(movement.getZ()) + ? position.getLocation().clone().setZ(position.getPreviousLocation().getZ()) + : position.getLocation().clone().setX(position.getPreviousLocation().getX()); + if (!position.getLocation().equals(updatePointXZ)) { + function.accept(updatePointXZ); + } + } + } + + @Override + public void hide() { + tntEntityMap.forEach((roundedTNTPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true)); + tntEntityMap.clear(); + updateEntityMap.forEach((roundedTNTPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true)); + updateEntityMap.clear(); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/AFKStopper.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/AFKStopper.java new file mode 100644 index 00000000..cf8e7bd2 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/AFKStopper.java @@ -0,0 +1,56 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; + +public class AFKStopper implements Listener { + + private static final String afkWarning = BauSystem.PREFIX + "§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt"; + + private int minutesAfk; + + public AFKStopper() { + minutesAfk = 0; + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), () -> { + switch (minutesAfk) { + case 5: + for (Player p : Bukkit.getOnlinePlayers()) + p.kickPlayer("§cAuf diesem Server ist seit 5 Minuten nichts passiert."); + break; + case 4: + Bukkit.broadcastMessage(afkWarning); + default: + minutesAfk++; + } + }, 1200, 1200); //every minute + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + minutesAfk = 0; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/AbstractAutoLoader.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/AbstractAutoLoader.java new file mode 100644 index 00000000..d30fe2dc --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/AbstractAutoLoader.java @@ -0,0 +1,122 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.LinkedList; + +abstract class AbstractAutoLoader { + + abstract Player getPlayer(); + abstract boolean setRedstone(Location location, boolean active); + abstract LinkedList getActions(); + abstract void resetLastActivation(); + abstract int getLastActivation(); + + void print(String message, boolean withSize){ + if(withSize) + getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message + " §8" + getActions().size())); + else + getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); + } + + abstract static class LoaderAction { + + final Location location; + final AbstractAutoLoader loader; + + LoaderAction(AbstractAutoLoader loader, Location location){ + this.location = location; + this.loader = loader; + loader.getActions().add(this); + loader.resetLastActivation(); + } + + abstract boolean perform(); + abstract int ticks(); + } + + static class RedstoneActivation extends LoaderAction{ + + final boolean active; + final int length; + int status; + + RedstoneActivation(AbstractAutoLoader loader, Location location, int ticks, boolean active){ + super(loader, location); + this.length = ticks; + this.active = active; + status = 0; + } + + @Override + public boolean perform() { + status++; + if(status < length) + return false; + + if(!loader.setRedstone(location, active)) + return false; + status = 0; + return true; + } + + @Override + int ticks() { + return 1; + } + } + + static class TemporaryActivation extends LoaderAction{ + + final int length; + int status; + + TemporaryActivation(AbstractAutoLoader loader, Location location, int ticks){ + super(loader, location); + this.length = ticks; + status = 0; + } + + @Override + public boolean perform() { + if(status == 0){ + if(!loader.setRedstone(location, true)) + return false; + }else if(status == length){ + if(!loader.setRedstone(location, false)) + return false; + status = 0; + return true; + } + status++; + return false; + } + + @Override + int ticks() { + return 1; + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/AutoLoader.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/AutoLoader.java new file mode 100644 index 00000000..92aa8bc1 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/AutoLoader.java @@ -0,0 +1,266 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.FlatteningWrapper; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.scheduler.BukkitTask; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.Map; + +public class AutoLoader extends AbstractAutoLoader implements Listener { + + private static final Map players = new HashMap<>(); + + public static AutoLoader getLoader(Player player){ + if(!players.containsKey(player)) + return new AutoLoader(player); + return players.get(player); + } + + public static boolean hasLoader(Player player){ + return players.containsKey(player); + } + + private final Player player; + private final BukkitTask task; + + private final LinkedList actions = new LinkedList<>(); + private int ticksBetweenShots = 80; + private int ticksBetweenBlocks = 1; + + private int lastActivation; + private int waitTicks; + private ListIterator lastAction; + private boolean setup; + private Location lastLocation; + + private AutoLoader(Player player){ + this.player = player; + Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), this::run, 1, 1); + players.put(player, this); + player.sendMessage(BauSystem.PREFIX + "§7Schieße bitte einmal die Kanone ab"); + player.sendMessage(BauSystem.PREFIX + "§7Und starte anschließend den AutoLader mit §8/§eloader start"); + setup(); + } + + public void setup(){ + print("§aAutoLader im Setup-Modus", false); + setup = true; + waitTicks = 0; + lastActivation = 0; + } + + public void start(){ + if(actions.isEmpty()){ + print("§cKeine Aktion vorhanden", false); + return; + } + + if(!setup){ + print("§cAutoLader läuft bereits", false); + return; + } + + setup = false; + waitTicks = 0; + lastActivation = 0; + lastAction = actions.listIterator(); + print("§aAutoLader gestartet", false); + } + + public void stop(){ + print("§cAutoLader gestoppt", false); + players.remove(player); + HandlerList.unregisterAll(this); + if(task != null) + task.cancel(); + } + + public void undo(){ + if(actions.isEmpty()){ + print("§cKeine Aktion vorhanden", false); + return; + } + + actions.removeLast(); + print("§aUndo erfolgreich", true); + } + + public void wait(int time){ + if(time < 1){ + print("§cDie Wartezeit ist zu klein", false); + return; + } + + print("§aSchusswartezeit §e" + time + " §aTicks§8, zuvor " + ticksBetweenShots, false); + ticksBetweenShots = time; + } + + public void blockWait(int time){ + if(time < 1){ + print("§cDie Wartezeit ist zu klein", false); + return; + } + + print("§aSetzwartezeit §e" + time + " §aTicks§8, zuvor " + ticksBetweenBlocks, false); + ticksBetweenBlocks = time; + } + + public int getTicksBetweenShots() { + return ticksBetweenShots; + } + + public int getTicksBetweenBlocks() { + return ticksBetweenBlocks; + } + + public boolean isSetup() { + return setup; + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event){ + if(!setup || !event.getPlayer().equals(player)) + return; + if(event.getBlock().getType() != Material.TNT) + return; + + new TNTPlaceAction(this, event.getBlock().getLocation()); + print("§eTNT platziert", true); + } + + //BlockRedstoneEvent? + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event){ + if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) + return; + if (event.getClickedBlock().getType() == Material.OBSERVER) + return; + if (event.getPlayer().isSneaking()) + return; + + if (!setup || !event.getPlayer().equals(player)) + return; + + Detoloader detoloader = FlatteningWrapper.impl.onPlayerInteractLoader(event); + if (detoloader == null || detoloader.getActivation() < 0) return; + + if (lastLocation != null && lastLocation.distance(event.getClickedBlock().getLocation()) <= 1) return; + + if (detoloader.useActive) { + new AbstractAutoLoader.RedstoneActivation(this, event.getClickedBlock().getLocation() + , detoloader.getActivation() == 0 ? getLastActivation() : detoloader.getActivation() + , detoloader.isActive()); + } else { + new AbstractAutoLoader.TemporaryActivation(this, event.getClickedBlock().getLocation() + , detoloader.getActivation()); + } + print(detoloader.addBack ? "§e" + detoloader.getBlock() + " betätigt" : + detoloader.getBlock(), detoloader.addBack); + lastLocation = event.getClickedBlock().getLocation(); + } + + @EventHandler + public void onLeave(PlayerQuitEvent event){ + if(!event.getPlayer().equals(player)) + return; + stop(); + } + + private void run(){ + lastActivation++; + if(setup) + return; + while(lastActivation >= waitTicks){ + lastActivation = 0; + + LoaderAction action = lastAction.next(); + if(action.perform()){ + waitTicks = action.ticks(); + }else{ + waitTicks = 1; + lastAction.previous(); + } + + if(!lastAction.hasNext()){ + lastAction = actions.listIterator(); + waitTicks = ticksBetweenShots; + } + } + } + + @Override + Player getPlayer() { + return player; + } + + @Override + boolean setRedstone(Location location, boolean active){ + return FlatteningWrapper.impl.setRedstone(location, active); + } + + @Override + LinkedList getActions() { + return actions; + } + + @Override + void resetLastActivation() { + lastActivation = 0; + } + + @Override + int getLastActivation() { + return lastActivation; + } + + class TNTPlaceAction extends AbstractAutoLoader.LoaderAction { + + TNTPlaceAction(AbstractAutoLoader loader, Location location){ + super(loader, location); + } + + @Override + public boolean perform() { + return FlatteningWrapper.impl.tntPlaceActionPerform(location); + } + + @Override + int ticks(){ + return ticksBetweenBlocks; + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/BauScoreboard.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/BauScoreboard.java new file mode 100644 index 00000000..380bc715 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/BauScoreboard.java @@ -0,0 +1,111 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.commands.CommandTPSLimiter; +import de.steamwar.bausystem.tracer.record.RecordStateMachine; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.core.TPSWatcher; +import de.steamwar.scoreboard.SWScoreboard; +import de.steamwar.scoreboard.ScoreboardCallback; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; + +public class BauScoreboard implements Listener { + + @EventHandler + public void handlePlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + SWScoreboard.impl.createScoreboard(player, new ScoreboardCallback() { + @Override + public HashMap getData() { + return sidebar(player); + } + + @Override + public String getTitle() { + return "§eSteam§8War"; + } + }); + } + + private HashMap sidebar(Player p) { + List strings = new ArrayList<>(); + strings.add("§1"); + strings.add("§eUhrzeit§8: §7" + new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime())); + strings.add("§2"); + Region region = Region.getRegion(p.getLocation()); + strings.add("§eTNT§8: " + region.getTntMode().getName()); + strings.add("§eFreeze§8: " + (region.isFreeze() ? "§aan" : "§caus")); + strings.add("§eFire§8: " + (region.isFire() ? "§aaus" : "§can")); + strings.add("§eTrace§8: " + RecordStateMachine.getRecordStatus().getName()); + strings.add("§eLoader§8: " + (AutoLoader.hasLoader(p) ? "§aan" : "§caus")); + if (region.hasProtection()) { + strings.add("§eProtect§8: " + (region.isProtect() ? "§aan" : "§caus")); + } + + if (RecordStateMachine.getRecordStatus().isTracing()) { + strings.add("§3"); + strings.add("§eTicks§8: §7" + traceTicks()); + strings.add("§eAnzahl TNT§8: §7" + RecordStateMachine.size()); + } + + strings.add("§4"); + strings.add("§eTPS§8: " + tpsColor() + TPSUtils.getTps(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit()); + + int i = strings.size(); + HashMap result = new HashMap<>(); + for (String s : strings) + result.put(s, i--); + return result; + } + + private long traceTicks() { + return (System.currentTimeMillis() - RecordStateMachine.getStartTime()) / 50; + } + + private String tpsColor() { + double tps = TPSUtils.getTps(TPSWatcher.TPSType.ONE_SECOND); + if (tps > CommandTPSLimiter.getCurrentTPSLimit() * 0.9) { + return "§a"; + } + if (tps > CommandTPSLimiter.getCurrentTPSLimit() * 0.5) { + return "§e"; + } + return "§c"; + } + + private String tpsLimit() { + if (CommandTPSLimiter.getCurrentTPSLimit() == 20) { + return ""; + } + return "§8/§7" + CommandTPSLimiter.getCurrentTPSLimit(); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/ClipboardListener.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/ClipboardListener.java new file mode 100644 index 00000000..6ab68478 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/ClipboardListener.java @@ -0,0 +1,63 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.sql.SchematicData; +import de.steamwar.sql.SchematicNode; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class ClipboardListener implements Listener { + + private static final String CLIPBOARD_SCHEMNAME = "//copy"; + + @EventHandler + public void onLogin(PlayerJoinEvent e) { + try { + SchematicNode schematic = SchematicNode.getSchematicNode(SteamwarUser.get(e.getPlayer().getUniqueId()).getId(), CLIPBOARD_SCHEMNAME, (Integer) null); + if (schematic != null) { + new SchematicData(schematic).loadToPlayer(e.getPlayer()); + } + } catch (Exception ex) { + // ignore cause players do all kind of stuff with schematics.... like massively oversized schems + } + } + + @EventHandler + public void onLogout(PlayerQuitEvent e) { + SchematicNode schematic = SchematicNode.getSchematicNode(SteamwarUser.get(e.getPlayer().getUniqueId()).getId(), CLIPBOARD_SCHEMNAME, (Integer) null); + boolean newSchem = false; + if (schematic == null) { + schematic = SchematicNode.createSchematic(SteamwarUser.get(e.getPlayer().getUniqueId()).getId(), CLIPBOARD_SCHEMNAME, null); + newSchem = true; + } + + try { + new SchematicData(schematic).saveFromPlayer(e.getPlayer()); + } catch (Exception ex) { + if (newSchem) { + schematic.delete(); + } + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/Color.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/Color.java new file mode 100644 index 00000000..2f068813 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/Color.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world; + +public enum Color { + WHITE, + ORANGE, + MAGENTA, + LIGHT_BLUE, + YELLOW, + LIME, + PINK, + GRAY, + LIGHT_GRAY, + CYAN, + PURPLE, + BLUE, + BROWN, + GREEN, + RED, + BLACK; +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/Detoloader.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/Detoloader.java new file mode 100644 index 00000000..531fff59 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/Detoloader.java @@ -0,0 +1,87 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import org.bukkit.Location; + +public class Detoloader { + + String message; + int activation; + boolean active, addBack = true, useActive = false; + + public Detoloader(String message, int activation) { + this.message = message; + this.activation = activation; + } + + public String getBlock() { + return message; + } + + public void setBlock(String message) { + this.message = message; + } + + public int getActivation() { + return activation; + } + + public boolean isActive() { + return active; + } + + public Detoloader setActive(boolean active) { + useActive = true; + this.active = active; + return this; + } + + public boolean isAddBack() { + return addBack; + } + + public Detoloader setAddBack(boolean addBack) { + this.addBack = addBack; + return this; + } + + static class DetonatorActivation { + + int activation = -1; + Location location; + + public DetonatorActivation(Location location) { + this.location = location; + } + + public DetonatorActivation(int activation, Location location) { + this.activation = activation; + this.location = location; + } + } + + //Timings + public static final int STONE_BUTTON = 20; + public static final int WOODEN_BUTTON = 30; + public static final int PRESSURE_PLATE = 20; + public static final int NOTE_BLOCK = 1; + public static final int TRIPWIRE = 20; +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/Detonator.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/Detonator.java new file mode 100644 index 00000000..93c90c54 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/Detonator.java @@ -0,0 +1,120 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.FlatteningWrapper; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.*; + +public class Detonator implements Listener { + + public static final ItemStack WAND; + + public static final Map> PLAYER_LOCS = new HashMap<>(); + + static { + WAND = new ItemStack(Material.BLAZE_ROD, 1); + ItemMeta im = WAND.getItemMeta(); + + im.setDisplayName("§eFernzünder"); + + List lorelist = Arrays.asList("§eLinks Klick §8- §7Setzte einen Punkt zum Aktivieren", + "§eLinks Klick + Shift §8- §7Füge einen Punkt hinzu", "§eRechts Klick §8- §7Löse alle Punkte aus"); + im.setLore(lorelist); + + WAND.setItemMeta(im); + } + + public static Detonator getDetonator(Player player, ItemStack item) { + return new Detonator(player, PLAYER_LOCS.get(player)); + } + + public static ItemStack setLocation(Player player, ItemStack item, Detoloader.DetonatorActivation detoloader) { + PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).clear(); + PLAYER_LOCS.get(player).add(detoloader); + return item; + } + + public static ItemStack toggleLocation(ItemStack item, Player player, Detoloader detoloader, Location location) { + if (PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).stream().anyMatch(activation -> activation.location.equals(location))) { + DetonatorListener.print(player, detoloader.addBack ? "§e" + detoloader.getBlock() + " entfernt" : + detoloader.getBlock(), Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() - 1); + PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).removeIf(activation -> activation.location.equals(location)); + return item; + } else { + DetonatorListener.print(player, detoloader.addBack ? "§e" + detoloader.getBlock() + " hinzugefügt" : + detoloader.getBlock(), Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() + 1); + if (detoloader.getActivation() == 0) { + PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).add(new Detoloader.DetonatorActivation(location)); + return item; + } else { + PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).add(new Detoloader.DetonatorActivation(detoloader.getActivation(), location)); + return item; + } + } + } + + public static void execute(Player player) { + execute(player, PLAYER_LOCS.get(player)); + } + + private static void execute(Player player, Set locs) { + for (Detoloader.DetonatorActivation activation : locs) { + + if (activation.activation == -1) { + FlatteningWrapper.impl.setRedstone(activation.location, !FlatteningWrapper.impl.getLever(activation.location.getBlock())); + } else { + FlatteningWrapper.impl.setRedstone(activation.location, true); + Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), () -> FlatteningWrapper.impl.setRedstone(activation.location, false), activation.activation); + } + } + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("§e" + locs.size() + " §7Punkt" + (locs.size() > 1 ? "e" : "") + " ausgelöst!")); + } + + public static void clear(Player player) { + PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).clear(); + } + + private final Set locs; + private final Player player; + + private Detonator(Player player, Set locs) { + this.player = player; + this.locs = locs; + } + + public Set getLocs() { + return locs; + } + + public Player getPlayer() { + return player; + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/DetonatorListener.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/DetonatorListener.java new file mode 100644 index 00000000..b616fb97 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/DetonatorListener.java @@ -0,0 +1,65 @@ +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.FlatteningWrapper; +import de.steamwar.bausystem.Permission; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class DetonatorListener implements Listener { + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getItem() == null) return; + if (event.getItem().isSimilar(Detonator.WAND)) { + Player player = event.getPlayer(); + if (Welt.noPermission(player, Permission.WORLD)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Detonator nutzen"); + return; + } + ItemStack item = event.getItem(); + event.setCancelled(true); + switch (event.getAction()) { + case LEFT_CLICK_BLOCK: + Detoloader detoloader = FlatteningWrapper.impl.onPlayerInteractLoader(event); + + if (detoloader == null) { + return; + } else if (detoloader.activation == -1) { + print(player, detoloader.getBlock(), detoloader.addBack ? Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() : 0); + return; + } + + if (event.getPlayer().isSneaking()) { + player.getInventory().setItemInMainHand(Detonator.toggleLocation(item, player, detoloader, event.getClickedBlock().getLocation())); + } else { + if (detoloader.getActivation() == 0) { + player.getInventory().setItemInMainHand(Detonator.setLocation(player, item, new Detoloader.DetonatorActivation(event.getClickedBlock().getLocation()))); + } else { + player.getInventory().setItemInMainHand(Detonator.setLocation(player, item, new Detoloader.DetonatorActivation(detoloader.activation, event.getClickedBlock().getLocation()))); + } + print(player, detoloader.addBack ? "§e" + detoloader.getBlock() + " gesetzt" : + detoloader.getBlock(), detoloader.addBack ? Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() : 0); + } + break; + case RIGHT_CLICK_AIR: + case RIGHT_CLICK_BLOCK: + Detonator.execute(player); + break; + } + } + } + + public static void print(Player player, String message, int size) { + if (size == 0) { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); + } else { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message + " §8" + size)); + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/ItemFrameListener.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/ItemFrameListener.java new file mode 100644 index 00000000..a8c9618f --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/ItemFrameListener.java @@ -0,0 +1,52 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.SWUtils; +import org.bukkit.Material; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; + +public class ItemFrameListener implements Listener { + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Player)) { + return; + } + if (!(event.getEntity() instanceof ItemFrame)) { + return; + } + event.setCancelled(true); + ItemFrame itemFrame = (ItemFrame) event.getEntity(); + ItemStack itemStack = itemFrame.getItem(); + if (itemStack.getType() != Material.AIR) { + SWUtils.giveItemToPlayer((Player) event.getDamager(), itemFrame.getItem()); + itemFrame.setItem(null); + } else { + itemFrame.remove(); + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/PredefinedBook.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/PredefinedBook.java new file mode 100644 index 00000000..355fd3b8 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/PredefinedBook.java @@ -0,0 +1,124 @@ +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class PredefinedBook { + + private static final FileConfiguration configuration; + private static List bookCache; + + static { + configuration = YamlConfiguration.loadConfiguration(new File(BauSystem.getPlugin().getDataFolder(), "books.yml")); + } + + public static List getBooks() { + if (bookCache != null) + return bookCache; + List books = new ArrayList<>(); + for (String book : configuration.getKeys(false)) { + ConfigurationSection section = Objects.requireNonNull(configuration.getConfigurationSection(book)); + books.add(new PredefinedBook(section)); + } + bookCache = books; + return books; + } + + public static int getBookCount() { + return configuration.getKeys(false).size(); + } + + private List lines; + private List lore; + private String author; + private String name; + private ItemStack finishedBook; + + PredefinedBook(ConfigurationSection section) { + this.lines = section.getStringList("lines"); + this.lore = section.getStringList("lore"); + this.author = section.getString("author", "§8Steam§eWar"); + this.name = section.getName(); + } + + public ItemStack toItemStack() { + if (finishedBook != null) + return finishedBook; + ItemStack book = new ItemStack(getBookMat()); + BookMeta meta = (BookMeta) book.getItemMeta(); + meta.setPages(getPages()); + meta.setDisplayName(name); + meta.setTitle(name); + meta.setAuthor(author); + meta.setGeneration(BookMeta.Generation.ORIGINAL); + meta.setLore(lore); + book.setItemMeta(meta); + finishedBook = book; + return book; + } + + public Material getBookMat() { + return Material.WRITTEN_BOOK; + } + + public List getLines() { + return lines; + } + + public String getAuthor() { + return author; + } + + public String getName() { + return name; + } + + public List getLore() { + return lore; + } + + private String[] getPages() { + List pages = new ArrayList<>(); + pages.add(0, new StringBuilder()); + int charsPerLine = 19; + int currentLine = 0; + int currentpage = 0; + boolean first = true; + for (String line : lines) { + int linesPlus = (int) Math.ceil((double) line.length() / charsPerLine); + currentLine += linesPlus; + if (currentLine >= 14 || line.equals("!")) { + currentLine = linesPlus; + currentpage++; + if (currentpage > 50) + throw new IllegalStateException("Book " + name + " has more pages than 50"); + pages.add(currentpage, new StringBuilder()); + first = true; + if (line.equals("!")) + continue; + } + if (!first) { + pages.get(currentpage).append("\n"); + } else { + first = false; + } + pages.get(currentpage).append(line); + } + + String[] finalPages = new String[pages.size()]; + for (int i = 0; i < pages.size(); i++) { + finalPages[i] = pages.get(i).toString(); + } + return finalPages; + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/RegionListener.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/RegionListener.java new file mode 100644 index 00000000..19f18c02 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/RegionListener.java @@ -0,0 +1,137 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.CraftbukkitWrapper; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.WorldeditWrapper; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.Sign; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import java.util.ArrayList; +import java.util.List; + +public class RegionListener implements Listener { + + private final List signEditing = new ArrayList<>(); + + private static final Class updateSign = Reflection.getClass("{nms}.PacketPlayInUpdateSign"); + private static final Class blockPosition = Reflection.getClass("{nms}.BlockPosition"); + private static final Reflection.Field blockPos = Reflection.getField(updateSign, blockPosition, 0); + private static final Reflection.Field signText = Reflection.getField(updateSign, String[].class, 0); + private static final Class baseBlockPosition = Reflection.getClass("{nms}.BaseBlockPosition"); + private static final Reflection.Field blockPosX = Reflection.getField(baseBlockPosition, int.class, 0); + private static final Reflection.Field blockPosY = Reflection.getField(baseBlockPosition, int.class, 1); + private static final Reflection.Field blockPosZ = Reflection.getField(baseBlockPosition, int.class, 2); + public RegionListener() { + TinyProtocol.instance.addFilter(updateSign, (player, packet) -> { + if(!signEditing.contains(player)) + return packet; + + String[] lines = signText.get(packet); + Object pos = blockPos.get(packet); + + Bukkit.getScheduler().runTask(BauSystem.getPlugin(), () -> { + Block signLoc = new Location(player.getWorld(), blockPosX.get(pos), blockPosY.get(pos), blockPosZ.get(pos)).getBlock(); + if (!signLoc.getType().name().contains("SIGN")) + return; + + Sign sign = ((Sign) signLoc.getState()); + for (int i = 0; i < lines.length; i++) { + sign.setLine(i, ChatColor.translateAlternateColorCodes('&', lines[i])); + } + sign.update(); + + signEditing.remove(player); + }); + + return packet; + }); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void playerCommandHandler(PlayerCommandPreprocessEvent e) { + if (!isWorldEditCommand(e.getMessage().split(" ")[0])) + return; + + Player p = e.getPlayer(); + + if (Welt.noPermission(p, Permission.WORLDEDIT)) { + p.sendMessage(BauSystem.PREFIX + "§cDu darfst hier kein WorldEdit benutzen"); + e.setCancelled(true); + } + } + + private static final String[] shortcutCommands = {"//1", "//2", "//90", "//-90", "//180", "//p", "//c", "//flopy", "//floppy", "//flopyp", "//floppyp", "//u", "//r"}; + + private boolean isWorldEditCommand(String command) { + for (String shortcut : shortcutCommands) + if (command.startsWith(shortcut)) + return true; + + return WorldeditWrapper.impl.isWorldEditCommand(command); + } + + @EventHandler + public void onSignChange(SignChangeEvent event) { + for (int i = 0; i <= 3; ++i) { + String line = event.getLine(i); + if (line == null) + continue; + line = ChatColor.translateAlternateColorCodes('&', line); + event.setLine(i, line); + } + } + + @EventHandler + public void editSign(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK || + !event.getClickedBlock().getType().name().contains("SIGN") || + !event.getPlayer().isSneaking() || + (event.getItem() != null && event.getItem().getType() != Material.AIR)) + return; + + Player player = event.getPlayer(); + Sign sign = (Sign) event.getClickedBlock().getState(); + String[] lines = sign.getLines(); + for (int i = 0; i < lines.length; i++) { + sign.setLine(i, lines[i].replace('\u00A7' /* WINDOWS \u00A7 -> § */, '&')); + } + sign.update(); + + CraftbukkitWrapper.impl.openSignEditor(player, event.getClickedBlock().getLocation()); + signEditing.add(player); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/ScriptListener.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/ScriptListener.java new file mode 100644 index 00000000..b26055fe --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/ScriptListener.java @@ -0,0 +1,542 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.FlatteningWrapper; +import de.steamwar.bausystem.commands.CommandScript; +import de.steamwar.bausystem.commands.CommandTNT; +import de.steamwar.bausystem.tracer.record.RecordStateMachine; +import de.steamwar.bausystem.world.regions.Region; +import de.steamwar.inventory.SWAnvilInv; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; + +import java.util.*; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.IntUnaryOperator; +import java.util.logging.Level; + +public class ScriptListener implements Listener { + + public static final Map> GLOBAL_VARIABLES = new HashMap<>(); + private static final Map> CONSTANTS = new HashMap<>(); + + static { + CONSTANTS.put("trace", player -> RecordStateMachine.getRecordStatus().isTracing() ? 1 : 0); + CONSTANTS.put("autotrace", player -> RecordStateMachine.getRecordStatus().isAutoTrace() ? 1 : 0); + CONSTANTS.put("tnt", player -> Region.getRegion(player.getLocation()).getTntMode() == CommandTNT.TNTMode.OFF ? 0 : 1); + CONSTANTS.put("freeze", player -> Region.getRegion(player.getLocation()).isFreeze() ? 1 : 0); + CONSTANTS.put("fire", player -> Region.getRegion(player.getLocation()).isFire() ? 1 : 0); + CONSTANTS.put("x", player -> player.getLocation().getBlockX()); + CONSTANTS.put("y", player -> player.getLocation().getBlockY()); + CONSTANTS.put("z", player -> player.getLocation().getBlockZ()); + } + + private Set playerSet = new HashSet<>(); + + public ScriptListener() { + Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), playerSet::clear, 5, 5); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onLeftClick(PlayerInteractEvent event) { + ItemStack item = event.getItem(); + if (item == null || isNoBook(item) || item.getItemMeta() == null) + return; + + if (CommandScript.BOOK.getItemMeta() != null && item.getItemMeta().hasDisplayName() && item.getItemMeta().getDisplayName().equals(CommandScript.BOOK.getItemMeta().getDisplayName())) { + return; + } + + if (event.getAction() != Action.LEFT_CLICK_AIR && event.getAction() != Action.LEFT_CLICK_BLOCK) { + if (event.getAction() == Action.RIGHT_CLICK_AIR) { + playerSet.add(event.getPlayer()); + } + return; + } + if (playerSet.remove(event.getPlayer())) { + return; + } + + event.setCancelled(true); + new ScriptExecutor((BookMeta) item.getItemMeta(), event.getPlayer()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + GLOBAL_VARIABLES.remove(event.getPlayer()); + } + + private boolean isNoBook(ItemStack item) { + return FlatteningWrapper.impl.isNoBook(item); + } + + private static class ScriptExecutor { + + private final Player player; + private final List commands = new ArrayList<>(); + private final Map jumpPoints = new HashMap<>(); + private Map variables = new HashMap<>(); + + private int index = 0; + + public ScriptExecutor(BookMeta bookMeta, Player player) { + this.player = player; + + for (String page : bookMeta.getPages()) { + for (String command : page.split("\n")) { + command = command.replaceAll(" +", " "); + if (command.startsWith("#") || command.trim().isEmpty()) continue; + if (command.startsWith(".")) { + jumpPoints.put(command.substring(1), commands.size()); + continue; + } + commands.add(command); + } + } + if (commands.isEmpty()) return; + resume(); + } + + private void resume() { + if (!player.isOnline()) { + return; + } + + int executionPoints = 0; + + while (index < commands.size()) { + String command = commands.get(index++); + if (executionPoints++ > 200) { + player.sendMessage(BauSystem.PREFIX + "§cFüge ein sleep in dein Script ein"); + return; + } + + String firstArg = command; + if (command.contains(" ")) { + firstArg = command.substring(0, command.indexOf(' ')); + } + switch (firstArg.toLowerCase()) { + case "sleep": + ScriptListener.sleepCommand(this, generateArgumentArray("sleep", this, command)); + return; + case "exit": + return; + case "jump": + int jumpIndex = ScriptListener.jumpCommand(this, generateArgumentArray("jump", this, command)); + if (jumpIndex != -1) { + index = jumpIndex; + } else { + player.sendMessage(BauSystem.PREFIX + "§cUnbekannter Jump Punkt: " + command); + } + continue; + case "echo": + ScriptListener.echoCommand(this, generateArgumentArray("echo", this, command)); + continue; + case "input": + ScriptListener.inputCommand(this, generateArgumentArray("input", this, command)); + return; + case "var": + ScriptListener.variableCommand(this, generateArgumentArray("var", this, command)); + continue; + case "unvar": + ScriptListener.unvariableCommand(this, generateArgumentArray("unvar", this, command)); + continue; + case "global": + ScriptListener.globalCommand(this, generateArgumentArray("global", this, command)); + continue; + case "unglobal": + ScriptListener.unglobalCommand(this, generateArgumentArray("unglobal", this, command)); + continue; + case "add": + ScriptListener.arithmeticCommand(this, generateArgumentArray("add", this, command), (left, right) -> left + right); + continue; + case "sub": + ScriptListener.arithmeticCommand(this, generateArgumentArray("sub", this, command), (left, right) -> left - right); + continue; + case "mul": + ScriptListener.arithmeticCommand(this, generateArgumentArray("mul", this, command), (left, right) -> left * right); + continue; + case "div": + ScriptListener.arithmeticCommand(this, generateArgumentArray("div", this, command), (left, right) -> left / right); + continue; + case "equal": + ScriptListener.arithmeticCommand(this, generateArgumentArray("equal", this, command), (left, right) -> left == right ? 1 : 0); + continue; + case "less": + ScriptListener.arithmeticCommand(this, generateArgumentArray("less", this, command), (left, right) -> left < right ? 1 : 0); + continue; + case "greater": + ScriptListener.arithmeticCommand(this, generateArgumentArray("greater", this, command), (left, right) -> left > right ? 1 : 0); + continue; + case "not": + ScriptListener.arithmeticInfixCommand(this, generateArgumentArray("not", this, command), (left) -> left == 1 ? 0 : 1); + continue; + case "and": + ScriptListener.arithmeticCommand(this, generateArgumentArray("and", this, command), (left, right) -> left == 1 && right == 1 ? 1 : 0); + continue; + case "or": + ScriptListener.arithmeticCommand(this, generateArgumentArray("or", this, command), (left, right) -> left == 1 || right == 1 ? 1 : 0); + continue; + case "if": + int ifJumpIndex = ScriptListener.ifCommand(this, generateArgumentArray("if", this, command)); + if (ifJumpIndex != -1) { + index = ifJumpIndex; + } + continue; + default: + break; + } + + PlayerCommandPreprocessEvent preprocessEvent = new PlayerCommandPreprocessEvent(player, "/" + command); + Bukkit.getServer().getPluginManager().callEvent(preprocessEvent); + if (preprocessEvent.isCancelled()) { + continue; + } + + // Variable Replaces in commands. + command = String.join(" ", generateArgumentArray("", this, command)); + + Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command); + Bukkit.getServer().dispatchCommand(player, command); + } + } + + } + + private static String[] generateArgumentArray(String command, ScriptExecutor scriptExecutor, String fullCommand) { + String[] strings; + if (command.isEmpty()) { + strings = fullCommand.split(" "); + } else { + strings = fullCommand.substring(command.length()).trim().split(" "); + } + return replaceVariables(scriptExecutor, strings); + } + + private static void sleepCommand(ScriptExecutor scriptExecutor, String[] args) { + int sleepTime = 1; + if (args.length > 0) { + try { + sleepTime = Integer.parseInt(args[0]); + if (sleepTime <= 0) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie Zeit muss eine Zahl großer 0 sein."); + sleepTime = 1; + } + } catch (NumberFormatException e) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie Zeit darf nur aus Zahlen bestehen."); + } + } + Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), scriptExecutor::resume, sleepTime); + } + + private static int jumpCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cEin Jump Punkt muss angegeben sein."); + return -1; + } + return scriptExecutor.jumpPoints.getOrDefault(args[0], -1); + } + + private static String[] replaceVariables(ScriptExecutor scriptExecutor, String[] args) { + // Legacy '$' notation for variable reference, could be removed later on. + for (int i = 0; i < args.length; i++) { + if (args[i].startsWith("$") && isVariable(scriptExecutor, args[i].substring(1))) { + args[i] = getValue(scriptExecutor, args[i].substring(1)) + ""; + } + } + + String s = String.join(" ", args); + Set variables = new HashSet<>(scriptExecutor.variables.keySet()); + variables.addAll(CONSTANTS.keySet()); + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + variables.addAll(GLOBAL_VARIABLES.get(scriptExecutor.player).keySet()); + } + for (String variable : variables) { + s = s.replace("<" + variable + ">", getValue(scriptExecutor, variable) + ""); + } + for (String constVariable : CONSTANTS.keySet()) { + s = s.replace("", getConstantValue(scriptExecutor, constVariable) + ""); + } + for (String localVariable : scriptExecutor.variables.keySet()) { + s = s.replace("", getLocalValue(scriptExecutor, localVariable) + ""); + } + for (String globalVariable : GLOBAL_VARIABLES.getOrDefault(scriptExecutor.player, new HashMap<>()).keySet()) { + s = s.replace("", getGlobalValue(scriptExecutor, globalVariable) + ""); + } + return s.split(" "); + } + + private static void echoCommand(ScriptExecutor scriptExecutor, String[] args) { + scriptExecutor.player.sendMessage("§eInfo§8» §7" + ChatColor.translateAlternateColorCodes('&', String.join(" ", replaceVariables(scriptExecutor, args)))); + } + + private static void variableCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen und Zahlen/Boolsche Wert fehlt."); + return; + } + if (args.length < 2) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cZahlen/Boolsche Wert fehlt."); + return; + } + switch (args[1]) { + case "inc": + case "increment": + case "++": + add(scriptExecutor, args[0], 1); + return; + case "dec": + case "decrement": + case "--": + add(scriptExecutor, args[0], -1); + return; + default: + break; + } + setValue(scriptExecutor, args[0], parseValue(args[1])); + } + + private static void unvariableCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen fehlt."); + return; + } + if (!isLocalVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariable is nicht definiert"); + return; + } + scriptExecutor.variables.remove(args[0]); + } + + private static void globalCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen fehlt."); + return; + } + if (!isLocalVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariable is nicht definiert"); + return; + } + GLOBAL_VARIABLES.computeIfAbsent(scriptExecutor.player, player -> new HashMap<>()).put(args[0], scriptExecutor.variables.getOrDefault(args[0], 0)); + } + + private static void unglobalCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen fehlt."); + return; + } + if (!isGlobalVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariable is nicht definiert"); + return; + } + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + GLOBAL_VARIABLES.get(scriptExecutor.player).remove(args[0]); + } + } + + private static int ifCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 2) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie ersten beiden Argumente sind Zahlen/Boolsche Werte oder Variablen."); + return -1; + } + if (args.length < 3) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDas dritte Argument muss ein JumpPoint sein."); + return -1; + } + + int jumpTruePoint = scriptExecutor.jumpPoints.getOrDefault(args[2], -1); + int jumpFalsePoint = args.length > 3 ? scriptExecutor.jumpPoints.getOrDefault(args[3], -1) : -1; + + if (args[1].equals("exists")) { + if (isVariable(scriptExecutor, args[0])) { + return jumpTruePoint; + } else { + return jumpFalsePoint; + } + } + int firstValue = getValueOrParse(scriptExecutor, args[0]); + int secondValue = getValueOrParse(scriptExecutor, args[1]); + if (firstValue == secondValue) { + return jumpTruePoint; + } else { + return jumpFalsePoint; + } + } + + private static void arithmeticCommand(ScriptExecutor scriptExecutor, String[] args, IntBinaryOperator operation) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls erstes Argument fehlt eine Variable"); + return; + } + if (args.length < 2) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls zweites Argument fehlt eine Zahl oder Variable"); + return; + } + + int firstValue; + int secondValue; + if (args.length < 3) { + if (!isVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDas erste Argument muss eine Variable sein"); + return; + } + firstValue = getValue(scriptExecutor, args[0]); + secondValue = getValueOrParse(scriptExecutor, args[1]); + } else { + firstValue = getValue(scriptExecutor, args[1]); + secondValue = getValueOrParse(scriptExecutor, args[2]); + } + setValue(scriptExecutor, args[0], operation.applyAsInt(firstValue, secondValue)); + } + + private static void arithmeticInfixCommand(ScriptExecutor scriptExecutor, String[] args, IntUnaryOperator operation) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls erstes Argument fehlt eine Variable"); + return; + } + + int firstValue; + if (args.length < 2) { + if (!isVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDas erste Argument muss eine Variable sein"); + return; + } + firstValue = getValue(scriptExecutor, args[0]); + } else { + firstValue = getValue(scriptExecutor, args[1]); + } + setValue(scriptExecutor, args[0], operation.applyAsInt(firstValue)); + } + + private static void inputCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls erstes Argument fehlt eine Variable"); + return; + } + String varName = args[0]; + StringBuilder st = new StringBuilder(); + for (int i = 1; i < args.length; i++) { + if (i != 1) { + st.append(" "); + } + st.append(args[i]); + } + + SWAnvilInv swAnvilInv = new SWAnvilInv(scriptExecutor.player, ChatColor.translateAlternateColorCodes('&', st.toString())); + swAnvilInv.setCallback(s -> { + int value = parseValue(s); + setValue(scriptExecutor, varName, value); + scriptExecutor.resume(); + }); + swAnvilInv.open(); + } + + private static void setValue(ScriptExecutor scriptExecutor, String key, int value) { + scriptExecutor.variables.put(key, value); + } + + private static void add(ScriptExecutor scriptExecutor, String key, int value) { + if (!isVariable(scriptExecutor, key)) { + scriptExecutor.variables.put(key, 0); + } + scriptExecutor.variables.put(key, scriptExecutor.variables.get(key) + value); + } + + private static int getValueOrParse(ScriptExecutor scriptExecutor, String key) { + if (isVariable(scriptExecutor, key)) { + return getValue(scriptExecutor, key); + } else { + return parseValue(key); + } + } + + private static int getValue(ScriptExecutor scriptExecutor, String key) { + if (CONSTANTS.containsKey(key)) { + return CONSTANTS.get(key).apply(scriptExecutor.player); + } + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player) && GLOBAL_VARIABLES.get(scriptExecutor.player).containsKey(key)) { + return GLOBAL_VARIABLES.get(scriptExecutor.player).get(key); + } + return scriptExecutor.variables.getOrDefault(key, 0); + } + + private static int getConstantValue(ScriptExecutor scriptExecutor, String key) { + return CONSTANTS.getOrDefault(key, player -> 0).apply(scriptExecutor.player); + } + + private static int getGlobalValue(ScriptExecutor scriptExecutor, String key) { + if (!GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + return 0; + } + return GLOBAL_VARIABLES.get(scriptExecutor.player).getOrDefault(key, 0); + } + + private static int getLocalValue(ScriptExecutor scriptExecutor, String key) { + return scriptExecutor.variables.getOrDefault(key, 0); + } + + private static boolean isVariable(ScriptExecutor scriptExecutor, String key) { + if (CONSTANTS.containsKey(key)) { + return true; + } + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player) && GLOBAL_VARIABLES.get(scriptExecutor.player).containsKey(key)) { + return true; + } + return scriptExecutor.variables.containsKey(key); + } + + private static boolean isLocalVariable(ScriptExecutor scriptExecutor, String key) { + return isVariable(scriptExecutor, key) && !isGlobalVariable(scriptExecutor, key); + } + + private static boolean isGlobalVariable(ScriptExecutor scriptExecutor, String key) { + if (!GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + return false; + } + return GLOBAL_VARIABLES.get(scriptExecutor.player).containsKey(key); + } + + public static int parseValue(String value) { + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) { + return 1; + } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) { + return 0; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return 0; + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/SizedStack.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/SizedStack.java new file mode 100644 index 00000000..d46b181d --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/SizedStack.java @@ -0,0 +1,123 @@ +package de.steamwar.bausystem.world; + +@SuppressWarnings({"unused", "UnusedReturnValue"}) +public class SizedStack { + + private final int maxSize; + private final T[] data; + private int size; + private int head; + + public SizedStack(int size) { + this.maxSize = size; + this.data = (T[]) new Object[this.maxSize]; + this.head = 0; + this.size = 0; + } + + public T push(final T element) { + this.data[this.head] = element; + this.increaseHead(); + this.increaseSize(); + return element; + } + + public T pop() { + this.decreaseHead(); + this.decreaseSize(); + final T result = this.data[this.head]; + this.data[this.head] = null; + return result; + } + + public T peek() { + return this.data[this.head]; + } + + public boolean empty() { + return this.size == 0; + } + + protected boolean canEqual(final Object other) { + return other instanceof SizedStack; + } + + private void increaseHead() { + this.head++; + while (this.head > this.maxSize - 1) { + this.head -= this.maxSize; + } + } + + private void decreaseHead() { + this.head--; + while (this.head < 0) { + this.head += this.maxSize; + } + } + + private void increaseSize() { + if (this.size < this.maxSize) { + this.size++; + } + } + + private void decreaseSize() { + if (this.size > 0) { + this.size--; + } + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.maxSize; + result = result * PRIME + this.toString().hashCode(); + result = result * PRIME + this.size; + return result; + } + + @Override + public boolean equals(final Object o) { + if (o == this) { + return true; + } + if (!(o instanceof SizedStack)) { + return false; + } + final SizedStack other = (SizedStack) o; + if (!other.canEqual(this)) { + return false; + } + if (this.maxSize != other.maxSize) { + return false; + } + if (this.size != other.size) { + return false; + } + if (!this.data.getClass().equals(other.data.getClass())) { + return false; + } + return this.toString().equals(other.toString()); + } + + public int getMaxSize() { + return maxSize; + } + + public int getSize() { + return size; + } + + @Override + public String toString() { + final StringBuilder result = new StringBuilder("["); + for (int i = 0; i < this.size - 1; i++) { + result.append(this.data[(this.head - i - 1 < 0) ? (this.head - i - 1 + this.maxSize) : (this.head - i - 1)]).append(","); + } + result.append(this.data[(this.head - this.size < 0) ? (this.head - this.size + this.maxSize) : (this.head - this.size)]); + result.append("]"); + return result.toString(); + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/TPSUtils.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/TPSUtils.java new file mode 100644 index 00000000..4f16230b --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/TPSUtils.java @@ -0,0 +1,77 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.CraftbukkitWrapper; +import de.steamwar.bausystem.commands.CommandTPSLimiter; +import de.steamwar.core.TPSWatcher; +import org.bukkit.Bukkit; + +import java.util.function.Supplier; + +public class TPSUtils { + + private TPSUtils() { + throw new IllegalStateException("Utility Class"); + } + + private static boolean warp = true; + private static long nanoOffset = 0; + private static long nanoDOffset = 0; + + public static void disableWarp() { + warp = false; + } + + public static long getNanoOffset() { + return nanoOffset; + } + + private static long ticksSinceServerStart = 0; + public static final Supplier currentTick = () -> ticksSinceServerStart; + + public static void init() { + CraftbukkitWrapper.impl.initTPS(); + Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), () -> nanoOffset += nanoDOffset, 1, 1); + Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), () -> ticksSinceServerStart++, 1, 1); + } + + public static void setTPS(double tps) { + double d = 50 - (50 / (tps / 20.0)); + nanoDOffset = Math.max(0, Math.min((long) (d * 1000000), 37500000)); + } + + public static boolean isWarpAllowed() { + return warp; + } + + public static boolean isWarping() { + return nanoDOffset > 0; + } + + public static double getTps(TPSWatcher.TPSType tpsType) { + if (TPSUtils.isWarping()) + return TPSWatcher.getTPS(tpsType, Math.max(CommandTPSLimiter.getCurrentTPSLimit(), 20)); + return TPSWatcher.getTPS(tpsType); + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/Welt.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/Welt.java new file mode 100644 index 00000000..74c87374 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/Welt.java @@ -0,0 +1,51 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.bausystem.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.sql.BauweltMember; +import org.bukkit.entity.Player; + +public class Welt { + + private Welt() { + } + + public static boolean noPermission(Player member, Permission perm) { + if (member.getUniqueId().equals(BauSystem.getOwner())) + return false; + + BauweltMember member1 = BauweltMember.getBauMember(BauSystem.getOwner(), member.getUniqueId()); + if (member1 == null) + return true; + + switch (perm) { + case WORLDEDIT: + return !member1.isWorldEdit(); + case WORLD: + return !member1.isWorld(); + case MEMBER: + return false; + default: + return true; + } + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/GlobalRegion.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/GlobalRegion.java new file mode 100644 index 00000000..363284c4 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/GlobalRegion.java @@ -0,0 +1,64 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +import org.bukkit.Location; + +public class GlobalRegion extends Region { + + private static final GlobalRegion GLOBAL_REGION = new GlobalRegion(); + + public static GlobalRegion getInstance() { + return GLOBAL_REGION; + } + + public static boolean isGlobalRegion(Region region) { + return region == GLOBAL_REGION; + } + + public GlobalRegion() { + super("Global"); + } + + @Override + public boolean inRegion(Location l, RegionType regionType, RegionExtensionType regionExtensionType) { + return true; + } + + @Override + public boolean hasBuildRegion() { + return false; + } + + @Override + public boolean hasTestblock() { + return false; + } + + @Override + public boolean hasProtection() { + return false; + } + + @Override + public boolean hasExtensionArea(RegionType regionType) { + return false; + } +} \ No newline at end of file diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/PasteOptions.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/PasteOptions.java new file mode 100644 index 00000000..2dfbea07 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/PasteOptions.java @@ -0,0 +1,99 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +import de.steamwar.bausystem.world.Color; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class PasteOptions { + + /** + * Used in 1.12 and 1.15 + */ + private boolean rotate = false; + + /** + * Used in 1.12 and 1.15 + */ + private boolean ignoreAir = false; + + /** + * Used in 1.15 + */ + private Color color = Color.YELLOW; + + /** + * Used in 1.15 + */ + private boolean reset = false; + + /** + * Used in 1.15 + */ + private Point minPoint = null; + + /** + * Used in 1.15 + */ + private Point maxPoint = null; + + /** + * Used in 1.15 + */ + private int waterLevel = 0; + + public PasteOptions(boolean rotate) { + this.rotate = rotate; + } + + public PasteOptions(boolean rotate, Color color) { + this.rotate = rotate; + this.color = color; + } + + public PasteOptions(boolean rotate, boolean ignoreAir) { + this.rotate = rotate; + this.ignoreAir = ignoreAir; + } + + public PasteOptions(boolean rotate, boolean ignoreAir, boolean reset) { + this.rotate = rotate; + this.ignoreAir = ignoreAir; + this.reset = reset; + } + + public PasteOptions(boolean rotate, Color color, boolean reset) { + this.rotate = rotate; + this.color = color; + this.reset = reset; + } + + public PasteOptions(boolean rotate, boolean ignoreAir, Color color) { + this.rotate = rotate; + this.ignoreAir = ignoreAir; + this.color = color; + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Point.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Point.java new file mode 100644 index 00000000..b7bdf43f --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Point.java @@ -0,0 +1,31 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class Point { + final int x; + final int y; + final int z; +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Prototype.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Prototype.java new file mode 100644 index 00000000..f1ccca1c --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Prototype.java @@ -0,0 +1,204 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import de.steamwar.bausystem.WorldeditWrapper; +import de.steamwar.bausystem.world.Color; +import de.steamwar.sql.NoClipboardException; +import de.steamwar.sql.SchematicData; +import de.steamwar.sql.SchematicNode; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class Prototype { + static final Map prototypes = new HashMap<>(); + + private final int sizeX; + private final int sizeY; + private final int sizeZ; + + private final int offsetX; + private final int offsetY; + private final int offsetZ; + + private final int extensionPositiveZ; + private final int extensionNegativeZ; + private final int extensionPositiveY; + private final int extensionAxisX; + final boolean extensionPrototypeArea; + + private final int waterLevel; + + private final String schematic; + private final boolean rotate; + + final Prototype testblock; //nullable + final Prototype buildArea; //nullable + + private final String protectSchematic; //nullable + + Prototype(ConfigurationSection config) { + sizeX = config.getInt("sizeX"); + sizeY = config.getInt("sizeY"); + sizeZ = config.getInt("sizeZ"); + schematic = config.getString("schematic"); + offsetX = config.getInt("offsetX", 0); + offsetY = config.getInt("offsetY", 0); + offsetZ = config.getInt("offsetZ", 0); + extensionPositiveZ = config.getInt("extensionPositiveZ", 0); + extensionNegativeZ = config.getInt("extensionNegativeZ", 0); + extensionPositiveY = config.getInt("extensionPositiveY", 0); + extensionAxisX = config.getInt("extensionAxisX", 0); + if (config.contains("extensionPositiveZ") || config.contains("extensionNegativeZ") || config.contains("extensionPositiveY") || config.contains("extensionAxisX")) { + Region.extensionArea = true; + } + extensionPrototypeArea = extensionNegativeZ != 0 || extensionPositiveZ != 0 || extensionPositiveY != 0 || extensionAxisX != 0; + waterLevel = config.getInt("waterLevel", 0); + rotate = config.getBoolean("rotate", false); + + ConfigurationSection testblockSection = config.getConfigurationSection("testblock"); + testblock = testblockSection != null ? new Prototype(testblockSection) : null; + + ConfigurationSection buildAreaSection = config.getConfigurationSection("buildArea"); + buildArea = buildAreaSection != null ? new Prototype(buildAreaSection) : null; + if (buildArea != null) { + Region.buildArea = true; + } + + protectSchematic = config.getString("protection", null); + + if (!config.getName().equals("testblock") && !config.getName().equals("buildArea")) + prototypes.put(config.getName(), this); + } + + public Point getMinPoint(Region region, RegionExtensionType regionExtensionType) { + switch (regionExtensionType) { + case EXTENSION: + return new Point( + region.minPoint.getX() + offsetX - extensionAxisX, + region.minPoint.getY() + offsetY, + region.minPoint.getZ() + offsetZ - extensionNegativeZ + ); + default: + case NORMAL: + return new Point( + region.minPoint.getX() + offsetX, + region.minPoint.getY() + offsetY, + region.minPoint.getZ() + offsetZ + ); + } + } + + public Point getMaxPoint(Region region, RegionExtensionType regionExtensionType) { + switch (regionExtensionType) { + case EXTENSION: + return new Point( + region.minPoint.getX() + offsetX - extensionAxisX + (sizeX + extensionAxisX * 2) - 1, + region.minPoint.getY() + offsetY + sizeY + extensionPositiveY - 1, + region.minPoint.getZ() + offsetZ - extensionNegativeZ + (sizeZ + extensionNegativeZ + extensionPositiveZ) - 1 + ); + default: + case NORMAL: + return new Point( + region.minPoint.getX() + offsetX + sizeX - 1, + region.minPoint.getY() + offsetY + sizeY - 1, + region.minPoint.getZ() + offsetZ + sizeZ - 1 + ); + } + } + + public boolean inRegion(Region region, Location l, RegionExtensionType regionExtensionType) { + switch (regionExtensionType) { + case EXTENSION: + return inRange(l.getX(), region.minPoint.getX() + offsetX - extensionAxisX, sizeX + extensionAxisX * 2) && + inRange(l.getY(), region.minPoint.getY() + offsetY, sizeY + extensionPositiveY) && + inRange(l.getZ(), region.minPoint.getZ() + offsetZ - extensionNegativeZ, sizeZ + extensionNegativeZ + extensionPositiveZ); + default: + case NORMAL: + return inRange(l.getX(), region.minPoint.getX() + offsetX, sizeX) && + inRange(l.getY(), region.minPoint.getY() + offsetY, sizeY) && + inRange(l.getZ(), region.minPoint.getZ() + offsetZ, sizeZ); + } + } + + public EditSession reset(Region region, SchematicNode schem, boolean ignoreAir, Color color) throws IOException, NoClipboardException { + return reset(region, schem, ignoreAir, color, false); + } + + public EditSession reset(Region region, SchematicNode schem, boolean ignoreAir, Color color, boolean reset) throws IOException, NoClipboardException { + PasteOptions pasteOptions; + if (reset) { + pasteOptions = new PasteOptions(rotate ^ (schem != null && (schem.getSchemtype().fightType() || schem.getSchemtype().check())), ignoreAir, color, true, getMinPoint(region, RegionExtensionType.EXTENSION), getMaxPoint(region, RegionExtensionType.EXTENSION), waterLevel); + } else { + pasteOptions = new PasteOptions(rotate ^ (schem != null && (schem.getSchemtype().fightType() || schem.getSchemtype().check())), ignoreAir, color); + } + + int x = region.minPoint.getX() + offsetX + sizeX / 2; + int y = region.minPoint.getY() + offsetY; + int z = region.minPoint.getZ() + offsetZ + sizeZ / 2; + if (schem == null) { + return paste(new File(schematic), x, y, z, pasteOptions); + } else { + return paste(new SchematicData(schem).load(), x, y, z, pasteOptions); + } + } + + public boolean hasProtection() { + return protectSchematic != null; + } + + public EditSession protect(Region region, SchematicNode schem) throws IOException, NoClipboardException { + int x = region.minPoint.getX() + offsetX + sizeX / 2; + int y = region.minPoint.getY() + testblock.offsetY - 1; + int z = region.minPoint.getZ() + offsetZ + sizeZ / 2; + if (schem == null) { + return paste(new File(protectSchematic), x, y, z, new PasteOptions(rotate, false, Color.YELLOW)); + } else { + return paste(new SchematicData(schem).load(), x, y, z, new PasteOptions(rotate, false, Color.YELLOW)); + } + } + + public boolean hasTestblock() { + return testblock != null; + } + + public EditSession resetTestblock(Region region, SchematicNode schem, Color color, boolean reset) throws IOException, NoClipboardException { + return testblock.reset(region, schem, false, color, reset && waterLevel == 0); + } + + private static boolean inRange(double l, int min, int size) { + return min <= l && l < min + size; + } + + private static EditSession paste(File file, int x, int y, int z, PasteOptions pasteOptions) { //Type of protect + return WorldeditWrapper.impl.paste(file, x, y, z, pasteOptions); + } + + private static EditSession paste(Clipboard clipboard, int x, int y, int z, PasteOptions pasteOptions) { + return WorldeditWrapper.impl.paste(clipboard, x, y, z, pasteOptions); + } +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Region.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Region.java new file mode 100644 index 00000000..591f8761 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/Region.java @@ -0,0 +1,388 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; +import com.sk89q.worldedit.EditSession; +import de.steamwar.bausystem.commands.CommandTNT.TNTMode; +import de.steamwar.bausystem.world.Color; +import de.steamwar.bausystem.world.SizedStack; +import de.steamwar.sql.NoClipboardException; +import de.steamwar.sql.SchematicNode; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.logging.Level; + +public class Region { + + private static final List regions = new ArrayList<>(); + static boolean buildArea = false; + static boolean extensionArea = false; + private static JsonObject regionsObject = new JsonObject(); + + static { + File regionsFile = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "regions.json"); + if (regionsFile.exists()) { + try { + regionsObject = new JsonParser().parse(new FileReader(regionsFile)).getAsJsonObject(); + } catch (JsonSyntaxException | IOException e) { + Bukkit.getLogger().log(Level.WARNING, "Item JSON error"); + } + } + + YamlConfiguration config = new YamlConfiguration(); + try { + config.load(new File(Bukkit.getWorlds().get(0).getWorldFolder(), "sections.yml")); + } catch (InvalidConfigurationException | IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Failed to load sections.yml", e); + } + + ConfigurationSection prototypes = config.getConfigurationSection("prototypes"); + assert prototypes != null; + for (String prototype : prototypes.getKeys(false)) { + new Prototype(Objects.requireNonNull(prototypes.getConfigurationSection(prototype))); + } + + ConfigurationSection regions = config.getConfigurationSection("regions"); + assert regions != null; + for (String region : regions.getKeys(false)) { + new Region(Objects.requireNonNull(regions.getConfigurationSection(region))); + } + } + + public static boolean buildAreaEnabled() { + return buildArea; + } + + public static boolean extensionAreaEnabled() { + return extensionArea; + } + + public static Region getRegion(Location location) { + for (Region region : regions) { + if (region.inRegion(location, RegionType.NORMAL, RegionExtensionType.NORMAL)) { + return region; + } + } + return GlobalRegion.getInstance(); + } + + public static void setGlobalColor(Color color) { + for (Region region : regions) { + region.setColor(color); + } + } + + public static void save() { + File colorsFile = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "regions.json"); + if (!colorsFile.exists()) { + try { + colorsFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + return; + } + } + try (FileOutputStream fileOutputStream = new FileOutputStream(colorsFile)) { + fileOutputStream.write(regionsObject.toString().getBytes()); + } catch (IOException e) { + e.printStackTrace(); + // Ignored + } + } + + private final String name; + final Point minPoint; + private final Prototype prototype; + private final String optionsLinkedWith; // nullable + private Region linkedRegion = null; // nullable + private SizedStack undosessions; + private SizedStack redosessions; + + private JsonObject regionOptions = new JsonObject(); + + @Getter + private TNTMode tntMode = Region.buildAreaEnabled() ? TNTMode.ONLY_TB : TNTMode.OFF; + + @Getter + private boolean freeze = false; + + @Getter + private boolean fire = false; + + @Getter + private boolean protect = false; + + @Getter + private Color color = Color.YELLOW; + + private Region(ConfigurationSection config) { + name = config.getName(); + minPoint = new Point(config.getInt("minX"), config.getInt("minY"), config.getInt("minZ")); + prototype = Prototype.prototypes.get(config.getString("prototype")); + optionsLinkedWith = config.getString("optionsLinkedWith", null); + if (!hasTestblock()) tntMode = TNTMode.OFF; + regions.add(this); + load(); + } + + public Region(String name) { + this.name = name; + this.minPoint = new Point(0, 0, 0); + this.prototype = null; + this.optionsLinkedWith = null; + tntMode = TNTMode.OFF; + load(); + } + + private void load() { + if (regionsObject.has(name)) { + regionOptions = regionsObject.getAsJsonObject(name); + if (regionOptions.has("tnt")) { + String tntName = regionsObject.getAsJsonObject(name).getAsJsonPrimitive("tnt").getAsString(); + try { + tntMode = TNTMode.valueOf(tntName); + } catch (Exception e) { + // Ignored + } + } + + if (regionOptions.has("fire")) { + fire = regionOptions.getAsJsonPrimitive("fire").getAsBoolean(); + } + + if (regionOptions.has("freeze")) { + freeze = regionOptions.getAsJsonPrimitive("freeze").getAsBoolean(); + } + + if (regionOptions.has("protect")) { + protect = regionOptions.getAsJsonPrimitive("protect").getAsBoolean(); + } + + if (regionOptions.has("color")) { + String colorName = regionOptions.getAsJsonPrimitive("color").getAsString(); + try { + color = Color.valueOf(colorName); + } catch (Exception e) { + // Ignored + } + } + } else { + regionsObject.add(name, regionOptions); + } + } + + public void setColor(Color color) { + this.color = color; + regionOptions.add("color", new JsonPrimitive(color.name())); + } + + private void setLinkedRegion(Consumer regionConsumer) { + if (optionsLinkedWith == null) { + return; + } + if (linkedRegion != null) { + regionConsumer.accept(linkedRegion); + return; + } + for (Region region : regions) { + if (region.name.equals(name)) { + linkedRegion = region; + regionConsumer.accept(linkedRegion); + return; + } + } + } + + public void setTntMode(TNTMode tntMode) { + this.tntMode = tntMode; + setLinkedRegion(region -> { + region.tntMode = tntMode; + region.regionOptions.add("tnt", new JsonPrimitive(tntMode.name())); + }); + regionOptions.add("tnt", new JsonPrimitive(tntMode.name())); + } + + public void setFreeze(boolean freeze) { + this.freeze = freeze; + setLinkedRegion(region -> { + region.freeze = freeze; + region.regionOptions.add("freeze", new JsonPrimitive(freeze)); + }); + regionOptions.add("freeze", new JsonPrimitive(freeze)); + } + + public void setFire(boolean fire) { + this.fire = fire; + setLinkedRegion(region -> { + region.fire = fire; + region.regionOptions.add("fire", new JsonPrimitive(fire)); + }); + regionOptions.add("fire", new JsonPrimitive(fire)); + } + + public void setProtect(boolean protect) { + this.protect = protect; + setLinkedRegion(region -> { + region.protect = protect; + region.regionOptions.add("protect", new JsonPrimitive(protect)); + }); + regionOptions.add("protect", new JsonPrimitive(protect)); + } + + public Point getMinPoint(RegionType regionType, RegionExtensionType regionExtensionType) { + switch (regionType) { + case BUILD: + return prototype.buildArea.getMinPoint(this, regionExtensionType); + case TESTBLOCK: + return prototype.testblock.getMinPoint(this, regionExtensionType); + default: + case NORMAL: + return prototype.getMinPoint(this, regionExtensionType); + } + } + + public Point getMaxPoint(RegionType regionType, RegionExtensionType regionExtensionType) { + switch (regionType) { + case BUILD: + return prototype.buildArea.getMaxPoint(this, regionExtensionType); + case TESTBLOCK: + return prototype.testblock.getMaxPoint(this, regionExtensionType); + default: + case NORMAL: + return prototype.getMaxPoint(this, regionExtensionType); + } + } + + public boolean inRegion(Location l, RegionType regionType, RegionExtensionType regionExtensionType) { + switch (regionType) { + case BUILD: + return prototype.buildArea.inRegion(this, l, regionExtensionType); + case TESTBLOCK: + return prototype.testblock.inRegion(this, l, regionExtensionType); + default: + case NORMAL: + return prototype.inRegion(this, l, regionExtensionType); + } + } + + public boolean hasBuildRegion() { + return prototype.buildArea != null; + } + + public void reset(SchematicNode schem, boolean ignoreAir) throws IOException, NoClipboardException { + initSessions(); + undosessions.push(prototype.reset(this, schem, ignoreAir, color)); + } + + public boolean hasTestblock() { + return prototype.hasTestblock(); + } + + public void resetTestblock(SchematicNode schem, boolean reset) throws IOException, NoClipboardException { + initSessions(); + undosessions.push(prototype.resetTestblock(this, schem, color, reset)); + } + + public boolean hasProtection() { + return prototype.hasProtection(); + } + + public void protect(SchematicNode schem) throws IOException, NoClipboardException { + initSessions(); + undosessions.push(prototype.protect(this, schem)); + } + + public int getProtectYLevel() { + return getMinPoint(RegionType.TESTBLOCK, RegionExtensionType.NORMAL).getY(); + } + + public boolean hasExtensionArea(RegionType regionType) { + switch (regionType) { + case BUILD: + return prototype.buildArea.extensionPrototypeArea; + case TESTBLOCK: + return prototype.testblock.extensionPrototypeArea; + default: + case NORMAL: + return prototype.extensionPrototypeArea; + } + } + + private void initSessions() { + if (undosessions == null) { + undosessions = new SizedStack<>(20); + redosessions = new SizedStack<>(20); + } + } + + public boolean undo() { + initSessions(); + EditSession session = null; + try { + session = undosessions.pop(); + if (session == null) { + return false; + } + session.undo(session); + redosessions.push(session); + return true; + } finally { + if (session != null) { + session.flushQueue(); + } + } + } + + public boolean redo() { + initSessions(); + EditSession session = null; + try { + session = redosessions.pop(); + if (session == null) { + return false; + } + session.redo(session); + undosessions.push(session); + return true; + } finally { + if (session != null) { + session.flushQueue(); + } + } + } + +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionExtensionType.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionExtensionType.java new file mode 100644 index 00000000..28be3b69 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionExtensionType.java @@ -0,0 +1,25 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +public enum RegionExtensionType { + NORMAL, + EXTENSION +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionSelectionType.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionSelectionType.java new file mode 100644 index 00000000..40cb2f23 --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionSelectionType.java @@ -0,0 +1,25 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +public enum RegionSelectionType { + GLOBAL, + LOCAL +} diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionType.java b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionType.java new file mode 100644 index 00000000..ac47eb9d --- /dev/null +++ b/LegacyBauSystem/src/de/steamwar/bausystem/world/regions/RegionType.java @@ -0,0 +1,26 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.world.regions; + +public enum RegionType { + NORMAL, + BUILD, + TESTBLOCK +} diff --git a/LegacyBauSystem/src/plugin.yml b/LegacyBauSystem/src/plugin.yml new file mode 100644 index 00000000..cef3aacc --- /dev/null +++ b/LegacyBauSystem/src/plugin.yml @@ -0,0 +1,9 @@ +name: BauSystem +authors: [Lixfel, YoyoNow, Chaoscaot, Zeanon] +version: "1.0" +depend: [WorldEdit, SpigotCore] +load: POSTWORLD +main: de.steamwar.bausystem.BauSystem +api-version: "1.13" +website: "https://steamwar.de" +description: "So unseriös wie wir sind: BauSystem nur besser. Jaja" diff --git a/settings.gradle.kts b/settings.gradle.kts index cea601bf..87430368 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -207,6 +207,8 @@ include( include("KotlinCore") +include("LegacyBauSystem") + include("LobbySystem") include("MissileWars") diff --git a/steamwarci.yml b/steamwarci.yml index 0fa07cde..3e3660b1 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -4,6 +4,7 @@ build: artifacts: "/jars/BauSystem.jar": "BauSystem/build/libs/BauSystem-all.jar" + "/jars/BauSystem-1.12.jar": "LegacyBauSystem/build/libs/LegacyBauSystem.jar" "/jars/FightSystem.jar": "FightSystem/build/libs/FightSystem-all.jar" #"/binarys/FightSystem_Standalone.jar": "FightSystem/FightSystem_Standalone/build/libs/FightSystem_Standalone-all.jar" From 8ec12603b6dcb636f7a8be7ce043a58b7a2c2827 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 17 Feb 2025 17:48:26 +0100 Subject: [PATCH 080/112] Add password reset URL generation and backend validation --- .../steamwar/messages/BungeeCore.properties | 1 + .../messages/BungeeCore_de.properties | 1 + .../commands/WebpasswordCommand.java | 30 +++++++++++++------ .../src/de/steamwar/routes/v2/Auth.kt | 3 +- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index c9527253..2315ed12 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -543,6 +543,7 @@ WEB_USAGE=§8/§7webpassword §8[§epassword§8] WEB_UPDATED=§7Your password was updated. WEB_CREATED=§7Your webaccount was created. WEB_PASSWORD_LENGTH=§cYour password is shorter than 8 characters. +WEB_RESET_URL=§7You can reset your Password here: §ehttps://steamwar.de/reset-password?token={0} #ChatListener CHAT_LIXFEL_ACTION_BAR=§4§lTechnical problems? diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index c50cf682..cbbb3e2e 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -518,6 +518,7 @@ WEB_USAGE=§8/§7webpassword §8[§ePasswort§8] WEB_UPDATED=§7Dein Passwort wurde aktualisiert. WEB_CREATED=§7Dein Webaccount wurde erstellt. WEB_PASSWORD_LENGTH=§cDein Passwort ist kürzer als 8 Zeichen. +WEB_RESET_URL=§7Hier kannst du dein Passwort zurücksetzen: §ehttps://steamwar.de/passwort-setzen?token={0} #ChatListener CHAT_LIXFEL_ACTION_BAR=§4§lTechnische Probleme? diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java index d19dedd0..8f9b7b60 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java @@ -19,29 +19,41 @@ package de.steamwar.velocitycore.commands; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; import de.steamwar.sql.SteamwarUser; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; + public class WebpasswordCommand extends SWCommand { public WebpasswordCommand() { super("webpassword", "webpw", "web"); } + private static final HttpClient client = HttpClient.newHttpClient(); @Register(description = "WEB_USAGE") - public void genericCommand(Chatter sender, String password) { - if(password.length() < 8) { - sender.system("WEB_PASSWORD_LENGTH"); - return; - } - + public void genericCommand(Chatter sender) { SteamwarUser user = sender.user(); - boolean resetPW = user.hasPassword(); - user.setPassword(password); + HttpRequest request = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.noBody()) + .uri(URI.create("http://localhost:1337/v2/auth/enroll/" + user.getId())).build(); - sender.system(resetPW ? "WEB_UPDATED" : "WEB_CREATED"); + client.sendAsync(request, responseInfo -> HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8)).thenAccept(httpResponse -> { + JsonObject jsonObject = JsonParser.parseString(httpResponse.body()).getAsJsonObject(); + + String token = jsonObject.get("token").getAsString(); + + sender.system("WEB_RESET_URL", URLEncoder.encode(token, StandardCharsets.UTF_8)); + }); } } diff --git a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt index 24e5cee6..b854d619 100644 --- a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt @@ -31,7 +31,6 @@ import de.steamwar.util.type import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* -import io.ktor.server.http.* import io.ktor.server.plugins.* import io.ktor.server.request.* import io.ktor.server.response.* @@ -64,7 +63,7 @@ fun Route.configureNewAuth() { route("/auth") { route("/enroll") { post("/{userId}") { - if (call.request.headers.contains("X-Forwarded-For")) { + if (call.request.headers.contains("X-Forwarded-For") || call.request.header("Host") != "localhost:1337") { SWException.log("Request to /auth/register from", "Invalid IP") call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid IP", "F_U")) return@post From 7f5b57516e65405ccd78f2aced3e79abe1f0924b Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 17 Feb 2025 18:28:43 +0100 Subject: [PATCH 081/112] Reduce access token duration and enhance auth endpoints --- .../src/de/steamwar/routes/v2/Auth.kt | 19 ++++++++++++++++--- .../src/de/steamwar/util/TokenUtils.kt | 3 +-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt index b854d619..9d6a5181 100644 --- a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt @@ -115,7 +115,7 @@ fun Route.configureNewAuth() { call.respond(HttpStatusCode.OK) } route("/state") { - post("/create") { + post { val request = call.receive() val user = SteamwarUser.get(request.name) @@ -128,12 +128,12 @@ fun Route.configureNewAuth() { call.respond(user.createAccessAndRefreshToken(request.keepLoggedIn)) } - post("/refresh") { + put { val token = call.principal() if (token == null || token.token.type != TokenType.REFRESH_TOKEN) { call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid token type", "invalid")) - return@post + return@put } val code = token.token.name.substringAfterLast('-') @@ -145,6 +145,19 @@ fun Route.configureNewAuth() { call.respond(token.user.createAccessAndRefreshToken(true)) } + delete { + val token = call.principal() + token?.let { t -> + t.token.delete() + val code = t.token.name.substringAfterLast('-') + Token.listUser(token.user) + .filter { it.type == TokenType.REFRESH_TOKEN } + .filter { it.name.endsWith(code) } + .forEach { it.delete() } + } + + call.respond(HttpStatusCode.OK) + } } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt b/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt index 7a70c2f3..4f5f8a4f 100644 --- a/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt +++ b/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt @@ -23,7 +23,6 @@ import de.steamwar.sql.Token import java.time.LocalDateTime import kotlin.time.Duration import kotlin.time.Duration.Companion.days -import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes import kotlin.time.toJavaDuration @@ -38,7 +37,7 @@ val Token.type: TokenType val TokenType.lifetime: Duration get() = when (this) { TokenType.REFRESH_TOKEN -> 7.days - TokenType.ACCESS_TOKEN -> 1.hours + TokenType.ACCESS_TOKEN -> 5.minutes TokenType.RESET_PASSWORD -> 10.minutes TokenType.OLD_TOKEN -> 1.days } From dea0d3318521709510924e64b3cd5e7f4a2d3b34 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 20 Feb 2025 22:13:13 +0100 Subject: [PATCH 082/112] Refactor token generation and remove unused endpoints. --- .../commands/WebpasswordCommand.java | 19 +++----------- .../src/de/steamwar/routes/Routes.kt | 6 ++--- .../src/de/steamwar/routes/Stats.kt | 1 - .../src/de/steamwar/routes/v2/Auth.kt | 26 ------------------- 4 files changed, 5 insertions(+), 47 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java index 8f9b7b60..6115f47f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java @@ -19,17 +19,13 @@ package de.steamwar.velocitycore.commands; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.Token; -import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; public class WebpasswordCommand extends SWCommand { @@ -44,16 +40,7 @@ public class WebpasswordCommand extends SWCommand { public void genericCommand(Chatter sender) { SteamwarUser user = sender.user(); - HttpRequest request = HttpRequest.newBuilder() - .POST(HttpRequest.BodyPublishers.noBody()) - .uri(URI.create("http://localhost:1337/v2/auth/enroll/" + user.getId())).build(); - - client.sendAsync(request, responseInfo -> HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8)).thenAccept(httpResponse -> { - JsonObject jsonObject = JsonParser.parseString(httpResponse.body()).getAsJsonObject(); - - String token = jsonObject.get("token").getAsString(); - - sender.system("WEB_RESET_URL", URLEncoder.encode(token, StandardCharsets.UTF_8)); - }); + String token = Token.createToken("PT" + user.getUserName(), user); + sender.system("WEB_RESET_URL", URLEncoder.encode(token, StandardCharsets.UTF_8)); } } diff --git a/WebsiteBackend/src/de/steamwar/routes/Routes.kt b/WebsiteBackend/src/de/steamwar/routes/Routes.kt index 1da4ed29..b28eef2e 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Routes.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Routes.kt @@ -19,7 +19,7 @@ package de.steamwar.routes -import de.steamwar.routes.v2.configureNewAuth +import de.steamwar.routes.v2.* import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.routing.* @@ -35,9 +35,7 @@ fun Application.configureRoutes() { configurePage() configureSchematic() configureAuthRoutes() - route("/v2") { - configureNewAuth() - } + configureNewAuth() } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Stats.kt b/WebsiteBackend/src/de/steamwar/routes/Stats.kt index 0c4e571b..11aa8b97 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Stats.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Stats.kt @@ -21,7 +21,6 @@ package de.steamwar.routes import de.steamwar.plugins.SWAuthPrincipal import de.steamwar.plugins.SWPermissionCheck -import de.steamwar.plugins.getUser import de.steamwar.sql.* import io.ktor.http.* import io.ktor.server.application.* diff --git a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt index 9d6a5181..79fcd2ac 100644 --- a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt @@ -61,32 +61,6 @@ fun SteamwarUser.createAccessAndRefreshToken(keepLoggedIn: Boolean = false): Aut fun Route.configureNewAuth() { route("/auth") { - route("/enroll") { - post("/{userId}") { - if (call.request.headers.contains("X-Forwarded-For") || call.request.header("Host") != "localhost:1337") { - SWException.log("Request to /auth/register from", "Invalid IP") - call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid IP", "F_U")) - return@post - } - - val userId = call.parameters["userId"]?.toInt() - if (userId == null) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Missing or invalid userId")) - return@post - } - - val user = SteamwarUser.get(userId) - if (user == null) { - call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid userId")) - return@post - } - - val token = Token.createToken("PT-${user.userName}", user) - - call.respond(HttpStatusCode.OK, ResponseToken(token, TokenType.RESET_PASSWORD.lifetime)) - } - } - post("/register") { val requester = call.request.header("X-Forwarded-For") ?: call.request.origin.remoteAddress From b045f16160cb66478dc9b03fabbfec281b0294de Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 20 Feb 2025 22:40:18 +0100 Subject: [PATCH 083/112] Remove deprecated configureAuthRoutes function call --- WebsiteBackend/src/de/steamwar/routes/Routes.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/Routes.kt b/WebsiteBackend/src/de/steamwar/routes/Routes.kt index b28eef2e..f0e287f0 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Routes.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Routes.kt @@ -34,7 +34,6 @@ fun Application.configureRoutes() { configureStats() configurePage() configureSchematic() - configureAuthRoutes() configureNewAuth() } } From a2b3661605fae6afe061f848684daf1270229bd9 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 23 Feb 2025 17:24:14 +0100 Subject: [PATCH 084/112] Refactor V2 Auth --- .../velocitycore/listeners/ChatListener.java | 10 +- .../src/de/steamwar/plugins/Plugins.kt | 2 +- WebsiteBackend/src/de/steamwar/routes/Auth.kt | 87 ++++++----- .../src/de/steamwar/routes/Routes.kt | 3 +- .../src/de/steamwar/routes/v2/Auth.kt | 137 ------------------ .../src/de/steamwar/util/TokenUtils.kt | 3 - 6 files changed, 60 insertions(+), 182 deletions(-) delete mode 100644 WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java index 0445be62..daccaa9f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java @@ -42,6 +42,7 @@ import de.steamwar.velocitycore.network.NetworkSender; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -53,6 +54,8 @@ public class ChatListener extends BasicListener { private static final List rankedModes = ArenaMode.getAllModes().stream().filter(ArenaMode::isRanked).map(ArenaMode::getSchemTypeOrInternalName).toList(); + private static final Set noLogCommands = Set.of("webpw", "webpassword"); + @Subscribe(order = PostOrder.FIRST) public void fixCommands(CommandExecuteEvent e) { String command = e.getCommand(); @@ -73,7 +76,8 @@ public class ChatListener extends BasicListener { public void logCommands(CommandExecuteEvent e) { String command = e.getCommand(); int space = command.indexOf(' '); - if(VelocityCore.getProxy().getCommandManager().hasCommand(space != -1 ? command.substring(0, space) : command)) { + String cmd = space != -1 ? command.substring(0, space) : command; + if(VelocityCore.getProxy().getCommandManager().hasCommand(cmd)) { CommandSource source = e.getCommandSource(); String name; if(source instanceof Player player) @@ -83,6 +87,10 @@ public class ChatListener extends BasicListener { else name = source.toString(); + if (noLogCommands.contains(cmd)) { + return; + } + cmdLogger.log(Level.INFO, "%s -> executed command /%s".formatted(name, command)); } else if (e.getCommandSource() instanceof Player player) { // System.out.println("spoofChatInput " + e); diff --git a/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt b/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt index 0cff0a03..95389abe 100644 --- a/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt +++ b/WebsiteBackend/src/de/steamwar/plugins/Plugins.kt @@ -74,7 +74,7 @@ fun Application.configurePlugins() { token.delete() return@authenticate null } - if (token.type == TokenType.RESET_PASSWORD || token.type == TokenType.REFRESH_TOKEN) { + if (token.type == TokenType.REFRESH_TOKEN) { token.delete() } diff --git a/WebsiteBackend/src/de/steamwar/routes/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/Auth.kt index 52238c32..e76ae47b 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Auth.kt @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2024 SteamWar.de-Serverteam + * 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 @@ -21,9 +21,11 @@ package de.steamwar.routes import de.steamwar.ResponseError import de.steamwar.plugins.SWAuthPrincipal -import de.steamwar.plugins.SWPermissionCheck import de.steamwar.sql.SteamwarUser import de.steamwar.sql.Token +import de.steamwar.util.TokenType +import de.steamwar.util.lifetime +import de.steamwar.util.type import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* @@ -31,64 +33,73 @@ import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.serialization.Serializable -import java.time.format.DateTimeFormatter import java.time.LocalDateTime +import kotlin.time.Duration +import kotlin.time.toJavaDuration @Serializable -data class AuthLoginRequest(val username: String, val password: String) +data class UsernamePassword(val name: String, val password: String, val keepLoggedIn: Boolean = false) @Serializable -data class AuthTokenResponse(val token: String) - -@Serializable -data class ResponseToken(val id: Int, val name: String, val created: String) { - constructor(token: Token) : this(token.id, token.name, token.created.toLocalDateTime().toString()) +data class ResponseToken(val token: String, val expires: String) { + constructor(token: String, lifetime: Duration) : this(token, LocalDateTime.now().plus(lifetime.toJavaDuration()).toString()) } @Serializable -data class CreateTokenRequest(val name: String, val password: String) +data class AuthTokenResponse(val accessToken: ResponseToken, val refreshToken: ResponseToken? = null) -fun Route.configureAuthRoutes() { +fun SteamwarUser.createAccessAndRefreshToken(keepLoggedIn: Boolean = false): AuthTokenResponse { + val code = System.currentTimeMillis() % 1000 + val accessToken = Token.createToken("AT-${userName}-${code}", this) + val refreshToken = if (keepLoggedIn) Token.createToken("RT-${userName}-${code}", this) else null + + return AuthTokenResponse(ResponseToken(accessToken, TokenType.ACCESS_TOKEN.lifetime), refreshToken?.let { ResponseToken(it, TokenType.REFRESH_TOKEN.lifetime) }) +} + +fun Route.configureAuth() { route("/auth") { - post("/login") { - if (call.principal() != null) { - call.respond(HttpStatusCode.Forbidden, ResponseError("Already logged in", "already_logged_in")) - return@post - } + post { + val request = call.receive() - val request = call.receive() + val user = SteamwarUser.get(request.name) + val valid = user?.verifyPassword(request.password) ?: false - val user = SteamwarUser.get(request.username) - - if (user == null) { + if (!valid) { call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username or password", "invalid")) return@post } - if (!user.verifyPassword(request.password)) { - call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username or password", "invalid")) - return@post - } - - val code = Token.createToken("Website: ${DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())}", user) - call.respond(AuthTokenResponse(code)) + call.respond(user.createAccessAndRefreshToken(request.keepLoggedIn)) } - route("/tokens") { - install(SWPermissionCheck) { - mustAuth = true + put { + val token = call.principal() + + if (token == null || token.token.type != TokenType.REFRESH_TOKEN) { + call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid token type", "invalid")) + return@put } - post("/logout") { - val auth = call.principal() + val code = token.token.name.substringAfterLast('-') - if(auth == null) { - call.respond(HttpStatusCode.InternalServerError) - return@post - } + Token.listUser(token.user) + .filter { it.type == TokenType.ACCESS_TOKEN } + .filter { it.name.endsWith(code) } + .forEach { it.delete() } - auth.token.delete() - call.respond(HttpStatusCode.OK) + call.respond(token.user.createAccessAndRefreshToken(true)) + } + delete { + val token = call.principal() + token?.let { t -> + t.token.delete() + val code = t.token.name.substringAfterLast('-') + Token.listUser(token.user) + .filter { it.type == TokenType.REFRESH_TOKEN } + .filter { it.name.endsWith(code) } + .forEach { it.delete() } } + + call.respond(HttpStatusCode.OK) } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/Routes.kt b/WebsiteBackend/src/de/steamwar/routes/Routes.kt index f0e287f0..388f8055 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Routes.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Routes.kt @@ -19,7 +19,6 @@ package de.steamwar.routes -import de.steamwar.routes.v2.* import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.routing.* @@ -34,7 +33,7 @@ fun Application.configureRoutes() { configureStats() configurePage() configureSchematic() - configureNewAuth() + configureAuth() } } } \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt deleted file mode 100644 index 79fcd2ac..00000000 --- a/WebsiteBackend/src/de/steamwar/routes/v2/Auth.kt +++ /dev/null @@ -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 . - */ - -package de.steamwar.routes.v2 - -import de.steamwar.ResponseError -import de.steamwar.plugins.SWAuthPrincipal -import de.steamwar.sql.SWException -import de.steamwar.sql.SteamwarUser -import de.steamwar.sql.Token -import de.steamwar.util.TokenType -import de.steamwar.util.isValid -import de.steamwar.util.lifetime -import de.steamwar.util.type -import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.auth.* -import io.ktor.server.plugins.* -import io.ktor.server.request.* -import io.ktor.server.response.* -import io.ktor.server.routing.* -import kotlinx.serialization.Serializable -import java.time.LocalDateTime -import kotlin.time.Duration -import kotlin.time.toJavaDuration - -@Serializable -data class UsernamePassword(val name: String, val password: String, val keepLoggedIn: Boolean = false) - -@Serializable -data class ResponseToken(val token: String, val expires: String) { - constructor(token: String, lifetime: Duration) : this(token, LocalDateTime.now().plus(lifetime.toJavaDuration()).toString()) -} - -@Serializable -data class AuthTokenResponse(val accessToken: ResponseToken, val refreshToken: ResponseToken? = null) - -fun SteamwarUser.createAccessAndRefreshToken(keepLoggedIn: Boolean = false): AuthTokenResponse { - val code = System.currentTimeMillis() % 1000 - val accessToken = Token.createToken("AT-${userName}-${code}", this) - val refreshToken = if (keepLoggedIn) Token.createToken("RT-${userName}-${code}", this) else null - - return AuthTokenResponse(ResponseToken(accessToken, TokenType.ACCESS_TOKEN.lifetime), refreshToken?.let { ResponseToken(it, TokenType.REFRESH_TOKEN.lifetime) }) -} - -fun Route.configureNewAuth() { - route("/auth") { - post("/register") { - val requester = call.request.header("X-Forwarded-For") ?: call.request.origin.remoteAddress - - val request = call.receive() - val token = call.principal() - - if (token == null || token.token.type != TokenType.RESET_PASSWORD || !token.token.isValid) { - SWException.log("$requester tried registering with invalid token", "") - call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid token", "invalid")) - return@post - } - - val user = token.user - - if (user.userName != request.name) { - SWException.log("$requester tried registering for invalid User", """ - User: ${user.userName} - Request: ${request.name} - """.trimIndent()) - call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username", "invalid")) - return@post - } - - user.setPassword(request.password) - - call.respond(HttpStatusCode.OK) - } - route("/state") { - post { - val request = call.receive() - - val user = SteamwarUser.get(request.name) - val valid = user?.verifyPassword(request.password) ?: false - - if (!valid) { - call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username or password", "invalid")) - return@post - } - - call.respond(user.createAccessAndRefreshToken(request.keepLoggedIn)) - } - put { - val token = call.principal() - - if (token == null || token.token.type != TokenType.REFRESH_TOKEN) { - call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid token type", "invalid")) - return@put - } - - val code = token.token.name.substringAfterLast('-') - - Token.listUser(token.user) - .filter { it.type == TokenType.ACCESS_TOKEN } - .filter { it.name.endsWith(code) } - .forEach { it.delete() } - - call.respond(token.user.createAccessAndRefreshToken(true)) - } - delete { - val token = call.principal() - token?.let { t -> - t.token.delete() - val code = t.token.name.substringAfterLast('-') - Token.listUser(token.user) - .filter { it.type == TokenType.REFRESH_TOKEN } - .filter { it.name.endsWith(code) } - .forEach { it.delete() } - } - - call.respond(HttpStatusCode.OK) - } - } - } -} \ No newline at end of file diff --git a/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt b/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt index 4f5f8a4f..54675dd0 100644 --- a/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt +++ b/WebsiteBackend/src/de/steamwar/util/TokenUtils.kt @@ -30,7 +30,6 @@ val Token.type: TokenType get() = when (name.substring((0..1))) { "RT" -> TokenType.REFRESH_TOKEN "AT" -> TokenType.ACCESS_TOKEN - "PT" -> TokenType.RESET_PASSWORD else -> TokenType.OLD_TOKEN } @@ -38,7 +37,6 @@ val TokenType.lifetime: Duration get() = when (this) { TokenType.REFRESH_TOKEN -> 7.days TokenType.ACCESS_TOKEN -> 5.minutes - TokenType.RESET_PASSWORD -> 10.minutes TokenType.OLD_TOKEN -> 1.days } @@ -49,7 +47,6 @@ val Token.isValid: Boolean get() = created.toLocalDateTime().plus(lifetime.toJavaDuration()).isAfter(LocalDateTime.now()) enum class TokenType { - RESET_PASSWORD, ACCESS_TOKEN, REFRESH_TOKEN, OLD_TOKEN From fd8270741428dffdd46d156e8c6e2cef4052b404 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 23 Feb 2025 17:27:29 +0100 Subject: [PATCH 085/112] Update `webpassword` command and clean up deprecated logic --- .../steamwar/messages/BungeeCore.properties | 1 - .../messages/BungeeCore_de.properties | 1 - .../commands/WebpasswordCommand.java | 21 ++++++++++--------- .../velocitycore/listeners/ChatListener.java | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index 2315ed12..c9527253 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -543,7 +543,6 @@ WEB_USAGE=§8/§7webpassword §8[§epassword§8] WEB_UPDATED=§7Your password was updated. WEB_CREATED=§7Your webaccount was created. WEB_PASSWORD_LENGTH=§cYour password is shorter than 8 characters. -WEB_RESET_URL=§7You can reset your Password here: §ehttps://steamwar.de/reset-password?token={0} #ChatListener CHAT_LIXFEL_ACTION_BAR=§4§lTechnical problems? diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index cbbb3e2e..c50cf682 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -518,7 +518,6 @@ WEB_USAGE=§8/§7webpassword §8[§ePasswort§8] WEB_UPDATED=§7Dein Passwort wurde aktualisiert. WEB_CREATED=§7Dein Webaccount wurde erstellt. WEB_PASSWORD_LENGTH=§cDein Passwort ist kürzer als 8 Zeichen. -WEB_RESET_URL=§7Hier kannst du dein Passwort zurücksetzen: §ehttps://steamwar.de/passwort-setzen?token={0} #ChatListener CHAT_LIXFEL_ACTION_BAR=§4§lTechnische Probleme? diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java index 6115f47f..d19dedd0 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WebpasswordCommand.java @@ -22,11 +22,6 @@ package de.steamwar.velocitycore.commands; import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; import de.steamwar.sql.SteamwarUser; -import de.steamwar.sql.Token; - -import java.net.URLEncoder; -import java.net.http.HttpClient; -import java.nio.charset.StandardCharsets; public class WebpasswordCommand extends SWCommand { @@ -34,13 +29,19 @@ public class WebpasswordCommand extends SWCommand { super("webpassword", "webpw", "web"); } - private static final HttpClient client = HttpClient.newHttpClient(); @Register(description = "WEB_USAGE") - public void genericCommand(Chatter sender) { - SteamwarUser user = sender.user(); + public void genericCommand(Chatter sender, String password) { + if(password.length() < 8) { + sender.system("WEB_PASSWORD_LENGTH"); + return; + } - String token = Token.createToken("PT" + user.getUserName(), user); - sender.system("WEB_RESET_URL", URLEncoder.encode(token, StandardCharsets.UTF_8)); + SteamwarUser user = sender.user(); + boolean resetPW = user.hasPassword(); + + user.setPassword(password); + + sender.system(resetPW ? "WEB_UPDATED" : "WEB_CREATED"); } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java index daccaa9f..17137bf5 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java @@ -54,7 +54,7 @@ public class ChatListener extends BasicListener { private static final List rankedModes = ArenaMode.getAllModes().stream().filter(ArenaMode::isRanked).map(ArenaMode::getSchemTypeOrInternalName).toList(); - private static final Set noLogCommands = Set.of("webpw", "webpassword"); + private static final Set noLogCommands = Set.of("webpw", "webpassword", "web"); @Subscribe(order = PostOrder.FIRST) public void fixCommands(CommandExecuteEvent e) { From ce907389df19de8b9558e9121a9427ff5e0687a2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 25 Feb 2025 22:46:54 +0100 Subject: [PATCH 086/112] Refactor SQL query to remove schema qualifiers. --- WebsiteBackend/src/de/steamwar/sql/Stats.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsiteBackend/src/de/steamwar/sql/Stats.kt b/WebsiteBackend/src/de/steamwar/sql/Stats.kt index d8beb867..e248a0df 100644 --- a/WebsiteBackend/src/de/steamwar/sql/Stats.kt +++ b/WebsiteBackend/src/de/steamwar/sql/Stats.kt @@ -34,7 +34,7 @@ private val eventFightParticipation = Statement("SELECT FightPlayer.UserID, COUN fun getEventFightParticipation(user: SteamwarUser): Int? = eventFightParticipation.select(getNum, user.id) -private val eventParticipation = Statement("SELECT FightPlayer.UserID, COUNT(DISTINCT EventID) as num FROM FightPlayer INNER JOIN core.Fight F on FightPlayer.FightID = F.FightID INNER JOIN core.EventFight EF on F.FightID = EF.Fight WHERE F.FightID = FightPlayer.FightID AND FightPlayer.FightID = EF.Fight AND F.Server LIKE '%vs%' AND FightPlayer.UserID = ? GROUP BY FightPlayer.UserID") +private val eventParticipation = Statement("SELECT FightPlayer.UserID, COUNT(DISTINCT EventID) as num FROM FightPlayer INNER JOIN Fight F on FightPlayer.FightID = F.FightID INNER JOIN EventFight EF on F.FightID = EF.Fight WHERE F.FightID = FightPlayer.FightID AND FightPlayer.FightID = EF.Fight AND F.Server LIKE '%vs%' AND FightPlayer.UserID = ? GROUP BY FightPlayer.UserID") fun getEventParticipation(user: SteamwarUser): Int? = eventParticipation.select(getNum, user.id) From ade9a1b5eb0df262bd0e07cba6c135fba79de6c6 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sat, 1 Mar 2025 08:32:19 +0100 Subject: [PATCH 087/112] Allow TNT in shulker boxes --- .../schematicsystem/autocheck/AutoChecker15.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java index e0823263..9dd5e456 100644 --- a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java +++ b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java @@ -115,7 +115,14 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker { static { itemsInInv.put(Material.BUCKET, EnumSet.of(Material.DISPENSER)); - itemsInInv.put(Material.TNT, EnumSet.of(Material.CHEST, Material.BARREL)); + itemsInInv.put(Material.TNT, EnumSet.of( + Material.CHEST, Material.BARREL, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, + Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, + Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, + Material.LIGHT_GRAY_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, + Material.ORANGE_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, + Material.RED_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX + )); itemsInInv.put(Material.FIRE_CHARGE, EnumSet.of(Material.DISPENSER)); itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER)); FLOWERS.forEach(material -> itemsInInv.put(material, INVENTORY)); From e3c02cfb60deb799e0d9c9cab71f6b0fd7dfc7e4 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sat, 1 Mar 2025 08:33:15 +0100 Subject: [PATCH 088/112] Revert "Update VV dependency version" This reverts commit 9f108a7cea8766146c1be1bebba40ec70b4726f9. --- settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index cd1db040..cea601bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -137,8 +137,8 @@ dependencyResolutionManagement { library("velocity", "de.steamwar:velocity:RELEASE") library("velocityapi", "com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") - library("viaapi", "com.viaversion:viaversion-api:5.2.1") - library("viavelocity", "com.viaversion:viaversion-velocity:5.2.1") + library("viaapi", "com.viaversion:viaversion-api:4.3.1") + library("viavelocity", "com.viaversion:viaversion-velocity:4.3.1") library("jda", "net.dv8tion:JDA:5.2.0") library("msgpack", "org.msgpack:msgpack-core:0.9.8") library("apolloprotos", "com.lunarclient:apollo-protos:1.0-SNAPSHOT") From 96a4168f379a2f095a1d7dbe6223e21856cb7c7b Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 1 Mar 2025 21:40:54 +0100 Subject: [PATCH 089/112] Add event count to Team info --- VelocityCore/src/de/steamwar/messages/BungeeCore.properties | 2 +- VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties | 2 +- .../src/de/steamwar/velocitycore/commands/TeamCommand.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index c9527253..8f288592 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -494,7 +494,7 @@ TEAM_INFO_USAGE=§8/§7team info §8[§eTeamname§8] TEAM_INFO_TEAM=§7Team §e{0} §8[§{1}{2}§8] TEAM_INFO_LEADER=§7Leader ({0})§8: {1} TEAM_INFO_MEMBER=§7Member ({0})§8: {1} -TEAM_INFO_EVENTS=§7Events§8: §e{0} +TEAM_INFO_EVENTS=§7Events ({0})§8: §e{1} #Team List TEAM_LIST_NOT_PAGE=§cNo page number entered diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index c50cf682..34ecb20f 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -468,7 +468,7 @@ TEAM_INFO_USAGE=§8/§7team info §8[§eTeamname§8] TEAM_INFO_TEAM=§7Team §e{0} §8[§{1}{2}§8] TEAM_INFO_LEADER=§7Leader ({0})§8: {1} TEAM_INFO_MEMBER=§7Member ({0})§8: {1} -TEAM_INFO_EVENTS=§7Events§8: §e{0} +TEAM_INFO_EVENTS=§7Events ({0})§8: §e{1} #Team List TEAM_LIST_NOT_PAGE=§cKeine Seitenzahl angegeben diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java index 928d6e78..0dd865b1 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java @@ -301,7 +301,7 @@ public class TeamCommand extends SWCommand { Set events = TeamTeilnahme.getEvents(team.getTeamId()); if(!events.isEmpty()){ - sender.prefixless("TEAM_INFO_EVENTS", events.stream().map(Event::getEventName).collect(Collectors.joining(", "))); + sender.prefixless("TEAM_INFO_EVENTS", events.size(), events.stream().map(Event::getEventName).collect(Collectors.joining(", "))); } } From b0bd7196274f428afce7ba9278860378816aa33c Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Mar 2025 09:08:49 +0100 Subject: [PATCH 090/112] Backend Fixes --- WebsiteBackend/src/de/steamwar/routes/Data.kt | 3 ++- WebsiteBackend/src/de/steamwar/routes/Events.kt | 2 +- WebsiteBackend/src/de/steamwar/routes/UserPerms.kt | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/WebsiteBackend/src/de/steamwar/routes/Data.kt b/WebsiteBackend/src/de/steamwar/routes/Data.kt index 103fb044..0a2dd3ae 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Data.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Data.kt @@ -45,7 +45,7 @@ data class ResponseSchematicType(val name: String, val db: String) @Serializable data class ResponseUser(val name: String, val uuid: String, val prefix: String, val perms: List) { - constructor(user: SteamwarUser) : this(user.userName, user.uuid.toString(), user.prefix().chatPrefix, user.perms().map { it.name }) { + constructor(user: SteamwarUser) : this(user.userName, user.uuid.toString(), user.prefix().chatPrefix, user.perms().filter { !it.name.startsWith("PREFIX_") }.map { it.name }) { synchronized(cache) { cache[user.id] = this } @@ -149,5 +149,6 @@ fun Route.configureDataRoutes() { inline fun catchException(yield: () -> T): T? = try { yield() } catch (e: Exception) { + e.printStackTrace() null } diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt index d1edcf07..d40cdd3b 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Events.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt @@ -215,7 +215,7 @@ fun Route.configureEventsRoute() { } } event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly) - call.respond(ResponseEvent(event)) + call.respond(ResponseEvent(Event.get(event.eventID))) } delete { val id = call.parameters["id"]?.toIntOrNull() diff --git a/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt b/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt index 2befc916..c1558787 100644 --- a/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt +++ b/WebsiteBackend/src/de/steamwar/routes/UserPerms.kt @@ -79,7 +79,7 @@ fun Route.configureUserPerms() { call.respond(RespondUserPermsPrefix(RespondPrefix(prefix.name, prefixs.colorCode, prefixs.chatPrefix), perms)) } put("/prefix/{prefix}") { - val (user, prefix) = call.receivePermission("prefix") ?: return@put + val (user, prefix) = call.receivePermission("prefix", isPrefix = true) ?: return@put user.perms().filter { it.name.startsWith("PREFIX_") }.forEach { UserPerm.removePerm(user, it) @@ -121,7 +121,8 @@ suspend fun ApplicationCall.receivePermission(fieldName: String = "perm", isPref val perm = parameters[fieldName] val permission = UserPerm.entries.find { it.name == perm } - if (perm == null || perm.startsWith("PREFIX_") == isPrefix || permission == null) { + if (perm == null || perm.startsWith("PREFIX_") != isPrefix || permission == null) { + println(perm) respond(HttpStatusCode.BadRequest) return null } From 2d28cc6182d8bff9877d4be2db8ba4249b8b5fc2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Mar 2025 14:58:26 +0100 Subject: [PATCH 091/112] Fix isEvent function to correctly check eventFightId --- TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index 7b1e865a..6f7ca84a 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -87,7 +87,7 @@ data class TNTLeagueConfig( }.mapKeys { Material.getMaterial(it.key) ?: Material.BARRIER } } - fun isEvent() = config.eventFightId != null + fun isEvent() = (config.eventFightId ?: 0) > 0 } data class Price( From 2fad352f6233553754b69eb10c2d3eece83890b1 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Mar 2025 15:02:11 +0100 Subject: [PATCH 092/112] Fix event initialization check in TNTLeagueConfig --- TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index 6f7ca84a..d3d75592 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -52,7 +52,7 @@ data class TNTLeagueConfig( val redTeam: TeamConfig init { - if (eventFightId != null) { + if (isEvent() && eventFightId != null) { eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") event = Event.get(eventFight.eventID) From 6d4ae9593d4e8ba28749ccf9b926f9bea080aa0f Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Mar 2025 15:14:10 +0100 Subject: [PATCH 093/112] Refine eventFight ID check in TNTLeagueConfig initialization. --- TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt index d3d75592..a44fe7d5 100644 --- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt +++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt @@ -52,7 +52,7 @@ data class TNTLeagueConfig( val redTeam: TeamConfig init { - if (isEvent() && eventFightId != null) { + if (eventFightId != null && eventFightId > 0) { eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") event = Event.get(eventFight.eventID) From 8b49b8a73653e8b7e7452689a322b64919a29e01 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 2 Mar 2025 15:31:33 +0100 Subject: [PATCH 094/112] Add player respawn handling with custom spawn location --- .../de/steamwar/towerrun/listener/GlobalListener.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java b/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java index b8256d80..5c2956b2 100644 --- a/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java +++ b/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java @@ -26,14 +26,17 @@ import de.steamwar.towerrun.state.GameStateBukkitListener; import de.steamwar.towerrun.state.GameStates; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import java.util.EnumSet; -public class GlobalListener extends GameStateBukkitListener { +public class GlobalListener extends GameStateBukkitListener implements Listener { public GlobalListener() { super(EnumSet.allOf(GameStates.class)); } @@ -59,4 +62,9 @@ public class GlobalListener extends GameStateBukkitListener { event.setCancelled(true); } + + @EventHandler + public void onPlayerRespawn(PlayerRespawnEvent event) { + event.setRespawnLocation(WorldConfig.SPAWN); + } } From af55c946a6892cd600e00c56065e7d8a55fbe855 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 2 Mar 2025 18:51:01 +0100 Subject: [PATCH 095/112] Remove player length constraint --- .../src/de/steamwar/velocitycore/commands/SendCommand.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java index 77cd2193..5480f277 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java @@ -39,15 +39,14 @@ import java.util.stream.Collectors; public class SendCommand extends SWCommand { - // /send to only [] - // can also be current + // /send [] public SendCommand() { super("send", UserPerm.TEAM); } - @Register("to") - public void sendCommand(Chatter sender, RegisteredServer toServer, @ArrayLength(min = 1) Player... players) { + @Register + public void sendCommand(Chatter sender, RegisteredServer toServer, Player... players) { for (Player player : players) { player.createConnectionRequest(toServer).fireAndForget(); } From f0beb22856980f1d37355a91a1debc8a536d51bf Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 2 Mar 2025 18:54:59 +0100 Subject: [PATCH 096/112] Hotfix the "to" back in --- .../src/de/steamwar/velocitycore/commands/SendCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java index 5480f277..8d8fa415 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java @@ -45,7 +45,7 @@ public class SendCommand extends SWCommand { super("send", UserPerm.TEAM); } - @Register + @Register("to") public void sendCommand(Chatter sender, RegisteredServer toServer, Player... players) { for (Player player : players) { player.createConnectionRequest(toServer).fireAndForget(); From 85c0db873c34db51e48ae030be6d888ee3cbfcd4 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 2 Mar 2025 19:09:59 +0100 Subject: [PATCH 097/112] Final Hotfix of Send Command! --- .../steamwar/messages/BungeeCore.properties | 4 ++ .../messages/BungeeCore_de.properties | 4 ++ .../velocitycore/commands/SendCommand.java | 40 ++++++++++++++----- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index 8f288592..863d1099 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -127,6 +127,10 @@ HELP_BAU_LOCK_HOVER=§eLock your build server HELP_BAU_UNLOCK=§8/§ebuild unlock §8- §7Unlocks the buildserver for added users HELP_BAU_UNLOCK_HOVER=§eUnlock your build server +#Send Command +SEND_MESSAGE=§e{0}§7 send you to §e{1}§8! +SEND_MESSAGE_SELF=§eYou§7 send §e{0}§7 to §e{1}§8! + #Usage description of various commands USAGE_ALERT=§8/§7alert §8[§emessage§8] USAGE_IGNORE=§8/§7ignore §8[§eplayer§8] diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index 34ecb20f..b758353c 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -112,6 +112,10 @@ HELP_BAU_LOCK_HOVER=§eSperre deinen Bau HELP_BAU_UNLOCK=§8/§ebau unlock §8- §7Öffne deinen Bauserver für alle hinzugefügten Spieler HELP_BAU_UNLOCK_HOVER=§eÖffne deinen Bau +#Send Command +SEND_MESSAGE=§e{0}§7 hat dich auf §e{1}§7 gesendet§8! +SEND_MESSAGE_SELF=§eDu§7 hast §e{0}§7 auf §e{1}§7 gesendet§8! + #Usage description of various commands USAGE_ALERT=§8/§7alert §8[§eNachricht§8] USAGE_IGNORE=§8/§7ignore §8[§eSpieler§8] diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java index 8d8fa415..1a5ba9f5 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java @@ -27,6 +27,7 @@ import de.steamwar.command.PreviousArguments; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; import de.steamwar.messages.Chatter; +import de.steamwar.messages.Message; import de.steamwar.persistent.Subserver; import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.UserPerm; @@ -47,24 +48,27 @@ public class SendCommand extends SWCommand { @Register("to") public void sendCommand(Chatter sender, RegisteredServer toServer, Player... players) { + String serverName = toServer.getServerInfo().getName(); for (Player player : players) { player.createConnectionRequest(toServer).fireAndForget(); + Chatter.of(player).send(true, null, null, new Message("SEND_MESSAGE", sender.user().getUserName(), serverName)); } + sender.send(true, null, null, new Message("SEND_MESSAGE_SELF", players.length, serverName)); + } + + private boolean check(SteamwarUser user, RegisteredServer registeredServer) { + if (registeredServer == null) return false; + ServerInfo serverInfo = registeredServer.getServerInfo(); + String name = serverInfo.getName(); + if (name.contains(" ")) return false; + + Subserver subserver = Subserver.getSubserver(serverInfo); + return subserver == null || Subserver.isArena(subserver) || (Subserver.isBuilder(subserver) && user.hasPerm(UserPerm.BUILD)); } @ClassMapper(value = RegisteredServer.class, local = true) public TypeMapper subserverTypeMapper() { return new TypeMapper<>() { - private boolean check(SteamwarUser user, RegisteredServer registeredServer) { - if (registeredServer == null) return false; - ServerInfo serverInfo = registeredServer.getServerInfo(); - String name = serverInfo.getName(); - if (name.contains(" ")) return false; - - Subserver subserver = Subserver.getSubserver(serverInfo); - return subserver == null || Subserver.isArena(subserver) || (Subserver.isBuilder(subserver) && user.hasPerm(UserPerm.BUILD)); - } - @Override public RegisteredServer map(Chatter sender, PreviousArguments previousArguments, String s) { SteamwarUser user = sender.user(); @@ -115,12 +119,26 @@ public class SendCommand extends SWCommand { return VelocityCore.getProxy().getPlayer(s).orElse(null); } + @Override + public boolean validate(Chatter sender, Player value, MessageSender messageSender) { + SteamwarUser user = sender.user(); + if (user.hasPerm(UserPerm.ADMINISTRATION)) return true; + return check(user, value.getCurrentServer().map(ServerConnection::getServer).orElse(null)); + } + @Override public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { List previous = previousArguments.getAll(RegisteredServer.class); if (previous.isEmpty()) return null; + SteamwarUser user = sender.user(); Collection players = previous.get(0).getPlayersConnected(); - return VelocityCore.getProxy().getAllPlayers().stream().filter(player -> !players.contains(player)).map(Player::getUsername).collect(Collectors.toList()); + return VelocityCore.getProxy() + .getAllPlayers() + .stream() + .filter(player -> !players.contains(player)) + .filter(player -> user.hasPerm(UserPerm.ADMINISTRATION) || check(user, player.getCurrentServer().map(ServerConnection::getServer).orElse(null))) + .map(Player::getUsername) + .collect(Collectors.toList()); } }; } From 0a60654a28468fe29168bef295de1c8dbd2241bc Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 09:35:42 +0100 Subject: [PATCH 098/112] Add some of the Easter Particles --- .../de/steamwar/lobby/LobbySystem.properties | 13 ++- .../steamwar/lobby/LobbySystem_de.properties | 4 +- .../de/steamwar/lobby/particle/Gradient.java | 53 +++++++++++ .../lobby/particle/ParticleElement.java | 4 + .../steamwar/lobby/particle/WingDesign.java | 6 ++ .../steamwar/lobby/particle/decorator/EV.png | Bin 0 -> 614 bytes .../lobby/particle/decorator/Ely_E.png | Bin 0 -> 198 bytes .../lobby/particle/decorator/Ely_L.png | Bin 0 -> 182 bytes .../lobby/particle/decorator/Ely_Y.png | Bin 0 -> 183 bytes .../lobby/particle/elements/DustParticle.java | 23 ++++- .../particle/elements/TrippleCircle.java | 61 +++++++++++++ .../particle/elements/custom/YOffset.java | 29 ++++-- .../particle/particles/EasterParticle.java | 2 +- .../particle/particles/PlayerParticle.java | 2 +- .../custom/CustomEasterParticle.java | 86 +++++++++++++++--- .../custom/CustomPlayerParticle.java | 4 +- 16 files changed, 251 insertions(+), 36 deletions(-) create mode 100644 LobbySystem/src/de/steamwar/lobby/particle/Gradient.java create mode 100644 LobbySystem/src/de/steamwar/lobby/particle/decorator/EV.png create mode 100644 LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_E.png create mode 100644 LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_L.png create mode 100644 LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_Y.png create mode 100644 LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties index 3375de0a..55fff341 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties @@ -50,6 +50,7 @@ PARTICLE_UNLOCKED_BY_EASTER_EGG_HUNT_DIFFICULTY = §fFind all Easter Eggs with d PARTICLE_ATTRIBUTE = §eAttributes§7: PARTICLE_ATTRIBUTE_CIRCLE = §8-§f Ring PARTICLE_ATTRIBUTE_BI_CIRCLE = §8-§f Double ring +PARTICLE_ATTRIBUTE_TRI_CIRCLE = §8-§f Tripple ring PARTICLE_ATTRIBUTE_CLOUD = §8-§f Cloud PARTICLE_ATTRIBUTE_TICK = §8-§f Always active PARTICLE_ATTRIBUTE_NON_FLOOR = §8-§f In air @@ -101,10 +102,16 @@ PARTICLE_MAGIC_ENCHANTING = §5Magic/Enchantment PARTICLE_WINGS_EVIL = §5Purple wings PARTICLE_PLAYER_HAYLIM_AURA = §fHaylim\'s Aura -PARTICLE_PLAYER_RONGAMER99091_AURA = §7Smoke Granade -PARTICLE_PLAYER_PLOMPA = §9ECAL +PARTICLE_PLAYER_1063 = §7Circling Circle +PARTICLE_PLAYER_10916_AURA = §7Tornado +PARTICLE_PLAYER_10697_AURA = §7Smoke Granade +PARTICLE_PLAYER_64 = §9ECAL +PARTICLE_PLAYER_153 = §9ELY +PARTICLE_PLAYER_3266 = §9Tricolo +PARTICLE_TEAM_158_1 = §9EV +PARTICLE_TEAM_158_2 = §9DNA -PARTICLE_TEAM_PULSE_AURA_1 = §fPulse Aura §cFlame +PARTICLE_TEAM_PULSE_AURA = §fPulse Aura §cFlame PARTICLE_TEAM_PULSE_AURA_2 = §fPulse Aura §7End Rod PARTICLE_TEAM_PULSE_AURA_3 = §fPulse Aura §fEnchanted PARTICLE_TEAM_PULSE_LOGO = §fPulse Logo diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties index 9823f57c..efe41798 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties @@ -49,6 +49,7 @@ PARTICLE_UNLOCKED_BY_EASTER_EGG_HUNT_DIFFICULTY = §fAlle Eierer mit Schwierigke PARTICLE_ATTRIBUTE_CIRCLE = §8-§f Ring PARTICLE_ATTRIBUTE_BI_CIRCLE = §8-§f Doppelring +PARTICLE_ATTRIBUTE_TRI_CIRCLE = §8-§f Dreifachring PARTICLE_ATTRIBUTE_CLOUD = §8-§f Wolke PARTICLE_ATTRIBUTE_TICK = §8-§f Immer aktiv PARTICLE_ATTRIBUTE_NON_FLOOR = §8-§f In der Luft @@ -99,7 +100,8 @@ PARTICLE_WATER_FIRE = §bWasser§7/§cFeuer PARTICLE_MAGIC_ENCHANTING = §5Magie§7/§eZauber PARTICLE_WINGS_EVIL = §5Lila Flügel -PARTICLE_PLAYER_RONGAMER99091_AURA = §7Rauchgranate +PARTICLE_PLAYER_1063 = §7Kreisende Kreise +PARTICLE_PLAYER_10697_AURA = §7Rauchgranate PARTICLE_TEAM_PULSE_HEART_BEAT = §cHerzschlag diff --git a/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java b/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java new file mode 100644 index 00000000..f7667294 --- /dev/null +++ b/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java @@ -0,0 +1,53 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.lobby.particle; + +import java.awt.*; +import java.util.Arrays; +import java.util.List; + +public class Gradient { + + private List colors; + + public Gradient(Color... colors) { + this.colors = Arrays.asList(colors); + } + + public Color getColor(double value, double maxValue) { + value /= maxValue / (double) (colors.size() - 1); + + return lerpColor( + colors.get((int) value), + colors.get((int) value + 1), + value - (int) value, + 1); + } + + private Color lerpColor(Color start, Color end, double step, double maxStep) { + double rStep = (end.getRed() - start.getRed()) / maxStep; + double gStep = (end.getGreen() - start.getGreen()) / maxStep; + double bStep = (end.getBlue() - start.getBlue()) / maxStep; + + return new Color(start.getRed() + (int) (rStep * step), + start.getGreen() + (int) (gStep * step), + start.getBlue() + (int) (bStep * step)); + } +} diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java index c9fac94c..c0039e86 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java @@ -24,6 +24,10 @@ public interface ParticleElement { return new Particle.DustOptions(randomColor(), randomSize()); } + default Particle.DustOptions withColor(int r, int g, int b) { + return new Particle.DustOptions(Color.fromRGB(r, g, b), randomSize()); + } + default void display(Location location, Player root, boolean onlySelf, boolean onlyOther, Consumer consumer) { if (onlySelf) { consumer.accept(root); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/WingDesign.java b/LobbySystem/src/de/steamwar/lobby/particle/WingDesign.java index 6954a565..125aa170 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/WingDesign.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/WingDesign.java @@ -53,4 +53,10 @@ public interface WingDesign { WingDesign PL = new WingDesignImpl(create("/de/steamwar/lobby/particle/decorator/PL-Logo.png")); WingDesign PlompaEasterWings = new WingDesignImpl(create("/de/steamwar/lobby/particle/decorator/ECAL-Logo.png")); + + WingDesign ELY_E = new WingDesignImpl(create("/de/steamwar/lobby/particle/decorator/Ely_E.png")); + WingDesign ELY_L = new WingDesignImpl(create("/de/steamwar/lobby/particle/decorator/Ely_L.png")); + WingDesign ELY_Y = new WingDesignImpl(create("/de/steamwar/lobby/particle/decorator/Ely_Y.png")); + + WingDesign EV = new WingDesignImpl(create("/de/steamwar/lobby/particle/decorator/EV.png")); } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/decorator/EV.png b/LobbySystem/src/de/steamwar/lobby/particle/decorator/EV.png new file mode 100644 index 0000000000000000000000000000000000000000..bb83cf9655e1f3e6859c34259d3e3312f1719cbb GIT binary patch literal 614 zcmeAS@N?(olHy`uVBq!ia0vp^d_c^_!2~3^cmJ5cz`)p&>FgZf>FlgfP?VpRnUl)E zpfRy_qOHea2brVs(cXVoSln2 zbvj|PF>^{w3q)BC@(YBEtGkM8eysOg=-R`6{BK41`@-*hAGT%r82)sS~QZBjJJf88M0shSjx{I|6a-F^xr%4lOyz`cs_6(DO~na?IT-Z&gCl> z?}ghVT&HxN?_6HGOW~vPb=CI!7SnUTeL6E?-sv;K?H#Q}{NA=_w01e!c*{%^o%(5S zWqazm=s8oPnoHlEjF-?^r5(BM@*D>tZx2OYMj@#ci`aw(qe6ptQZnoxK9b-5H?zp| z$*QJ_$&95M0=f1-cz5QQ>qI-$YMZJL0!dc)ESeT{;BuiW)N}Tg^b5rw57@Uhz6H8K46v{J8G8EiBeFMT9 z`NV;W%sgEjLnJOICmdk-4+i#XvpX9z4lrGJ5txvqrL3&HELzias^EUlDKooHuN9c@ w;NoE*%JAZbG=oRt)NMc$_);T0(|mmyw18|5AO?X;!IMFhr>mdKI;Vst01s;N?*IS* literal 0 HcmV?d00001 diff --git a/LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_E.png b/LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_E.png new file mode 100644 index 0000000000000000000000000000000000000000..dff09601a0cdb003a624473453348dc1796f7309 GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^fanMprE{`i(`ny<>Uj5 z608q&cFa%^D`ko>;o#!pN-&<>$jBhp%h378>`V?&DPL-YXPU1sgBFm@0mLA1DR?r7 N@^tlcS?83{1OWX+E5QH& literal 0 HcmV?d00001 diff --git a/LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_Y.png b/LobbySystem/src/de/steamwar/lobby/particle/decorator/Ely_Y.png new file mode 100644 index 0000000000000000000000000000000000000000..3855e46fdb1515022e714118ed6cb3be9ca24979 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&T!VDxEEDx9iDaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheYymzYuK)l42QotsU9JOCoCO|{#S9F5he4R}c>anMprC@Mi(`ny<>Ujb z5&zSIcMG+$o^Eg+i%h(X{|@MI9> M>FVdQ&MBb@0H!D@iU0rr literal 0 HcmV?d00001 diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java index 9c2f8389..8c143ac2 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java @@ -1,10 +1,13 @@ package de.steamwar.lobby.particle.elements; +import de.steamwar.lobby.particle.Gradient; import de.steamwar.lobby.particle.ParticleElement; import de.steamwar.lobby.particle.ParticleTickData; import org.bukkit.Location; import org.bukkit.Particle; +import java.awt.*; + public class DustParticle implements ParticleElement { private Particle particle; @@ -13,32 +16,44 @@ public class DustParticle implements ParticleElement { private float vz = 0.01f; private double speed = 0.01; private int count = 5; + private Gradient gradient; - public DustParticle(Particle particle) { + public DustParticle(Particle particle, Gradient gradient) { this.particle = particle; + this.gradient = gradient; } - public DustParticle(Particle particle, float vx, float vy, float vz) { + public DustParticle(Particle particle, float vx, float vy, float vz, Gradient gradient) { this.particle = particle; this.vx = vx; this.vy = vy; this.vz = vz; + this.gradient = gradient; } - public DustParticle(Particle particle, float vx, float vy, float vz, double speed, int count) { + public DustParticle(Particle particle, float vx, float vy, float vz, double speed, int count, Gradient gradient) { this.particle = particle; this.vx = vx; this.vy = vy; this.vz = vz; this.speed = speed; this.count = count; + this.gradient = gradient; } @Override public void tick(ParticleTickData particleTickData) { Location location = particleTickData.getLocation().add(0.0, 0.2, 0.0); + Particle.DustOptions dustOptions; + if (gradient != null) { + double result = particleTickData.getDeg() % 360; + Color color = gradient.getColor(result, 360); + dustOptions = withColor(color.getRed(), color.getGreen(), color.getBlue()); + } else { + dustOptions = randomParticleDust(); + } display(location, particleTickData.getPlayer(), particleTickData.isOnlySelf(), particleTickData.isOnlyOthers(), player -> { - player.spawnParticle(particle, location, count, vx, vy, vz, speed, randomParticleDust()); + player.spawnParticle(particle, location, count, vx, vy, vz, speed, dustOptions); }); } } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java new file mode 100644 index 00000000..45e8f8a3 --- /dev/null +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java @@ -0,0 +1,61 @@ +package de.steamwar.lobby.particle.elements; + +import de.steamwar.lobby.particle.ParticleElement; +import de.steamwar.lobby.particle.ParticleTickData; +import de.steamwar.lobby.particle.ParticleTickType; +import org.bukkit.Location; +import org.bukkit.util.Vector; + +public class TrippleCircle extends Circle { + + private ParticleElement second; + private ParticleElement third; + + private double distance; + private double speed; + + public TrippleCircle(ParticleElement first, ParticleElement second, ParticleElement third) { + super(first); + this.second = second; + this.distance = 1; + this.speed = 1; + } + + public TrippleCircle(ParticleElement first, ParticleElement second, ParticleElement third, double distance, double speed) { + super(first); + this.second = second; + this.distance = distance; + this.speed = speed; + } + + @Override + public String attribute() { + return "PARTICLE_ATTRIBUTE_TRI_CIRCLE"; + } + + @Override + public ParticleTickType tickType() { + if (particleElement.tickType() == second.tickType() && particleElement.tickType() == third.tickType()) { + return particleElement.tickType(); + } + return ParticleTickType.MOVE; + } + + @Override + public void tick(ParticleTickData particleTickData) { + Location location = particleTickData.getLocation(); + + Vector vector = new Vector(distance, 0, 0); + vector.rotateAroundY((particleTickData.getDeg() * speed) % 360); + ParticleTickData nParticleTickData = particleTickData.withLocation(location.clone().add(vector)); + particleElement.tick(nParticleTickData); + + vector.rotateAroundY(120); + nParticleTickData = particleTickData.withLocation(location.clone().add(vector)); + second.tick(nParticleTickData); + + vector.rotateAroundY(120); + nParticleTickData = particleTickData.withLocation(location.clone().add(vector)); + third.tick(nParticleTickData); + } +} diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/custom/YOffset.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/custom/YOffset.java index 1be82423..0af32eac 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/custom/YOffset.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/custom/YOffset.java @@ -10,13 +10,15 @@ public class YOffset extends DelegatingParticleElement { private double minY; private double maxY; private boolean inverted; + private boolean bounce; - public YOffset(ParticleElement particleElement, double speed, double minY, double maxY, boolean inverted) { + public YOffset(ParticleElement particleElement, double speed, double minY, double maxY, boolean inverted, boolean bounce) { super(particleElement); this.multiplication = speed; this.minY = minY; this.maxY = maxY; this.inverted = inverted; + this.bounce = bounce; } @Override @@ -26,19 +28,28 @@ public class YOffset extends DelegatingParticleElement { @Override public void tick(ParticleTickData particleTickData) { - double value = ((particleTickData.getDeg() * multiplication) % 360) / 180; double y; - if (inverted) { - if (value <= 1) { - y = maxY - (maxY - minY) * value; + if (bounce) { + double value = ((particleTickData.getDeg() * multiplication) % 360) / 180; + if (inverted) { + if (value <= 1) { + y = maxY - (maxY - minY) * value; + } else { + y = minY + (maxY - minY) * (value - 1); + } } else { - y = minY + (maxY - minY) * (value - 1); + if (value <= 1) { + y = minY + (maxY - minY) * value; + } else { + y = maxY - (maxY - minY) * (value - 1); + } } } else { - if (value <= 1) { - y = minY + (maxY - minY) * value; + double value = ((particleTickData.getDeg() * multiplication) % 360) / 360; + if (inverted) { + y = maxY - (maxY - minY) * value; } else { - y = maxY - (maxY - minY) * (value - 1); + y = minY + (maxY - minY) * value; } } ParticleTickData current = particleTickData.withLocation(particleTickData.getLocation().clone().add(0, y, 0)); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/EasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/EasterParticle.java index cecd91b9..0d94f2ea 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/EasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/EasterParticle.java @@ -21,7 +21,7 @@ public enum EasterParticle implements ParticleEnum { new Always(new Floor(new Sneaking(new SimpleParticle(Particle.GLOW_SQUID_INK, 0.4F, 0.9F, 0.4F, 0.01))))) ), EGG_HUNT_HARD(new ParticleData(Material.RED_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_HARD", ParticleRequirement.EGG_HUNT_HARD, - new Always(new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0.01, 1), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0.01, 1)), 0, 0.5, 0))) + new Always(new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0.01, 1, null), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0.01, 1, null)), 0, 0.5, 0))) ), EGG_HUNT_EXTREME(new ParticleData(Material.PURPLE_CONCRETE_POWDER, "PARTICLE_EGG_HUNT_EXTREME", ParticleRequirement.EGG_HUNT_EXTREME, new Always(new LocationMutator(new SimpleParticle(Particle.FALLING_OBSIDIAN_TEAR, 0.5F, 0.1F, 0.5F, 1, 1), 0, 2.2, 0))) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/PlayerParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/PlayerParticle.java index f54c516a..bf421bea 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/PlayerParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/PlayerParticle.java @@ -38,7 +38,7 @@ public enum PlayerParticle implements ParticleEnum { new SimpleParticle(Particle.SNOWBALL, 0.2F, 0.2F ,0.2F, 0.01)) ), EFFECT(new ParticleData(Material.GLASS_BOTTLE, "PARTICLE_EFFECT", - new DustParticle(Particle.REDSTONE, 0, 0.2F, 0, 0.01, 5)) + new DustParticle(Particle.REDSTONE, 0, 0.2F, 0, 0.01, 5, null)) ), CAMPFIRE(new ParticleData(Material.CAMPFIRE, "PARTICLE_CAMPFIRE", new SimpleParticle(Particle.CAMPFIRE_COSY_SMOKE, 0, 0.2F ,0, 0.01)) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java index 0a4206af..55bbf146 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java @@ -1,44 +1,100 @@ package de.steamwar.lobby.particle.particles.custom; -import de.steamwar.lobby.particle.ParticleData; -import de.steamwar.lobby.particle.ParticleEnum; -import de.steamwar.lobby.particle.ParticleRequirement; -import de.steamwar.lobby.particle.WingDesign; +import de.steamwar.lobby.particle.*; import de.steamwar.lobby.particle.elements.*; import de.steamwar.lobby.particle.elements.custom.HearthBeat; import de.steamwar.lobby.particle.elements.custom.NonMoving; import de.steamwar.lobby.particle.elements.custom.PulseShimmer; +import de.steamwar.lobby.particle.elements.custom.YOffset; import lombok.AllArgsConstructor; import lombok.Getter; import org.bukkit.Material; import org.bukkit.Particle; +import java.awt.*; + @AllArgsConstructor public enum CustomEasterParticle implements ParticleEnum { - /* - Lord_Loading(new ParticleData(Material.ENDER_PEARL, "Loading Test", ParticleRequirement.easterEventSpecificPlayer(1063), - new Always(new DoubleCircle(new DoubleCircle(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), - new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 0.5, 4), - new DoubleCircle(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), - new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 0.5, 4), 1.5, 1))) + PLAYER_1063(new ParticleData(Material.ENDER_PEARL, "PARTICLE_PLAYER_1063", ParticleRequirement.easterEventSpecificPlayer(1063), + new Always(new DoubleCircle( + new DoubleCircle( + new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), + new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 0.5, 4), + new DoubleCircle( + new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), + new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 0.5, 4), 1.5, 1) + )) ), - */ - Rongamer99091(new ParticleData(Material.GUNPOWDER, "PARTICLE_PLAYER_RONGAMER99091_AURA", ParticleRequirement.easterEventSpecificPlayer(10697), + PLAYER_10916(new ParticleData(Material.TORCHFLOWER, "PARTICLE_PLAYER_10916_AURA", ParticleRequirement.easterEventSpecificPlayer(10916), + new Always(new NonMoving(new Group( + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.2, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.3, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.4, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.5, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.6, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.7, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.8, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.9, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.0, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.1, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.2, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.3, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.4, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.5, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.6, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.7, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.8, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.9, 0)), + new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 2.0, 0)) + )))) + ), + PLAYER_10697(new ParticleData(Material.GUNPOWDER, "PARTICLE_PLAYER_10697_AURA", ParticleRequirement.easterEventSpecificPlayer(10697), new Always(new Sneaking(new Group( new OnlySelf(new Delayed(new SimpleParticle(Particle.EXPLOSION_HUGE, 0, 0, 0, 0.01, 1), 20)), new OnlyOthers(new Delayed(new SimpleParticle(Particle.EXPLOSION_HUGE, 0, 0, 0, 0.01, 1), 2)) )))) ), - Plompa(new ParticleData(Material.PUFFERFISH_BUCKET, "PARTICLE_PLAYER_PLOMPA", ParticleRequirement.specificPlayer(64), + PLAYER_64(new ParticleData(Material.PUFFERFISH_BUCKET, "PARTICLE_PLAYER_64", ParticleRequirement.easterEventSpecificPlayer(64), new Always(new Delayed(new NonFlying(new Wing(new SimpleParticle(Particle.END_ROD, 0, 0, 0, 0, 1), 0.15, WingDesign.PlompaEasterWings)), 80))) ), - Pulse_EASTER_1(new ParticleData(Material.RED_CANDLE, "PARTICLE_TEAM_PULSE_AURA_1", ParticleRequirement.easterEventSpecificTeam(210), + TEAM_210_1(new ParticleData(Material.RED_CANDLE, "PARTICLE_TEAM_PULSE_AURA", ParticleRequirement.easterEventSpecificTeam(210), new Always(new NonMoving(new PulseShimmer(new SimpleParticle(Particle.FLAME, 0, 0, 0, 0, 1), 80, 2)))) ), - Pulse_EASTER_3(new ParticleData(Material.APPLE, "PARTICLE_TEAM_PULSE_HEART_BEAT", ParticleRequirement.easterEventSpecificTeam(210), + TEAM_210_2(new ParticleData(Material.APPLE, "PARTICLE_TEAM_PULSE_HEART_BEAT", ParticleRequirement.easterEventSpecificTeam(210), new Always(new NonFlying(new HearthBeat(new SimpleParticle(Particle.FLAME, 0, 0, 0, 0, 1), 80)))) ), + PLAYER_153(new ParticleData(Material.OAK_SIGN, "PARTICLE_PLAYER_153", ParticleRequirement.easterEventSpecificPlayer(153), + new Always(new Delayed(new NonFlying(new Group( + new Wing(new SimpleParticle(Particle.VILLAGER_ANGRY, 0, 0, 0, 0, 1), 0.15, WingDesign.ELY_E), + new Wing(new SimpleParticle(Particle.COMPOSTER, 0, 0, 0, 0, 1), 0.15, WingDesign.ELY_L), + new Wing(new SimpleParticle(Particle.CRIT, 0, 0, 0, 0, 1), 0.15, WingDesign.ELY_Y) + )), 80))) + ), + // TODO: Implement zSalos! -> Team + // TODO: Implement GroupXyz! + // TODO: Implement minecrafter_133 1817! + // TODO: Implement TheReaper22122! + // TODO: Implement Bosslar! + // TODO: Implement ATOM65! + PLAYER_3266(new ParticleData(Material.CHORUS_FRUIT, "PARTICLE_PLAYER_3266", ParticleRequirement.easterEventSpecificPlayer(3266), + new Always(new NonFlying(new Cloud(new LocationMutator(new TrippleCircle( + new DustParticle(Particle.REDSTONE, new Gradient(Color.CYAN, Color.BLUE, Color.MAGENTA.darker(), Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN)), + new DustParticle(Particle.REDSTONE, new Gradient(Color.CYAN, Color.BLUE, Color.MAGENTA.darker(), Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN)), + new DustParticle(Particle.REDSTONE, new Gradient(Color.CYAN, Color.BLUE, Color.MAGENTA.darker(), Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN)), + 0.7, + 0.5), location -> location.add(0, 1.2, 0) + ))))) + ), + // TODO: Implement Gehfxhler! + // TODO: Implement SchwarzerFuerst + // TODO: Implement byVallu + TEAM_158_1(new ParticleData(Material.ENCHANTED_BOOK, "PARTICLE_TEAM_158_1", ParticleRequirement.easterEventSpecificTeam(158), + new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 80)))) + ), + TEAM_158_2(new ParticleData(Material.ENDER_EYE, "PARTICLE_TEAM_158_2", ParticleRequirement.easterEventSpecificTeam(158), + new Always(new NonFlying(new YOffset(new DoubleCircle(new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0, 0, 0, 0, 1), new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0, 0, 0, 0, 1), 0.5, 1), 1, 0, 2, false, false)))) + ), ; public static ParticleEnum[] particles = values(); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomPlayerParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomPlayerParticle.java index 3cfe0875..79c42b3b 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomPlayerParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomPlayerParticle.java @@ -16,8 +16,8 @@ public enum CustomPlayerParticle implements ParticleEnum { Haylim_(new ParticleData(Material.WHITE_CANDLE, "PARTICLE_PLAYER_HAYLIM_AURA", ParticleRequirement.specificPlayer(9426), new Always(new NonMoving(new NonFlying(new Group( - new DoubleCircle(new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.01, 5), 40, 0, 2, false), new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.0,5), 40, 0, 2, true)), - new DoubleCircle(new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.01, 5), 40, 0, 2, true), new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.0,5), 40, 0, 2, false)) + new DoubleCircle(new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.01, 5), 40, 0, 2, false, false), new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.0,5), 40, 0, 2, true, false)), + new DoubleCircle(new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.01, 5), 40, 0, 2, true, false), new YOffset(new SimpleParticle(Particle.ENCHANTMENT_TABLE, 0, 0, 0, 0.0,5), 40, 0, 2, false, false)) ))))) ), ; From b4eab65757a367f677592a7b7bcf925dbff1e377 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 09:42:39 +0100 Subject: [PATCH 099/112] Hotfix xsome exceptions --- .../de/steamwar/lobby/particle/Gradient.java | 7 +++ .../particle/elements/TrippleCircle.java | 1 + .../custom/CustomEasterParticle.java | 48 +++++++++---------- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java b/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java index f7667294..35ffcd72 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/Gradient.java @@ -32,6 +32,13 @@ public class Gradient { } public Color getColor(double value, double maxValue) { + if (colors.isEmpty()) { + return Color.BLACK; + } + if (colors.size() == 1) { + return colors.get(0); + } + value /= maxValue / (double) (colors.size() - 1); return lerpColor( diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java index 45e8f8a3..8c259f8b 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java @@ -24,6 +24,7 @@ public class TrippleCircle extends Circle { public TrippleCircle(ParticleElement first, ParticleElement second, ParticleElement third, double distance, double speed) { super(first); this.second = second; + this.third = third; this.distance = distance; this.speed = speed; } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java index 55bbf146..2d243d15 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java @@ -28,25 +28,25 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_10916(new ParticleData(Material.TORCHFLOWER, "PARTICLE_PLAYER_10916_AURA", ParticleRequirement.easterEventSpecificPlayer(10916), new Always(new NonMoving(new Group( - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.2, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.3, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.4, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.5, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.6, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.7, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.8, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 0.9, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.0, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.1, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.2, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.3, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.4, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.5, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.6, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.7, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.8, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 1.9, 0)), - new LocationMutator(new Circle(new SimpleParticle(Particle.REDSTONE, 0, 0, 0, 0, 1), 0.1, 1), location -> location.add(0, 2.0, 0)) + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.2, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.3, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.4, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.5, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.6, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.7, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.8, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.9, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.0, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.1, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.2, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.3, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.4, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.5, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.6, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.7, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.8, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.9, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 2.0, 0)) )))) ), PLAYER_10697(new ParticleData(Material.GUNPOWDER, "PARTICLE_PLAYER_10697_AURA", ParticleRequirement.easterEventSpecificPlayer(10697), @@ -66,9 +66,9 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_153(new ParticleData(Material.OAK_SIGN, "PARTICLE_PLAYER_153", ParticleRequirement.easterEventSpecificPlayer(153), new Always(new Delayed(new NonFlying(new Group( - new Wing(new SimpleParticle(Particle.VILLAGER_ANGRY, 0, 0, 0, 0, 1), 0.15, WingDesign.ELY_E), - new Wing(new SimpleParticle(Particle.COMPOSTER, 0, 0, 0, 0, 1), 0.15, WingDesign.ELY_L), - new Wing(new SimpleParticle(Particle.CRIT, 0, 0, 0, 0, 1), 0.15, WingDesign.ELY_Y) + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.DARK_GRAY)), 0.15, WingDesign.ELY_E), + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GREEN)), 0.15, WingDesign.ELY_L), + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GRAY)), 0.15, WingDesign.ELY_Y) )), 80))) ), // TODO: Implement zSalos! -> Team @@ -90,10 +90,10 @@ public enum CustomEasterParticle implements ParticleEnum { // TODO: Implement SchwarzerFuerst // TODO: Implement byVallu TEAM_158_1(new ParticleData(Material.ENCHANTED_BOOK, "PARTICLE_TEAM_158_1", ParticleRequirement.easterEventSpecificTeam(158), - new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 80)))) + new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 20)))) ), TEAM_158_2(new ParticleData(Material.ENDER_EYE, "PARTICLE_TEAM_158_2", ParticleRequirement.easterEventSpecificTeam(158), - new Always(new NonFlying(new YOffset(new DoubleCircle(new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0, 0, 0, 0, 1), new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0, 0, 0, 0, 1), 0.5, 1), 1, 0, 2, false, false)))) + new Always(new NonFlying(new YOffset(new DoubleCircle(new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0.01f, 0.01f, 0.01f, 0.1, 1), new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0.01f, 0.01f, 0.01f, 0.1, 1), 0.5, 1), 1, 0, 2, false, false)))) ), ; public static ParticleEnum[] particles = values(); From 5f73395b633daa80ac2f85b5c46bae290c5fe160 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 09:56:12 +0100 Subject: [PATCH 100/112] Hotfix some exceptions --- .../lobby/particle/ParticleElement.java | 2 +- .../particle/elements/TrippleCircle.java | 14 +++--- .../custom/CustomEasterParticle.java | 50 +++++++++---------- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java index c0039e86..d4bc37ff 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java @@ -25,7 +25,7 @@ public interface ParticleElement { } default Particle.DustOptions withColor(int r, int g, int b) { - return new Particle.DustOptions(Color.fromRGB(r, g, b), randomSize()); + return new Particle.DustOptions(Color.fromRGB(r, g, b), RANDOM.nextFloat() / 2); } default void display(Location location, Player root, boolean onlySelf, boolean onlyOther, Consumer consumer) { diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java index 8c259f8b..fdbdf611 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java @@ -48,15 +48,13 @@ public class TrippleCircle extends Circle { Vector vector = new Vector(distance, 0, 0); vector.rotateAroundY((particleTickData.getDeg() * speed) % 360); - ParticleTickData nParticleTickData = particleTickData.withLocation(location.clone().add(vector)); - particleElement.tick(nParticleTickData); - vector.rotateAroundY(120); - nParticleTickData = particleTickData.withLocation(location.clone().add(vector)); - second.tick(nParticleTickData); + particleElement.tick(particleTickData.withLocation(location.clone().add(vector))); - vector.rotateAroundY(120); - nParticleTickData = particleTickData.withLocation(location.clone().add(vector)); - third.tick(nParticleTickData); + vector.rotateAroundY(120 / 180.0); + second.tick(particleTickData.withLocation(location.clone().add(vector))); + + vector.rotateAroundY(120 / 180.0); + third.tick(particleTickData.withLocation(location.clone().add(vector))); } } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java index 2d243d15..f4a202e2 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java @@ -28,25 +28,25 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_10916(new ParticleData(Material.TORCHFLOWER, "PARTICLE_PLAYER_10916_AURA", ParticleRequirement.easterEventSpecificPlayer(10916), new Always(new NonMoving(new Group( - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.2, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.3, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.4, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.5, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.6, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.7, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.8, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 0.9, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.0, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.1, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.2, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.3, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.4, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.5, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.6, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.7, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.8, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 1.9, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.1, 1), location -> location.add(0, 2.0, 0)) + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 1), location -> location.add(0, 0.2, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 1), location -> location.add(0, 0.3, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 1), location -> location.add(0, 0.4, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 1), location -> location.add(0, 0.5, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 1), location -> location.add(0, 0.6, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 1), location -> location.add(0, 0.7, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 1), location -> location.add(0, 0.8, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 1), location -> location.add(0, 0.9, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 1), location -> location.add(0, 1.0, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 1), location -> location.add(0, 1.1, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 1), location -> location.add(0, 1.2, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 1), location -> location.add(0, 1.3, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 1), location -> location.add(0, 1.4, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 1), location -> location.add(0, 1.5, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 1), location -> location.add(0, 1.6, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 1), location -> location.add(0, 1.7, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 1), location -> location.add(0, 1.8, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 1), location -> location.add(0, 1.9, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.9, 1), location -> location.add(0, 2.0, 0)) )))) ), PLAYER_10697(new ParticleData(Material.GUNPOWDER, "PARTICLE_PLAYER_10697_AURA", ParticleRequirement.easterEventSpecificPlayer(10697), @@ -66,10 +66,10 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_153(new ParticleData(Material.OAK_SIGN, "PARTICLE_PLAYER_153", ParticleRequirement.easterEventSpecificPlayer(153), new Always(new Delayed(new NonFlying(new Group( - new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.DARK_GRAY)), 0.15, WingDesign.ELY_E), - new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GREEN)), 0.15, WingDesign.ELY_L), - new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GRAY)), 0.15, WingDesign.ELY_Y) - )), 80))) + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.DARK_GRAY)), 0.2, WingDesign.ELY_E), + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GREEN)), 0.2, WingDesign.ELY_L), + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GRAY)), 0.2, WingDesign.ELY_Y) + )), 20))) ), // TODO: Implement zSalos! -> Team // TODO: Implement GroupXyz! @@ -83,7 +83,7 @@ public enum CustomEasterParticle implements ParticleEnum { new DustParticle(Particle.REDSTONE, new Gradient(Color.CYAN, Color.BLUE, Color.MAGENTA.darker(), Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN)), new DustParticle(Particle.REDSTONE, new Gradient(Color.CYAN, Color.BLUE, Color.MAGENTA.darker(), Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN)), 0.7, - 0.5), location -> location.add(0, 1.2, 0) + 0.5), location -> location.add(0, 0.6, 0) ))))) ), // TODO: Implement Gehfxhler! @@ -93,7 +93,7 @@ public enum CustomEasterParticle implements ParticleEnum { new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 20)))) ), TEAM_158_2(new ParticleData(Material.ENDER_EYE, "PARTICLE_TEAM_158_2", ParticleRequirement.easterEventSpecificTeam(158), - new Always(new NonFlying(new YOffset(new DoubleCircle(new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0.01f, 0.01f, 0.01f, 0.1, 1), new SimpleParticle(Particle.SPORE_BLOSSOM_AIR, 0.01f, 0.01f, 0.01f, 0.1, 1), 0.5, 1), 1, 0, 2, false, false)))) + new Always(new NonFlying(new YOffset(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.BLUE)), 0.5, 1), 1, 0, 2, false, false)))) ), ; public static ParticleEnum[] particles = values(); From caee70c07e19641578a5fbf0120e2c8b101c98b5 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 10:01:56 +0100 Subject: [PATCH 101/112] Hotfix some exceptions --- .../lobby/particle/ParticleElement.java | 2 +- .../particle/elements/TrippleCircle.java | 4 +- .../custom/CustomEasterParticle.java | 40 +++++++++---------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java index d4bc37ff..33b497f0 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleElement.java @@ -25,7 +25,7 @@ public interface ParticleElement { } default Particle.DustOptions withColor(int r, int g, int b) { - return new Particle.DustOptions(Color.fromRGB(r, g, b), RANDOM.nextFloat() / 2); + return new Particle.DustOptions(Color.fromRGB(r, g, b), (float) (RANDOM.nextFloat() / 2 + 0.5)); } default void display(Location location, Player root, boolean onlySelf, boolean onlyOther, Consumer consumer) { diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java index fdbdf611..20372aa1 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/TrippleCircle.java @@ -51,10 +51,10 @@ public class TrippleCircle extends Circle { particleElement.tick(particleTickData.withLocation(location.clone().add(vector))); - vector.rotateAroundY(120 / 180.0); + vector.rotateAroundY(Math.toRadians(120)); second.tick(particleTickData.withLocation(location.clone().add(vector))); - vector.rotateAroundY(120 / 180.0); + vector.rotateAroundY(Math.toRadians(120)); third.tick(particleTickData.withLocation(location.clone().add(vector))); } } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java index f4a202e2..c35d1006 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java @@ -28,25 +28,25 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_10916(new ParticleData(Material.TORCHFLOWER, "PARTICLE_PLAYER_10916_AURA", ParticleRequirement.easterEventSpecificPlayer(10916), new Always(new NonMoving(new Group( - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 1), location -> location.add(0, 0.2, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 1), location -> location.add(0, 0.3, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 1), location -> location.add(0, 0.4, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 1), location -> location.add(0, 0.5, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 1), location -> location.add(0, 0.6, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 1), location -> location.add(0, 0.7, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 1), location -> location.add(0, 0.8, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 1), location -> location.add(0, 0.9, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 1), location -> location.add(0, 1.0, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 1), location -> location.add(0, 1.1, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 1), location -> location.add(0, 1.2, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 1), location -> location.add(0, 1.3, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 1), location -> location.add(0, 1.4, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 1), location -> location.add(0, 1.5, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 1), location -> location.add(0, 1.6, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 1), location -> location.add(0, 1.7, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 1), location -> location.add(0, 1.8, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 1), location -> location.add(0, 1.9, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.9, 1), location -> location.add(0, 2.0, 0)) + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 10), location -> location.add(0, 0.2, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 10), location -> location.add(0, 0.3, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 10), location -> location.add(0, 0.4, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 10), location -> location.add(0, 0.5, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 10), location -> location.add(0, 0.6, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 10), location -> location.add(0, 0.7, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 0.8, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 0.9, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 1.0, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.1, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.2, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.3, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.4, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.5, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.6, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.7, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.8, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.9, 0)), + new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.9, 10), location -> location.add(0, 2.0, 0)) )))) ), PLAYER_10697(new ParticleData(Material.GUNPOWDER, "PARTICLE_PLAYER_10697_AURA", ParticleRequirement.easterEventSpecificPlayer(10697), @@ -93,7 +93,7 @@ public enum CustomEasterParticle implements ParticleEnum { new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 20)))) ), TEAM_158_2(new ParticleData(Material.ENDER_EYE, "PARTICLE_TEAM_158_2", ParticleRequirement.easterEventSpecificTeam(158), - new Always(new NonFlying(new YOffset(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.BLUE)), 0.5, 1), 1, 0, 2, false, false)))) + new Always(new NonFlying(new YOffset(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.BLUE)), 0.5, 1), 10, 0, 2, false, false)))) ), ; public static ParticleEnum[] particles = values(); From f3b5a45f622eaa43856258cd6466f81e975257fe Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 10:05:08 +0100 Subject: [PATCH 102/112] Fix final things --- .../lobby/particle/elements/DustParticle.java | 2 +- .../custom/CustomEasterParticle.java | 42 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java index 8c143ac2..a7edb3f0 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/DustParticle.java @@ -46,7 +46,7 @@ public class DustParticle implements ParticleElement { Location location = particleTickData.getLocation().add(0.0, 0.2, 0.0); Particle.DustOptions dustOptions; if (gradient != null) { - double result = particleTickData.getDeg() % 360; + double result = (particleTickData.getDeg() * 10) % 360; Color color = gradient.getColor(result, 360); dustOptions = withColor(color.getRed(), color.getGreen(), color.getBlue()); } else { diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java index c35d1006..138362a0 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java @@ -28,25 +28,25 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_10916(new ParticleData(Material.TORCHFLOWER, "PARTICLE_PLAYER_10916_AURA", ParticleRequirement.easterEventSpecificPlayer(10916), new Always(new NonMoving(new Group( - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 10), location -> location.add(0, 0.2, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 10), location -> location.add(0, 0.3, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 10), location -> location.add(0, 0.4, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 10), location -> location.add(0, 0.5, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 10), location -> location.add(0, 0.6, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 10), location -> location.add(0, 0.7, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 0.8, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 0.9, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 1.0, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.1, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.2, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.3, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.4, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.5, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.6, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.7, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.8, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.9, 0)), - new LocationMutator(new Circle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.9, 10), location -> location.add(0, 2.0, 0)) + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 10), location -> location.add(0, 0.2, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.5, 10), location -> location.add(0, 0.3, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 10), location -> location.add(0, 0.4, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.55, 10), location -> location.add(0, 0.5, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 10), location -> location.add(0, 0.6, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.65, 10), location -> location.add(0, 0.7, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 0.8, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 0.9, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.7, 10), location -> location.add(0, 1.0, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.1, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.2, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.75, 10), location -> location.add(0, 1.3, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.4, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.5, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.8, 10), location -> location.add(0, 1.6, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.7, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.8, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.85, 10), location -> location.add(0, 1.9, 0)), + new LocationMutator(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.RED)), 0.9, 10), location -> location.add(0, 2.0, 0)) )))) ), PLAYER_10697(new ParticleData(Material.GUNPOWDER, "PARTICLE_PLAYER_10697_AURA", ParticleRequirement.easterEventSpecificPlayer(10697), @@ -69,7 +69,7 @@ public enum CustomEasterParticle implements ParticleEnum { new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.DARK_GRAY)), 0.2, WingDesign.ELY_E), new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GREEN)), 0.2, WingDesign.ELY_L), new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GRAY)), 0.2, WingDesign.ELY_Y) - )), 20))) + )), 10))) ), // TODO: Implement zSalos! -> Team // TODO: Implement GroupXyz! @@ -90,7 +90,7 @@ public enum CustomEasterParticle implements ParticleEnum { // TODO: Implement SchwarzerFuerst // TODO: Implement byVallu TEAM_158_1(new ParticleData(Material.ENCHANTED_BOOK, "PARTICLE_TEAM_158_1", ParticleRequirement.easterEventSpecificTeam(158), - new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 20)))) + new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 15)))) ), TEAM_158_2(new ParticleData(Material.ENDER_EYE, "PARTICLE_TEAM_158_2", ParticleRequirement.easterEventSpecificTeam(158), new Always(new NonFlying(new YOffset(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.BLUE)), 0.5, 1), 10, 0, 2, false, false)))) From 600c24441cfb3f125dfc93e97104de5450894245 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 10:09:54 +0100 Subject: [PATCH 103/112] Fix final things --- .../custom/CustomEasterParticle.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java index 138362a0..3c8d43c5 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/particles/custom/CustomEasterParticle.java @@ -17,13 +17,14 @@ import java.awt.*; public enum CustomEasterParticle implements ParticleEnum { PLAYER_1063(new ParticleData(Material.ENDER_PEARL, "PARTICLE_PLAYER_1063", ParticleRequirement.easterEventSpecificPlayer(1063), - new Always(new DoubleCircle( + new Always( new DoubleCircle( - new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), - new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 0.5, 4), - new DoubleCircle( - new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), - new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 0.5, 4), 1.5, 1) + new DoubleCircle( + new YOffset(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 20, 0, 2, true, true), + new YOffset(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 20, 0, 2, false, true), 0.5, 4), + new DoubleCircle( + new YOffset(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 20, 0, 2, false, true), + new YOffset(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0.01, 1), 20, 0, 2, true, true), 0.5, 4), 1.5, 1) )) ), PLAYER_10916(new ParticleData(Material.TORCHFLOWER, "PARTICLE_PLAYER_10916_AURA", ParticleRequirement.easterEventSpecificPlayer(10916), @@ -66,9 +67,9 @@ public enum CustomEasterParticle implements ParticleEnum { ), PLAYER_153(new ParticleData(Material.OAK_SIGN, "PARTICLE_PLAYER_153", ParticleRequirement.easterEventSpecificPlayer(153), new Always(new Delayed(new NonFlying(new Group( - new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.DARK_GRAY)), 0.2, WingDesign.ELY_E), - new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GREEN)), 0.2, WingDesign.ELY_L), - new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GRAY)), 0.2, WingDesign.ELY_Y) + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.DARK_GRAY)), 0.15, WingDesign.ELY_E), + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GREEN)), 0.15, WingDesign.ELY_L), + new Wing(new DustParticle(Particle.REDSTONE, 0, 0, 0, 0, 1, new Gradient(Color.GRAY)), 0.15, WingDesign.ELY_Y) )), 10))) ), // TODO: Implement zSalos! -> Team @@ -93,7 +94,7 @@ public enum CustomEasterParticle implements ParticleEnum { new Always(new NonFlying(new Delayed(new Wing(new SimpleParticle(Particle.CRIT_MAGIC, 0, 0, 0, 0, 1), 0.2, WingDesign.EV), 15)))) ), TEAM_158_2(new ParticleData(Material.ENDER_EYE, "PARTICLE_TEAM_158_2", ParticleRequirement.easterEventSpecificTeam(158), - new Always(new NonFlying(new YOffset(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.BLUE)), 0.5, 1), 10, 0, 2, false, false)))) + new Always(new NonFlying(new YOffset(new DoubleCircle(new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.RED)), new DustParticle(Particle.REDSTONE, 0.01f, 0.01f, 0.01f, 0.1, 1, new Gradient(Color.BLUE)), 0.7, 1), 40, 0, 2, false, false)))) ), ; public static ParticleEnum[] particles = values(); From f38b85f9cbed9e9d236b143dce17f2e9db54ddbe Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 3 Mar 2025 11:27:46 +0100 Subject: [PATCH 104/112] Fix TPSSystem in 1.21 and beyond --- .../src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java index 5cb1e1b6..1e25ff18 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java @@ -38,6 +38,7 @@ import de.steamwar.inventory.SWAnvilInv; import de.steamwar.inventory.SWItem; import de.steamwar.linkage.Linked; import de.steamwar.linkage.LinkedInstance; +import de.steamwar.linkage.MaxVersion; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -51,6 +52,7 @@ import org.bukkit.inventory.ItemStack; import java.util.Arrays; @Linked +@MaxVersion(20) // Hotfix for 1.21 tps limit! -> Backport coming later public class TPSSystem implements Listener { @Getter From 9bc1f8b328d956019c91fa53b99b7cbcbcb40643 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 4 Mar 2025 21:05:01 +0100 Subject: [PATCH 105/112] Refactor password check and add cache clearance. --- CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java | 2 +- WebsiteBackend/src/de/steamwar/Application.kt | 1 + WebsiteBackend/src/de/steamwar/routes/Auth.kt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java index d4bed21c..025e501c 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java +++ b/CommonCore/SQL/src/de/steamwar/sql/SteamwarUser.java @@ -335,7 +335,7 @@ public class SteamwarUser { public boolean verifyPassword(String password) { try { - if (this.password == null) { + if (!hasPassword()) { return false; } diff --git a/WebsiteBackend/src/de/steamwar/Application.kt b/WebsiteBackend/src/de/steamwar/Application.kt index 23fc3066..08cb7dcb 100644 --- a/WebsiteBackend/src/de/steamwar/Application.kt +++ b/WebsiteBackend/src/de/steamwar/Application.kt @@ -48,6 +48,7 @@ fun main() { while (true) { Thread.sleep(1000 * 10) ResponseUser.clearCache() + SteamwarUser.clear() } }.start() embeddedServer(Netty, port = 1337, host = "127.0.0.1", module = Application::module) diff --git a/WebsiteBackend/src/de/steamwar/routes/Auth.kt b/WebsiteBackend/src/de/steamwar/routes/Auth.kt index e76ae47b..1100201d 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Auth.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Auth.kt @@ -61,6 +61,7 @@ fun Route.configureAuth() { post { val request = call.receive() + SteamwarUser.clear() val user = SteamwarUser.get(request.name) val valid = user?.verifyPassword(request.password) ?: false From 644cc9da840b9bbc30a4fc5c36115160aa0c4b08 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sat, 8 Mar 2025 15:58:50 +0100 Subject: [PATCH 106/112] Fix /arena bugs with event arenas --- VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index a6707c45..56620468 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -110,7 +110,7 @@ public class ServerStarter { fightMap = eventFight.getMap(); gameMode = eventFight.getSpielmodus(); - String serverName = Team.get(eventFight.getTeamBlue()).getTeamKuerzel() + " vs " + Team.get(eventFight.getTeamRed()).getTeamKuerzel(); + String serverName = Team.get(eventFight.getTeamBlue()).getTeamKuerzel() + "_vs_" + Team.get(eventFight.getTeamRed()).getTeamKuerzel(); serverNameProvider = port -> serverName; worldName = serverToWorldName(serverName + eventFight.getStartTime().toLocalDateTime().format(DateTimeFormatter.ISO_TIME)); return this; From b60111e717c10c345c4bf4d7e4792e725ff866a7 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 8 Mar 2025 17:44:46 +0100 Subject: [PATCH 107/112] Hotfix ShieldPrinting pasting AIR, it should not --- .../bausystem/features/shieldprinting/ShieldPrinting.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java index 28a65a99..780c2bb3 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java @@ -177,6 +177,9 @@ public class ShieldPrinting implements Listener { BlockData worldOriginal = block.getBlockData(); BlockData copied = entry.getValue().clone(); + if (copied.getMaterial().isAir()) { + continue; + } for (BlockDataConfiguration blockDataConfiguration : stateConfigurations) { if (blockDataConfiguration == null) continue; blockDataConfiguration.apply(copied, worldOriginal); From 17eaefe3d0379d951bc0bf49c39ba679ff11b354 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 8 Mar 2025 17:51:41 +0100 Subject: [PATCH 108/112] Hotfix ShieldPrinting pasting AIR, it should not --- .../bausystem/features/shieldprinting/ShieldPrinting.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java index 780c2bb3..329ad9f4 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java @@ -170,13 +170,16 @@ public class ShieldPrinting implements Listener { } BlockDataConfiguration[] stateConfigurations = stateConfiguration.get(entry.getValue().getMaterial()); + BlockData copied = entry.getValue(); if (stateConfigurations == null) { - block.setBlockData(entry.getValue(), false); + if (!copied.getMaterial().isAir()) { + block.setBlockData(copied, false); + } continue; } BlockData worldOriginal = block.getBlockData(); - BlockData copied = entry.getValue().clone(); + copied = copied.clone(); if (copied.getMaterial().isAir()) { continue; } From 82723e4c315a96c5bd9e5f473b8ea59b407461db Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 8 Mar 2025 18:34:22 +0100 Subject: [PATCH 109/112] Hotfix ShieldPrinting pasting AIR, it should not --- .../features/shieldprinting/ShieldPrinting.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java index 329ad9f4..e3b60f1e 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/shieldprinting/ShieldPrinting.java @@ -160,6 +160,11 @@ public class ShieldPrinting implements Listener { private void paste(Map[]> stateConfiguration) { for (Map.Entry entry : shieldData.entrySet()) { + BlockData copied = entry.getValue(); + if (copied.getMaterial().isAir()) { + continue; + } + Block block = entry.getKey().toLocation(WORLD).getBlock(); if (entry.getValue().getMaterial() != block.getType()) { block.setBlockData(entry.getValue(), false); @@ -170,19 +175,12 @@ public class ShieldPrinting implements Listener { } BlockDataConfiguration[] stateConfigurations = stateConfiguration.get(entry.getValue().getMaterial()); - BlockData copied = entry.getValue(); if (stateConfigurations == null) { - if (!copied.getMaterial().isAir()) { - block.setBlockData(copied, false); - } continue; } BlockData worldOriginal = block.getBlockData(); copied = copied.clone(); - if (copied.getMaterial().isAir()) { - continue; - } for (BlockDataConfiguration blockDataConfiguration : stateConfigurations) { if (blockDataConfiguration == null) continue; blockDataConfiguration.apply(copied, worldOriginal); From 96c25687b64a72fcf131c7ff9b1183130a7d0b31 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 8 Mar 2025 22:16:39 +0100 Subject: [PATCH 110/112] Hotfix SendCommand --- .../de/steamwar/velocitycore/commands/SendCommand.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java index 1a5ba9f5..f1590957 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/SendCommand.java @@ -49,11 +49,15 @@ public class SendCommand extends SWCommand { @Register("to") public void sendCommand(Chatter sender, RegisteredServer toServer, Player... players) { String serverName = toServer.getServerInfo().getName(); + int count = 0; for (Player player : players) { - player.createConnectionRequest(toServer).fireAndForget(); - Chatter.of(player).send(true, null, null, new Message("SEND_MESSAGE", sender.user().getUserName(), serverName)); + if (sender.user().hasPerm(UserPerm.ADMINISTRATION) || check(sender.user(), player.getCurrentServer().map(ServerConnection::getServer).orElse(null))) { + player.createConnectionRequest(toServer).fireAndForget(); + Chatter.of(player).send(true, null, null, new Message("SEND_MESSAGE", sender.user().getUserName(), serverName)); + count++; + } } - sender.send(true, null, null, new Message("SEND_MESSAGE_SELF", players.length, serverName)); + sender.send(true, null, null, new Message("SEND_MESSAGE_SELF", count, serverName)); } private boolean check(SteamwarUser user, RegisteredServer registeredServer) { From 2225b811fa13146a9a78e9b4ba18beea00f15434 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 9 Mar 2025 18:18:13 +0100 Subject: [PATCH 111/112] Update Bossbar of FightSystem --- .../fightsystem/FightSystem.properties | 18 +++++++++--------- .../fightsystem/FightSystem_de.properties | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties index 3d9a9218..dde4e266 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties @@ -176,15 +176,15 @@ UI_WIN={0}Victory {1} UI_DRAW=§7Draw BAR_PRE_LEADER=§7Waiting for team leader -BAR_PRE_SCHEM={1} §7Schematic selection {0} {2} -BAR_PREPARE={1} {3} §7Preparation {0} {4} {2} -BAR_PRE_RUNNING={1} {3} §7Start of fight in {0} {4} {2} -BAR_RUNNING0={1} {3} {0} {4} {2} -BAR_RUNNING1={1} {3} {5} {0} {6} {4} {2} -BAR_RUNNING2={1} {3} {5} {7} {0} {6} {8} {4} {2} -BAR_RUNNING3={1} {3} {5} {7} {9} {0} {6} {8} {10} {4} {2} -BAR_TIE={1} §7Draw {0} {2} -BAR_WIN={1} §7Victory {3} {0} {2} +BAR_PRE_SCHEM = {1} §7Schematic selection {0} {2} +BAR_PREPARE = {1} {3} §7Preparation {0} {4} {2} +BAR_PRE_RUNNING = {1} {3} §7Start of fight in {0} {4} {2} +BAR_RUNNING0 = {1} {3} {0} {4} {2} +BAR_RUNNING1 = {1} {3} {5} {0} {6} {4} {2} +BAR_RUNNING2 = {1} {3} {5} {7} {0} {6} {8} {4} {2} +BAR_RUNNING3 = {1} {3} {5} {7} {9} {0} {6} {8} {10} {4} {2} +BAR_TIE = {1} §7Draw {0} {2} +BAR_WIN = {1} §7Victory {3} {0} {2} BAR_POINTS={0} §8Points BAR_POINTS_OF={0}§8/§7{1} §8Points BAR_PERCENT={0}§8% diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties index d45cdfd0..470226a8 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties @@ -161,11 +161,11 @@ UI_WIN={0}Sieg {1} UI_DRAW=§7Unentschieden BAR_PRE_LEADER=§7Warten auf Teamleader -BAR_PRE_SCHEM={1} §7Schemauswahl {0} {2} -BAR_PREPARE={1} {3} §7Vorbereitung {0} {4} {2} -BAR_PRE_RUNNING={1} {3} §7Kampfbeginn in {0} {4} {2} -BAR_TIE={1} §7Unentschieden {0} {2} -BAR_WIN={1} §7Sieg {3} {0} {2} +BAR_PRE_SCHEM = {1} §7Schemauswahl {0} {2} +BAR_PREPARE = {1} {3} §7Vorbereitung {0} {4} {2} +BAR_PRE_RUNNING = {1} {3} §7Kampfbeginn in {0} {4} {2} +BAR_TIE = {1} §7Unentschieden {0} {2} +BAR_WIN = {1} §7Sieg {3} {0} {2} BAR_POINTS={0} §8Punkte BAR_POINTS_OF={0}§8/§7{1} §8Punkte BAR_PERCENT={0}§8% From 1d293b446c10baa8e32f608cbff617c94b68ec1a Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Tue, 11 Mar 2025 18:31:31 +0100 Subject: [PATCH 112/112] Hotfix WhoisCommand for Developers not showing the User ID --- .../src/de/steamwar/velocitycore/commands/WhoisCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java index 4daa5b78..2fc6f08d 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/WhoisCommand.java @@ -71,7 +71,7 @@ public class WhoisCommand extends SWCommand { if (!sender.user().hasPerm(UserPerm.TEAM)) return; - if (sender.user().hasPerm(UserPerm.MODERATION)) { + if (sender.user().hasPerm(UserPerm.MODERATION) || sender.user().hasPerm(UserPerm.PREFIX_DEVELOPER)) { sender.system("WHOIS_ID", user.getId()); sender.system("WHOIS_UUID", new Message("WHOIS_UUID_HOVER"), ClickEvent.copyToClipboard(user.getUUID().toString()), user.getUUID().toString()); if (user.getDiscordId() != null)