Update from Git Manager GUI
This commit is contained in:
253
src/main/java/de/fussball/plugin/arena/Arena.java
Normal file
253
src/main/java/de/fussball/plugin/arena/Arena.java
Normal file
@@ -0,0 +1,253 @@
|
||||
package de.fussball.plugin.arena;
|
||||
|
||||
import de.fussball.plugin.Fussball;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import java.util.*;
|
||||
|
||||
public class Arena implements ConfigurationSerializable {
|
||||
|
||||
private final String name;
|
||||
private Location center, redSpawn, blueSpawn, ballSpawn;
|
||||
private Location redGoalMin, redGoalMax, blueGoalMin, blueGoalMax, lobby;
|
||||
private Location fieldMin, fieldMax;
|
||||
private int minPlayers, maxPlayers, gameDuration;
|
||||
|
||||
/**
|
||||
* Neue Arena erstellt – Standardwerte werden aus der config.yml gelesen.
|
||||
* Bereits gespeicherte Arenen laden ihre eigenen Werte über deserialize().
|
||||
*/
|
||||
public Arena(String name) {
|
||||
this.name = name;
|
||||
Fussball plugin = Fussball.getInstance();
|
||||
if (plugin != null) {
|
||||
this.minPlayers = plugin.getConfig().getInt("defaults.min-players", 2);
|
||||
this.maxPlayers = plugin.getConfig().getInt("defaults.max-players", 10);
|
||||
this.gameDuration = plugin.getConfig().getInt("defaults.game-duration", 300);
|
||||
} else {
|
||||
// Fallback falls getInstance() noch nicht verfügbar (z.B. Deserialisierung)
|
||||
this.minPlayers = 2;
|
||||
this.maxPlayers = 10;
|
||||
this.gameDuration = 300;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSetupComplete() {
|
||||
return center != null && redSpawn != null && blueSpawn != null && ballSpawn != null
|
||||
&& redGoalMin != null && redGoalMax != null
|
||||
&& blueGoalMin != null && blueGoalMax != null && lobby != null;
|
||||
}
|
||||
|
||||
public boolean isInRedGoal(Location loc) { return isInRegion(loc, redGoalMin, redGoalMax); }
|
||||
public boolean isInBlueGoal(Location loc) { return isInRegion(loc, blueGoalMin, blueGoalMax); }
|
||||
|
||||
/**
|
||||
* BUG FIX: Nur X und Z prüfen (Y ignorieren).
|
||||
* Vorher führte die Y-Prüfung dazu, dass der Ball beim Anstoß sofort
|
||||
* als Aus erkannt wurde, weil der ArmorStand über dem Boden schwebt.
|
||||
*/
|
||||
public boolean isInField(Location loc) {
|
||||
if (fieldMin == null || fieldMax == null) return true;
|
||||
return isInField2D(loc);
|
||||
}
|
||||
|
||||
private boolean isInField2D(Location loc) {
|
||||
if (fieldMin == null || fieldMax == null || loc == null) return true;
|
||||
double minX = Math.min(fieldMin.getX(), fieldMax.getX());
|
||||
double maxX = Math.max(fieldMin.getX(), fieldMax.getX());
|
||||
double minZ = Math.min(fieldMin.getZ(), fieldMax.getZ());
|
||||
double maxZ = Math.max(fieldMin.getZ(), fieldMax.getZ());
|
||||
return loc.getX() >= minX && loc.getX() <= maxX
|
||||
&& loc.getZ() >= minZ && loc.getZ() <= maxZ;
|
||||
}
|
||||
|
||||
/** Auf welcher Seite hat der Ball das Feld verlassen? (nur XZ, kein Y) */
|
||||
public String getOutSide(Location loc) {
|
||||
if (fieldMin == null || fieldMax == null) return null;
|
||||
if (isInField2D(loc)) return null;
|
||||
|
||||
double minX = Math.min(fieldMin.getX(), fieldMax.getX());
|
||||
double maxX = Math.max(fieldMin.getX(), fieldMax.getX());
|
||||
double minZ = Math.min(fieldMin.getZ(), fieldMax.getZ());
|
||||
double maxZ = Math.max(fieldMin.getZ(), fieldMax.getZ());
|
||||
double lenX = maxX - minX;
|
||||
double lenZ = maxZ - minZ;
|
||||
|
||||
if (lenZ >= lenX) {
|
||||
if (loc.getZ() < minZ) return "redEnd";
|
||||
if (loc.getZ() > maxZ) return "blueEnd";
|
||||
return "side";
|
||||
} else {
|
||||
if (loc.getX() < minX) return "redEnd";
|
||||
if (loc.getX() > maxX) return "blueEnd";
|
||||
return "side";
|
||||
}
|
||||
}
|
||||
|
||||
public Location clampToField(Location loc) {
|
||||
if (fieldMin == null || fieldMax == null) return loc;
|
||||
double x = Math.max(Math.min(fieldMin.getX(), fieldMax.getX()),
|
||||
Math.min(loc.getX(), Math.max(fieldMin.getX(), fieldMax.getX())));
|
||||
double y = loc.getY();
|
||||
double z = Math.max(Math.min(fieldMin.getZ(), fieldMax.getZ()),
|
||||
Math.min(loc.getZ(), Math.max(fieldMin.getZ(), fieldMax.getZ())));
|
||||
return new Location(loc.getWorld(), x, y, z);
|
||||
}
|
||||
|
||||
// Tor-Erkennung: volle 3D-Prüfung (Y ist für das Tor wichtig!)
|
||||
private boolean isInRegion(Location loc, Location min, Location max) {
|
||||
if (min == null || max == null || loc == null) return false;
|
||||
if (loc.getWorld() == null || min.getWorld() == null) return false;
|
||||
if (!loc.getWorld().equals(min.getWorld())) return false;
|
||||
return loc.getX() >= Math.min(min.getX(), max.getX()) && loc.getX() <= Math.max(min.getX(), max.getX())
|
||||
&& loc.getY() >= Math.min(min.getY(), max.getY()) && loc.getY() <= Math.max(min.getY(), max.getY())
|
||||
&& loc.getZ() >= Math.min(min.getZ(), max.getZ()) && loc.getZ() <= Math.max(min.getZ(), max.getZ());
|
||||
}
|
||||
|
||||
// ── Spielfeld-Achse (für Abseits-Berechnung) ────────────────────────────
|
||||
|
||||
/**
|
||||
* Gibt den Einheitsvektor zurück der vom roten Tor zum blauen Tor zeigt.
|
||||
* Funktioniert unabhängig davon ob das Feld in X- oder Z-Richtung ausgerichtet ist.
|
||||
*/
|
||||
public org.bukkit.util.Vector getFieldDirection() {
|
||||
if (redGoalMin == null || redGoalMax == null || blueGoalMin == null || blueGoalMax == null) return null;
|
||||
double rX = (redGoalMin.getX() + redGoalMax.getX()) / 2.0;
|
||||
double rZ = (redGoalMin.getZ() + redGoalMax.getZ()) / 2.0;
|
||||
double bX = (blueGoalMin.getX() + blueGoalMax.getX()) / 2.0;
|
||||
double bZ = (blueGoalMin.getZ() + blueGoalMax.getZ()) / 2.0;
|
||||
org.bukkit.util.Vector dir = new org.bukkit.util.Vector(bX - rX, 0, bZ - rZ);
|
||||
double len = dir.length();
|
||||
if (len < 0.001) return null;
|
||||
return dir.multiply(1.0 / len);
|
||||
}
|
||||
|
||||
/** Projektionswert einer Location auf die Spielfeld-Achse */
|
||||
public double getAxisValue(org.bukkit.Location loc) {
|
||||
org.bukkit.util.Vector dir = getFieldDirection();
|
||||
if (dir == null || loc == null) return 0;
|
||||
return loc.getX() * dir.getX() + loc.getZ() * dir.getZ();
|
||||
}
|
||||
|
||||
public double getRedGoalAxisValue() {
|
||||
if (redGoalMin == null || redGoalMax == null) return 0;
|
||||
org.bukkit.util.Vector dir = getFieldDirection();
|
||||
if (dir == null) return 0;
|
||||
double cx = (redGoalMin.getX() + redGoalMax.getX()) / 2.0;
|
||||
double cz = (redGoalMin.getZ() + redGoalMax.getZ()) / 2.0;
|
||||
return cx * dir.getX() + cz * dir.getZ();
|
||||
}
|
||||
|
||||
public double getBlueGoalAxisValue() {
|
||||
if (blueGoalMin == null || blueGoalMax == null) return 0;
|
||||
org.bukkit.util.Vector dir = getFieldDirection();
|
||||
if (dir == null) return 0;
|
||||
double cx = (blueGoalMin.getX() + blueGoalMax.getX()) / 2.0;
|
||||
double cz = (blueGoalMin.getZ() + blueGoalMax.getZ()) / 2.0;
|
||||
return cx * dir.getX() + cz * dir.getZ();
|
||||
}
|
||||
|
||||
public double getCenterAxisValue() {
|
||||
return (getRedGoalAxisValue() + getBlueGoalAxisValue()) / 2.0;
|
||||
}
|
||||
|
||||
// ── Serialisierung ───────────────────────────────────────────────────────
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("name", name);
|
||||
map.put("minPlayers", minPlayers);
|
||||
map.put("maxPlayers", maxPlayers);
|
||||
map.put("gameDuration", gameDuration);
|
||||
if (lobby != null) map.put("lobby", serLoc(lobby));
|
||||
if (center != null) map.put("center", serLoc(center));
|
||||
if (redSpawn != null) map.put("redSpawn", serLoc(redSpawn));
|
||||
if (blueSpawn != null) map.put("blueSpawn", serLoc(blueSpawn));
|
||||
if (ballSpawn != null) map.put("ballSpawn", serLoc(ballSpawn));
|
||||
if (redGoalMin != null) map.put("redGoalMin", serLoc(redGoalMin));
|
||||
if (redGoalMax != null) map.put("redGoalMax", serLoc(redGoalMax));
|
||||
if (blueGoalMin != null) map.put("blueGoalMin", serLoc(blueGoalMin));
|
||||
if (blueGoalMax != null) map.put("blueGoalMax", serLoc(blueGoalMax));
|
||||
if (fieldMin != null) map.put("fieldMin", serLoc(fieldMin));
|
||||
if (fieldMax != null) map.put("fieldMax", serLoc(fieldMax));
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Beim Laden gespeicherter Arenen werden die eigenen Werte aus der YAML-Datei
|
||||
* gelesen – NICHT aus der config.yml. So kann jede Arena eigene Werte haben.
|
||||
*/
|
||||
public static Arena deserialize(Map<String, Object> map) {
|
||||
Arena a = new Arena((String) map.get("name"));
|
||||
// Überschreibe Konstruktor-Defaults mit den gespeicherten Werten
|
||||
a.minPlayers = getInt(map, "minPlayers", a.minPlayers);
|
||||
a.maxPlayers = getInt(map, "maxPlayers", a.maxPlayers);
|
||||
a.gameDuration = getInt(map, "gameDuration", a.gameDuration);
|
||||
if (map.containsKey("lobby")) a.lobby = desLoc(map.get("lobby"));
|
||||
if (map.containsKey("center")) a.center = desLoc(map.get("center"));
|
||||
if (map.containsKey("redSpawn")) a.redSpawn = desLoc(map.get("redSpawn"));
|
||||
if (map.containsKey("blueSpawn")) a.blueSpawn = desLoc(map.get("blueSpawn"));
|
||||
if (map.containsKey("ballSpawn")) a.ballSpawn = desLoc(map.get("ballSpawn"));
|
||||
if (map.containsKey("redGoalMin")) a.redGoalMin = desLoc(map.get("redGoalMin"));
|
||||
if (map.containsKey("redGoalMax")) a.redGoalMax = desLoc(map.get("redGoalMax"));
|
||||
if (map.containsKey("blueGoalMin")) a.blueGoalMin = desLoc(map.get("blueGoalMin"));
|
||||
if (map.containsKey("blueGoalMax")) a.blueGoalMax = desLoc(map.get("blueGoalMax"));
|
||||
if (map.containsKey("fieldMin")) a.fieldMin = desLoc(map.get("fieldMin"));
|
||||
if (map.containsKey("fieldMax")) a.fieldMax = desLoc(map.get("fieldMax"));
|
||||
return a;
|
||||
}
|
||||
|
||||
private static String serLoc(Location l) {
|
||||
return l.getWorld().getName() + ";" + l.getX() + ";" + l.getY() + ";" + l.getZ() + ";" + l.getYaw() + ";" + l.getPitch();
|
||||
}
|
||||
|
||||
private static Location desLoc(Object obj) {
|
||||
if (obj == null) return null;
|
||||
try {
|
||||
String[] p = obj.toString().split(";");
|
||||
World world = Bukkit.getWorld(p[0]);
|
||||
if (world == null) return null;
|
||||
return new Location(world, Double.parseDouble(p[1]), Double.parseDouble(p[2]), Double.parseDouble(p[3]),
|
||||
p.length > 4 ? Float.parseFloat(p[4]) : 0f, p.length > 5 ? Float.parseFloat(p[5]) : 0f);
|
||||
} catch (Exception e) { return null; }
|
||||
}
|
||||
|
||||
private static int getInt(Map<String, Object> map, String key, int def) {
|
||||
Object v = map.get(key); return v instanceof Number ? ((Number) v).intValue() : def;
|
||||
}
|
||||
|
||||
// ── Getter / Setter ──────────────────────────────────────────────────────
|
||||
|
||||
public String getName() { return name; }
|
||||
public Location getCenter() { return center; }
|
||||
public void setCenter(Location l) { this.center = l; }
|
||||
public Location getRedSpawn() { return redSpawn; }
|
||||
public void setRedSpawn(Location l) { this.redSpawn = l; }
|
||||
public Location getBlueSpawn() { return blueSpawn; }
|
||||
public void setBlueSpawn(Location l) { this.blueSpawn = l; }
|
||||
public Location getBallSpawn() { return ballSpawn; }
|
||||
public void setBallSpawn(Location l) { this.ballSpawn = l; }
|
||||
public Location getRedGoalMin() { return redGoalMin; }
|
||||
public void setRedGoalMin(Location l) { this.redGoalMin = l; }
|
||||
public Location getRedGoalMax() { return redGoalMax; }
|
||||
public void setRedGoalMax(Location l) { this.redGoalMax = l; }
|
||||
public Location getBlueGoalMin() { return blueGoalMin; }
|
||||
public void setBlueGoalMin(Location l) { this.blueGoalMin = l; }
|
||||
public Location getBlueGoalMax() { return blueGoalMax; }
|
||||
public void setBlueGoalMax(Location l) { this.blueGoalMax = l; }
|
||||
public Location getLobby() { return lobby; }
|
||||
public void setLobby(Location l) { this.lobby = l; }
|
||||
public Location getFieldMin() { return fieldMin; }
|
||||
public void setFieldMin(Location l) { this.fieldMin = l; }
|
||||
public Location getFieldMax() { return fieldMax; }
|
||||
public void setFieldMax(Location l) { this.fieldMax = l; }
|
||||
public int getMinPlayers() { return minPlayers; }
|
||||
public void setMinPlayers(int n) { this.minPlayers = n; }
|
||||
public int getMaxPlayers() { return maxPlayers; }
|
||||
public void setMaxPlayers(int n) { this.maxPlayers = n; }
|
||||
public int getGameDuration() { return gameDuration; }
|
||||
public void setGameDuration(int n) { this.gameDuration = n; }
|
||||
}
|
||||
Reference in New Issue
Block a user