diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties index ea4451e7..ba8e3b98 100644 --- a/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem_Main/src/BauSystem.properties @@ -171,16 +171,33 @@ LOADER_MESSAGE_CLEAR-HELP = §cDu must im Setup-Modus sein um den Loader zu clea LOADER_MESSAGE_TNT = §eTNT hinzugefügt {0} LOADER_MESSAGE_INTERACT = §e{0} hinzugefügt {1} -LOADER_BUTTON_SWITCH = Hebel -LOADER_BUTTON_WOOD-Button = Knopf -LOADER_BUTTON_STONE-Button = Knopf -LOADER_BUTTON_PRESSURE-PLATE = Druckplatte -LOADER_BUTTON_WEIGHTED-PRESSURE-PLATE = Druckplatte -LOADER_BUTTON_TRIPWIRE = Tripwire -LOADER_BUTTON_NOTEBLOCK = Noteblock -LOADER_BUTTON_DAYLIGHTSENSOR = Tageslichtsensor -LOADER_BUTTON_INVALID = Invalider - +LOADER_BUTTON_SWITCH=Hebel +LOADER_BUTTON_WOOD-Button=Knopf +LOADER_BUTTON_STONE-Button=Knopf +LOADER_BUTTON_PRESSURE-PLATE=Druckplatte +LOADER_BUTTON_WEIGHTED-PRESSURE-PLATE=Druckplatte +LOADER_BUTTON_TRIPWIRE=Tripwire +LOADER_BUTTON_NOTEBLOCK=Noteblock +LOADER_BUTTON_DAYLIGHTSENSOR=Tageslichtsensor +LOADER_BUTTON_INVALID=Invalider +#Loadtimer +LOADTIMER_WAITING=§7Platziere ein TNT zum starten... +LOADTIMER_BOSSBAR=§7Tick: §e{0}§7(§e{1}§7) Zeit: §e{2}s §7Tnt: §e{3} §7Blöcke +LOADTIMER_ACTIVATED=§7Warte auf Zündung +LOADTIMER_IGNITION=§7Warte auf Explosion +LOADTIMER_SUMARY_HEAD=§7---=== (§eLoadtimer-Auswertung§7) ===--- +LOADTIMER_SUMARY_PLAYERTABLE_HEAD=§7Spieler: §eTNT §7(§eTNT/s§7) +LOADTIMER_SUMARY_PLAYERTABLE_PLAYER=§7{0}: §e{1} §7(§e{2}/s§7) +LOADTIMER_SUMARY_PLAYERTABLE_ALL=Insgesamt +LOADTIMER_SUMARY_TIMES_HEAD=§7Zeiten: §eSekunden §7(§eTicks§7) +LOADTIMER_SUMARY_TIMES_START=§7 || §7Start! +LOADTIMER_SUMARY_TIMES_ACTIVATION=§7 || Aktivierung: §e{0}s §7(§e{1}t§7) +LOADTIMER_SUMARY_TIMES_IGNITION=§7 || Zündung: §e{0}s §7(§e{1}t§7) +LOADTIMER_SUMARY_TIMES_EXPLOSION=§7 || Explosion: §e{0}s §7(§e{1}t§7) +LOADTIMER_SUMARY_TIMES_LAST=§7\\/ +LOADTIMER_SUMARY_STATS_HEAD=§7Kanonen-Stats§8: +LOADTIMER_SUMARY_STATS_TNT=§7TNT: §e{0} +LOADTIMER_SUMARY_STATS_FREQ=§7Belade Frequenz: §e{0}/m§8, §7Schuss Frequenz: §e{1}/m # Other -OTHER_ITEMS_TELEPORT_GUI-NAME = Teleportieren -OTHER_ITEMS_TELEPORT_PLAYER-OFFLINE = §cDer Spieler ist Offline \ No newline at end of file +OTHER_ITEMS_TELEPORT_GUI-NAME=Teleportieren +OTHER_ITEMS_TELEPORT_PLAYER-OFFLINE=§cDer Spieler ist Offline \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/Loadtimer.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/Loadtimer.java new file mode 100644 index 00000000..35353caf --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/Loadtimer.java @@ -0,0 +1,260 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.loadtimer; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.config.ColorConfig; +import de.steamwar.bausystem.features.tpslimit.TPSUtils; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.region.utils.RegionExtensionType; +import de.steamwar.bausystem.region.utils.RegionType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.scheduler.BukkitTask; + +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class Loadtimer implements Listener { + + private static final Map timers = new HashMap<>(); + private final Region region; + private final Map tntPlaced = new HashMap<>(); + private final BukkitTask task; + private final Map bars = new HashMap(); + private Stage stage; + private boolean finishOnActive = true; + + private long start = -1; + private long activate = -1; + private long ignite = -1; + private long explode = -1; + + public Loadtimer(Region region, boolean finishOnActive) { + this.finishOnActive = finishOnActive; + this.region = region; + this.stage = Stage.WAITING; + Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance()); + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { + Bukkit.getOnlinePlayers().forEach(player -> { + if (!Region.getRegion(player.getLocation()).equals(region) && bars.containsKey(player)) { + bars.remove(player).removeAll(); + } + }); + if (stage == Stage.COUNTING) { + long timeSinceStart = TPSUtils.currentTick.get() - start; + long timeSinceHalf = timeSinceStart / 2; + double timeSec = (timeSinceStart / 20d); + String sec = new DecimalFormat("#.#").format(timeSec); + AtomicInteger tnt = new AtomicInteger(); + tntPlaced.forEach((player, integer) -> tnt.addAndGet(integer)); + Bukkit.getOnlinePlayers().forEach(player -> { + if (Region.getRegion(player.getLocation()).equals(region)) { + BossBar bar = getOrDefault(player); + bar.setTitle(BauSystem.MESSAGE.parse("LOADTIMER_BOSSBAR", player, timeSinceStart, timeSinceHalf, sec, tnt)); + bar.setProgress((timeSinceStart % 20d) / 20); + bar.setColor(BarColor.GREEN); + bar.setStyle(BarStyle.SEGMENTED_20); + } + }); + } else if (stage == Stage.WAITING) { + Bukkit.getOnlinePlayers().forEach(player -> { + if (Region.getRegion(player.getLocation()).equals(region)) { + BossBar bar = getOrDefault(player); + bar.setStyle(BarStyle.SOLID); + bar.setTitle(BauSystem.MESSAGE.parse("LOADTIMER_WAITING", player)); + bar.setColor(BarColor.GREEN); + bar.setProgress(1); + } + }); + } else if (stage == Stage.ACTIVATED || stage == Stage.IGNITION) { + Bukkit.getOnlinePlayers().forEach(player -> { + if (Region.getRegion(player.getLocation()).equals(region)) { + BossBar bar = getOrDefault(player); + bar.setStyle(BarStyle.SOLID); + bar.setTitle(BauSystem.MESSAGE.parse(stage == Stage.ACTIVATED ? "LOADTIMER_ACTIVATED" : "LOADTIMER_IGNITION", player)); + bar.setColor(BarColor.YELLOW); + bar.setProgress(1); + } + }); + } + }, 1, 1); + } + + public static boolean hasTimer(Region r) { + return timers.containsKey(r); + } + + public static Loadtimer getTimer(Region r) { + return timers.get(r); + } + + public static Loadtimer createLoadtimer(Region r, boolean finishOnActive) { + return timers.computeIfAbsent(r, region1 -> new Loadtimer(region1, finishOnActive)); + } + + private BossBar getOrDefault(Player player) { + return bars.computeIfAbsent(player, player1 -> { + BossBar bar1 = Bukkit.createBossBar("%PLACEHOLDER%", BarColor.GREEN, BarStyle.SEGMENTED_20); + bar1.addPlayer(player1); + return bar1; + }); + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + if (Region.getRegion(event.getBlock().getLocation()).equals(region) && event.getBlockPlaced().getType() == Material.TNT) { + if (stage == Stage.WAITING) { + this.stage = Stage.COUNTING; + this.start = TPSUtils.currentTick.get(); + } + + if (stage == Stage.COUNTING) { + tntPlaced.put(event.getPlayer(), tntPlaced.getOrDefault(event.getPlayer(), 0) + 1); + } + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (Region.getRegion(event.getPlayer().getLocation()).equals(region)) { + if (stage == Stage.COUNTING) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Material type = event.getClickedBlock().getType(); + if (type.name().contains("_BUTTON") || type == Material.LEVER || type.name().contains("_TRAPDOOR") || type == Material.NOTE_BLOCK) { + setActivate(); + } + } else if (event.getAction() == Action.PHYSICAL) { + setActivate(); + } + } + } + } + + @EventHandler + public void onEntitySpawn(EntitySpawnEvent event) { + if (event.getEntityType() == EntityType.PRIMED_TNT && Region.getRegion(event.getLocation()).equals(region) && + (stage == Stage.COUNTING || stage == Stage.ACTIVATED)) { + stage = Stage.IGNITION; + ignite = TPSUtils.currentTick.get(); + if (activate == -1) + activate = TPSUtils.currentTick.get(); + if (finishOnActive) { + stage = Stage.END; + print(); + delete(); + } + } + } + + @EventHandler + public void onEntityExplode(EntityExplodeEvent event) { + if (event.getEntityType() == EntityType.PRIMED_TNT) { + Region r = Region.getRegion(event.getLocation()); + if (r.equals(region) && r.inRegion(event.getLocation(), RegionType.BUILD, RegionExtensionType.EXTENSION) && stage == Stage.IGNITION) { + stage = Stage.END; + explode = TPSUtils.currentTick.get(); + print(); + delete(); + } + } + } + + private void setActivate() { + activate = TPSUtils.currentTick.get(); + stage = Stage.ACTIVATED; + if (finishOnActive) { + print(); + delete(); + } + } + + public void print() { + long loadTime = activate - start; + int allTnt = 0; + for (Map.Entry e : tntPlaced.entrySet()) { + allTnt += e.getValue(); + } + + long ignTime = ignite - activate; + long explTime = explode - ignTime - activate; + if (explTime < 0) + explTime = loadTime; + + int finalAllTnt = allTnt; + long finalExplTime = explTime; + Bukkit.getOnlinePlayers().forEach(player -> { + if (Region.getRegion(player.getLocation()).equals(region)) { + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_HEAD", player); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_PLAYERTABLE_HEAD", player); + for (Map.Entry e : tntPlaced.entrySet()) { + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_PLAYERTABLE_PLAYER", player, e.getKey().getName(), e.getValue(), new DecimalFormat("#.#").format(e.getValue() / (loadTime / 20D))); + } + if (tntPlaced.size() > 1) { + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_PLAYERTABLE_PLAYER", player, BauSystem.MESSAGE.parse("LOADTIMER_SUMARY_PLAYERTABLE_ALL", player), finalAllTnt, new DecimalFormat("#.#").format(finalAllTnt / (loadTime / 20D))); + } + player.sendMessage(ColorConfig.BASE + ""); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_TIMES_HEAD", player); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_TIMES_START", player); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_TIMES_ACTIVATION", player, new DecimalFormat("#.#").format((loadTime / 20D)), loadTime); + if (!finishOnActive) { + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_TIMES_IGNITION", player, new DecimalFormat("#.#").format((ignTime / 20D)), ignTime); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_TIMES_EXPLOSION", player, new DecimalFormat("#.#").format((finalExplTime / 20D)), finalExplTime); + } + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_TIMES_LAST", player); + player.sendMessage(ColorConfig.BASE + ""); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_STATS_HEAD", player); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_STATS_TNT", player, finalAllTnt); + BauSystem.MESSAGE.sendPrefixless("LOADTIMER_SUMARY_STATS_FREQ", player, 60D / (loadTime / 20D), 60D / ((finalExplTime + Math.max(ignTime, 0) + loadTime) / 20D)); + } + }); + } + + public void delete() { + HandlerList.unregisterAll(this); + timers.remove(region, this); + bars.forEach((player, bossBar) -> bossBar.removeAll()); + bars.clear(); + task.cancel(); + } + + private enum Stage { + WAITING, + COUNTING, + ACTIVATED, + IGNITION, + END + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/LoadtimerCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/LoadtimerCommand.java new file mode 100644 index 00000000..4c3d1b9a --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/LoadtimerCommand.java @@ -0,0 +1,70 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.loadtimer; + +import de.steamwar.bausystem.config.ColorConfig; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.region.Region; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + +@Linked(LinkageType.COMMAND) +public class LoadtimerCommand extends SWCommand { + protected LoadtimerCommand() { + super("loadtimer", "lt", "stopuhr"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + p.sendMessage(ColorConfig.BASE + "---===( " + ColorConfig.HIGHLIGHT + "Loadtimer" + ColorConfig.BASE + ") ===---"); + p.sendMessage(ColorConfig.BASE + "Messe dich und deine Freunde beim Beladen einer Kanone und bekomme informationen über die Kanone"); + p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "loadtimer start" + ColorConfig.OTHER + "-" + ColorConfig.BASE + " Startet den einfachen Loadtimer"); + p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.BASE + "loadtimer start " + ColorConfig.OTHER + "[" + ColorConfig.BASE + "full/half" + ColorConfig.OTHER + "] - " + ColorConfig.BASE + "Starte den Timer in einem bestimmten Modus"); + p.sendMessage(ColorConfig.BASE + "Loadtimer Modis: Full -> Misst vom ersten TNT bis zur Treib-Explosion, kann somit besser die Schuss Frequent berechnen. Half -> Misst nur bis zur Aktivierung"); + p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "loadtimer stop" + ColorConfig.OTHER + "-" + ColorConfig.BASE + " Stoppe den Aktuellen Loadtimer"); + } + + @Register("start") + public void start(Player p) { + start(p, TimerMode.HALF); + } + + @Register("start") + public void start(Player p, TimerMode mode) { + Region r = Region.getRegion(p.getLocation()); + if (r.isGlobal()) return; + if (!Loadtimer.hasTimer(r)) + Loadtimer.createLoadtimer(r, mode == TimerMode.HALF); + } + + @Register("stop") + public void stop(Player p) { + Region r = Region.getRegion(p.getLocation()); + if (r.isGlobal()) return; + if (Loadtimer.hasTimer(r)) + Loadtimer.getTimer(r).delete(); + } + + public enum TimerMode { + FULL, + HALF + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/LoadtimerGuiItem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/LoadtimerGuiItem.java new file mode 100644 index 00000000..bd1403f1 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loadtimer/LoadtimerGuiItem.java @@ -0,0 +1,77 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.loadtimer; + +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.config.ColorConfig; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.linkage.specific.BauGuiItem; +import de.steamwar.bausystem.region.Region; +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWItem; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@Linked(LinkageType.BAU_GUI_ITEM) +public class LoadtimerGuiItem extends BauGuiItem { + + public LoadtimerGuiItem() { + super(27); + } + + @Override + public Permission permission() { + return Permission.MEMBER; + } + + @Override + public ItemStack getItem(Player player) { + Region r = Region.getRegion(player.getLocation()); + if (r.isGlobal()) + return new SWItem(Material.BOWL, ColorConfig.HIGHLIGHT + "Loadtimer gibt es nicht in der Global Region!").getItemStack(); + if (Loadtimer.hasTimer(r)) { + return new SWItem(Material.BOW, ColorConfig.HIGHLIGHT + "Loadtimer stoppen").getItemStack(); + } else { + return new SWItem(Material.BOW, ColorConfig.HIGHLIGHT + "Loadtimer starten").getItemStack(); + } + } + + @Override + public boolean click(ClickType click, Player p) { + Region r = Region.getRegion(p.getLocation()); + if (r.isGlobal()) return false; + if (Loadtimer.hasTimer(r)) { + p.performCommand("lt stop"); + } else { + SWInventory inv = new SWInventory(p, 9, "Loadtimer Modus"); + inv.setItem(1, Material.OAK_PLANKS, ColorConfig.HIGHLIGHT + "Full", clickType -> { + p.performCommand("lt start full"); + }); + inv.setItem(7, Material.OAK_SLAB, ColorConfig.HIGHLIGHT + "Half", clickType -> { + p.performCommand("lt start half"); + }); + inv.open(); + } + return true; + } +}