Arrows Stopping in Techhider Blocks #208
@ -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();
|
||||
|
||||
|
111
FightSystem_Main/src/de/steamwar/fightsystem/listener/ArrowStopper.java
Normale Datei
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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() {
|
||||
Lixfel
hat
Die Init-Methode kann gestrichen werden und alles in den Konstruktor (der dann Public wird) übernommen werden. Konstruktor wäre dann super(Config.ArrowTechhiderCollision != 0 ? EnumSet.of(RUNNING), EnumSet.empty()); Die Init-Methode kann gestrichen werden und alles in den Konstruktor (der dann Public wird) übernommen werden. Konstruktor wäre dann super(Config.ArrowTechhiderCollision != 0 ? EnumSet.of(RUNNING), EnumSet.empty());
|
||||
for (Arrow arrow : Bukkit.getWorlds().get(0).getEntitiesByClass(Arrow.class)) {
|
||||
if (invalidEntity(arrow))
|
||||
continue;
|
||||
Lixfel
hat
BasicListener übernimmt im Konstruktor schon das Registrieren als StateDependent BasicListener übernimmt im Konstruktor schon das Registrieren als StateDependent
|
||||
|
||||
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;
|
||||
Lixfel
hat
Das dürfte nichts bringen, da der Iterator eigens auf einem für diese Aufgabe erstellter ArrayList läuft. Die Zeile drüber reicht schon vollkommen aus, um den Pfeil zu entfernen. Das dürfte nichts bringen, da der Iterator eigens auf einem für diese Aufgabe erstellter ArrayList läuft. Die Zeile drüber reicht schon vollkommen aus, um den Pfeil zu entfernen.
|
||||
}
|
||||
Lixfel
hat
Das müsste aus meiner Java-Erfahrung heraus auf jeden fall eine ConcurrentModificationException werfen Das müsste aus meiner Java-Erfahrung heraus auf jeden fall eine ConcurrentModificationException werfen
|
||||
if (checkBlocks(arrow.getLocation().getBlock(), prevLocation.getBlock())) {
|
||||
Lixfel
hat
Da musst du iterator.remove() verwenden. Da musst du iterator.remove() verwenden.
|
||||
arrow.remove();
|
||||
}
|
||||
}
|
||||
Lixfel
hat
Die Verschachtelung kann man evtl. durch eine else if-Konstruktion ersetzen. Die Verschachtelung kann man evtl. durch eine else if-Konstruktion ersetzen.
|
||||
}
|
||||
Lixfel
hat
Ebenfalls. Nutze einen Iterator. Ebenfalls. Nutze einen Iterator.
|
||||
|
||||
Lixfel
hat
Auch hier wieder: Iterator benutzen. Auch hier wieder: Iterator benutzen.
|
||||
@Override
|
||||
public void enable() {
|
||||
Lixfel
hat
Ich denke, dass du auch hier den Iterator benutzen musst, weiß aber gerade nicht, ob eine Änderung da überhaupt vorgesehen ist. Ich denke, dass du auch hier den Iterator benutzen musst, weiß aber gerade nicht, ob eine Änderung da überhaupt vorgesehen ist.
|
||||
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())) {
|
||||
Lixfel
hat
Das kannst du nicht Asynchron machen (es dauert 50ms+, bis du einen Chunk für Blockabfragen bekommst), das produziert hier nur Threads. Das kannst du nicht Asynchron machen (es dauert 50ms+, bis du einen Chunk für Blockabfragen bekommst), das produziert hier nur Threads.
|
||||
BlockFace nearest = BlockFace.SELF;
|
||||
double nearestDistance = cursor.getLocation().distance(end.getLocation());
|
||||
for (BlockFace face : BLOCK_FACES) {
|
||||
Lixfel
hat
Ok, wenn ich jetzt richtig verstanden habe, was diese Funktion macht, dann tut sie linear zwischen den Blöcken interpolieren? Ich meine, das ist zwar nicht die korrekte Minecraft-Berechnungsreihenfolge, soll mir aber auch recht sein. Ok, wenn ich jetzt richtig verstanden habe, was diese Funktion macht, dann tut sie linear zwischen den Blöcken interpolieren? Ich meine, das ist zwar nicht die korrekte Minecraft-Berechnungsreihenfolge, soll mir aber auch recht sein.
|
||||
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());
|
||||
Lixfel
hat
Der Name der Funktion verwirrt etwas, da die Funktion ja einen Invalid boolean zurückgibt. evtl. isInvalid? Der Name der Funktion verwirrt etwas, da die Funktion ja einen Invalid boolean zurückgibt. evtl. isInvalid?
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Statt der (aufwändigen) Verwaltung von LAST_LOCATIONS wäre es wsl. eleganter, mit entity.getVelocity() / 20 zu arbeiten. Das dürfte einiges an Verwaltungsaufwand sparen. Man könnte dann wsl. in run auch mit world.getEntitiesWithClass() arbeiten.
?, entity.getVelocity() gibt einen Vektor zurück, welchen man nicht einfach durch 20 teilen kann
.divide?
braucht einen Vektor
Du brauchst ja sowieso nur die einzelnen Komponenten, also teile doch einfach die durch 20....