diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java index 9ddb221..93f333b 100644 --- a/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem_Main/src/de/steamwar/fightsystem/FightSystem.java @@ -32,10 +32,7 @@ import de.steamwar.fightsystem.record.RecordSystem; import de.steamwar.fightsystem.record.Recorder; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependent; -import de.steamwar.fightsystem.utils.EnterHandler; -import de.steamwar.fightsystem.utils.FightScoreboard; -import de.steamwar.fightsystem.utils.FightStatistics; -import de.steamwar.fightsystem.utils.TechHider; +import de.steamwar.fightsystem.utils.*; import de.steamwar.fightsystem.winconditions.*; import de.steamwar.sql.EventFight; import de.steamwar.sql.Schematic; @@ -103,6 +100,7 @@ public class FightSystem extends JavaPlugin { new GameplayListener(); new PersonalKitCreator(); new ScoreboardListener(); + new ArrowStopper(); if(Core.getVersion() > 8) new VersionDependentListener(); diff --git a/FightSystem_Main/src/de/steamwar/fightsystem/listener/ArrowStopper.java b/FightSystem_Main/src/de/steamwar/fightsystem/listener/ArrowStopper.java new file mode 100644 index 0000000..7dcfc68 --- /dev/null +++ b/FightSystem_Main/src/de/steamwar/fightsystem/listener/ArrowStopper.java @@ -0,0 +1,111 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.fightsystem.listener; + +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.FightSystem; +import de.steamwar.fightsystem.states.FightState; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.projectiles.ProjectileSource; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; + +import java.util.EnumSet; + +public class ArrowStopper extends BasicListener { + + private BukkitTask task; + private static final Vector NULL_VECTOR = new Vector(0, 0, 0); + private static final BlockFace[] BLOCK_FACES = {BlockFace.UP, BlockFace.DOWN, BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH}; + public ArrowStopper() { + super(Config.TechhiderActive ? EnumSet.of(FightState.RUNNING) : EnumSet.noneOf(FightState.class)); + } + + private void run() { + for (Arrow arrow : Bukkit.getWorlds().get(0).getEntitiesByClass(Arrow.class)) { + if (invalidEntity(arrow)) + continue; + + Location prevLocation = arrow.getLocation().toVector().subtract(arrow.getVelocity()).toLocation(arrow.getWorld()); + if (arrow.getTicksLived() == 0){ + ProjectileSource projSource = arrow.getShooter(); + if(projSource instanceof Player) + prevLocation = ((Player) arrow.getShooter()).getEyeLocation(); + else + continue; + } + if (checkBlocks(arrow.getLocation().getBlock(), prevLocation.getBlock())) { + arrow.remove(); + } + } + } + + @Override + public void enable() { + super.enable(); + task = Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), this::run, 1, 1); + } + + @Override + public void disable() { + super.disable(); + task.cancel(); + } + + private boolean checkBlocks(Block start, Block end) { + Block cursor = start; + + while (!cursor.getLocation().equals(end.getLocation())) { + BlockFace nearest = BlockFace.SELF; + double nearestDistance = cursor.getLocation().distance(end.getLocation()); + for (BlockFace face : BLOCK_FACES) { + Block relative = cursor.getRelative(face); + double distance = relative.getLocation().distance(end.getLocation()); + if(distance < nearestDistance) { + nearestDistance = distance; + nearest = face; + } + } + cursor = cursor.getRelative(nearest); + if(checkBlock(cursor)) + return true; + } + + return false; + } + + private boolean checkBlock(Block block) { + return Config.HiddenBlockTags.contains(block.getType().name()); + } + + private boolean invalidEntity(Arrow entity) { + boolean teamFrom = entity.getVelocity().getZ() > 0; + boolean overMid = entity.getLocation().getZ() > Config.SpecSpawn.getZ(); + boolean otherSide = teamFrom == overMid; + return otherSide || + entity.isInBlock() || + entity.getVelocity().equals(NULL_VECTOR); + } +}