12
1

HellsBells #275

Manuell gemergt
Lixfel hat 19 Commits von Hells_bells nach master 2021-06-25 07:17:45 +02:00 zusammengeführt
3 geänderte Dateien mit 271 neuen und 1 gelöschten Zeilen

Datei anzeigen

@ -30,5 +30,6 @@ public enum Winconditions {
POINTS,
TIME_TECH_KO,
WATER_TECH_KO,
PUMPKIN_TECH_KO
PUMPKIN_TECH_KO,
HELLS_BELLS
}

Datei anzeigen

@ -23,6 +23,7 @@ import de.steamwar.core.CommandRemover;
import de.steamwar.core.Core;
import de.steamwar.fightsystem.commands.*;
import de.steamwar.fightsystem.countdown.*;
import de.steamwar.fightsystem.event.HellsBells;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.fight.FightWorld;
@ -106,6 +107,9 @@ public class FightSystem extends JavaPlugin {
new RankedPlayerLeftWincondition();
new WinconditionPercentTimeout();
//noinspection InstantiationOfUtilityClass
Zeanon markierte diese Unterhaltung als gelöst
Review

Bitte rausnehmen (sollte auch nicht nötig sein?!?)

Bitte rausnehmen (sollte auch nicht nötig sein?!?)
new HellsBells();
new NoPlayersOnlineCountdown();
new PreSchemCountdown();
new PostSchemCountdown();

Datei anzeigen

@ -0,0 +1,265 @@
/*
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

License fehlt.

License fehlt.
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.event;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.countdown.Countdown;
import de.steamwar.fightsystem.countdown.SWSound;
import de.steamwar.fightsystem.states.FightState;
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Du kannst dafür nicht BlockFace verwenden?

Du kannst dafür nicht BlockFace verwenden?
Veraltet
Review

In der 1.8 gibt es BlockFace mit dem toVector intern noch nicht.

In der 1.8 gibt es BlockFace mit dem toVector intern noch nicht.
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.winconditions.Winconditions;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.scheduler.BukkitTask;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
public class HellsBells {
public static final Random random = new Random();
private final World world = Bukkit.getWorlds().get(0);
Veraltet
Review

Subklassen bitte nach dem Inhalt der Hauptklasse.

Subklassen bitte nach dem Inhalt der Hauptklasse.
private final int xLength = Config.RedPasteRegion.getMaxX() - Config.RedPasteRegion.getMinX();
private final int zLength = Config.RedPasteRegion.getMaxZ() - Config.RedPasteRegion.getMinZ();
private State current = State.PRE;
private int currentDrops = 0;
private HellsBellsCountdown currentCountdown;
private BukkitTask currentDropping;
Veraltet
Review

Warum das nochmal extra vorhalten? In getRandom kann ja auch values() aufgerufen werden...

Warum das nochmal extra vorhalten? In getRandom kann ja auch values() aufgerufen werden...
Veraltet
Review

values() auf einem Enum erzeugt immer eine kopie der Enum Elemente intern, daher recht inefficient.

values() auf einem Enum erzeugt immer eine kopie der Enum Elemente intern, daher recht inefficient.
Veraltet
Review

Ich finde, es ist ineffizienter, eine Kopie ständig im RAM zu halten, als alle x Minuten mal eine neue Kopie des 4! Elemente großen Array anzulegen. Ist zudem kürzer und einfacher, einfach neu zu kopieren.

Ich finde, es ist ineffizienter, eine Kopie ständig im RAM zu halten, als alle x Minuten mal eine neue Kopie des 4! Elemente großen Array anzulegen. Ist zudem kürzer und einfacher, einfach neu zu kopieren.
private final List<String> startMessages = Arrays.asList("§c!!Achtung!! Bomber im Anflug, noch ca. eine Minute bis zur Ankunft.",
"§cBomber im Anflug, ca. eine Minute bis zur Ankunft.",
"§cBomber auf dem Radar gesichtet, geschätzte Ankunftszeit: eine Minute.",
"§cUnbekanntes Flugobjekt gesichtet, trifft in ca. einer Minute ein.",
"§cFlugobjekt gesichtet. Ankunft in ca. einer Minute.",
"§cBomber erschienen, Ankunft ca. eine Minute.");
private final List<String> stateSwapMessages = Arrays.asList("§aDie Bomben fallen nun schneller.",
"§aMehr Bomber im Anflug.",
"§aZusätzliche Bomber gesichtet.",
"§aDas Bombardement scheint sich zu erhöhen.");
public void startCountdown() {
if (current == State.PRE) {
Bukkit.broadcastMessage(FightSystem.PREFIX + (startMessages.get(random.nextInt(startMessages.size()))));
current = current.getNext();
} else if (current != State.LAST && currentDrops >= current.SWITCH_AFTER) {
Bukkit.broadcastMessage(FightSystem.PREFIX + (stateSwapMessages.get(random.nextInt(stateSwapMessages.size()))));
currentDrops = 0;
}
currentDrops++;
currentCountdown = new HellsBellsCountdown(current.MIN_TIME + random.nextInt(current.MAX_TIME - current.MIN_TIME));
currentCountdown.enable();
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

In der enable() ist sichergestellt, dass es noch nie ausgeführt wurde oder vorher die disable() ausgeführt wurde, die Überprüfung sollte demnach unnötig sein.

In der enable() ist sichergestellt, dass es noch nie ausgeführt wurde oder vorher die disable() ausgeführt wurde, die Überprüfung sollte demnach unnötig sein.
}
public void drop() {
Direction direction = Direction.getRandom();
AtomicInteger length = new AtomicInteger(10 + random.nextInt(direction.getLength(zLength, xLength) - 10));
int width = 5 + random.nextInt(5);
int xOffset = getWidthStart(direction.getLength(xLength, zLength), direction.getLength(length.get(), width));
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Es ist garantiert, dass vor der disable() die enable() ausgeführt wurde.

Es ist garantiert, dass vor der disable() die enable() ausgeführt wurde.
int zOffset = getLengthStart(direction.getLength(zLength, xLength), direction.getLength(width, length.get()));
int yOffset = getHeightStart();
Point redStart;
Point blueStart;
if (direction.isNorthOrWest()) {
redStart = new Point(Config.RedPasteRegion.getMaxX() - xOffset, Config.RedExtendRegion.getMaxY() + yOffset, Config.RedPasteRegion.getMaxZ() - zOffset);
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Diese Unterklasse scheint mir ziemlich unnötig, die Inhalte dieser Klasse sollten in die übergeordnete Klasse eingebaut werden können.

Diese Unterklasse scheint mir ziemlich unnötig, die Inhalte dieser Klasse sollten in die übergeordnete Klasse eingebaut werden können.
blueStart = new Point(Config.BluePasteRegion.getMinX() + xOffset, Config.BlueExtendRegion.getMaxY() + yOffset, Config.BluePasteRegion.getMinZ() + zOffset);
} else {
redStart = new Point(Config.RedPasteRegion.getMinX() + xOffset, Config.RedExtendRegion.getMaxY() + yOffset, Config.RedPasteRegion.getMinZ() + zOffset);
blueStart = new Point(Config.BluePasteRegion.getMaxX() - xOffset, Config.BlueExtendRegion.getMaxY() + yOffset, Config.BluePasteRegion.getMaxZ() - zOffset);
}
Zeanon markierte diese Unterhaltung als gelöst
Review

Das StateDependent sollte nur die Sachen (de-)aktivieren, nicht das ganze Behaviour innehaben. Um die Nestung zu verringern: Nimm den ganzen Code bis auf die Enable und Disable und bewege den in die HellsBells-Klasse. (Also die übergeordnete)

Das StateDependent sollte nur die Sachen (de-)aktivieren, nicht das ganze Behaviour innehaben. Um die Nestung zu verringern: Nimm den ganzen Code bis auf die Enable und Disable und bewege den in die HellsBells-Klasse. (Also die übergeordnete)
currentDropping = Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), () -> {
for (int w = 0; w < width; w++) {
if (direction.isNorthOrWest()) {
world.spawnEntity(redStart.addAndToLocation(world, -1 * (direction.dx * length.get() + w * direction.other().dx), 0, -1 * (direction.dz * length.get() + w * direction.other().dz)), EntityType.PRIMED_TNT);
world.spawnEntity(blueStart.addAndToLocation(world, direction.dx * length.get() + w * direction.other().dx, 0, direction.dz * length.get() + w * direction.other().dz), EntityType.PRIMED_TNT);
} else {
world.spawnEntity(redStart.addAndToLocation(world, direction.dx * length.get() + w * direction.other().dx, 0, direction.dz * length.get() + w * direction.other().dz), EntityType.PRIMED_TNT);
world.spawnEntity(blueStart.addAndToLocation(world, -1 * (direction.dx * length.get() + w * direction.other().dx), 0, -1 * (direction.dz * length.get() + w * direction.other().dz)), EntityType.PRIMED_TNT);
}
}
if (length.addAndGet(-2) <= 0) {
currentDropping.cancel();
}
}, 0L, 4L);
}
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

init() und terminate() lesen sich mir wie eine enable() und disable() eines StateDependent...

init() und terminate() lesen sich mir wie eine enable() und disable() eines StateDependent...
Zeanon markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Wird der State NONE wirklich benötigt?

Wird der State NONE wirklich benötigt?
private int getLengthStart(int regionSize, int length) {
return random.nextInt(regionSize - length);
}
private int getWidthStart(int regionSize, int length) {
return random.nextInt(regionSize - length);
}
private int getHeightStart() {
return 5 + random.nextInt(15);
}
public HellsBells() {
new StateDependent(Winconditions.HELLS_BELLS, FightState.Running) {
@Override
public void enable() {
startCountdown();
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Gibt es nicht random.nextInt(MIN, MAX)? (kA)

Gibt es nicht random.nextInt(MIN, MAX)? (kA)
Veraltet
Review

Nein leider bietet die normale Random implementation dies nicht an.

Nein leider bietet die normale Random implementation dies nicht an.
}
@Override
public void disable() {
currentCountdown.disable();
}
}.register();
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Diesen if-Block kann man denke ich vereinfachen, wenn man stattdessen in den Assignments mit dem conditional-Operator arbeitet ?:.

Diesen if-Block kann man denke ich vereinfachen, wenn man stattdessen in den Assignments mit dem conditional-Operator arbeitet ?:.
}
private static class HellsBellsCountdown extends Countdown {
Veraltet
Review

Kann glaube noch private static sein.

Kann glaube noch private static sein.
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Könnte man statt diesen Ifs nicht einfach eine Methode in der Direction machen, die dann den passenden Wert zurückgibt?

Könnte man statt diesen Ifs nicht einfach eine Methode in der Direction machen, die dann den passenden Wert zurückgibt?
public HellsBellsCountdown(int time) {
super(time, SWSound.BLOCK_NOTE_BASS, true);
}
@Override
public String countdownCounting() {
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Auch hier müsste das zu einer Methode in Direction umwandelbar sein.

Auch hier müsste das zu einer Methode in Direction umwandelbar sein.
Veraltet
Review

Stat dem If-Block mit Subtract and add: Alle Werte mit int factor = direction.isNorthOrWest() ? 1 : -1; multiplizieren.

Stat dem If-Block mit Subtract and add: Alle Werte mit `int factor = direction.isNorthOrWest() ? 1 : -1;` multiplizieren.
return "bis die Bomben fallen";
}
@Override
public void countdownFinished() {
drop();
startCountdown();
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Üblicherweise verwenden wir eher Bukkit...getScheduler().runTaskTimer(Plugin, lambda-Methode, Zeit(en))

Üblicherweise verwenden wir eher Bukkit...getScheduler().runTaskTimer(Plugin, lambda-Methode, Zeit(en))
}
}
private static class Point {
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Location addAndToLocation(World world, int x, int y, int z) {
return new Location(world, this.x + x, this.y + y, this.z + z); //NOSONAR
}
}
private enum State {
PRE(60, 80, 1),
FIRST(40, 60, 5),
SECOND(30, 40, 6),
THIRD(20, 30, 6),
FOURTH(10, 20, 7),
LAST(5, 10, 0);
State(int minTime, int maxTime, int switchAfter) {
this.MIN_TIME = minTime;
this.MAX_TIME = maxTime;
this.SWITCH_AFTER = switchAfter;
}
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Ich glaube, du verwendest immer dieselben Parameter (bis auf die variable Zeit), daher kannst du den Sound und Level direkt im Konstruktor setzen und musst das nicht übergeben...

Ich glaube, du verwendest immer dieselben Parameter (bis auf die variable Zeit), daher kannst du den Sound und Level direkt im Konstruktor setzen und musst das nicht übergeben...
private final int MIN_TIME; //NOSONAR
private final int MAX_TIME; //NOSONAR
private final int SWITCH_AFTER; //NOSONAR
public State getNext() {
switch (this) {
case PRE:
return FIRST;
case FIRST:
return SECOND;
case SECOND:
return THIRD;
case THIRD:
return FOURTH;
Zeanon markierte diese Unterhaltung als gelöst
Review

Ich weiß nicht, aber ich glaube, dafür, dass an einer Stelle mal ein subtract und ein add ausgeführt wird (generalisierbar mit * +-1) ist es etwas overkill, eine eigene Klasse dafür vorzuhalten, selbst wenn Location in der 1.8 (glaube war der Grund) eine .add o.ä. Methode bereitstellt, ist etwas overkill. Dann hat man halt beim Aufruf etwas (mehr) Arithmetik.

Ich weiß nicht, aber ich glaube, dafür, dass an einer Stelle mal ein subtract und ein add ausgeführt wird (generalisierbar mit * +-1) ist es etwas overkill, eine eigene Klasse dafür vorzuhalten, selbst wenn Location in der 1.8 (glaube war der Grund) eine .add o.ä. Methode bereitstellt, ist etwas overkill. Dann hat man halt beim Aufruf etwas (mehr) Arithmetik.
case FOURTH:
case LAST:
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Warum geht es nicht, Location oder Vector zu verwenden?

Warum geht es nicht, Location oder Vector zu verwenden?
Veraltet
Review

Weil Location und Vektor zu mehr undurchsichtigem code führt

Weil Location und Vektor zu mehr undurchsichtigem code führt
return LAST;
default:
return PRE;
}
}
}
private enum Direction {
NORTH(0, 0, 1),
SOUTH(0, 0, -1),
EAST(1, 0, 0),
WEST(-1, 0, 0);
int dx;
int dy;
int dz;
Direction(int dx, int dy, int dz) {
this.dx = dx;
this.dy = dy;
this.dz = dz;
}
public static Direction getRandom() {
return Direction.values()[random.nextInt(Direction.values().length)];
}
Direction other() {
switch (this) {
case NORTH:
return EAST;
case SOUTH:
return WEST;
case EAST:
return NORTH;
case WEST:
return SOUTH;
default:
return this;
}
}
public int getLength(int length1, int length2) {
return isNorthOrSouth() ? length1 : length2;
}
public boolean isNorthOrSouth() {
return this == NORTH || this == SOUTH;
}
public boolean isNorthOrWest() {
return this == NORTH || this == WEST;
}
}
}