Update from Git Manager GUI

This commit is contained in:
2026-03-17 13:05:46 +01:00
parent 80dd5446e1
commit 731c5228ad
6 changed files with 324 additions and 33 deletions

View File

@@ -281,7 +281,7 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
}
// ── Hologramm-Verwaltung ─────────────────────────────────────────
// /fb hologram set <id> goals|wins Hologramm erstellen
// /fb hologram set <id> goals|wins|match Hologramm erstellen
// /fb hologram remove Nächstes Hologramm (< 5 Blöcke) entfernen
// /fb hologram delete <id> Hologramm nach ID löschen
// /fb hologram reload Alle Hologramme neu spawnen
@@ -291,7 +291,7 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
if (args.length < 2) {
player.sendMessage(MessageUtil.header("Hologramm-Befehle"));
player.sendMessage("§e/fb hologram set <id> goals|wins §7 Hologramm setzen");
player.sendMessage("§e/fb hologram set <id> goals|wins|match §7 Hologramm setzen");
player.sendMessage("§e/fb hologram remove §7 Nächstes entfernen (< 5 Blöcke)");
player.sendMessage("§e/fb hologram delete <id> §7 Nach ID löschen");
player.sendMessage("§e/fb hologram reload §7 Alle neu laden");
@@ -303,18 +303,27 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
switch (args[1].toLowerCase()) {
case "set" -> {
if (args.length < 4) {
player.sendMessage(MessageUtil.error("Benutze: /fb hologram set <id> goals|wins"));
player.sendMessage(MessageUtil.error("Benutze: /fb hologram set <id> goals|wins|match"));
return true;
}
String id = args[2];
FussballHologram.HoloType type = switch (args[3].toLowerCase()) {
case "wins", "siege" -> FussballHologram.HoloType.WINS;
case "match", "live", "game" -> FussballHologram.HoloType.MATCH;
default -> FussballHologram.HoloType.GOALS;
};
plugin.getHologramManager().createHologram(id, player.getLocation(), type);
String holoLabel = type == FussballHologram.HoloType.WINS ? "Top-10-Siege" : "Top-10-Tore";
String holoLabel = switch (type) {
case WINS -> "Top-10-Siege";
case MATCH -> "Live-Match";
default -> "Top-10-Tore";
};
player.sendMessage(MessageUtil.success("§e" + id + " §a(" + holoLabel + ") Hologramm gesetzt!"));
player.sendMessage("§7§oRechtsklick auf das Hologramm wechselt zwischen Tore und Siege.");
if (type == FussballHologram.HoloType.MATCH) {
player.sendMessage("§7§oLive-Match-Hologramm aktualisiert sich automatisch bei Toren und Nachspielzeit.");
} else {
player.sendMessage("§7§oRechtsklick auf das Hologramm wechselt zwischen Tore und Siege.");
}
}
case "remove" -> {
String removed = plugin.getHologramManager().removeNearest(player.getLocation());
@@ -346,7 +355,7 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
}
}
}
default -> player.sendMessage(MessageUtil.error("Gültig: set <id> goals|wins | remove | delete <id> | reload | list"));
default -> player.sendMessage(MessageUtil.error("Gültig: set <id> goals|wins|match | remove | delete <id> | reload | list"));
}
}
@@ -485,7 +494,7 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
s.sendMessage("§e/fb history [n] §7- Letzte Spiele anzeigen");
if (s.hasPermission("fussball.admin")) {
s.sendMessage("§c§lAdmin: §ccreate / delete / setup / stop / debug / dropball");
s.sendMessage("§c§lAdmin: §chologram set goals|wins / remove / reload");
s.sendMessage("§c§lAdmin: §chologram set goals|wins|match / remove / reload");
}
}
@@ -519,7 +528,7 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
} else if (args.length == 3 && args[0].equalsIgnoreCase("hologram") && args[1].equalsIgnoreCase("set")) {
list.addAll(plugin.getArenaManager().getArenaNames()); // id-Vorschläge (frei wählbar, aber arena-namen passen)
} else if (args.length == 4 && args[0].equalsIgnoreCase("hologram") && args[1].equalsIgnoreCase("set")) {
list.addAll(List.of("goals", "wins"));
list.addAll(List.of("goals", "wins", "match"));
} else if (args.length == 3 && args[0].equalsIgnoreCase("hologram") && args[1].equalsIgnoreCase("delete")) {
list.addAll(plugin.getHologramManager().getHologramIds());
} else if (args.length == 3 && args[0].equalsIgnoreCase("setgk")) {

View File

@@ -16,6 +16,8 @@ import org.bukkit.boss.BossBar;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.FireworkEffect;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.potion.PotionEffect;
@@ -94,6 +96,8 @@ public class Game {
private int spawnCooldown = 0;
private int ballMissingTicks = 0; // Ticks ohne lebenden Ball → Respawn
private static final int BALL_MISSING_TIMEOUT = 80; // 4s
private static final int GOAL_BEACON_SCAN_RADIUS = 10;
private static final int GOAL_BEACON_MAX_PER_SIDE = 4;
/** Ticks, in denen der Anstoß-Kreis erzwungen wird (Gegner müssen Abstand halten) */
private int kickoffEnforceTicks = 0;
@@ -356,6 +360,7 @@ public class Game {
secondHalf = false;
timeLeft = arena.getGameDuration();
secondsPlayed = 0;
updateGoalBeaconColors();
bossBar = Bukkit.createBossBar("§e⚽ §c0 §7: §90 §8| §e05:00", BarColor.GREEN, BarStyle.SOLID);
bossBar.setProgress(1.0);
@@ -438,6 +443,7 @@ public class Game {
state = GameState.RUNNING;
secondHalf = true;
timeLeft = arena.getGameDuration() / 2;
updateGoalBeaconColors();
// Nachspielzeit der 1. Halbzeit zurücksetzen
injuryTimeBuffer = 0;
inInjuryTime = false;
@@ -487,6 +493,7 @@ public class Game {
state = GameState.OVERTIME;
overtimeDone = true;
timeLeft = 600; // 2x5min = 10 Min Verlängerung
updateGoalBeaconColors();
if (ball != null) ball.remove();
spawnBallDelayed(arena.getBallSpawn());
@@ -891,8 +898,7 @@ public class Game {
switch (side) {
case "side" -> {
resumeLocation = arena.clampToField(outLocation);
resumeLocation.setY(outLocation.getY());
resumeLocation = moveInsideField(arena.clampToField(outLocation), 1.25);
if (touchTeam == null) {
throwInTeam = null;
message = "§e⚽ §7Ball im Aus! §7Einwurf!";
@@ -905,28 +911,28 @@ public class Game {
}
case "redEnd" -> {
if (touchTeam == Team.RED) {
resumeLocation = getCornerLocation(outLocation);
resumeLocation = moveInsideField(getCornerLocation(outLocation), 1.25);
throwInTeam = Team.BLUE;
message = "§e⚽ §7Ball im Aus! §9Ecke für Blaues Team§7!";
} else {
resumeLocation = arena.getRedSpawn() != null ? arena.getRedSpawn() : arena.getBallSpawn();
resumeLocation = moveInsideField(arena.getRedSpawn() != null ? arena.getRedSpawn() : arena.getBallSpawn(), 1.25);
throwInTeam = Team.RED;
message = "§e⚽ §7Ball im Aus! §cAbstoß für Rotes Team§7!";
}
}
case "blueEnd" -> {
if (touchTeam == Team.BLUE) {
resumeLocation = getCornerLocation(outLocation);
resumeLocation = moveInsideField(getCornerLocation(outLocation), 1.25);
throwInTeam = Team.RED;
message = "§e⚽ §7Ball im Aus! §cEcke für Rotes Team§7!";
} else {
resumeLocation = arena.getBlueSpawn() != null ? arena.getBlueSpawn() : arena.getBallSpawn();
resumeLocation = moveInsideField(arena.getBlueSpawn() != null ? arena.getBlueSpawn() : arena.getBallSpawn(), 1.25);
throwInTeam = Team.BLUE;
message = "§e⚽ §7Ball im Aus! §9Abstoß für Blaues Team§7!";
}
}
default -> {
resumeLocation = arena.getBallSpawn();
resumeLocation = moveInsideField(arena.getBallSpawn(), 1.25);
throwInTeam = null;
message = "§e⚽ §7Ball im Aus!";
}
@@ -956,6 +962,25 @@ public class Game {
return new Location(outLoc.getWorld(), cx, y, cz);
}
private Location moveInsideField(Location source, double inset) {
if (source == null) return arena.getBallSpawn();
if (arena.getFieldMin() == null || arena.getFieldMax() == null) return source.clone();
double minX = Math.min(arena.getFieldMin().getX(), arena.getFieldMax().getX()) + inset;
double maxX = Math.max(arena.getFieldMin().getX(), arena.getFieldMax().getX()) - inset;
double minZ = Math.min(arena.getFieldMin().getZ(), arena.getFieldMax().getZ()) + inset;
double maxZ = Math.max(arena.getFieldMin().getZ(), arena.getFieldMax().getZ()) - inset;
// Bei sehr kleinen Feldern: notfalls exakt klemmen statt invertierter Grenzen.
if (minX > maxX) { minX = Math.min(arena.getFieldMin().getX(), arena.getFieldMax().getX()); maxX = Math.max(arena.getFieldMin().getX(), arena.getFieldMax().getX()); }
if (minZ > maxZ) { minZ = Math.min(arena.getFieldMin().getZ(), arena.getFieldMax().getZ()); maxZ = Math.max(arena.getFieldMin().getZ(), arena.getFieldMax().getZ()); }
double x = Math.max(minX, Math.min(source.getX(), maxX));
double z = Math.max(minZ, Math.min(source.getZ(), maxZ));
double y = arena.getBallSpawn() != null ? arena.getBallSpawn().getY() : source.getY();
return new Location(source.getWorld(), x, y, z, source.getYaw(), source.getPitch());
}
private void checkPlayerBallInteraction() {
if (ball == null || !ball.isActive() || ball.isHeld()) return;
for (UUID uuid : allPlayers) {
@@ -1744,6 +1769,14 @@ public class Game {
if (bossBar != null) bossBar.removePlayer(player);
scoreboard.remove(player);
resetPlayer(player);
// Wenn ein Team komplett disqualifiziert wurde, gewinnt das andere Team sofort.
if (state == GameState.RUNNING || state == GameState.OVERTIME || state == GameState.PENALTY || state == GameState.GOAL) {
if (redTeam.isEmpty() && !blueTeam.isEmpty()) { endGame(Team.BLUE); return; }
if (blueTeam.isEmpty() && !redTeam.isEmpty()) { endGame(Team.RED); return; }
if (redTeam.isEmpty() && blueTeam.isEmpty()) { endGame(null); return; }
}
if (allPlayers.size() < arena.getMinPlayers()) { endGame(getWinnerTeam()); return; }
scoreboard.updateAll(); refreshSigns();
}
@@ -1810,6 +1843,8 @@ public class Game {
lastKicker = null;
secondLastKicker = null;
lastKickWasHeader = false;
secondHalf = false;
updateGoalBeaconColors();
// Persistente Statistiken speichern
// BUG FIX: nach Elfmeter kann redScore == blueScore true sein obwohl ein Gewinner existiert.
@@ -1945,6 +1980,70 @@ public class Game {
private void refreshSigns() { plugin.getSignListener().refreshSignsForArena(arena.getName()); }
private void updateGoalBeaconColors() {
setGoalBeaconColor(getGoalCenter(true), secondHalf ? Team.BLUE : Team.RED);
setGoalBeaconColor(getGoalCenter(false), secondHalf ? Team.RED : Team.BLUE);
}
private void setGoalBeaconColor(Location goalCenter, Team defendingTeam) {
List<Block> beacons = findNearbyBeacons(goalCenter, GOAL_BEACON_SCAN_RADIUS, GOAL_BEACON_MAX_PER_SIDE);
if (beacons.isEmpty()) return;
Material colorGlass = defendingTeam == Team.RED
? Material.RED_STAINED_GLASS
: Material.BLUE_STAINED_GLASS;
for (Block beacon : beacons) {
Block above = beacon.getRelative(BlockFace.UP);
Material current = above.getType();
if (current == Material.AIR || isStainedGlass(current)) {
above.setType(colorGlass, false);
}
}
}
private List<Block> findNearbyBeacons(Location center, int radius, int maxCount) {
if (center == null || center.getWorld() == null) return Collections.emptyList();
List<Block> found = new ArrayList<>();
int cx = center.getBlockX();
int cy = center.getBlockY();
int cz = center.getBlockZ();
for (int x = cx - radius; x <= cx + radius; x++) {
for (int y = cy - 6; y <= cy + 6; y++) {
for (int z = cz - radius; z <= cz + radius; z++) {
Block block = center.getWorld().getBlockAt(x, y, z);
if (block.getType() != Material.BEACON) continue;
found.add(block);
}
}
}
found.sort(Comparator.comparingDouble(b -> b.getLocation().distanceSquared(center)));
if (found.size() > maxCount) {
return new ArrayList<>(found.subList(0, maxCount));
}
return found;
}
private boolean isStainedGlass(Material material) {
return material.name().endsWith("_STAINED_GLASS");
}
private Location getGoalCenter(boolean redGoal) {
Location min = redGoal ? arena.getRedGoalMin() : arena.getBlueGoalMin();
Location max = redGoal ? arena.getRedGoalMax() : arena.getBlueGoalMax();
if (min == null || max == null || min.getWorld() == null) return null;
return new Location(
min.getWorld(),
(min.getX() + max.getX()) / 2.0,
(min.getY() + max.getY()) / 2.0,
(min.getZ() + max.getZ()) / 2.0
);
}
/** Broadcast an alle Spieler UND Zuschauer */
public void broadcastAll(String msg) {
for (UUID uuid : getAllAndSpectators()) { Player p = Bukkit.getPlayer(uuid); if (p != null) p.sendMessage(msg); }

View File

@@ -1,6 +1,8 @@
package de.fussball.plugin.hologram;
import de.fussball.plugin.Fussball;
import de.fussball.plugin.game.Game;
import de.fussball.plugin.game.GameState;
import de.fussball.plugin.stats.StatsManager;
import org.bukkit.Bukkit;
import org.bukkit.Color;
@@ -9,6 +11,9 @@ import org.bukkit.entity.Display;
import org.bukkit.entity.Interaction;
import org.bukkit.entity.Player;
import org.bukkit.entity.TextDisplay;
import org.bukkit.util.Transformation;
import org.joml.AxisAngle4f;
import org.joml.Vector3f;
import java.util.Map;
import java.util.UUID;
@@ -28,7 +33,7 @@ public class FussballHologram {
/** Render-Radius: 48 Blöcke (2304 = 48²) */
private static final double RENDER_RADIUS_SQ = 2304.0;
public enum HoloType { GOALS, WINS }
public enum HoloType { GOALS, WINS, MATCH }
private final String id;
private final Location location;
@@ -53,6 +58,9 @@ public class FussballHologram {
/** Rechtsklick → zur nächsten Seite (GOALS ↔ WINS) */
public void nextPage(Player player) {
if (type == HoloType.MATCH) {
return;
}
// Wir haben 2 Seiten: 0 = GOALS, 1 = WINS
int next = (currentPage.getOrDefault(player.getUniqueId(), 0) + 1) % 2;
currentPage.put(player.getUniqueId(), next);
@@ -74,8 +82,13 @@ public class FussballHologram {
}
// Seite bestimmen
int pageIdx = currentPage.getOrDefault(player.getUniqueId(), type == HoloType.WINS ? 1 : 0);
HoloType displayType = pageIdx == 1 ? HoloType.WINS : HoloType.GOALS;
HoloType displayType;
if (type == HoloType.MATCH) {
displayType = HoloType.MATCH;
} else {
int pageIdx = currentPage.getOrDefault(player.getUniqueId(), type == HoloType.WINS ? 1 : 0);
displayType = pageIdx == 1 ? HoloType.WINS : HoloType.GOALS;
}
String text = buildText(displayType);
@@ -93,34 +106,47 @@ public class FussballHologram {
entity.setText(text);
entity.setInvulnerable(true);
entity.setSeeThrough(false);
});
// ── Interaction-Entity spawnen (Hitbox für Rechtsklick) ──────────
Interaction interact = location.getWorld().spawn(location, Interaction.class, entity -> {
entity.setInteractionWidth(2.5f);
entity.setInteractionHeight(2.5f);
entity.setCustomNameVisible(false);
entity.setPersistent(false);
applyVisualScale(entity, displayType);
});
// ── Nur für diesen Spieler sichtbar machen ───────────────────────
TextDisplay finalDisplay = display;
Interaction interact = null;
if (displayType != HoloType.MATCH) {
// Match-Hologramme sind nur Anzeige, ohne Klick-Hitbox.
interact = location.getWorld().spawn(location, Interaction.class, entity -> {
entity.setInteractionWidth(2.5f);
entity.setInteractionHeight(2.5f);
entity.setCustomNameVisible(false);
entity.setPersistent(false);
});
}
Interaction finalInteract = interact;
for (Player other : Bukkit.getOnlinePlayers()) {
if (!other.getUniqueId().equals(player.getUniqueId())) {
other.hideEntity(plugin, finalDisplay);
other.hideEntity(plugin, finalInteract);
if (finalInteract != null) {
other.hideEntity(plugin, finalInteract);
}
}
}
playerEntities.put(player.getUniqueId(), display);
playerInteractions.put(player.getUniqueId(), interact);
if (interact != null) {
playerInteractions.put(player.getUniqueId(), interact);
}
} else {
// ── Bestehende Entity nur aktualisieren (kein Re-Spawn) ──────────
if (!display.getText().equals(text)) {
display.setText(text);
}
applyVisualScale(display, displayType);
if (displayType == HoloType.MATCH) {
Interaction interact = playerInteractions.remove(player.getUniqueId());
if (interact != null) interact.remove();
}
}
}
@@ -159,6 +185,10 @@ public class FussballHologram {
/** Baut den anzuzeigenden Text aus den aktuellen Top-10-Statistiken */
private String buildText(HoloType showType) {
if (showType == HoloType.MATCH) {
return buildMatchText();
}
StringBuilder sb = new StringBuilder();
if (showType == HoloType.GOALS) {
@@ -202,6 +232,91 @@ public class FussballHologram {
return sb.toString();
}
private String buildMatchText() {
Game game = findRelevantGame();
if (game == null) {
return "§e§lLive Match\n§8§m────────────────\n§7Kein Spiel aktiv\n§8- : -\n§8--:--";
}
String header = "§e§lLive Match";
String separator = "§8§m────────────────";
String phase = buildPhaseLabel(game);
String score = "§c§l" + game.getRedScore() + " §r§7: §9§l" + game.getBlueScore();
String timeLabel = game.isInInjuryTime()
? "§c+" + formatInjury(game.getInjuryTimeBuffer()) + " §7(Nachspielzeit)"
: "§e" + formatMainTime(game.getTimeLeft());
return header + "\n" + separator + "\n" + phase + "\n" + score + "\n" + timeLabel;
}
private String buildPhaseLabel(Game game) {
return switch (game.getState()) {
case WAITING -> "§7⏳ Wartet auf Spieler";
case STARTING -> "§aStartet...";
case RUNNING -> game.isSecondHalf() ? "§72. Halbzeit" : "§71. Halbzeit";
case HALFTIME -> "§e⏸ Halbzeit";
case OVERTIME -> "§6⚡ Verlängerung";
case GOAL -> "§6§l⚽ TOR!";
case PENALTY -> "§c🥊 Elfmeterschießen";
case ENDING -> "§8Spiel beendet";
};
}
private void applyVisualScale(TextDisplay display, HoloType showType) {
float scale = showType == HoloType.MATCH ? 5.0f : 1.0f;
display.setTransformation(new Transformation(
new Vector3f(0f, 0f, 0f),
new AxisAngle4f(),
new Vector3f(scale, scale, scale),
new AxisAngle4f()
));
}
private Game findRelevantGame() {
Game best = null;
int bestPrio = Integer.MAX_VALUE;
double bestDist = Double.MAX_VALUE;
for (Game game : plugin.getGameManager().getAllGames()) {
Location ref = game.getArena().getCenter();
if (ref == null) ref = game.getArena().getBallSpawn();
if (ref == null) ref = game.getArena().getLobby();
if (ref == null || ref.getWorld() == null) continue;
if (!ref.getWorld().equals(location.getWorld())) continue;
int prio = switch (game.getState()) {
case RUNNING, OVERTIME, GOAL, PENALTY -> 0;
case STARTING, HALFTIME -> 1;
case WAITING -> 2;
case ENDING -> 3;
};
double dist = ref.distanceSquared(location);
if (prio < bestPrio || (prio == bestPrio && dist < bestDist)) {
best = game;
bestPrio = prio;
bestDist = dist;
}
}
return best;
}
private String formatMainTime(int totalSeconds) {
int safe = Math.max(0, totalSeconds);
int m = safe / 60;
int s = safe % 60;
return String.format("%02d:%02d", m, s);
}
private String formatInjury(int seconds) {
int safe = Math.max(0, seconds);
if (safe >= 60) {
return "+" + (safe / 60) + ":" + String.format("%02d", safe % 60);
}
return "+" + safe + "s";
}
private String medal(int rank) {
return switch (rank) {
case 1 -> "§6§l#1"; // Gold bleibt hebt sich gut ab

View File

@@ -106,10 +106,14 @@ public class HologramManager implements Listener {
);
String typeStr = holoConfig.getString(path + ".type", "GOALS");
FussballHologram.HoloType type =
"WINS".equalsIgnoreCase(typeStr)
? FussballHologram.HoloType.WINS
: FussballHologram.HoloType.GOALS;
FussballHologram.HoloType type;
if ("WINS".equalsIgnoreCase(typeStr)) {
type = FussballHologram.HoloType.WINS;
} else if ("MATCH".equalsIgnoreCase(typeStr) || "LIVE".equalsIgnoreCase(typeStr)) {
type = FussballHologram.HoloType.MATCH;
} else {
type = FussballHologram.HoloType.GOALS;
}
holograms.put(id, new FussballHologram(id, loc, type, plugin));
}

View File

@@ -3,6 +3,8 @@ package de.fussball.plugin.listeners;
import de.fussball.plugin.Fussball;
import de.fussball.plugin.game.Game;
import de.fussball.plugin.game.Team;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -10,7 +12,11 @@ import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
public class PlayerListener implements Listener {
@@ -63,6 +69,64 @@ public class PlayerListener implements Listener {
if (plugin.getGameManager().isInAnyGame(player)) event.setCancelled(true);
}
/**
* Team-Rüstung darf im aktiven Spiel nicht ausgezogen oder verschoben werden.
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player player)) return;
if (!plugin.getGameManager().isInGame(player)) return;
// Direkter Klick auf Helm/Brust/Beine/Schuhe-Slot
if (event.getSlotType() == InventoryType.SlotType.ARMOR) {
event.setCancelled(true);
return;
}
// Shift-Klick auf Rüstung im Inventar (würde in Rüstungsslot auto-equipen/verschieben)
if (event.isShiftClick() && isArmorPiece(event.getCurrentItem())) {
event.setCancelled(true);
return;
}
// Hotbar-Zahlen-Tausch mit Rüstungsteilen blockieren
if (event.getClick().isKeyboardClick()) {
int hotbar = event.getHotbarButton();
if (hotbar >= 0 && hotbar <= 8) {
ItemStack hotbarItem = player.getInventory().getItem(hotbar);
if (isArmorPiece(hotbarItem) || event.getSlotType() == InventoryType.SlotType.ARMOR) {
event.setCancelled(true);
}
}
}
}
/**
* Draggen auf Rüstungsslots blockieren.
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInventoryDrag(InventoryDragEvent event) {
HumanEntity who = event.getWhoClicked();
if (!(who instanceof Player player)) return;
if (!plugin.getGameManager().isInGame(player)) return;
for (int rawSlot : event.getRawSlots()) {
if (event.getView().getSlotType(rawSlot) == InventoryType.SlotType.ARMOR) {
event.setCancelled(true);
return;
}
}
}
private boolean isArmorPiece(ItemStack item) {
if (item == null) return false;
Material t = item.getType();
return t.name().endsWith("_HELMET")
|| t.name().endsWith("_CHESTPLATE")
|| t.name().endsWith("_LEGGINGS")
|| t.name().endsWith("_BOOTS");
}
/**
* Zuschauer dürfen die Arena nicht verlassen (Weltenwechsel blockieren).
* GM3 erlaubt Portale das verhindert, dass ein Zuschauer durch ein Portal

View File

@@ -1,5 +1,5 @@
name: Fussball
version: 1.0.0
version: 1.0.1
main: de.fussball.plugin.Fussball
api-version: 1.21
author: M_Viper