diff --git a/MissileWars/build.gradle.kts b/MissileWars/build.gradle.kts
new file mode 100644
index 00000000..71351cfa
--- /dev/null
+++ b/MissileWars/build.gradle.kts
@@ -0,0 +1,70 @@
+/*
+ * 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 {
+ id("java")
+ id("base")
+ id("application")
+
+ id("com.github.johnrengelman.shadow")
+}
+
+group = "de.steamwar"
+version = ""
+
+tasks.compileJava {
+ options.encoding = "UTF-8"
+}
+
+tasks.build {
+ finalizedBy(tasks.shadowJar)
+}
+
+tasks.compileJava {
+ options.encoding = "UTF-8"
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+}
+
+sourceSets {
+ main {
+ java {
+ srcDirs("src/")
+ }
+ resources {
+ srcDirs("src/")
+ exclude("**/*.java", "**/*.kt")
+ }
+ }
+}
+
+dependencies {
+ compileOnly("org.projectlombok:lombok:1.18.32")
+ annotationProcessor("org.projectlombok:lombok:1.18.32")
+
+ compileOnly(project(":SpigotCore"))
+
+ compileOnly("de.steamwar:spigot:1.20")
+ compileOnly("de.steamwar:fastasyncworldedit:1.18")
+
+ compileOnly("org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
+}
diff --git a/MissileWars/src/config.yml b/MissileWars/src/config.yml
new file mode 100644
index 00000000..c963eef2
--- /dev/null
+++ b/MissileWars/src/config.yml
@@ -0,0 +1,31 @@
+WaitingTime: 600
+ItemTime: 300
+ShieldFlyTime: 100
+PlatformTime: 30
+EndTime: 200
+
+# Special
+Barrier: true
+
+Arena:
+ MinX: 0
+ MaxX: 0
+ MinY: 0
+ MinZ: 0
+ MaxZ: 0
+
+Red:
+ PortalZ: -60
+ SpawnX: 0
+ SpawnY: 0
+ SpawnZ: 0
+ SpawnYaw: 0
+ SpawnPitch: 0
+
+Blue:
+ PortalZ: 60
+ SpawnX: 0
+ SpawnY: 0
+ SpawnZ: 0
+ SpawnYaw: 0
+ SpawnPitch: 0
diff --git a/MissileWars/src/de/steamwar/misslewars/Config.java b/MissileWars/src/de/steamwar/misslewars/Config.java
new file mode 100644
index 00000000..b50ec741
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/Config.java
@@ -0,0 +1,180 @@
+/*
+ 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.misslewars;
+
+import de.steamwar.sql.Event;
+import de.steamwar.sql.EventFight;
+import de.steamwar.sql.Team;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.util.UUID;
+import java.util.logging.Level;
+
+public class Config {
+ private Config() {
+ }
+
+ public static final int ArenaMinX;
+ public static final int ArenaMaxX;
+ public static final int ArenaMinY;
+ public static final int ArenaMinZ;
+ public static final int ArenaMaxZ;
+
+ public static final Location RedSpawn;
+ public static final int RedPortalZ;
+ public static final Location BlueSpawn;
+ public static final int BluePortalZ;
+
+ public static final int WaitingTime;
+ public static final int PlatformTime;
+ public static final int ItemTime;
+ public static final int ShieldFlyTime;
+ public static final int EndTime;
+
+ public static final double MissileChance;
+
+ public static final boolean Barrier;
+ public static final boolean Space;
+
+ // Challenge
+ public static UUID BlueLeader;
+ public static UUID RedLeader;
+
+ private static final int EventKampfID;
+
+ // Event
+ public static final EventFight EventKampf;
+ public static final String TeamBlueName;
+ public static final String TeamRedName;
+ public static final String TeamBlueColor;
+ public static final String TeamRedColor;
+ public static final int EventTeamBlueID;
+ public static final int EventTeamRedID;
+ public static final int MaximumTeamMembers;
+
+ static {
+ File configfile = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "config.yml");
+ if (!configfile.exists()) {
+ Bukkit.getLogger().log(Level.SEVERE, "Config fehlt!");
+ Bukkit.shutdown();
+ }
+
+ FileConfiguration config = YamlConfiguration.loadConfiguration(configfile);
+ WaitingTime = config.getInt("WaitingTime");
+ PlatformTime = config.getInt("PlatformTime");
+ ItemTime = config.getInt("ItemTime");
+ ShieldFlyTime = config.getInt("ShieldFlyTime");
+ EndTime = config.getInt("EndTime");
+
+ MissileChance = config.getDouble("MissileChance");
+
+ ConfigurationSection arena = config.getConfigurationSection("Arena");
+ assert arena != null;
+ ArenaMinX = arena.getInt("MinX");
+ ArenaMaxX = arena.getInt("MaxX");
+ ArenaMinY = arena.getInt("MinY");
+ ArenaMinZ = arena.getInt("MinZ");
+ ArenaMaxZ = arena.getInt("MaxZ");
+
+ ConfigurationSection red = config.getConfigurationSection("Red");
+ assert red != null;
+ RedPortalZ = red.getInt("PortalZ");
+ RedSpawn = new Location(Bukkit.getWorlds().get(0), red.getDouble("SpawnX"), red.getDouble("SpawnY"), red.getDouble("SpawnZ"), (float) red.getDouble("SpawnYaw"), (float) red.getDouble("SpawnPitch"));
+
+ ConfigurationSection blue = config.getConfigurationSection("Blue");
+ assert blue != null;
+ BluePortalZ = blue.getInt("PortalZ");
+ BlueSpawn = new Location(Bukkit.getWorlds().get(0), blue.getDouble("SpawnX"), blue.getDouble("SpawnY"), blue.getDouble("SpawnZ"), (float) blue.getDouble("SpawnYaw"), (float) blue.getDouble("SpawnPitch"));
+
+ String blueLeader = System.getProperty("blueLeader", null);
+ String redLeader = System.getProperty("redLeader", null);
+ if (blueLeader != null)
+ BlueLeader = UUID.fromString(blueLeader);
+ else
+ BlueLeader = null;
+ if (redLeader != null)
+ RedLeader = UUID.fromString(redLeader);
+ else
+ RedLeader = null;
+
+ Barrier = config.getBoolean("Barrier", false);
+ Space = config.getBoolean("Space", false);
+
+ EventKampfID = Integer.parseInt(System.getProperty("fightID", "0"));
+ if (EventKampfID >= 1) {
+ EventKampf = EventFight.get(EventKampfID);
+ if (EventKampf == null) {
+ Bukkit.getLogger().log(Level.SEVERE, "Failed to load EventFight");
+ Bukkit.shutdown();
+ }
+ assert EventKampf != null;
+
+ Team team1 = Team.get(EventKampf.getTeamBlue());
+ Team team2 = Team.get(EventKampf.getTeamRed());
+
+ if (team1 == null || team2 == null) {
+ Bukkit.getLogger().log(Level.SEVERE, "Failed to load Team");
+ Bukkit.shutdown();
+ }
+ assert team1 != null;
+ assert team2 != null;
+
+ TeamBlueName = team1.getTeamKuerzel();
+ TeamRedName = team2.getTeamKuerzel();
+ TeamBlueColor = "§" + team1.getTeamColor();
+ TeamRedColor = "§" + team2.getTeamColor();
+ EventTeamBlueID = team1.getTeamId();
+ EventTeamRedID = team2.getTeamId();
+
+ Event event = Event.get(EventKampf.getEventID());
+ if (EventTeamBlueID == 0 && EventTeamRedID == 0) {
+ MaximumTeamMembers = Integer.MAX_VALUE;
+ } else {
+ MaximumTeamMembers = event.getMaximumTeamMembers();
+ }
+ } else {
+ EventKampf = null;
+ TeamBlueName = "Blau";
+ TeamRedName = "Rot";
+ TeamBlueColor = "§3";
+ TeamRedColor = "§c";
+ EventTeamBlueID = 0;
+ EventTeamRedID = 0;
+ MaximumTeamMembers = Integer.MAX_VALUE;
+ }
+ }
+
+ public static boolean isEvent() {
+ return EventKampfID >= 1;
+ }
+
+ public static boolean isChallenge() {
+ return BlueLeader != null && RedLeader != null;
+ }
+
+ public static boolean test() {
+ return EventKampfID == -1;
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/FightInfoPacketSender.java b/MissileWars/src/de/steamwar/misslewars/FightInfoPacketSender.java
new file mode 100644
index 00000000..ca58263f
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/FightInfoPacketSender.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.misslewars;
+
+import de.steamwar.network.NetworkSender;
+import de.steamwar.network.packets.common.FightInfoPacket;
+import de.steamwar.sql.SteamwarUser;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class FightInfoPacketSender implements Runnable {
+
+ private final World world = Bukkit.getWorlds().get(0);
+
+ private final String serverName = Bukkit.getServer().getName();
+ private final String gameMode = "missilewars";
+ private final String worldName = world.getName();
+ private final String blueName = Config.TeamBlueColor + Config.TeamBlueName;
+ private final String redName = Config.TeamRedColor + Config.TeamRedName;
+ private final int blueLeader = Config.BlueLeader != null ? SteamwarUser.get(Config.BlueLeader).getId() : 0;
+ private final int redLeader = Config.RedLeader != null ? SteamwarUser.get(Config.RedLeader).getId() : 0;
+
+ @Override
+ public void run() {
+ if (Config.test()) {
+ return;
+ }
+
+ int countdown;
+ if (FightScoreboard.getStartTime() == 0) {
+ countdown = 0;
+ } else {
+ countdown = (int) ((System.currentTimeMillis() - FightScoreboard.getStartTime()) / 1000);
+ }
+
+ List bluePlayers = MissileWars.getBlueTeam().getPlayers().stream()
+ .map(player -> SteamwarUser.get(player.getUniqueId()).getId())
+ .collect(Collectors.toList());
+ List redPlayers = MissileWars.getRedTeam().getPlayers().stream()
+ .map(player -> SteamwarUser.get(player.getUniqueId()).getId())
+ .collect(Collectors.toList());
+ List spectatorPlayers = Bukkit.getOnlinePlayers().stream()
+ .map(player -> SteamwarUser.get(player.getUniqueId()).getId())
+ .filter(integer -> !(bluePlayers.contains(integer) || redPlayers.contains(integer)))
+ .collect(Collectors.toList());
+
+ NetworkSender.send(new FightInfoPacket(serverName, gameMode, worldName, blueName, redName, MissileWars.getFightState().name().toLowerCase(), countdown, blueLeader, redLeader, 0, 0, bluePlayers, redPlayers, spectatorPlayers));
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/FightScoreboard.java b/MissileWars/src/de/steamwar/misslewars/FightScoreboard.java
new file mode 100644
index 00000000..8b16b403
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/FightScoreboard.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.misslewars;
+
+import de.steamwar.scoreboard.SWScoreboard;
+import de.steamwar.scoreboard.ScoreboardCallback;
+import org.bukkit.Bukkit;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.scoreboard.DisplaySlot;
+import org.bukkit.scoreboard.Objective;
+import org.bukkit.scoreboard.Scoreboard;
+
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+import java.util.Objects;
+
+/**
+ * Modified Version of the Fight-System Scoreboard
+ */
+class FightScoreboard implements Listener {
+
+ public FightScoreboard() {
+ Bukkit.getPluginManager().registerEvents(this, MissileWars.getPlugin());
+ }
+
+ private static final Scoreboard scoreboard = Objects.requireNonNull(Bukkit.getScoreboardManager()).getMainScoreboard();
+
+ private static long startTime = 0;
+
+ public static long getStartTime() {
+ return startTime;
+ }
+
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ SWScoreboard.createScoreboard(event.getPlayer(), new ScoreboardCallback() {
+ @Override
+ public String getTitle() {
+ return "§eMissileWars";
+ }
+
+ @Override
+ public HashMap getData() {
+ HashMap data = new HashMap<>();
+ data.put("§eSpielzeit", 5);
+ if (startTime == 0) {
+ data.put("§7??:??:??", 4);
+ } else {
+ long current_time = System.currentTimeMillis() - startTime;
+ data.put(String.format("§7%02d:%02d", current_time / 60000, (current_time / 1000) % 60), 4);
+ }
+
+ data.put("", 3);
+ data.put("§eSpieler", 2);
+ MissileWars.getBlueTeam().teamScoreboard(data);
+ MissileWars.getRedTeam().teamScoreboard(data);
+ return data;
+ }
+ });
+ }
+
+ @EventHandler
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ SWScoreboard.removeScoreboard(event.getPlayer());
+ }
+
+ static Scoreboard getScoreboard() {
+ return scoreboard;
+ }
+
+ static void startTime() {
+ startTime = System.currentTimeMillis();
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/FightState.java b/MissileWars/src/de/steamwar/misslewars/FightState.java
new file mode 100644
index 00000000..d0210605
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/FightState.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.misslewars;
+
+public enum FightState {
+ WAITING, // waiting for at least 2 players
+ FIGHTING, // no one has won
+ END // fight ended for some reason
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/FightWorld.java b/MissileWars/src/de/steamwar/misslewars/FightWorld.java
new file mode 100644
index 00000000..38dfab08
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/FightWorld.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.misslewars;
+
+import de.steamwar.core.CraftbukkitWrapper;
+import net.minecraft.world.level.chunk.Chunk;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.WorldCreator;
+import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+
+import java.util.function.ObjIntConsumer;
+
+public class FightWorld {
+
+ private static final World world = Bukkit.getWorlds().get(0);
+
+ private static double posToChunk(int pos){
+ return pos / 16.0;
+ }
+
+ private static int getMinChunkX(){
+ return (int) Math.floor(posToChunk(Config.ArenaMinX));
+ }
+
+ private static int getMaxChunkX(){
+ return (int) Math.ceil(posToChunk(Config.ArenaMaxX));
+ }
+
+ private static int getMinChunkZ(){
+ return (int) Math.floor(posToChunk(Config.ArenaMinZ));
+ }
+
+ private static int getMaxChunkZ(){
+ return (int) Math.ceil(posToChunk(Config.ArenaMaxZ));
+ }
+
+ private static void forEachChunk(ObjIntConsumer executor) {
+ for(int x = getMinChunkX(); x <= getMaxChunkX(); x++)
+ for(int z = getMinChunkZ(); z <= getMaxChunkZ(); z++)
+ executor.accept(x, z);
+ }
+
+ public static void resetWorld(){
+ world.getEntities().stream().filter(entity -> entity.getType() != EntityType.PLAYER).forEach(Entity::remove);
+
+ World backup = new WorldCreator(world.getName() + "/backup").createWorld();
+ assert backup != null;
+ forEachChunk((x, z) -> resetChunk(world, backup, x, z));
+ Bukkit.unloadWorld(backup, false);
+ }
+
+ private static void resetChunk(World world, World backup, int x, int z) {
+ Chunk chunk = ((CraftWorld) world).getHandle().d(x, z);
+ Chunk backupChunk = ((CraftWorld) backup).getHandle().d(x, z);
+
+ System.arraycopy(backupChunk.d(), 0, chunk.d(), 0, chunk.d().length);
+
+ for(Player p : Bukkit.getOnlinePlayers())
+ CraftbukkitWrapper.impl.sendChunk(p, x, z);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/MWTeam.java b/MissileWars/src/de/steamwar/misslewars/MWTeam.java
new file mode 100644
index 00000000..7d4224dc
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/MWTeam.java
@@ -0,0 +1,251 @@
+/*
+ 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.misslewars;
+
+import lombok.Getter;
+import org.bukkit.ChatColor;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.Damageable;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.scoreboard.Team;
+
+import java.util.*;
+
+public class MWTeam {
+ public static final ItemStack bow = new ItemStack(Material.BOW);
+
+ static {
+ ItemMeta bowMeta = Objects.requireNonNull(bow.getItemMeta());
+ bowMeta.addEnchant(Enchantment.ARROW_FIRE, 1, true);
+ bowMeta.addEnchant(Enchantment.ARROW_KNOCKBACK, 1, true);
+ bowMeta.addEnchant(Enchantment.KNOCKBACK, 1, true);
+ bowMeta.addEnchant(Enchantment.DAMAGE_ALL, 2, true);
+ bowMeta.setUnbreakable(true);
+ bow.setItemMeta(bowMeta);
+ }
+
+ private final String color;
+ private final String teamName;
+ private final Team sbteam; //scoreboard-Team
+ @Getter
+ private final Location spawn;
+ @Getter
+ private final int portalZ;
+
+ @Getter
+ private final LinkedList players = new LinkedList<>();
+ private final Set openInvitations = new HashSet<>();
+
+ MWTeam(String color, Location spawn, String teamName, int portalZ) {
+ this.teamName = teamName;
+ this.color = color;
+ this.spawn = spawn;
+ this.portalZ = portalZ;
+ if (FightScoreboard.getScoreboard().getTeam(teamName) == null)
+ sbteam = FightScoreboard.getScoreboard().registerNewTeam(teamName);
+ else
+ sbteam = FightScoreboard.getScoreboard().getTeam(teamName);
+ assert sbteam != null;
+ sbteam.setAllowFriendlyFire(false);
+ sbteam.setColor(ChatColor.getByChar(color.charAt(1)));
+ }
+
+ public void countdown(int timeDelay, int offset) {
+ if (players.isEmpty()) {
+ return;
+ }
+
+ int i = 0;
+ for (Player p : players) {
+ int time = timeDelay * (i + 1) - offset;
+ i++;
+
+ p.setExp(time / (float) Config.ItemTime);
+ p.setLevel(0);
+ }
+ }
+
+ private int getUsesOfItem(ItemStack itemStack) {
+ ItemMeta itemMeta = itemStack.getItemMeta();
+ if (itemMeta instanceof Damageable) {
+ Damageable damageable = (Damageable) itemMeta;
+ return itemStack.getType().getMaxDurability() - damageable.getDamage();
+ }
+ return 1_000_000;
+ }
+
+ private boolean hasUses(ItemStack itemStack) {
+ switch (itemStack.getType()) {
+ case WOODEN_AXE:
+ case STONE_AXE:
+ case IRON_AXE:
+ case GOLDEN_AXE:
+ case DIAMOND_AXE:
+ case NETHERITE_AXE:
+ // return true;
+ case WOODEN_SHOVEL:
+ case STONE_SHOVEL:
+ case IRON_SHOVEL:
+ case GOLDEN_SHOVEL:
+ case DIAMOND_SHOVEL:
+ case NETHERITE_SHOVEL:
+ // return true;
+ case WOODEN_PICKAXE:
+ case STONE_PICKAXE:
+ case IRON_PICKAXE:
+ case GOLDEN_PICKAXE:
+ case DIAMOND_PICKAXE:
+ case NETHERITE_PICKAXE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public void givePlayerItem(ItemStack item) {
+ if (players.isEmpty()) {
+ return;
+ }
+ Player p = players.removeFirst();
+ players.addLast(p);
+
+ Inventory inventory = p.getInventory();
+ for (int i = 0; i <= 35; i++) { // 35 is the last normal inventory slot
+ ItemStack itemStack = inventory.getItem(i);
+ if (itemStack == null) continue;
+ if (itemStack.isSimilar(item) && itemStack.getAmount() + item.getAmount() <= item.getMaxStackSize()) {
+ itemStack.setAmount(itemStack.getAmount() + item.getAmount());
+ inventory.setItem(i, itemStack);
+ return;
+ }
+ if (hasUses(itemStack) && hasUses(item) && getUsesOfItem(itemStack) + getUsesOfItem(item) <= itemStack.getType().getMaxDurability()) {
+ int uses = getUsesOfItem(itemStack) + getUsesOfItem(item);
+ ItemMeta itemMeta = itemStack.getItemMeta();
+ Damageable damageable = (Damageable) itemMeta;
+ damageable.setDamage(itemStack.getType().getMaxDurability() - uses);
+ itemStack.setItemMeta(damageable);
+ inventory.setItem(i, itemStack);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 35; i++) { // 35 is the last normal inventory slot
+ ItemStack itemStack = inventory.getItem(i);
+ if (itemStack == null || itemStack.getType().equals(Material.AIR)) {
+ inventory.setItem(i, item);
+ return;
+ }
+ }
+ }
+
+ public void teamScoreboard(HashMap data) {
+ players.forEach(player -> {
+ data.put(getColorCode() + player.getName(), 1);
+ });
+ }
+
+ public int size() {
+ return players.size();
+ }
+
+ public void join(Player p) {
+ players.add(p);
+ p.teleport(spawn);
+ p.setGameMode(GameMode.SURVIVAL);
+ p.getInventory().setItem(0, bow);
+ sbteam.addPlayer(p);
+ p.setDisplayName(color + p.getName());
+ if (MissileWars.getFightState() == FightState.WAITING && !enemy().players.isEmpty())
+ MissileWars.startRound();
+ }
+
+ public void leave(Player p) {
+ if (!players.contains(p)) return;
+
+ players.remove(p);
+ for (ItemStack stack : p.getInventory().getContents()) {
+ if (stack == null) continue;
+ if (stack.getType() == Material.AIR) continue;
+ if (stack.isSimilar(bow)) continue;
+ givePlayerItem(stack);
+ }
+
+ p.getInventory().clear();
+
+ p.setDisplayName("§7" + p.getName());
+ sbteam.removePlayer(p);
+ if (players.isEmpty() && MissileWars.getFightState() == FightState.FIGHTING)
+ MissileWars.end(WinReasons.NO_ENEMY, enemy());
+ }
+
+ public void reset() {
+ openInvitations.clear();
+
+ List tempPlayer = new ArrayList<>(players);
+ players.clear();
+ tempPlayer.forEach(player -> player.getInventory().clear());
+ tempPlayer.forEach(player -> player.setHealth(20.0));
+ tempPlayer.forEach(this::join);
+ }
+
+ public void invitePlayer(Player p) {
+ if (enemy().openInvitations.contains(p)) return;
+ openInvitations.add(p);
+ }
+
+ public void acceptInvite(Player p) {
+ removeInvitations(p);
+ join(p);
+ }
+
+ private MWTeam enemy() {
+ if (this == MissileWars.getRedTeam())
+ return MissileWars.getBlueTeam();
+
+ return MissileWars.getRedTeam();
+ }
+
+ public String getColorCode() {
+ return color;
+ }
+
+ public boolean hasPlayer(Player p) {
+ return players.contains(p);
+ }
+
+ public boolean hasInvite(Player p) {
+ return openInvitations.contains(p);
+ }
+
+ public String getColoredName() {
+ return color + teamName;
+ }
+
+ public static void removeInvitations(Player p) {
+ MissileWars.getRedTeam().openInvitations.remove(p);
+ MissileWars.getBlueTeam().openInvitations.remove(p);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/MissileWars.java b/MissileWars/src/de/steamwar/misslewars/MissileWars.java
new file mode 100644
index 00000000..2dab0597
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/MissileWars.java
@@ -0,0 +1,217 @@
+/*
+ This file is a part of the SteamWar software.
+
+ Copyright (C) 2023 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.misslewars;
+
+import de.steamwar.misslewars.commands.AcceptCommand;
+import de.steamwar.misslewars.commands.DeclineCommand;
+import de.steamwar.misslewars.commands.InviteCommand;
+import de.steamwar.misslewars.commands.SpectateCommand;
+import de.steamwar.misslewars.countdowns.EndCountdown;
+import de.steamwar.misslewars.countdowns.ItemCountdown;
+import de.steamwar.misslewars.countdowns.WaitingCountdown;
+import de.steamwar.misslewars.items.CustomItem;
+import de.steamwar.misslewars.items.Missile;
+import de.steamwar.misslewars.listener.*;
+import de.steamwar.misslewars.listener.special.BarrierListener;
+import de.steamwar.misslewars.listener.special.SpaceListener;
+import de.steamwar.misslewars.slowmo.SlowMoRunner;
+import de.steamwar.network.NetworkSender;
+import de.steamwar.network.packets.common.FightEndsPacket;
+import de.steamwar.sql.SteamwarUser;
+import org.bukkit.*;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+public class MissileWars extends JavaPlugin {
+ private static MissileWars plugin;
+ private static MWTeam redTeam; //red has South side -> spawns missles towards north
+ private static MWTeam blueTeam;
+ private static FightState fightState;
+
+ /**
+ * create teams, ect
+ */
+ @Override
+ public void onLoad() {
+ plugin = this;
+ fightState = FightState.WAITING;
+ }
+
+ @Override
+ public void onEnable() {
+ redTeam = new MWTeam(Config.TeamRedColor, Config.RedSpawn, Config.TeamRedName, Config.RedPortalZ);
+ blueTeam = new MWTeam(Config.TeamBlueColor, Config.BlueSpawn, Config.TeamBlueName, Config.BluePortalZ);
+ new BreakListener();
+ new DeathListener();
+ new ItemListener();
+ new ArenaListener();
+ new ConnectionListener();
+ new JoinListener();
+ new EndListener();
+ new PortalDestructListener();
+ new WaitingListener();
+ new FightListener();
+ new ChatListener();
+ new SpectateCommand();
+
+ // Invitation Commands
+ new InviteCommand();
+ new AcceptCommand();
+ new DeclineCommand();
+
+ new WaitingCountdown();
+ new ItemCountdown();
+ new EndCountdown();
+
+ new FightScoreboard();
+ Missile.init();
+ CustomItem.init();
+
+ StateDependent.setupState(fightState);
+
+ new BarrierListener();
+ new SpaceListener();
+
+ Bukkit.getScheduler().runTaskTimer(this, new FightInfoPacketSender(), 20, 20);
+
+ Bukkit.getWorlds().forEach(world -> {
+ world.setGameRule(GameRule.KEEP_INVENTORY, true);
+ world.setGameRule(GameRule.MOB_GRIEFING, true);
+ world.setGameRule(GameRule.DO_TILE_DROPS, false);
+ });
+
+ // TODO: Enable Item Dropping, and the own team can pick them up! Add config value for that?
+ }
+
+ public static void waiting() {
+ if (fightState == FightState.END) {
+ fightState = FightState.WAITING;
+ StateDependent.setupState(fightState);
+
+ SlowMoRunner.resetSlowMoTime();
+
+ Set uuidList = Bukkit.getOnlinePlayers().stream().map(Entity::getUniqueId).collect(Collectors.toSet());
+ if (!uuidList.contains(Config.RedLeader) || !uuidList.contains(Config.BlueLeader)) {
+ Config.RedLeader = null;
+ Config.BlueLeader = null;
+ }
+
+ redTeam.reset();
+ blueTeam.reset();
+ }
+ }
+
+ /**
+ * call to change fightstate from WAITING to INGAME
+ */
+ static void startRound() {
+ if (fightState != FightState.WAITING) // anti dual-call
+ return;
+ fightState = FightState.FIGHTING;
+ StateDependent.setupState(fightState);
+ }
+
+ /**
+ * Fight beenden
+ * @param reason Grund fürs ende
+ * @param winner Gewinner (oder null)
+ */
+ public static void end(WinReasons reason, MWTeam winner) {
+ if (fightState == FightState.END) //verhindern dass es mehrfach gecallt wird
+ return;
+ fightState = FightState.END;
+ StateDependent.setupState(fightState);
+
+ for(Player player : Bukkit.getOnlinePlayers()) {
+ player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_DEATH, 100f, 1f);
+ player.setGameMode(GameMode.SPECTATOR);
+ }
+
+ byte ergebnis = winner == blueTeam ? (byte) 1 : (byte) 2;
+ if (Config.isEvent()) {
+ Config.EventKampf.setErgebnis(ergebnis);
+ }
+ if (Config.isEvent() || Config.isChallenge()) {
+ FightEndsPacket packet = FightEndsPacket.builder()
+ .gameMode("MissileWars")
+ .duration((int)((System.currentTimeMillis() - FightScoreboard.getStartTime()) / 1000))
+ .win(ergebnis)
+ .bluePlayers(blueTeam.getPlayers().stream().map(Player::getUniqueId).map(SteamwarUser::get).map(SteamwarUser::getId).collect(Collectors.toList()))
+ .redPlayers(redTeam.getPlayers().stream().map(Player::getUniqueId).map(SteamwarUser::get).map(SteamwarUser::getId).collect(Collectors.toList()))
+ .blueSchem(-1)
+ .redSchem(-1)
+ .build();
+ NetworkSender.send(packet);
+ }
+
+ switch (reason) {
+ case PORTAL_DESTROYED:
+ Bukkit.getServer().broadcastMessage(winner.getColoredName() + ChatColor.RESET + " §7hat das gegnerische Portal zerstört");
+ break;
+ case NO_ENEMY:
+ default:
+ Bukkit.getServer().broadcastMessage("§7Team " + winner.getColoredName() + ChatColor.RESET + " §7hat aufgrund fehlenden Gegners gewonnen");
+ break;
+ }
+ }
+
+ public static MissileWars getPlugin() {
+ return plugin;
+ }
+
+ public static FightState getFightState() {
+ return fightState;
+ }
+
+ public static MWTeam getRedTeam() {
+ return redTeam;
+ }
+
+ public static MWTeam getBlueTeam() {
+ return blueTeam;
+ }
+
+ public static MWTeam getTeam(Player p) {
+ if(blueTeam.hasPlayer(p))
+ return blueTeam;
+ if(redTeam.hasPlayer(p))
+ return redTeam;
+ return null;
+ }
+
+ public static MWTeam getInvitation(Player p) {
+ if(blueTeam.hasInvite(p))
+ return blueTeam;
+ if(redTeam.hasInvite(p))
+ return redTeam;
+ return null;
+ }
+
+ public static void leave(Player p) {
+ MissileWars.getBlueTeam().leave(p);
+ MissileWars.getRedTeam().leave(p);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/SpawnPlatformCreator.java b/MissileWars/src/de/steamwar/misslewars/SpawnPlatformCreator.java
new file mode 100644
index 00000000..b9c222a1
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/SpawnPlatformCreator.java
@@ -0,0 +1,83 @@
+/*
+ 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.misslewars;
+
+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.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitTask;
+
+public class SpawnPlatformCreator {
+
+ private final Player player;
+ private final Location spawn;
+ private final BukkitTask task;
+
+ private Block currentBlock;
+ private int ticks;
+
+ public SpawnPlatformCreator(Player player){
+ this.player = player;
+ MWTeam team = MissileWars.getTeam(player);
+ if(team == null)
+ this.spawn = Config.BlueSpawn;
+ else
+ this.spawn = team.getSpawn();
+ ticks = Config.PlatformTime;
+ currentBlock = null;
+ task = Bukkit.getScheduler().runTaskTimer(MissileWars.getPlugin(), this::createPlatform, 0, 1);
+ }
+
+ private void createPlatform(){
+ Location playerLoc = player.getLocation();
+ playerLoc.setY(spawn.getY() - 1);
+
+ if(currentBlock == null || !currentBlock.getLocation().equals(playerLoc)){
+ if(currentBlock != null){
+ if(currentBlock.getType() == Material.OBSIDIAN)
+ currentBlock.setType(Material.AIR);
+ currentBlock = null;
+ }
+
+ Block newBlock = playerLoc.getBlock();
+ if(newBlock.getType() == Material.AIR){
+ newBlock.setType(Material.OBSIDIAN);
+ currentBlock = newBlock;
+ }
+ }
+
+ if(currentBlock != null && player.getLocation().getY() - 1 < currentBlock.getY())
+ player.teleport(playerLoc.add(0, 1, 0));
+
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("Spawnplattform§8: §c§l" + String.format("%.2f", ticks / 20f) + "§8s"));
+
+ if(ticks == 0){
+ if(currentBlock != null && currentBlock.getType() == Material.OBSIDIAN)
+ currentBlock.setType(Material.AIR);
+
+ task.cancel();
+ }
+ ticks--;
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/StateDependent.java b/MissileWars/src/de/steamwar/misslewars/StateDependent.java
new file mode 100644
index 00000000..155d824d
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/StateDependent.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.misslewars;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class StateDependent {
+ private static Set listeners = new HashSet<>();
+
+ private final Set active;
+ private boolean running;
+
+ public StateDependent(final Set active){
+ this.active = active;
+ running = false;
+ listeners.add(this);
+ }
+
+ public abstract void enable();
+ public abstract void disable();
+
+ static void setupState(FightState state){
+ if (state == FightState.FIGHTING) {
+ FightScoreboard.startTime();
+ }
+ for(StateDependent listener : listeners){
+ if(listener.running && !listener.active.contains(state)){
+ listener.disable();
+ listener.running = false;
+ }else if(!listener.running && listener.active.contains(state)){
+ listener.enable();
+ listener.running = true;
+ }
+ }
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/WinReasons.java b/MissileWars/src/de/steamwar/misslewars/WinReasons.java
new file mode 100644
index 00000000..ef52a173
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/WinReasons.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.misslewars;
+
+public enum WinReasons {
+ NO_ENEMY,
+ PORTAL_DESTROYED
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/commands/AcceptCommand.java b/MissileWars/src/de/steamwar/misslewars/commands/AcceptCommand.java
new file mode 100644
index 00000000..60b4b056
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/commands/AcceptCommand.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 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.misslewars.commands;
+
+import de.steamwar.command.SWCommand;
+import de.steamwar.command.TypeValidator;
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class AcceptCommand extends SWCommand {
+
+ public AcceptCommand() {
+ super("accept");
+ }
+
+ @Register
+ public void onCommand(@Validator Player player, String... varargs) {
+ MWTeam teamInvitation = MissileWars.getInvitation(player);
+ if (teamInvitation == null) {
+ player.sendMessage("§cDu wurdest nicht eingeladen.");
+ } else {
+ teamInvitation.acceptInvite(player);
+ message(teamInvitation, "§7Der Spieler §e" + player.getName() + "§7 ist dem Team §abeigetreten§7.");
+ }
+ }
+
+ @ClassValidator(value = Player.class, local = true)
+ public TypeValidator validator() {
+ return new TypeValidator() {
+ @Override
+ public boolean validate(CommandSender commandSender, Player player, MessageSender messageSender) {
+ if (!Config.isChallenge()) {
+ messageSender.send("§cDieser Command ist deaktiviert.");
+ return false;
+ }
+ return true;
+ }
+ };
+ }
+
+ @Override
+ protected void sendMessage(CommandSender sender, String message, Object[] args) {
+ sender.sendMessage(message);
+ }
+
+ private void message(MWTeam mwTeam, String s) {
+ mwTeam.getPlayers().forEach(player -> player.sendMessage(s));
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/commands/DeclineCommand.java b/MissileWars/src/de/steamwar/misslewars/commands/DeclineCommand.java
new file mode 100644
index 00000000..f0df4aa9
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/commands/DeclineCommand.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 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.misslewars.commands;
+
+import de.steamwar.command.SWCommand;
+import de.steamwar.command.TypeValidator;
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class DeclineCommand extends SWCommand {
+
+ public DeclineCommand() {
+ super("decline");
+ }
+
+ @Register
+ public void onCommand(@Validator Player player, String... varargs) {
+ MWTeam teamInvitation = MissileWars.getInvitation(player);
+ if (teamInvitation == null) {
+ player.sendMessage("§cDu wurdest nicht eingeladen.");
+ } else {
+ MWTeam.removeInvitations(player);
+ message(teamInvitation, "§7Der Spieler §e" + player.getName() + "§7 hat die Einladung §cabgelehnt§7.");
+ }
+ }
+
+ @ClassValidator(value = Player.class, local = true)
+ public TypeValidator validator() {
+ return new TypeValidator() {
+ @Override
+ public boolean validate(CommandSender commandSender, Player player, MessageSender messageSender) {
+ if (!Config.isChallenge()) {
+ messageSender.send("§cDieser Command ist deaktiviert.");
+ return false;
+ }
+ return true;
+ }
+ };
+ }
+
+ @Override
+ protected void sendMessage(CommandSender sender, String message, Object[] args) {
+ sender.sendMessage(message);
+ }
+
+ private void message(MWTeam mwTeam, String s) {
+ mwTeam.getPlayers().forEach(player -> player.sendMessage(s));
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/commands/InviteCommand.java b/MissileWars/src/de/steamwar/misslewars/commands/InviteCommand.java
new file mode 100644
index 00000000..b0925723
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/commands/InviteCommand.java
@@ -0,0 +1,99 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 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.misslewars.commands;
+
+import de.steamwar.command.PreviousArguments;
+import de.steamwar.command.SWCommand;
+import de.steamwar.command.TypeMapper;
+import de.steamwar.command.TypeValidator;
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+public class InviteCommand extends SWCommand {
+
+ public InviteCommand() {
+ super("invite", "inv");
+ }
+
+ @Register
+ public void onCommand(@Validator Player player, @AllowNull @OptionalValue("") Player invitedPlayer) {
+ MWTeam team = MissileWars.getTeam(player);
+
+ if (!player.getUniqueId().equals(Config.RedLeader) && !player.getUniqueId().equals(Config.BlueLeader) || team == null) {
+ player.sendMessage("§cDu kannst keine Spieler einladen.");
+ } else if (invitedPlayer == null) {
+ player.sendMessage("§cDieser Spieler ist nicht online.");
+ } else if (MissileWars.getTeam(invitedPlayer) != null) {
+ player.sendMessage("§cDieser Spieler ist bereits in einem Team.");
+ } else if (MissileWars.getInvitation(invitedPlayer) != null) {
+ player.sendMessage("§cDieser Spieler wurde bereits eingeladen.");
+ } else {
+ team.invitePlayer(invitedPlayer);
+ player.sendMessage("§7Du hast §e" + invitedPlayer.getName() + " §7eingeladen.");
+ invitedPlayer.sendMessage("§7Du wurdest von §e" + player.getName() + "§7 in das Team §e" + MissileWars.getTeam(player).getColoredName() + "§7 eingeladen.");
+ invitedPlayer.sendMessage("§8/§eaccept §8- §7Zum akzeptieren.");
+ invitedPlayer.sendMessage("§8/§edecline §8- §7Zum ablehnen.");
+ }
+ }
+
+ @ClassMapper(value = Player.class, local = true)
+ public TypeMapper typeMapper() {
+ return new TypeMapper<>() {
+ @Override
+ public Player map(CommandSender commandSender, String[] previousArguments, String s) {
+ return Bukkit.getPlayer(s);
+ }
+
+ @Override
+ public Collection tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
+ return Bukkit.getOnlinePlayers()
+ .stream()
+ .filter(p -> MissileWars.getTeam(p) != null)
+ .filter(p -> MissileWars.getInvitation(p) != null)
+ .map(Player::getName)
+ .collect(Collectors.toList());
+ }
+ };
+ }
+
+ @ClassValidator(value = Player.class, local = true)
+ public TypeValidator validator() {
+ return (commandSender, player, messageSender) -> {
+ if (!Config.isChallenge()) {
+ messageSender.send("§cDieser Command ist deaktiviert.");
+ return false;
+ }
+ return true;
+ };
+ }
+
+ @Override
+ protected void sendMessage(CommandSender sender, String message, Object[] args) {
+ sender.sendMessage(message);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/commands/SpectateCommand.java b/MissileWars/src/de/steamwar/misslewars/commands/SpectateCommand.java
new file mode 100644
index 00000000..f70fb063
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/commands/SpectateCommand.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 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.misslewars.commands;
+
+import de.steamwar.command.SWCommand;
+import de.steamwar.command.TypeValidator;
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.GameMode;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SpectateCommand extends SWCommand {
+
+ public SpectateCommand() {
+ super("spectate", "spec");
+ }
+
+ @Register
+ public void onCommand(@Validator Player player) {
+ MWTeam mwTeam = MissileWars.getTeam(player);
+ if (mwTeam == null) return;
+ if (mwTeam.size() == 1) {
+ player.sendMessage("§cDu bist alleine im Team, zuschauen ist daher nicht möglich.");
+ }
+ MissileWars.leave(player);
+ player.setGameMode(GameMode.SPECTATOR);
+ player.getInventory().clear();
+ player.updateInventory();
+ }
+
+ @ClassValidator(value = Player.class, local = true)
+ public TypeValidator validator() {
+ return new TypeValidator() {
+ @Override
+ public boolean validate(CommandSender commandSender, Player player, MessageSender messageSender) {
+ if (Config.isChallenge()) {
+ messageSender.send("§cDieser Command ist deaktiviert.");
+ return false;
+ }
+ return true;
+ }
+ };
+ }
+
+ @Override
+ protected void sendMessage(CommandSender sender, String message, Object[] args) {
+ sender.sendMessage(message);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.java b/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.java
new file mode 100644
index 00000000..292071a6
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.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.misslewars.countdowns;
+
+import de.steamwar.misslewars.*;
+import de.steamwar.misslewars.listener.JoinListener;
+import org.bukkit.Bukkit;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.EnumSet;
+
+public class EndCountdown extends StateDependent {
+
+ private BukkitTask task;
+
+ public EndCountdown() {
+ super(EnumSet.of(FightState.END));
+ }
+
+ @Override
+ public void enable() {
+ if (Config.isEvent()) {
+ task = Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), this::stop, 1200);
+ } else {
+ task = Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), this::restart, Config.EndTime);
+ }
+ }
+
+ private void restart() {
+ FightWorld.resetWorld();
+ MissileWars.waiting();
+ }
+
+ private void stop() {
+ //Staggered kick to prevent lobby overloading
+ if(Bukkit.getOnlinePlayers().isEmpty()){
+ Bukkit.shutdown();
+ return;
+ }
+
+ Bukkit.getOnlinePlayers().iterator().next().kickPlayer(null);
+ Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), this::stop, 10);
+ }
+
+ @Override
+ public void disable() {
+ if (task != null && !task.isCancelled())
+ task.cancel();
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/countdowns/ItemCountdown.java b/MissileWars/src/de/steamwar/misslewars/countdowns/ItemCountdown.java
new file mode 100644
index 00000000..5270934d
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/countdowns/ItemCountdown.java
@@ -0,0 +1,72 @@
+/*
+ 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.misslewars.countdowns;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.StateDependent;
+import de.steamwar.misslewars.items.SpecialItem;
+import org.bukkit.Bukkit;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.EnumSet;
+
+public class ItemCountdown extends StateDependent {
+
+ private BukkitTask task;
+ private int lastTime = 0;
+ private int currenTime = 0;
+
+ public ItemCountdown() {
+ super(EnumSet.of(FightState.FIGHTING));
+ }
+
+ private void run() {
+ currenTime++;
+
+ int teamCount = Math.max(MissileWars.getBlueTeam().size(), MissileWars.getRedTeam().size());
+ if (teamCount == 0) return;
+ int timeDelay = Config.ItemTime / teamCount;
+
+ if (lastTime + timeDelay < currenTime) {
+ lastTime = currenTime;
+
+ ItemStack itemStack = SpecialItem.getRandomItem();
+ MissileWars.getBlueTeam().givePlayerItem(itemStack);
+ MissileWars.getRedTeam().givePlayerItem(itemStack);
+ }
+
+ MissileWars.getBlueTeam().countdown(timeDelay, currenTime - lastTime);
+ MissileWars.getRedTeam().countdown(timeDelay, currenTime - lastTime);
+ }
+
+ @Override
+ public void enable() {
+ task = Bukkit.getScheduler().runTaskTimer(MissileWars.getPlugin(), this::run, 0, 1);
+ }
+
+ @Override
+ public void disable() {
+ if(task != null && !task.isCancelled())
+ task.cancel();
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/countdowns/WaitingCountdown.java b/MissileWars/src/de/steamwar/misslewars/countdowns/WaitingCountdown.java
new file mode 100644
index 00000000..57c85f77
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/countdowns/WaitingCountdown.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.misslewars.countdowns;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.StateDependent;
+import org.bukkit.Bukkit;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.EnumSet;
+
+public class WaitingCountdown extends StateDependent {
+
+ private BukkitTask task;
+
+ public WaitingCountdown() {
+ super(EnumSet.of(FightState.WAITING));
+ }
+
+ @Override
+ public void enable() {
+ task = Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), () -> {
+ if(Bukkit.getOnlinePlayers().isEmpty())
+ Bukkit.shutdown();
+ }, Config.WaitingTime);
+ }
+
+ @Override
+ public void disable() {
+ if(task != null && !task.isCancelled())
+ task.cancel();
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/items/CustomItem.java b/MissileWars/src/de/steamwar/misslewars/items/CustomItem.java
new file mode 100644
index 00000000..51c689b8
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/items/CustomItem.java
@@ -0,0 +1,84 @@
+/*
+ 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.misslewars.items;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.scripts.ScriptedItem;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Objects;
+
+public class CustomItem extends SpecialItem {
+
+ private ScriptedItem scriptedItem;
+
+ public CustomItem(ScriptedItem scriptedItem) {
+ this.scriptedItem = scriptedItem;
+ }
+
+ @Override
+ public ItemStack getItem() {
+ return scriptedItem.getItemStack();
+ }
+
+ @Override
+ public boolean handleUse(Player p) {
+ return scriptedItem.execute(ScriptedItem.EventType.onClick, p, p.getLocation());
+ }
+
+ @Override
+ public void handleThrow(Entity e) {
+ scriptedItem.execute(ScriptedItem.EventType.onThrow, e, e.getLocation());
+ }
+
+ @Override
+ public void handleHit(Entity e, Location l) {
+ scriptedItem.execute(ScriptedItem.EventType.onHit, e, l);
+ }
+
+ public static void init() {
+ File itemsFolder = new File(MissileWars.getPlugin().getDataFolder(), "items");
+ if (!itemsFolder.exists() || !itemsFolder.canRead() || !itemsFolder.isDirectory()) throw new SecurityException("Items could not be loaded");
+ for (File itemFile : Objects.requireNonNull(itemsFolder.listFiles())) {
+ if (!itemFile.canRead() || !itemFile.isFile()) continue;
+ try {
+ JsonObject jsonObject = new JsonParser().parse(new FileReader(itemFile)).getAsJsonObject();
+ new CustomItem(new ScriptedItem(jsonObject));
+ } catch (JsonSyntaxException | IOException e) {
+ e.printStackTrace();
+ throw new SecurityException("Item JSON error " + itemFile, e);
+ }
+ }
+ }
+
+ public ScriptedItem getScriptedItem() {
+ return scriptedItem;
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/items/Missile.java b/MissileWars/src/de/steamwar/misslewars/items/Missile.java
new file mode 100644
index 00000000..6e648e49
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/items/Missile.java
@@ -0,0 +1,135 @@
+/*
+ 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.misslewars.items;
+
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.bukkit.BukkitWorld;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
+import com.sk89q.worldedit.function.mask.BlockTypeMask;
+import com.sk89q.worldedit.function.operation.Operations;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.math.transform.AffineTransform;
+import com.sk89q.worldedit.session.ClipboardHolder;
+import com.sk89q.worldedit.world.World;
+import com.sk89q.worldedit.world.block.BlockTypes;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class Missile extends SpecialItem {
+
+ private static final World world = new BukkitWorld(Bukkit.getWorlds().get(0));
+
+ private final Clipboard clipboard;
+ private final ItemStack item;
+
+ private Missile(File missileFile) {
+ String[] strings = missileFile.getName().split("\\.");
+ String name = strings[0];
+ String material = strings[1];
+ if (!material.endsWith("_SPAWN_EGG")) material += "_SPAWN_EGG";
+ Material itemType = Material.valueOf(material);
+
+ ClipboardFormat format = ClipboardFormats.findByFile(missileFile);
+ try {
+ assert format != null;
+ clipboard = format.getReader(new FileInputStream(missileFile)).read();
+ } catch (IOException e) {
+ throw new SecurityException("Corrupt missile");
+ }
+
+ List lore = new ArrayList<>();
+ lore(lore, strings, 2, "§7Speed");
+ lore(lore, strings, 3, "§7Size");
+
+ EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
+ BlockTypeMask blockTypeMask = new BlockTypeMask(clipboard, BlockTypes.TNT);
+ lore.add("§7TNT §8: §e" + e.countBlocks(clipboard.getRegion(), blockTypeMask));
+
+ item = createItem(itemType, "§c" + name, 1, lore);
+ }
+
+ private void lore(List lore, String[] args, int index, String tag) {
+ if (args.length > index) {
+ lore.add(tag + " §8: §e" + Integer.parseInt(args[index]) + "§8/§77");
+ } else {
+ lore.add(tag + " §8: §e0§8/§77");
+ }
+ }
+
+ @Override
+ public ItemStack getItem() {
+ return item;
+ }
+
+ @Override
+ public boolean handleUse(Player p) {
+ BlockVector3 dimensions = clipboard.getDimensions();
+ Location location = p.getLocation();
+ BlockVector3 v = BlockVector3.ZERO;
+ BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
+ AffineTransform aT = new AffineTransform();
+
+ double yaw = (p.getLocation().getYaw() + 360f) % 360;
+ if (yaw > 45 && yaw <= 135) aT = aT.rotateY(270);
+ else if (yaw > 135 && yaw <= 225) aT = aT.rotateY(180);
+ else if (yaw > 225 && yaw <= 315) aT = aT.rotateY(90);
+
+ v = v.subtract(dimensions.getX()/2, dimensions.getY() + 2, -2).subtract(offset);
+ v = aT.apply(v.toVector3()).toBlockPoint();
+ v = v.add(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+
+ EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
+ ClipboardHolder ch = new ClipboardHolder(clipboard);
+ ch.setTransform(aT);
+ Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(true).build());
+ e.flushSession();
+ return true;
+ }
+
+ @Override
+ public boolean isMissile() {
+ return true;
+ }
+
+ public static void init() {
+ File missileFolder = new File(MissileWars.getPlugin().getDataFolder(), "missiles");
+ if (!missileFolder.exists() || !missileFolder.canRead() || !missileFolder.isDirectory()) throw new SecurityException("Missiles could not be loaded");
+ for (File missileFile : Objects.requireNonNull(missileFolder.listFiles())) {
+ if (!missileFile.canRead() || !missileFile.isFile()) continue;
+ if (!missileFile.getName().endsWith(".schem")) continue;
+ new Missile(missileFile);
+ }
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/items/SpecialItem.java b/MissileWars/src/de/steamwar/misslewars/items/SpecialItem.java
new file mode 100644
index 00000000..de8b6847
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/items/SpecialItem.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.misslewars.items;
+
+import de.steamwar.misslewars.Config;
+import net.md_5.bungee.api.ChatMessageType;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.ProjectileHitEvent;
+import org.bukkit.event.entity.ProjectileLaunchEvent;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.potion.PotionEffectType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public abstract class SpecialItem {
+
+ private static final Random random = new Random();
+ private static double count = 0;
+ private static int consecutiveSupportItems = 0;
+
+ private static List supportItems = new ArrayList<>();
+ private static List missileItems = new ArrayList<>();
+
+ SpecialItem() {
+ if (this.isMissile()) missileItems.add(this);
+ else supportItems.add(this);
+ }
+
+ private String materialName = null;
+ public abstract ItemStack getItem();
+ public abstract boolean handleUse(Player p);
+ public void handleThrow(Entity e) {}
+ public void handleHit(Entity e, Location l) {}
+ public boolean isMissile() {
+ return false;
+ }
+
+ public ItemStack createItem(Material material, String name, int amount, List lore) {
+ ItemStack item = new ItemStack(material, amount);
+ ItemMeta meta = item.getItemMeta();
+ assert meta != null;
+ meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
+ meta.setLore(lore);
+ meta.setDisplayName(name);
+ item.setItemMeta(meta);
+ return item;
+ }
+
+ public static boolean handleUse(ItemStack item, Player player) {
+ if (player.hasPotionEffect(PotionEffectType.LEVITATION)) {
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("§cDu kannst dieses Item derzeit nicht nutzen!"));
+ return false;
+ }
+ return handleUse(item, player, missileItems) || handleUse(item, player, supportItems);
+ }
+
+ private static boolean handleUse(ItemStack item, Player player, List items) {
+ for (SpecialItem specialItem : items)
+ if (item.isSimilar(specialItem.getItem())) return specialItem.handleUse(player);
+ return false;
+ }
+
+ public static void handleThrow(ProjectileLaunchEvent e) {
+ String name = e.getEntity().getClass().getName().toLowerCase();
+ for (SpecialItem specialItem : supportItems) {
+ if (specialItem.materialName == null)
+ specialItem.materialName = specialItem.getItem().getType().name().toLowerCase();
+ if (name.contains(specialItem.materialName))
+ specialItem.handleThrow(e.getEntity());
+ }
+ }
+
+ public static void handleHit(ProjectileHitEvent e) {
+ String name = e.getEntity().getClass().getName().toLowerCase();
+
+ Location location = null;
+ if (e.getHitEntity() != null) location = e.getHitEntity().getLocation();
+ else if (e.getHitBlock() != null) location = e.getHitBlock().getLocation();
+ if (location == null) return;
+
+ for (SpecialItem specialItem : supportItems) {
+ if (name.contains(((CustomItem) specialItem).getScriptedItem().getEntityName())) {
+ specialItem.handleHit(e.getEntity(), location);
+ }
+ }
+ }
+
+ public static ItemStack getRandomItem() {
+ if (Config.MissileChance == 0 || consecutiveSupportItems > 1) {
+ consecutiveSupportItems = 0;
+ return supportItems.get(random.nextInt(supportItems.size())).getItem();
+ }
+ if (Config.MissileChance == 1) {
+ return missileItems.get(random.nextInt(missileItems.size())).getItem();
+ }
+
+ double missileChance = Config.MissileChance + count * 0.1;
+ if (random.nextDouble() > missileChance) {
+ count += Config.MissileChance;
+ consecutiveSupportItems++;
+ return supportItems.get(random.nextInt(supportItems.size())).getItem();
+ } else {
+ count -= 1 - Config.MissileChance;
+ return missileItems.get(random.nextInt(missileItems.size())).getItem();
+ }
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/ArenaListener.java b/MissileWars/src/de/steamwar/misslewars/listener/ArenaListener.java
new file mode 100644
index 00000000..4d7a7ecc
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/ArenaListener.java
@@ -0,0 +1,88 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityPickupItemEvent;
+import org.bukkit.event.entity.FoodLevelChangeEvent;
+import org.bukkit.event.entity.ItemDespawnEvent;
+import org.bukkit.event.inventory.InventoryOpenEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.player.PlayerDropItemEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerPickupArrowEvent;
+
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Objects;
+
+public class ArenaListener extends BasicListener {
+
+ public ArenaListener() {
+ super(EnumSet.allOf(FightState.class));
+ }
+
+ @EventHandler
+ public void onMove(PlayerMoveEvent e) {
+ Location location = e.getTo();
+ Player p = e.getPlayer();
+
+ assert location != null;
+ if(location.getY() < Config.ArenaMinY){
+ if(p.getGameMode() == GameMode.SPECTATOR)
+ p.teleport(e.getFrom());
+ else if(MissileWars.getFightState() == FightState.WAITING)
+ p.teleport(Objects.requireNonNull(MissileWars.getTeam(p)).getSpawn());
+ else
+ p.damage(20.0f);
+ }else if(
+ location.getX() < Config.ArenaMinX ||
+ location.getX() > Config.ArenaMaxX ||
+ location.getZ() < Config.ArenaMinZ ||
+ location.getZ() > Config.ArenaMaxZ){
+ p.teleport(e.getFrom());
+ }
+ }
+
+ @EventHandler
+ public void onArrowPickup(PlayerPickupArrowEvent e){
+ e.setCancelled(true);
+ }
+
+ @EventHandler
+ public void onHunger(FoodLevelChangeEvent e){
+ e.setCancelled(true);
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onInventoryOpen(InventoryOpenEvent event) {
+ if(event.getView().getType() != InventoryType.PLAYER &&
+ event.getView().getType() != InventoryType.CRAFTING &&
+ event.getView().getType() != InventoryType.CREATIVE)
+ event.setCancelled(true);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/BasicListener.java b/MissileWars/src/de/steamwar/misslewars/listener/BasicListener.java
new file mode 100644
index 00000000..b210216e
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/BasicListener.java
@@ -0,0 +1,47 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.StateDependent;
+import org.bukkit.Bukkit;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+
+import java.util.Set;
+
+public abstract class BasicListener extends StateDependent implements Listener {
+
+
+ protected BasicListener(final Set active){
+ super(active);
+ }
+
+ @Override
+ public void enable(){
+ Bukkit.getPluginManager().registerEvents(this, MissileWars.getPlugin());
+ }
+
+ @Override
+ public void disable(){
+ HandlerList.unregisterAll(this);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/BreakListener.java b/MissileWars/src/de/steamwar/misslewars/listener/BreakListener.java
new file mode 100644
index 00000000..bbaf1a65
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/BreakListener.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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.block.BlockBreakEvent;
+
+import java.util.EnumSet;
+
+public class BreakListener extends BasicListener {
+
+ public BreakListener() {
+ super(EnumSet.of(FightState.WAITING));
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onBlockBreak(BlockBreakEvent event) {
+ event.setCancelled(true);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/ChatListener.java b/MissileWars/src/de/steamwar/misslewars/listener/ChatListener.java
new file mode 100644
index 00000000..3e039b7b
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/ChatListener.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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+
+import java.util.EnumSet;
+
+public class ChatListener extends BasicListener {
+
+ public ChatListener() {
+ super(EnumSet.allOf(FightState.class));
+ }
+
+ @EventHandler
+ public void onChat(AsyncPlayerChatEvent e) {
+ e.setCancelled(true);
+
+ Player p = e.getPlayer();
+ MWTeam team = MissileWars.getTeam(p);
+ String message = e.getPlayer().getDisplayName() + "§8» §7" + e.getMessage();
+ if (team == null) {
+ Bukkit.broadcastMessage(message);
+ } else {
+ if (e.getMessage().startsWith("+")) {
+ String teamMessage = "§8[" + team.getColorCode() + "TEAM§8] " + e.getPlayer().getDisplayName() + "§8» §7" + e.getMessage().substring(1);
+ team.getPlayers().forEach(player -> player.sendMessage(teamMessage));
+ } else {
+ Bukkit.broadcastMessage(message);
+ }
+ }
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/ConnectionListener.java b/MissileWars/src/de/steamwar/misslewars/listener/ConnectionListener.java
new file mode 100644
index 00000000..dab36fa4
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/ConnectionListener.java
@@ -0,0 +1,61 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+import java.util.EnumSet;
+
+public class ConnectionListener extends BasicListener{
+
+ public ConnectionListener(){
+ super(EnumSet.allOf(FightState.class));
+ }
+
+ @EventHandler(priority = EventPriority.HIGH)
+ public void onJoin(PlayerJoinEvent e) {
+ e.getPlayer().setDisplayName("§7" + e.getPlayer().getName());
+ e.getPlayer().setGameMode(GameMode.SPECTATOR);
+ e.getPlayer().teleport(MissileWars.getRedTeam().getSpawn().toVector().midpoint(MissileWars.getBlueTeam().getSpawn().toVector()).toLocation(e.getPlayer().getWorld()));
+ if(Config.test()) {
+ e.getPlayer().setOp(true);
+ }
+ }
+
+ @EventHandler
+ public void onLeave(PlayerQuitEvent e) {
+ MWTeam.removeInvitations(e.getPlayer());
+ MissileWars.leave(e.getPlayer());
+
+ if (Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().contains(e.getPlayer()) && Bukkit.getOnlinePlayers().size() == 1)) {
+ Bukkit.shutdown();
+ }
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/DeathListener.java b/MissileWars/src/de/steamwar/misslewars/listener/DeathListener.java
new file mode 100644
index 00000000..5e77523a
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/DeathListener.java
@@ -0,0 +1,89 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.SpawnPlatformCreator;
+import net.md_5.bungee.api.ChatMessageType;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.util.Vector;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DeathListener extends BasicListener {
+
+ private static final Vector ZERO = new Vector(0, 0, 0);
+ private final Set respawnedPlayers = new HashSet<>();
+
+ public DeathListener() {
+ super(EnumSet.allOf(FightState.class));
+ }
+
+ @EventHandler
+ public void onDeath(PlayerDeathEvent e) {
+ e.setDeathMessage(null);
+ if(Bukkit.getOnlinePlayers().size() > 10) {
+ for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
+ onlinePlayer.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(e.getEntity().getDisplayName() + " §cstarb"));
+ }
+ } else {
+ Bukkit.broadcastMessage(e.getEntity().getDisplayName() + " §cstarb");
+ }
+ }
+
+ @EventHandler
+ public void onRespawn(PlayerRespawnEvent e){
+ Player p = e.getPlayer();
+ p.setFireTicks(0);
+ MWTeam team = MissileWars.getTeam(p);
+ if(team == null)
+ return;
+
+ e.setRespawnLocation(team.getSpawn());
+ e.getPlayer().setVelocity(ZERO);
+ respawnedPlayers.add(p);
+ }
+
+ @EventHandler
+ public void onPlayerMove(PlayerMoveEvent event) {
+ if (respawnedPlayers.isEmpty()) return;
+ Player player = event.getPlayer();
+ if (!respawnedPlayers.contains(player)) return;
+ respawnedPlayers.remove(player);
+ new SpawnPlatformCreator(player);
+ }
+
+ @EventHandler
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ respawnedPlayers.remove(event.getPlayer());
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/EndListener.java b/MissileWars/src/de/steamwar/misslewars/listener/EndListener.java
new file mode 100644
index 00000000..14833544
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/EndListener.java
@@ -0,0 +1,40 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import org.bukkit.GameMode;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+import java.util.EnumSet;
+
+public class EndListener extends BasicListener {
+
+ public EndListener(){
+ super(EnumSet.of(FightState.END));
+ }
+
+ @EventHandler
+ public void onJoin(PlayerJoinEvent e) {
+ e.setJoinMessage(null);
+ e.getPlayer().setGameMode(GameMode.SPECTATOR);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/FightListener.java b/MissileWars/src/de/steamwar/misslewars/listener/FightListener.java
new file mode 100644
index 00000000..7ed369f8
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/FightListener.java
@@ -0,0 +1,47 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+
+import java.util.EnumSet;
+
+public class FightListener extends BasicListener {
+
+ public FightListener() {
+ super(EnumSet.of(FightState.FIGHTING));
+ }
+
+ @EventHandler
+ public void onDamage(EntityDamageByEntityEvent e){
+ if(!(e.getDamager() instanceof Player && e.getEntity() instanceof Player))
+ return;
+
+ Player damager = (Player)e.getDamager();
+ Player reciever = (Player)e.getEntity();
+
+ if(MissileWars.getTeam(damager) == MissileWars.getTeam(reciever))
+ e.setCancelled(true);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/ItemListener.java b/MissileWars/src/de/steamwar/misslewars/listener/ItemListener.java
new file mode 100644
index 00000000..4856dc17
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/ItemListener.java
@@ -0,0 +1,123 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MWTeam;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.items.SpecialItem;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityPickupItemEvent;
+import org.bukkit.event.entity.ItemDespawnEvent;
+import org.bukkit.event.entity.ProjectileHitEvent;
+import org.bukkit.event.entity.ProjectileLaunchEvent;
+import org.bukkit.event.player.PlayerDropItemEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ItemListener extends BasicListener {
+
+ private Set RED_ITEMS = new HashSet<>();
+ private Set BLUE_ITEMS = new HashSet<>();
+
+ public ItemListener() {
+ super(EnumSet.of(FightState.FIGHTING));
+ }
+
+ @Override
+ public void enable() {
+ super.enable();
+ RED_ITEMS.clear();
+ BLUE_ITEMS.clear();
+ }
+
+ @EventHandler
+ public void onItemClick(PlayerInteractEvent e) {
+ ItemStack item = e.getItem();
+ if (item == null)
+ return;
+ if (e.getPlayer().hasCooldown(item.getType())) return;
+
+ if (e.getAction() != Action.RIGHT_CLICK_BLOCK && e.getAction() != Action.RIGHT_CLICK_AIR)
+ return;
+
+ if (SpecialItem.handleUse(item, e.getPlayer()) && item.getType() != Material.SPLASH_POTION) {
+ item.setAmount(item.getAmount()-1);
+ e.getPlayer().updateInventory();
+ e.setCancelled(true);
+ }
+ }
+
+ @EventHandler
+ public void onThrow(ProjectileLaunchEvent e) {
+ SpecialItem.handleThrow(e);
+ }
+
+ @EventHandler
+ public void onHit(ProjectileHitEvent e) {
+ SpecialItem.handleHit(e);
+ }
+
+ @EventHandler
+ public void onItemDrop(PlayerDropItemEvent e){
+ MWTeam mwTeam = MissileWars.getTeam(e.getPlayer());
+ if (mwTeam == null) {
+ e.setCancelled(true);
+ return;
+ }
+ if (e.getItemDrop().getItemStack().isSimilar(MWTeam.bow)) {
+ e.setCancelled(true);
+ return;
+ }
+ if (mwTeam == MissileWars.getRedTeam()) {
+ RED_ITEMS.add(e.getItemDrop().getEntityId());
+ } else {
+ BLUE_ITEMS.add(e.getItemDrop().getEntityId());
+ }
+ }
+
+ @EventHandler
+ public void onEntityPickupItem(EntityPickupItemEvent e) {
+ Player player = (Player) e.getEntity();
+ MWTeam mwTeam = MissileWars.getTeam(player);
+ if (mwTeam == null) {
+ e.setCancelled(true);
+ return;
+ }
+ if (mwTeam == MissileWars.getRedTeam() && !RED_ITEMS.contains(e.getItem().getEntityId())) {
+ e.setCancelled(true);
+ } else if (mwTeam == MissileWars.getBlueTeam() && !BLUE_ITEMS.contains(e.getItem().getEntityId())) {
+ e.setCancelled(true);
+ }
+ }
+
+ @EventHandler
+ public void onItemDespawn(ItemDespawnEvent event) {
+ RED_ITEMS.remove(event.getEntity().getEntityId());
+ BLUE_ITEMS.remove(event.getEntity().getEntityId());
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/JoinListener.java b/MissileWars/src/de/steamwar/misslewars/listener/JoinListener.java
new file mode 100644
index 00000000..5947da8f
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/JoinListener.java
@@ -0,0 +1,101 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.sql.SteamwarUser;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+import java.util.EnumSet;
+
+public class JoinListener extends BasicListener {
+
+ public JoinListener(){
+ super(EnumSet.of(FightState.WAITING, FightState.FIGHTING));
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onJoin(PlayerJoinEvent e){
+ e.setJoinMessage("§a» " + e.getPlayer().getDisplayName());
+ join(e.getPlayer());
+ }
+
+ public static void join(Player p) {
+ if (Config.isEvent()) {
+ joinEvent(p);
+ return;
+ }
+
+ if (Config.isChallenge()) {
+ joinChallenge(p);
+ return;
+ }
+
+ joinNormal(p);
+ }
+
+ private static void joinEvent(Player p) {
+ if (Config.EventTeamRedID == 0 && Config.EventTeamBlueID == 0) {
+ joinNormal(p);
+ return;
+ }
+
+ int teamId = SteamwarUser.get(p.getUniqueId()).getTeam();
+ if (teamId != Config.EventTeamRedID && teamId != Config.EventTeamBlueID) {
+ teamId = 0;
+ }
+ if (teamId == Config.EventTeamRedID && MissileWars.getRedTeam().size() < Config.MaximumTeamMembers) {
+ MissileWars.getRedTeam().join(p);
+ } else if (teamId == Config.EventTeamBlueID && MissileWars.getBlueTeam().size() < Config.MaximumTeamMembers) {
+ MissileWars.getBlueTeam().join(p);
+ } else {
+ p.teleport(MissileWars.getRedTeam().getSpawn().toVector().midpoint(MissileWars.getBlueTeam().getSpawn().toVector()).toLocation(p.getWorld()));
+ }
+ }
+
+ private static void joinChallenge(Player p) {
+ if (Config.RedLeader.equals(p.getUniqueId())) {
+ MissileWars.getRedTeam().join(p);
+ } else if (Config.BlueLeader.equals(p.getUniqueId())) {
+ MissileWars.getBlueTeam().join(p);
+ } else {
+ p.teleport(MissileWars.getRedTeam().getSpawn().toVector().midpoint(MissileWars.getBlueTeam().getSpawn().toVector()).toLocation(p.getWorld()));
+ }
+ }
+
+ private static void joinNormal(Player p) {
+ if (MissileWars.getRedTeam().size() == MissileWars.getBlueTeam().size()) {
+ if (Math.random() > 0.5) {
+ MissileWars.getRedTeam().join(p);
+ } else {
+ MissileWars.getBlueTeam().join(p);
+ }
+ } else if (MissileWars.getRedTeam().size() < MissileWars.getBlueTeam().size()) {
+ MissileWars.getRedTeam().join(p);
+ } else {
+ MissileWars.getBlueTeam().join(p);
+ }
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/PortalDestructListener.java b/MissileWars/src/de/steamwar/misslewars/listener/PortalDestructListener.java
new file mode 100644
index 00000000..c235ff35
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/PortalDestructListener.java
@@ -0,0 +1,62 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.WinReasons;
+import org.bukkit.Material;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.block.BlockPhysicsEvent;
+import org.bukkit.event.entity.EntityExplodeEvent;
+
+import java.util.EnumSet;
+
+public class PortalDestructListener extends BasicListener {
+
+ public PortalDestructListener(){
+ super(EnumSet.of(FightState.FIGHTING));
+ }
+
+ @EventHandler
+ public void onBlockupdate(BlockPhysicsEvent e) {
+ if (e.getBlock().getType() != Material.NETHER_PORTAL)
+ return;
+ int z = e.getBlock().getZ();
+ if (z == MissileWars.getRedTeam().getPortalZ())
+ MissileWars.end(WinReasons.PORTAL_DESTROYED, MissileWars.getBlueTeam());
+ if (z == MissileWars.getBlueTeam().getPortalZ())
+ MissileWars.end(WinReasons.PORTAL_DESTROYED, MissileWars.getRedTeam());
+ }
+
+ @EventHandler
+ public void onExplosion(EntityExplodeEvent e){
+ if(e.getEntityType() != EntityType.FIREBALL)
+ return;
+
+ double z = e.getLocation().getZ();
+ double distRed = Math.abs(Config.RedPortalZ + 0.5 - z);
+ double distBlue = Math.abs(Config.BluePortalZ + 0.5 - z);
+ if(distRed < 2 || distBlue < 2)
+ e.setCancelled(true);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/WaitingListener.java b/MissileWars/src/de/steamwar/misslewars/listener/WaitingListener.java
new file mode 100644
index 00000000..1180edc3
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/WaitingListener.java
@@ -0,0 +1,47 @@
+/*
+ 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.misslewars.listener;
+
+import de.steamwar.misslewars.FightState;
+import org.bukkit.Bukkit;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+import java.util.EnumSet;
+
+public class WaitingListener extends BasicListener {
+ public WaitingListener() {
+ super(EnumSet.of(FightState.WAITING));
+ }
+
+ @EventHandler
+ public void onDisconnect(PlayerQuitEvent e){
+ if (Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().contains(e.getPlayer()) && Bukkit.getOnlinePlayers().size() == 1)) {
+ Bukkit.shutdown();
+ }
+ }
+
+ @EventHandler
+ public void onDamage(EntityDamageEvent e){
+ if(e.getCause() != EntityDamageEvent.DamageCause.VOID)
+ e.setCancelled(true);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/special/BarrierListener.java b/MissileWars/src/de/steamwar/misslewars/listener/special/BarrierListener.java
new file mode 100644
index 00000000..5220778c
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/special/BarrierListener.java
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.misslewars.listener.special;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.listener.BasicListener;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.block.BlockPhysicsEvent;
+
+import java.util.EnumSet;
+
+public class BarrierListener extends BasicListener {
+
+ public BarrierListener() {
+ super(EnumSet.allOf(FightState.class));
+ }
+
+ private int middle = Config.ArenaMinZ + (Config.ArenaMaxZ - Config.ArenaMinZ) / 2;
+
+ @EventHandler
+ public void onBlockPhysics(BlockPhysicsEvent event) {
+ if (!Config.Barrier) return;
+ Block block = event.getBlock();
+ if (block.getZ() > middle - 10 && block.getZ() < middle + 10) {
+ switch (block.getType()) {
+ case SLIME_BLOCK:
+ case HONEY_BLOCK:
+ case TNT:
+ block.setType(Material.AIR);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/listener/special/SpaceListener.java b/MissileWars/src/de/steamwar/misslewars/listener/special/SpaceListener.java
new file mode 100644
index 00000000..654811ab
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/listener/special/SpaceListener.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * 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.misslewars.listener.special;
+
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.FightState;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.listener.BasicListener;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.TNTPrimed;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntitySpawnEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.util.Vector;
+
+import java.util.EnumSet;
+
+public class SpaceListener extends BasicListener {
+
+ public SpaceListener() {
+ super(EnumSet.allOf(FightState.class));
+ }
+
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ if (!Config.Space) return;
+ Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), () -> {
+ Player player = event.getPlayer();
+ player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 3));
+ player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, Integer.MAX_VALUE, 3));
+ player.setHealth(0.5);
+ player.setHealthScale(0.5);
+ }, 5);
+ }
+
+ @EventHandler
+ public void onPlayerRespawn(PlayerRespawnEvent event) {
+ if (!Config.Space) return;
+ Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), () -> {
+ Player player = event.getPlayer();
+ player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 3));
+ player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, Integer.MAX_VALUE, 3));
+ player.setHealth(0.5);
+ player.setHealthScale(0.5);
+ }, 5);
+ }
+
+ @EventHandler
+ public void onEntitySpawn(EntitySpawnEvent event) {
+ if (!Config.Space) return;
+ if (event.getEntity() instanceof Player) return;
+ event.getEntity().setGravity(false);
+ Vector vector = event.getEntity().getVelocity();
+ if (event.getEntity() instanceof TNTPrimed) {
+ vector.setY(0);
+ }
+ event.getEntity().setVelocity(vector);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/RunnableScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/RunnableScript.java
new file mode 100644
index 00000000..5328bc31
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/RunnableScript.java
@@ -0,0 +1,35 @@
+/*
+ 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.misslewars.scripts;
+
+import java.util.function.UnaryOperator;
+
+public interface RunnableScript {
+ boolean execute(RunnableScriptEvent runnableScriptEvent);
+
+ interface ScriptFunction {
+ boolean execute(RunnableScriptEvent runnableScriptEvent, double... doubles);
+ }
+
+ default boolean defaultExecution(ScriptFunction scriptFunction, boolean nullReturn, UnaryOperator returnValue, RunnableScriptEvent runnableScriptEvent, double... doubles) {
+ if (scriptFunction == null) return nullReturn;
+ return returnValue.apply(scriptFunction.execute(runnableScriptEvent, doubles));
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/RunnableScriptEvent.java b/MissileWars/src/de/steamwar/misslewars/scripts/RunnableScriptEvent.java
new file mode 100644
index 00000000..8459f559
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/RunnableScriptEvent.java
@@ -0,0 +1,82 @@
+/*
+ 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.misslewars.scripts;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public class RunnableScriptEvent {
+
+ public enum LocationType {
+ STATIC,
+ DYNAMIC,
+ DEFAULT,
+ CUSTOM
+ }
+
+ public final ScriptedItem.EventType eventType;
+ public final Entity entity;
+ private final Location location;
+ private Location customLocation;
+ private LocationType locationType = LocationType.DEFAULT;
+ Script.ScriptExecutor scriptExecutor = null;
+
+ public RunnableScriptEvent(ScriptedItem.EventType eventType, Entity entity, Location location) {
+ this.eventType = eventType;
+ this.entity = entity;
+ this.location = location;
+ }
+
+ public Location getLocation() {
+ // Custom location
+ if (locationType == LocationType.CUSTOM && customLocation != null) return customLocation;
+
+ // Static initial Location
+ if (locationType == LocationType.STATIC) return location;
+
+ // Dynamic Location if entity is not null
+ if (locationType == LocationType.DYNAMIC) return entity != null ? entity.getLocation() : location;
+
+ // Default Location is static if EventType is onClick otherwise dynamic
+ if (eventType == ScriptedItem.EventType.onClick) return location;
+ if (entity != null) return entity.getLocation();
+ return location;
+ }
+
+ public void setLocationType(LocationType locationType) {
+ if (locationType == null) return;
+ this.locationType = locationType;
+ }
+
+ public void setCustomLocation(double x, double y, double z, float pitch, float yaw) {
+ this.customLocation = new Location(location.getWorld(), x, y, z, yaw, pitch);
+ }
+
+ public Player getPlayer() {
+ return (Player) entity;
+ }
+
+ public void resumeScriptExecution() {
+ if (scriptExecutor == null) return;
+ scriptExecutor.resume();
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/Script.java b/MissileWars/src/de/steamwar/misslewars/scripts/Script.java
new file mode 100644
index 00000000..095dfaf3
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/Script.java
@@ -0,0 +1,97 @@
+/*
+ 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.misslewars.scripts;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.implemented.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Script {
+
+ private List runnableScriptList = new ArrayList<>();
+
+ class ScriptExecutor {
+
+ private int index = 0;
+ private final RunnableScriptEvent runnableScriptEvent;
+
+ public ScriptExecutor(RunnableScriptEvent runnableScriptEvent) {
+ this.runnableScriptEvent = runnableScriptEvent;
+ runnableScriptEvent.scriptExecutor = this;
+ resume();
+ }
+
+ void resume() {
+ while (index < runnableScriptList.size()) {
+ if (!runnableScriptList.get(index++).execute(runnableScriptEvent)) return;
+ }
+ }
+ }
+
+ public void execute(RunnableScriptEvent runnableScriptEvent) {
+ new ScriptExecutor(runnableScriptEvent);
+ }
+
+ public static Script parseScript(JsonArray jsonArray) {
+ Script script = new Script();
+ jsonArray.forEach(jsonElement -> {
+ RunnableScript runnableScript = parseScriptSnippet((JsonObject) jsonElement);
+ if (runnableScript == null) return;
+ script.runnableScriptList.add(runnableScript);
+ });
+ return script;
+ }
+
+ private static RunnableScript parseScriptSnippet(JsonObject jsonObject) {
+ if (!jsonObject.has("type")) return null;
+ switch (jsonObject.getAsJsonPrimitive("type").getAsString().toLowerCase()) {
+ case "delay":
+ return new DelayScript(jsonObject);
+ case "filter":
+ return new FilterScript(jsonObject);
+ case "remove":
+ return new RemoveScript(jsonObject);
+ case "launch":
+ return new LaunchScript(jsonObject);
+ case "location":
+ return new LocationScript(jsonObject);
+ case "paste":
+ return new PasteScript(jsonObject);
+ case "potion":
+ return new PotionScript(jsonObject);
+ case "sound":
+ return new SoundScript(jsonObject);
+ case "summon":
+ return new SummonScript(jsonObject);
+ case "slowmo":
+ return new SlowMoScript(jsonObject);
+ case "cooldown":
+ return new CooldownScript(jsonObject);
+ case "randomplayer":
+ return new RandomPlayerScript(jsonObject);
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/ScriptedItem.java b/MissileWars/src/de/steamwar/misslewars/scripts/ScriptedItem.java
new file mode 100644
index 00000000..4e1587d6
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/ScriptedItem.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.misslewars.scripts;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.utils.JsonUtils;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LingeringPotion;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.Damageable;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.PotionMeta;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getString;
+
+public class ScriptedItem {
+
+ // "type": Material name (STRING)
+ // "name": Item name (STRING)
+ // "lore": Lore array (OPTIONAL STRING.ARRAY)
+ // "amount": Item amount (OPTIONAL [default 1] INT)
+ // "potion": Object with key value pairs for PotionType and Object containing duration and amplifier (OPTIONAL OBJECT)
+ // "uses": Uses of Item (OPTIONAL INT)
+ // "EVENT.": Event (OPTIONAL JSONobject.ARRAY)
+ // - onClick
+ // - onHit
+ // - onThrow
+
+ public enum EventType {
+ onHit,
+ onThrow,
+ onClick
+ }
+
+ private Map scriptMap = new HashMap<>();
+ private String entityName = "";
+
+ private ItemStack itemStack;
+
+ public ScriptedItem(JsonObject jsonObject) {
+ itemStack = createItemStack(jsonObject);
+
+ getString(jsonObject, "entityName", string -> entityName = string);
+
+ for (EventType eventType : EventType.values()) {
+ String eventString = "EVENT." + eventType.name();
+ if (!jsonObject.has(eventString) || !jsonObject.get(eventString).isJsonArray()) continue;
+ scriptMap.put(eventType, Script.parseScript(jsonObject.getAsJsonArray(eventString)));
+ }
+ }
+
+ private static ItemStack createItemStack(JsonObject jsonObject) {
+ ItemStack itemStack = new ItemStack(Material.valueOf(getString(jsonObject, "type", "")), JsonUtils.getInt(jsonObject, "amount", 1));
+ ItemMeta itemMeta = itemStack.getItemMeta();
+ if (itemMeta == null) return itemStack;
+ getString(jsonObject, "name", itemMeta::setDisplayName);
+
+ if (jsonObject.has("lore")) {
+ List lore = new ArrayList<>();
+ jsonObject.getAsJsonArray("lore").forEach(jsonElement -> lore.add(jsonElement.getAsString()));
+ itemMeta.setLore(lore);
+ }
+
+ if (jsonObject.has("potion") && itemMeta instanceof PotionMeta) {
+ JsonObject potionObject = jsonObject.getAsJsonObject("potion");
+ potionObject.entrySet().forEach(stringJsonElementEntry -> {
+ String key = stringJsonElementEntry.getKey();
+ JsonObject currentObject = stringJsonElementEntry.getValue().getAsJsonObject();
+ PotionEffectType potionEffectType = PotionEffectType.getByName(key);
+ if (potionEffectType == null) return;
+ int duration = JsonUtils.getInt(currentObject, "duration", 0);
+ int amplifier = JsonUtils.getInt(currentObject, "amplifier", 0);
+ PotionMeta potionMeta = (PotionMeta) itemMeta;
+ potionMeta.addCustomEffect(new PotionEffect(potionEffectType, duration, amplifier), true);
+ });
+ }
+
+ if (jsonObject.has("uses") && itemMeta instanceof Damageable) {
+ int uses = jsonObject.getAsJsonPrimitive("uses").getAsInt();
+ Damageable damageable = (Damageable) itemMeta;
+ damageable.setDamage(itemStack.getType().getMaxDurability() - uses);
+ }
+
+ itemStack.setItemMeta(itemMeta);
+ return itemStack;
+ }
+
+ public boolean execute(EventType eventType, Entity entity, Location location) {
+ if (!scriptMap.containsKey(eventType)) return false;
+ scriptMap.get(eventType).execute(new RunnableScriptEvent(eventType, entity, location));
+ return true;
+ }
+
+ public ItemStack getItemStack() {
+ return itemStack;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/CooldownScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/CooldownScript.java
new file mode 100644
index 00000000..9b6dfcf5
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/CooldownScript.java
@@ -0,0 +1,31 @@
+package de.steamwar.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+public class CooldownScript implements RunnableScript {
+
+ private int cooldown = 0;
+
+ public CooldownScript(JsonObject object) {
+ JsonPrimitive primitive = object.getAsJsonPrimitive("cooldown");
+ if(primitive.isNumber()) cooldown = primitive.getAsInt();
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ Material mainHand = runnableScriptEvent.getPlayer().getInventory().getItemInMainHand().getType();
+ Material offHand = runnableScriptEvent.getPlayer().getInventory().getItemInOffHand().getType();
+ Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), () -> {
+ if (mainHand != Material.AIR) runnableScriptEvent.getPlayer().setCooldown(mainHand, cooldown);
+ if (offHand != Material.AIR) runnableScriptEvent.getPlayer().setCooldown(offHand, cooldown);
+ }, 1);
+ return true;
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/DelayScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/DelayScript.java
new file mode 100644
index 00000000..f77b985a
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/DelayScript.java
@@ -0,0 +1,62 @@
+/*
+ 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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import de.steamwar.misslewars.Config;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.Bukkit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class DelayScript implements RunnableScript {
+
+ private static final Map delayMap = new HashMap<>();
+
+ static {
+ delayMap.put("config.mineflytime", Config.ShieldFlyTime);
+ delayMap.put("config.shieldflytime", Config.ShieldFlyTime);
+ delayMap.put("config.endtime", Config.EndTime);
+ delayMap.put("config.waitingtime", Config.WaitingTime);
+ delayMap.put("config.itemtime", Config.ItemTime);
+ delayMap.put("config.platformtime", Config.PlatformTime);
+
+ delayMap.put("config.tick", 1);
+ }
+
+ private int delayTime = 0;
+
+ public DelayScript(JsonObject delay) {
+ JsonPrimitive jsonPrimitive = delay.getAsJsonPrimitive("time");
+ if (jsonPrimitive.isString()) delayTime = delayMap.getOrDefault(jsonPrimitive.getAsString().toLowerCase(), 0);
+ else if (jsonPrimitive.isNumber()) delayTime = jsonPrimitive.getAsInt();
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), runnableScriptEvent::resumeScriptExecution, delayTime);
+ return false;
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/FilterScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/FilterScript.java
new file mode 100644
index 00000000..4cf250c9
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/FilterScript.java
@@ -0,0 +1,68 @@
+/*
+ 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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.Location;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getBoolean;
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getString;
+
+public class FilterScript implements RunnableScript {
+
+ private static final Map filterMap = new HashMap<>();
+
+ static {
+ filterMap.put("nearportal", (runnableScriptEvent, doubles) -> {
+ Location location = runnableScriptEvent.getLocation();
+ int bz = MissileWars.getBlueTeam().getPortalZ();
+ int rz = MissileWars.getRedTeam().getPortalZ();
+ int offset = (int) Math.signum(bz - rz) * 5;
+
+ int blockZ = location.getBlockZ();
+ if (offset > 0) return (blockZ > bz - offset) || (blockZ < rz + offset);
+ else return (blockZ < bz - offset) || (blockZ > rz + offset);
+ });
+ filterMap.put("nearspawn", (runnableScriptEvent, doubles) -> {
+ Location location = runnableScriptEvent.getLocation();
+ return MissileWars.getBlueTeam().getSpawn().distance(location) < 3 || MissileWars.getRedTeam().getSpawn().distance(location) < 3;
+ });
+ }
+
+ private boolean inverted;
+ private ScriptFunction filter;
+
+ public FilterScript(JsonObject filter) {
+ this.filter = filterMap.getOrDefault(getString(filter, "filter", "").toLowerCase(), null);
+ inverted = getBoolean(filter, "invert", false);
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ return defaultExecution(filter, true, b -> b ^ inverted, runnableScriptEvent);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/LaunchScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/LaunchScript.java
new file mode 100644
index 00000000..83b44edf
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/LaunchScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import de.steamwar.misslewars.scripts.ScriptedItem;
+import de.steamwar.misslewars.scripts.utils.EntityUtils;
+import de.steamwar.misslewars.scripts.utils.EntityUtils.ScriptShortcut;
+import org.bukkit.entity.Projectile;
+
+public class LaunchScript implements RunnableScript {
+
+ private ScriptFunction launch = null;
+
+ public LaunchScript(JsonObject launch) {
+ ScriptShortcut scriptShortcut = EntityUtils.getEntity(launch.getAsJsonPrimitive("entity").getAsString(), EntityUtils.EntityType.Projectile);
+ if (scriptShortcut == null) return;
+
+ this.launch = (runnableScriptEvent, doubles) -> {
+ Projectile projectile = runnableScriptEvent.getPlayer().launchProjectile(scriptShortcut.entityClass);
+ scriptShortcut.consumer.accept(launch, projectile, runnableScriptEvent);
+ return false;
+ };
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ if (runnableScriptEvent.eventType != ScriptedItem.EventType.onClick) return true;
+ return defaultExecution(launch, false, b -> true, runnableScriptEvent);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/LocationScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/LocationScript.java
new file mode 100644
index 00000000..1fb272ed
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/LocationScript.java
@@ -0,0 +1,89 @@
+/*
+ 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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent.LocationType;
+import org.bukkit.Location;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getDouble;
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getString;
+
+public class LocationScript implements RunnableScript {
+
+ private static final Map locationTypeMap = new HashMap<>();
+ private static final Map locationMap = new HashMap<>();
+
+ static {
+ locationTypeMap.put("static", LocationType.STATIC);
+ locationTypeMap.put("dynamic", LocationType.DYNAMIC);
+ locationTypeMap.put("custom", LocationType.CUSTOM);
+ locationTypeMap.put("default", LocationType.DEFAULT);
+
+ locationMap.put("offsetentity", (runnableScriptEvent, doubles) -> {
+ if (runnableScriptEvent.entity == null) return false;
+ Location location1 = runnableScriptEvent.entity.getLocation();
+ runnableScriptEvent.setCustomLocation(location1.getX() + doubles[0], location1.getY() + doubles[1], location1.getZ() + doubles[2], 0, 0);
+ return false;
+ });
+ locationMap.put("offsetlocation", (runnableScriptEvent, doubles) -> {
+ Location location1 = runnableScriptEvent.getLocation();
+ runnableScriptEvent.setCustomLocation(location1.getX() + doubles[0], location1.getY() + doubles[1], location1.getZ() + doubles[2], 0, 0);
+ return false;
+ });
+ ScriptFunction absoluteLocation = (runnableScriptEvent, doubles) -> {
+ runnableScriptEvent.setCustomLocation(doubles[0], doubles[1], doubles[2], 0, 0);
+ return false;
+ };
+ locationMap.put("absolute", absoluteLocation);
+ locationMap.put("fix", absoluteLocation);
+ locationMap.put("fixed", absoluteLocation);
+ }
+
+ private LocationType locationType = null;
+ private ScriptFunction locationExecutor = null;
+
+ private double x, y, z = 0;
+
+ public LocationScript(JsonObject location) {
+ if (location.has("location")) {
+ JsonObject jsonObject = location.getAsJsonObject("location");
+ getDouble(jsonObject, "x", value -> x = value);
+ getDouble(jsonObject, "y", value -> y = value);
+ getDouble(jsonObject, "z", value -> z = value);
+ locationExecutor = locationMap.getOrDefault(getString(jsonObject, "type", "").toLowerCase(), null);
+ locationType = LocationType.CUSTOM;
+ } else if (location.has("locationType")) {
+ locationType = locationTypeMap.getOrDefault(getString(location, "locationType", "").toLowerCase(), LocationType.DEFAULT);
+ }
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ runnableScriptEvent.setLocationType(locationType);
+ return defaultExecution(locationExecutor, true, b -> true, runnableScriptEvent, x, y, z);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/PasteScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/PasteScript.java
new file mode 100644
index 00000000..db1b2cb4
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/PasteScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.bukkit.BukkitWorld;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
+import com.sk89q.worldedit.function.operation.Operations;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.session.ClipboardHolder;
+import com.sk89q.worldedit.world.World;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Objects;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getBoolean;
+
+public class PasteScript implements RunnableScript {
+
+ private static final World world = new BukkitWorld(Bukkit.getWorlds().get(0));
+
+ private final Clipboard clipboard;
+ private final BlockVector3 centeredOffset;
+
+ private boolean centered, ignoreAir;
+ private int xOffset, yOffset, zOffset = 0;
+
+ public PasteScript(JsonObject paste) {
+ String schemFileName = paste.getAsJsonPrimitive("schem").getAsString();
+ if (!schemFileName.endsWith(".schem")) schemFileName += ".schem";
+
+ File schemFile = new File(MissileWars.getPlugin().getDataFolder(), schemFileName);
+ try {
+ clipboard = Objects.requireNonNull(ClipboardFormats.findByFile(schemFile)).getReader(new FileInputStream(schemFile)).read();
+ } catch (IOException e) {
+ throw new SecurityException("Could not load " + schemFileName, e);
+ }
+ centeredOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()).add(clipboard.getDimensions().divide(2));
+
+ centered = getBoolean(paste, "centered", false);
+ ignoreAir = getBoolean(paste, "ignoreAir", false);
+ if (paste.has("offset"))
+ return;
+ JsonArray jsonArray = paste.getAsJsonArray("offset");
+ if (jsonArray.size() == 3)
+ return;
+ xOffset = jsonArray.get(0).getAsInt();
+ yOffset = jsonArray.get(1).getAsInt();
+ zOffset = jsonArray.get(2).getAsInt();
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ Location location = runnableScriptEvent.getLocation();
+ BlockVector3 paste = BlockVector3.at(location.getX() + xOffset, location.getY() + yOffset, location.getZ() + zOffset);
+ if (centered) paste = paste.subtract(centeredOffset);
+
+ EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
+ Operations.completeBlindly(new ClipboardHolder(clipboard).createPaste(editSession).ignoreAirBlocks(ignoreAir).to(paste).build());
+ editSession.flushSession();
+ return true;
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/PotionScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/PotionScript.java
new file mode 100644
index 00000000..34777dce
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/PotionScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import de.steamwar.misslewars.scripts.ScriptedItem;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getBoolean;
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getInt;
+
+public class PotionScript implements RunnableScript {
+
+ private PotionEffect potionEffect = null;
+
+ public PotionScript(JsonObject potion) {
+ int duration = getInt(potion, "duration", 1);
+ int amplifier = getInt(potion, "amplifier", 1);
+ boolean ambient = getBoolean(potion, "ambient", true);
+ boolean particles = getBoolean(potion, "particles", true);
+ boolean icon = getBoolean(potion, "icon", true);
+
+ PotionEffectType potionEffectType = PotionEffectType.getByName(potion.getAsJsonPrimitive("potion").getAsString());
+ if (potionEffectType == null) return;
+ potionEffect = new PotionEffect(potionEffectType, duration, amplifier, ambient, particles, icon);
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ if (potionEffect == null) return false;
+ if (runnableScriptEvent.eventType != ScriptedItem.EventType.onClick) return true;
+ runnableScriptEvent.getPlayer().addPotionEffect(potionEffect);
+ return true;
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/RandomPlayerScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/RandomPlayerScript.java
new file mode 100644
index 00000000..240c5a24
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/RandomPlayerScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.MissileWars;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.entity.Player;
+
+import java.util.Random;
+
+public class RandomPlayerScript implements RunnableScript {
+
+ private Random random = new Random();
+
+ public RandomPlayerScript(JsonObject __) {
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ int size = MissileWars.getBlueTeam().getPlayers().size() + MissileWars.getRedTeam().getPlayers().size();
+ if (size == 0) return true;
+ int index = random.nextInt(size);
+ Player player;
+ if (index >= MissileWars.getBlueTeam().getPlayers().size()) {
+ player = MissileWars.getRedTeam().getPlayers().get(index - MissileWars.getBlueTeam().getPlayers().size());
+ } else {
+ player = MissileWars.getBlueTeam().getPlayers().get(index);
+ }
+ runnableScriptEvent.setLocationType(RunnableScriptEvent.LocationType.CUSTOM);
+ runnableScriptEvent.setCustomLocation(player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), player.getLocation().getPitch(), player.getLocation().getYaw());
+ return true;
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/RemoveScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/RemoveScript.java
new file mode 100644
index 00000000..ede587ed
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/RemoveScript.java
@@ -0,0 +1,38 @@
+/*
+ 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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.entity.Player;
+
+public class RemoveScript implements RunnableScript {
+
+ public RemoveScript(JsonObject jsonObject) {}
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ if (runnableScriptEvent.entity instanceof Player) return true;
+ runnableScriptEvent.entity.remove();
+ return true;
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SlowMoScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SlowMoScript.java
new file mode 100644
index 00000000..54587fdf
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SlowMoScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import de.steamwar.misslewars.slowmo.SlowMoRunner;
+
+public class SlowMoScript implements RunnableScript {
+
+ private int slowMoTime = 0;
+
+ public SlowMoScript(JsonObject jsonObject) {
+ JsonPrimitive jsonPrimitive = jsonObject.getAsJsonPrimitive("time");
+ if (jsonPrimitive.isNumber()) slowMoTime = jsonPrimitive.getAsInt();
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ SlowMoRunner.addSlowMoTime(slowMoTime);
+ return true;
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SoundScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SoundScript.java
new file mode 100644
index 00000000..32e40bb3
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SoundScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import de.steamwar.misslewars.scripts.ScriptedItem;
+import org.bukkit.Sound;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getFloat;
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.getString;
+
+public class SoundScript implements RunnableScript {
+
+ private Sound sound;
+ private float volume;
+ private float pitch;
+
+ public SoundScript(JsonObject sound) {
+ getString(sound, "sound", value -> this.sound = Sound.valueOf(value));
+ volume = getFloat(sound, "volume", 100);
+ pitch = getFloat(sound, "pitch", 1);
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ if (sound == null) return false;
+ if (runnableScriptEvent.eventType != ScriptedItem.EventType.onClick) return true;
+ runnableScriptEvent.getPlayer().playSound(runnableScriptEvent.getPlayer().getLocation(), sound, volume, pitch);
+ return true;
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SummonScript.java b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SummonScript.java
new file mode 100644
index 00000000..a85ea3a6
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/implemented/SummonScript.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.misslewars.scripts.implemented;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScript;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import de.steamwar.misslewars.scripts.utils.EntityUtils;
+import de.steamwar.misslewars.scripts.utils.EntityUtils.ScriptShortcut;
+import org.bukkit.entity.Entity;
+
+public class SummonScript implements RunnableScript {
+
+ private ScriptFunction summon = null;
+
+ public SummonScript(JsonObject summon) {
+ ScriptShortcut scriptShortcut = EntityUtils.getEntity(summon.getAsJsonPrimitive("entity").getAsString(), EntityUtils.EntityType.Normal);
+ if (scriptShortcut == null) return;
+
+ this.summon = (runnableScriptEvent, doubles) -> {
+ Entity entity = runnableScriptEvent.entity.getWorld().spawn(runnableScriptEvent.getLocation(), scriptShortcut.entityClass);
+ scriptShortcut.consumer.accept(summon, entity, runnableScriptEvent);
+ return false;
+ };
+ }
+
+ @Override
+ public boolean execute(RunnableScriptEvent runnableScriptEvent) {
+ return defaultExecution(summon, false, b -> true, runnableScriptEvent);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/utils/EntityUtils.java b/MissileWars/src/de/steamwar/misslewars/scripts/utils/EntityUtils.java
new file mode 100644
index 00000000..823751ee
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/utils/EntityUtils.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.misslewars.scripts.utils;
+
+import com.google.gson.JsonObject;
+import de.steamwar.misslewars.scripts.RunnableScriptEvent;
+import org.bukkit.entity.*;
+
+import static de.steamwar.misslewars.scripts.utils.JsonUtils.*;
+
+public class EntityUtils {
+
+ private EntityUtils() {
+ throw new IllegalStateException("Utility class");
+ }
+
+ public static void setEntityOptions(Entity entity, JsonObject jsonObject) {
+ getDouble(jsonObject, "velocity", aDouble -> entity.setVelocity(entity.getVelocity().multiply(aDouble)));
+ getBoolean(jsonObject, "glowing", entity::setGlowing);
+ getBoolean(jsonObject, "gravity", entity::setGravity);
+ }
+
+ public static void setProjectileOptions(Projectile projectile, JsonObject jsonObject) {
+ getBoolean(jsonObject, "bounce", projectile::setBounce);
+ setEntityOptions(projectile, jsonObject);
+ }
+
+ public static void setExplosiveOptions(Explosive explosive, JsonObject jsonObject) {
+ getFloat(jsonObject, "yield", explosive::setYield);
+ getBoolean(jsonObject, "incendiary", explosive::setIsIncendiary);
+ setEntityOptions(explosive, jsonObject);
+ }
+
+ public static void setFireballOptions(Fireball fireball, JsonObject jsonObject) {
+ setProjectileOptions(fireball, jsonObject);
+ setExplosiveOptions(fireball, jsonObject);
+ }
+
+ public static void setTNTPrimedOptions(TNTPrimed tntPrimed, JsonObject jsonObject) {
+ getInt(jsonObject, "fuse", tntPrimed::setFuseTicks);
+ setExplosiveOptions(tntPrimed, jsonObject);
+ }
+
+ public enum EntityType {
+ Projectile,
+ Normal
+ }
+
+ public static ScriptShortcut getEntity(String name, EntityType entityType) {
+ switch (name.toLowerCase()) {
+ case "tntprimed":
+ if (entityType != EntityType.Normal) return null;
+ return new ScriptShortcut<>(TNTPrimed.class, (jsonObject, entity, runnableScriptEvent) -> setTNTPrimedOptions(entity, jsonObject));
+
+ case "fireball":
+ return new ScriptShortcut<>(Fireball.class, (jsonObject, entity, runnableScriptEvent) -> {
+ setFireballOptions(entity, jsonObject);
+ entity.setDirection(runnableScriptEvent.getLocation().getDirection());
+ });
+ case "arrow":
+ return new ScriptShortcut<>(Arrow.class, (jsonObject, entity, runnableScriptEvent) -> setProjectileOptions(entity, jsonObject));
+ }
+ return null;
+ }
+
+ public static class ScriptShortcut {
+
+ public Class entityClass;
+ public TriConsumer consumer;
+
+ public ScriptShortcut(Class entityClass, TriConsumer consumer) {
+ this.entityClass = entityClass;
+ this.consumer = consumer;
+ }
+
+ }
+
+ public interface TriConsumer {
+ void accept(T t, R r, K k);
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/scripts/utils/JsonUtils.java b/MissileWars/src/de/steamwar/misslewars/scripts/utils/JsonUtils.java
new file mode 100644
index 00000000..f0a703ad
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/scripts/utils/JsonUtils.java
@@ -0,0 +1,51 @@
+package de.steamwar.misslewars.scripts.utils;
+
+import com.google.gson.JsonObject;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+
+public class JsonUtils {
+
+ private JsonUtils() {
+ throw new IllegalStateException("Utility class");
+ }
+
+ public static boolean getBoolean(JsonObject jsonObject, String key, boolean defaultValue) {
+ return jsonObject.has(key) ? jsonObject.getAsJsonPrimitive(key).getAsBoolean() : defaultValue;
+ }
+
+ public static int getInt(JsonObject jsonObject, String key, int defaultValue) {
+ return jsonObject.has(key) ? jsonObject.getAsJsonPrimitive(key).getAsInt() : defaultValue;
+ }
+
+ public static float getFloat(JsonObject jsonObject, String key, float defaultValue) {
+ return jsonObject.has(key) ? jsonObject.getAsJsonPrimitive(key).getAsFloat() : defaultValue;
+ }
+
+ public static String getString(JsonObject jsonObject, String key, String defaultValue) {
+ return jsonObject.has(key) ? jsonObject.getAsJsonPrimitive(key).getAsString() : defaultValue;
+ }
+
+ public static void getBoolean(JsonObject jsonObject, String key, Consumer booleanConsumer) {
+ if (jsonObject.has(key)) booleanConsumer.accept(jsonObject.getAsJsonPrimitive(key).getAsBoolean());
+ }
+
+ public static void getInt(JsonObject jsonObject, String key, IntConsumer booleanConsumer) {
+ if (jsonObject.has(key)) booleanConsumer.accept(jsonObject.getAsJsonPrimitive(key).getAsInt());
+ }
+
+ public static void getDouble(JsonObject jsonObject, String key, DoubleConsumer booleanConsumer) {
+ if (jsonObject.has(key)) booleanConsumer.accept(jsonObject.getAsJsonPrimitive(key).getAsDouble());
+ }
+
+ public static void getFloat(JsonObject jsonObject, String key, Consumer booleanConsumer) {
+ if (jsonObject.has(key)) booleanConsumer.accept(jsonObject.getAsJsonPrimitive(key).getAsFloat());
+ }
+
+ public static void getString(JsonObject jsonObject, String key, Consumer booleanConsumer) {
+ if (jsonObject.has(key)) booleanConsumer.accept(jsonObject.getAsJsonPrimitive(key).getAsString());
+ }
+
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/slowmo/SlowMoRunner.java b/MissileWars/src/de/steamwar/misslewars/slowmo/SlowMoRunner.java
new file mode 100644
index 00000000..7a637d5c
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/slowmo/SlowMoRunner.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.misslewars.slowmo;
+
+import de.steamwar.misslewars.MissileWars;
+import org.bukkit.Bukkit;
+
+public class SlowMoRunner {
+
+ private static long currentTime = 0;
+ private static long current = 0;
+
+ public static void addSlowMoTime(int time) {
+ currentTime += time;
+ }
+
+ public static void resetSlowMoTime() {
+ currentTime = 0;
+ }
+
+ static {
+ Bukkit.getScheduler().runTaskTimer(MissileWars.getPlugin(), () -> {
+ if(currentTime > 0) {
+ current += 1;
+ if (current % 5 == 0) {
+ SlowMoUtils.unfreeze();
+ current = 0;
+ } else {
+ SlowMoUtils.freeze();
+ }
+ currentTime--;
+ } else {
+ SlowMoUtils.unfreeze();
+ }
+ }, 0, 1);
+ }
+}
diff --git a/MissileWars/src/de/steamwar/misslewars/slowmo/SlowMoUtils.java b/MissileWars/src/de/steamwar/misslewars/slowmo/SlowMoUtils.java
new file mode 100644
index 00000000..dbde1f0f
--- /dev/null
+++ b/MissileWars/src/de/steamwar/misslewars/slowmo/SlowMoUtils.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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.misslewars.slowmo;
+
+import com.comphenix.tinyprotocol.Reflection;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+
+import java.lang.reflect.Field;
+
+public class SlowMoUtils {
+
+ private static final Field field;
+ public static final boolean freezeEnabled;
+
+ private static final Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(Reflection.getClass("{obc}.CraftWorld"), "getHandle", null);
+ private static boolean frozen = false;
+
+ private static final World world;
+
+ static {
+ Field temp;
+ try {
+ temp = Reflection.getClass("{nms.server.level}.WorldServer").getField("freezed");
+ } catch (NoSuchFieldException e) {
+ temp = null;
+ }
+ field = temp;
+ if (field != null) field.setAccessible(true);
+ freezeEnabled = field != null;
+ world = Bukkit.getWorlds().get(0);
+ }
+
+ public static void freeze() {
+ setFreeze(world, true);
+ }
+
+ public static void unfreeze() {
+ setFreeze(world, false);
+ }
+
+ public static boolean frozen() {
+ return freezeEnabled && frozen;
+ }
+
+ private static void setFreeze(World world, boolean state) {
+ if (freezeEnabled) {
+ if (frozen == state) return;
+ try {
+ field.set(getWorldHandle.invoke(world), state);
+ frozen = state;
+ } catch (IllegalAccessException e) {
+ // Ignored;
+ }
+ }
+ }
+}
diff --git a/MissileWars/src/plugin.yml b/MissileWars/src/plugin.yml
new file mode 100644
index 00000000..b05dc547
--- /dev/null
+++ b/MissileWars/src/plugin.yml
@@ -0,0 +1,17 @@
+name: MissileWars
+prefix: MW
+main: de.steamwar.misslewars.MissileWars
+authors:
+ - Jan9103
+ - Lixfel
+ - YoyoNow
+version: "1.0"
+api-version: "1.13"
+depend:
+ - WorldEdit
+ - SpigotCore
+commands:
+ spectate:
+ invite:
+ accept:
+ decline:
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 39cbbfdd..310f80cc 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -22,6 +22,8 @@ rootProject.name = "SteamWar"
include("CommandFramework")
include("CommonCore")
+include("MissileWars")
+
include("SpigotCore")
include("SpigotCore:SpigotCore_8")
include("SpigotCore:SpigotCore_9")