Delete src/main/java/de/lasertag/game/Game.java via Git Manager GUI
This commit is contained in:
@@ -1,736 +0,0 @@
|
||||
package de.lasertag.game;
|
||||
|
||||
import de.lasertag.LasertagPlugin;
|
||||
import de.lasertag.arena.Arena;
|
||||
import de.lasertag.camp.AntiCampManager;
|
||||
import de.lasertag.player.LaserPlayer;
|
||||
import de.lasertag.protection.ModProtectionManager;
|
||||
import de.lasertag.weapon.WeaponType;
|
||||
import de.lasertag.weapon.WeaponUtil;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Game {
|
||||
|
||||
private final LasertagPlugin plugin;
|
||||
private final Arena arena;
|
||||
private final AntiCampManager antiCamp;
|
||||
private final ModProtectionManager modProtect;
|
||||
|
||||
private GameState state = GameState.WAITING;
|
||||
private int timeLeft;
|
||||
private int countdown;
|
||||
|
||||
private final Map<UUID, LaserPlayer> players = new ConcurrentHashMap<>();
|
||||
private final Map<Team, Integer> teamScore = new LinkedHashMap<>();
|
||||
private final Map<UUID, Long> shotCooldown= new ConcurrentHashMap<>();
|
||||
|
||||
private BukkitTask countdownTask, gameTask, healTask;
|
||||
|
||||
public Game(LasertagPlugin plugin, Arena arena) {
|
||||
this.plugin = plugin;
|
||||
this.arena = arena;
|
||||
this.antiCamp = new AntiCampManager(plugin);
|
||||
this.modProtect = new ModProtectionManager(plugin);
|
||||
this.timeLeft = plugin.getConfigManager().getGameDuration();
|
||||
this.countdown = plugin.getConfigManager().getCountdown();
|
||||
for (Team t : Team.values()) teamScore.put(t, 0);
|
||||
arena.initBaseHealth(plugin.getConfigManager().getBaseHealth());
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// SPIELER-VERWALTUNG
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
public boolean addPlayer(Player player) {
|
||||
if (players.containsKey(player.getUniqueId())) return false;
|
||||
if (!isJoinable()) return false;
|
||||
int maxTotal = plugin.getConfigManager().getMaxPlayersPerTeam() * 4;
|
||||
if (players.size() >= maxTotal) return false;
|
||||
|
||||
LaserPlayer lp = new LaserPlayer(player.getUniqueId(), player.getName());
|
||||
lp.setTeam(pickBalancedTeam());
|
||||
lp.setSavedInventory(player.getInventory().getContents().clone());
|
||||
players.put(player.getUniqueId(), lp);
|
||||
|
||||
setupPlayer(player, lp);
|
||||
sendToSpawn(player, lp.getTeam());
|
||||
modProtect.applyProtection(player, this);
|
||||
|
||||
broadcast(plugin.getConfigManager().getText("join",
|
||||
"§e{player} §7hat Team {team} §7beigetreten.",
|
||||
"player", player.getName(), "team", lp.getTeam().colored()));
|
||||
|
||||
plugin.getScoreboardManager().update(player, this);
|
||||
|
||||
if (state == GameState.WAITING
|
||||
&& players.size() >= plugin.getConfigManager().getMinPlayers()) {
|
||||
startCountdown();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
LaserPlayer lp = players.remove(player.getUniqueId());
|
||||
if (lp == null) return;
|
||||
shotCooldown.remove(player.getUniqueId());
|
||||
antiCamp.remove(player.getUniqueId());
|
||||
modProtect.removeProtection(player);
|
||||
|
||||
saveStats(lp, player);
|
||||
restorePlayer(player, lp);
|
||||
plugin.getScoreboardManager().remove(player);
|
||||
|
||||
broadcast(plugin.getConfigManager().getText("leave",
|
||||
"§c{player} §7hat das Spiel verlassen.", "player", player.getName()));
|
||||
|
||||
if (state == GameState.RUNNING
|
||||
&& players.size() < plugin.getConfigManager().getMinPlayers()) {
|
||||
endGame();
|
||||
}
|
||||
}
|
||||
|
||||
private void saveStats(LaserPlayer lp, Player player) {
|
||||
var stats = plugin.getPlayerDataManager().getStats(lp.getUuid());
|
||||
stats.setName(player.getName());
|
||||
stats.apply(lp);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// SPIEL-ABLAUF
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
public void startCountdown() {
|
||||
if (state != GameState.WAITING) return;
|
||||
state = GameState.STARTING;
|
||||
|
||||
final int[] cd = { plugin.getConfigManager().getCountdown() };
|
||||
countdownTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
if (cd[0] <= 0) { countdownTask.cancel(); startGame(); return; }
|
||||
if (cd[0] <= 5 || cd[0] == 10) {
|
||||
broadcast("§eSpiel startet in §b" + cd[0] + " §eSekunden!");
|
||||
playAll(Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f);
|
||||
}
|
||||
float prog = (float) cd[0] / plugin.getConfigManager().getCountdown();
|
||||
for (Player p : getOnline()) p.setExp(Math.max(0f, Math.min(1f, prog)));
|
||||
cd[0]--;
|
||||
}, 0L, 20L);
|
||||
}
|
||||
|
||||
public void startGame() {
|
||||
state = GameState.RUNNING;
|
||||
placeBaseBlocks();
|
||||
|
||||
for (Player p : getOnline()) {
|
||||
p.sendTitle("§b§l⚡ LASERTAG", "§7Verteidige eure Basis!", 10, 50, 10);
|
||||
p.setExp(1f);
|
||||
}
|
||||
playAll(plugin.getConfigManager().getSound("game-start", Sound.ENTITY_ENDER_DRAGON_GROWL), 0.5f, 1.2f);
|
||||
broadcast(plugin.getConfigManager().getText("game-start", "§a§l⚡ DAS SPIEL BEGINNT!"));
|
||||
|
||||
// Heal-Check + AntiCamp: jede Sekunde
|
||||
healTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
tickHeal();
|
||||
antiCamp.tick(this);
|
||||
}, 0L, 20L);
|
||||
|
||||
// Haupt-Timer
|
||||
final int[] tl = { plugin.getConfigManager().getGameDuration() };
|
||||
gameTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
if (tl[0] <= 0) { gameTask.cancel(); endGame(); return; }
|
||||
if (tl[0] == 60) broadcast(plugin.getConfigManager().getText("time-60", "§e⏰ Noch §b60 §eSekunden!"));
|
||||
if (tl[0] == 30) broadcast(plugin.getConfigManager().getText("time-30", "§c⏰ Noch §b30 §eSekunden!"));
|
||||
if (tl[0] == 10) broadcast(plugin.getConfigManager().getText("time-10", "§4⏰ Noch §b10 §4Sekunden!"));
|
||||
|
||||
// Basis regenerieren?
|
||||
if (plugin.getConfigManager().isBaseRegenerate()) {
|
||||
int interval = plugin.getConfigManager().getBaseRegenInterval();
|
||||
if (tl[0] % interval == 0) {
|
||||
for (Team t : Team.values()) {
|
||||
int hp = arena.getBaseHealth(t);
|
||||
int max = plugin.getConfigManager().getBaseHealth();
|
||||
if (hp < max && hp > 0) {
|
||||
arena.damageBase(t); // Missbrauche: erhöhe via setBaseHealth direkt
|
||||
// Eigentlich: arena.regenBase(t); — wir ergänzen das
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timeLeft = tl[0];
|
||||
for (Player p : getOnline()) {
|
||||
plugin.getScoreboardManager().update(p, this);
|
||||
sendActionBar(p);
|
||||
}
|
||||
tl[0]--;
|
||||
}, 0L, 20L);
|
||||
}
|
||||
|
||||
public void endGame() {
|
||||
if (state == GameState.ENDING) return;
|
||||
state = GameState.ENDING;
|
||||
cancelTasks();
|
||||
removeBaseBlocks();
|
||||
modProtect.removeAll(this);
|
||||
antiCamp.reset();
|
||||
|
||||
Team winner = getLeader();
|
||||
for (Player p : getOnline()) {
|
||||
LaserPlayer lp = players.get(p.getUniqueId());
|
||||
boolean won = winner != null && lp != null && lp.getTeam() == winner;
|
||||
p.sendTitle(won ? "§a§lSIEG!" : "§c§lNIEDERLAGE!",
|
||||
winner != null ? "Team " + winner.colored() + " §7gewinnt!" : "§7Unentschieden!",
|
||||
10, 80, 20);
|
||||
p.playSound(p.getLocation(),
|
||||
won ? Sound.UI_TOAST_CHALLENGE_COMPLETE : Sound.ENTITY_VILLAGER_NO, 1f, 1f);
|
||||
showEndStats(p, lp);
|
||||
saveStats(lp, p);
|
||||
}
|
||||
plugin.getPlayerDataManager().saveAll();
|
||||
|
||||
String endMsg = winner != null
|
||||
? plugin.getConfigManager().getText("game-end", "§6§l🏆 Team {team} §6§lhat gewonnen!",
|
||||
"team", winner.colored())
|
||||
: plugin.getConfigManager().getText("game-draw", "§7Unentschieden!");
|
||||
broadcast(endMsg);
|
||||
|
||||
int delay = plugin.getConfigManager().getEndDisplayTime() * 20;
|
||||
Bukkit.getScheduler().runTaskLater(plugin, this::reset, delay);
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
new ArrayList<>(getOnline()).forEach(this::removePlayer);
|
||||
state = GameState.WAITING;
|
||||
timeLeft = plugin.getConfigManager().getGameDuration();
|
||||
countdown = plugin.getConfigManager().getCountdown();
|
||||
players.clear();
|
||||
shotCooldown.clear();
|
||||
antiCamp.reset();
|
||||
for (Team t : Team.values()) teamScore.put(t, 0);
|
||||
arena.initBaseHealth(plugin.getConfigManager().getBaseHealth());
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// SCHUSS-MECHANIK
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
public boolean handleShot(Player shooter, WeaponType weapon) {
|
||||
LaserPlayer lp = players.get(shooter.getUniqueId());
|
||||
if (lp == null || state != GameState.RUNNING) return false;
|
||||
|
||||
if (lp.isHit()) {
|
||||
sendActionBarMsg(shooter, "§c☠ GETROFFEN – Gehe zur §e"
|
||||
+ lp.getTeam().colored() + " §cBasis!");
|
||||
playSound(shooter, Sound.BLOCK_NOTE_BLOCK_DIDGERIDOO, 0.5f, 0.5f);
|
||||
return false;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
long last = shotCooldown.getOrDefault(shooter.getUniqueId(), 0L);
|
||||
int cooldown = plugin.getConfigManager().getWeaponCooldown(weapon.getConfigKey());
|
||||
if (now - last < cooldown) {
|
||||
double rem = (cooldown - (now - last)) / 1000.0;
|
||||
sendActionBarMsg(shooter, "§c⏳ Nachladen... §7(" + String.format("%.1f", rem) + "s)");
|
||||
return false;
|
||||
}
|
||||
shotCooldown.put(shooter.getUniqueId(), now);
|
||||
|
||||
int pellets = plugin.getConfigManager().getWeaponPellets(weapon.getConfigKey());
|
||||
if (pellets > 1) {
|
||||
for (int i = 0; i < pellets; i++) shootRay(shooter, lp, weapon, spreadDir(shooter));
|
||||
} else {
|
||||
shootRay(shooter, lp, weapon, shooter.getEyeLocation().getDirection());
|
||||
}
|
||||
|
||||
Sound shootSnd = plugin.getConfigManager().getSound("shoot", Sound.ENTITY_FIREWORK_ROCKET_BLAST);
|
||||
float shootPitch = plugin.getConfigManager().getSoundPitch("shoot-pitch", 1.8f);
|
||||
float shootVol = plugin.getConfigManager().getSoundVolume("shoot-volume", 0.4f);
|
||||
if (shootSnd != null) shooter.getWorld().playSound(shooter.getLocation(), shootSnd, shootVol, shootPitch);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void shootRay(Player shooter, LaserPlayer shooterLp, WeaponType weapon, Vector dir) {
|
||||
Location eye = shooter.getEyeLocation();
|
||||
int range = plugin.getConfigManager().getWeaponRange(weapon.getConfigKey());
|
||||
|
||||
if (plugin.getConfigManager().isLaserTrailEnabled())
|
||||
drawLaser(eye, dir, weapon, range);
|
||||
|
||||
RayTraceResult result = shooter.getWorld().rayTrace(
|
||||
eye, dir, range, FluidCollisionMode.NEVER, true, 0.5,
|
||||
e -> e instanceof Player && !e.equals(shooter));
|
||||
if (result == null) return;
|
||||
|
||||
// ── Spieler getroffen ─────────────────────────────────────────────────
|
||||
if (result.getHitEntity() instanceof Player victim) {
|
||||
LaserPlayer vLp = players.get(victim.getUniqueId());
|
||||
if (vLp == null || vLp.isHit()) return;
|
||||
if (vLp.getTeam() == shooterLp.getTeam()) return;
|
||||
|
||||
vLp.applyHit();
|
||||
|
||||
// Partikel
|
||||
if (plugin.getConfigManager().isHitEffectEnabled()) {
|
||||
victim.getWorld().spawnParticle(Particle.CRIT,
|
||||
victim.getLocation().add(0,1,0),
|
||||
plugin.getConfigManager().getHitParticleCount(),
|
||||
0.4, 0.4, 0.4, 0.1);
|
||||
}
|
||||
|
||||
// Sounds
|
||||
playSound(victim, plugin.getConfigManager().getSound("hit-victim", Sound.ENTITY_PLAYER_HURT), 1f, 0.8f);
|
||||
playSound(shooter, plugin.getConfigManager().getSound("hit-shooter", Sound.BLOCK_NOTE_BLOCK_BELL), 1f, 2f);
|
||||
|
||||
// Punkte
|
||||
int pts = plugin.getConfigManager().getKillPoints();
|
||||
int streak = shooterLp.getKillStreak() + 1;
|
||||
int bonus = 0;
|
||||
if (streak == 3) bonus = plugin.getConfigManager().getStreak3Bonus();
|
||||
if (streak == 5) bonus = plugin.getConfigManager().getStreak5Bonus();
|
||||
if (streak == 10) bonus = plugin.getConfigManager().getStreak10Bonus();
|
||||
|
||||
shooterLp.registerKill();
|
||||
shooterLp.addScore(pts + bonus);
|
||||
teamScore.merge(shooterLp.getTeam(), pts + bonus, Integer::sum);
|
||||
|
||||
String streakInfo = streak >= 3 ? " §6[" + streak + "er-Serie!+"+bonus+"]" : "";
|
||||
shooter.sendMessage(plugin.getConfigManager().getText("hit-shooter",
|
||||
"§aDu hast §e{victim} §agetroffen! §7(+{pts} Pkt){streak}",
|
||||
"victim", victim.getName(), "pts", pts + bonus, "streak", streakInfo));
|
||||
victim.sendMessage(plugin.getConfigManager().getText("hit-victim",
|
||||
"§cDu wurdest von §e{shooter} §cgetroffen!",
|
||||
"shooter", shooter.getName()));
|
||||
|
||||
// Streak-Broadcast
|
||||
if (streak == 3) broadcastStreak(shooter, "streak-3", "§6TRIPLE KILL!", 3);
|
||||
if (streak == 5) broadcastStreak(shooter, "streak-5", "§bPENTA KILL!", 5);
|
||||
if (streak == 10) broadcastStreak(shooter, "streak-10", "§5§lGODLIKE!", 10);
|
||||
|
||||
sendActionBar(victim);
|
||||
sendActionBar(shooter);
|
||||
plugin.getScoreboardManager().update(shooter, this);
|
||||
plugin.getScoreboardManager().update(victim, this);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Block getroffen (Basisangriff) ────────────────────────────────────
|
||||
if (result.getHitBlock() != null) {
|
||||
Team baseTeam = arena.getBaseTeam(result.getHitBlock().getLocation());
|
||||
if (baseTeam != null && baseTeam != shooterLp.getTeam()) {
|
||||
handleBaseAttack(shooter, shooterLp, baseTeam,
|
||||
result.getHitBlock().getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// HEAL-TICK
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
private void tickHeal() {
|
||||
double baseRadiusSq = Math.pow(plugin.getConfigManager().getBaseRadius(), 2);
|
||||
int healTimeSec = plugin.getConfigManager().getBaseHealTime();
|
||||
|
||||
for (Map.Entry<UUID, LaserPlayer> e : players.entrySet()) {
|
||||
Player p = Bukkit.getPlayer(e.getKey());
|
||||
LaserPlayer lp = e.getValue();
|
||||
if (p == null || !lp.isHit()) continue;
|
||||
|
||||
Location base = arena.getBase(lp.getTeam());
|
||||
if (base == null) continue;
|
||||
|
||||
boolean near = p.getLocation().distanceSquared(base) <= baseRadiusSq;
|
||||
|
||||
if (near) {
|
||||
if (!lp.isHealing()) {
|
||||
lp.startHealing();
|
||||
p.sendMessage(plugin.getConfigManager().getText("heal-start",
|
||||
"§aHeilung gestartet...", "secs", healTimeSec));
|
||||
playSound(p, plugin.getConfigManager().getSound("heal-start",
|
||||
Sound.BLOCK_ENCHANTMENT_TABLE_USE), 1f, 1f);
|
||||
} else if (lp.healElapsedMs() >= healTimeSec * 1000L) {
|
||||
lp.completeHeal();
|
||||
p.sendMessage(plugin.getConfigManager().getText("heal-complete",
|
||||
"§a✔ Du bist wieder einsatzbereit!"));
|
||||
Sound hs = plugin.getConfigManager().getSound("heal-complete",
|
||||
Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
|
||||
float hp = plugin.getConfigManager().getSoundPitch("heal-complete-pitch", 1.5f);
|
||||
playSound(p, hs, 1f, hp);
|
||||
p.sendTitle("§a§lBEREIT!", "§7Du kannst wieder schießen!", 5, 30, 5);
|
||||
if (plugin.getConfigManager().isInvincibleAfterHeal()) {
|
||||
p.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,
|
||||
plugin.getConfigManager().getInvincibleDuration(), 4, false, false));
|
||||
}
|
||||
if (plugin.getConfigManager().isHealEffectEnabled()) {
|
||||
p.getWorld().spawnParticle(Particle.VILLAGER_HAPPY,
|
||||
p.getLocation().add(0,1,0), 20, 0.5, 0.5, 0.5, 0.05);
|
||||
}
|
||||
} else {
|
||||
double prog = lp.healElapsedMs() / (healTimeSec * 1000.0);
|
||||
sendActionBarMsg(p, "§a🛡 Heilung: " + buildBar(prog, 15)
|
||||
+ " §7" + String.format("%.1f", lp.healElapsedMs()/1000.0)
|
||||
+ "§8/" + healTimeSec + "s");
|
||||
}
|
||||
} else {
|
||||
if (lp.isHealing()) {
|
||||
lp.stopHealing();
|
||||
p.sendMessage(plugin.getConfigManager().getText("heal-interrupted",
|
||||
"§c⚠ Heilung abgebrochen!"));
|
||||
}
|
||||
Location bl = base;
|
||||
double dist = p.getLocation().distance(bl);
|
||||
sendActionBarMsg(p, "§c☠ GETROFFEN – Zur §e" + lp.getTeam().colored()
|
||||
+ " §cBasis! §8(" + String.format("%.0f",dist) + "m)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// BASIS-ANGRIFF
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
private void handleBaseAttack(Player shooter, LaserPlayer lp, Team baseTeam, Location blockLoc) {
|
||||
if (arena.isBaseDestroyed(baseTeam)) return;
|
||||
boolean damaged = arena.damageBase(baseTeam);
|
||||
if (!damaged) return;
|
||||
|
||||
int pts = plugin.getConfigManager().getBaseAttackPoints();
|
||||
int hp = arena.getBaseHealth(baseTeam);
|
||||
int maxHp = plugin.getConfigManager().getBaseHealth();
|
||||
lp.addScore(pts);
|
||||
lp.addBaseAttack();
|
||||
teamScore.merge(lp.getTeam(), pts, Integer::sum);
|
||||
|
||||
updateBaseBlock(baseTeam, hp, maxHp);
|
||||
|
||||
if (plugin.getConfigManager().isParticlesEnabled()) {
|
||||
blockLoc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE,
|
||||
blockLoc.clone().add(0.5,0.5,0.5), 3, 0.2,0.2,0.2,0.05);
|
||||
}
|
||||
Sound bhs = plugin.getConfigManager().getSound("base-hit", Sound.ENTITY_GENERIC_EXPLODE);
|
||||
if (bhs != null) blockLoc.getWorld().playSound(blockLoc, bhs, 0.5f, 1.5f);
|
||||
|
||||
shooter.sendMessage(plugin.getConfigManager().getPrefix() + "§6⚔ Basis von Team "
|
||||
+ baseTeam.colored() + " §6angegriffen! §7(+" + pts + " Pkt) §8[HP: " + hp + "/" + maxHp + "]");
|
||||
|
||||
// Warn-HP aus Config
|
||||
int warnHp = plugin.getConfigManager().getBaseWarnHp();
|
||||
|
||||
for (Map.Entry<UUID, LaserPlayer> e : players.entrySet()) {
|
||||
if (e.getValue().getTeam() != baseTeam) continue;
|
||||
Player p = Bukkit.getPlayer(e.getKey());
|
||||
if (p == null) continue;
|
||||
p.sendMessage(plugin.getConfigManager().getText("base-attacked",
|
||||
"§c⚠ Eure Basis wird angegriffen! §8[HP: {hp}/{max}]",
|
||||
"hp", hp, "max", maxHp));
|
||||
if (hp <= warnHp)
|
||||
p.sendTitle("§c§l⚠ BASIS KRITISCH!", "§7HP: " + hp + "/" + maxHp, 5, 40, 10);
|
||||
playSound(p, plugin.getConfigManager().getSound("warning", Sound.BLOCK_BELL_USE), 1f, 0.5f);
|
||||
}
|
||||
|
||||
broadcast(plugin.getConfigManager().getPrefix() + "§6⚔ §e" + shooter.getName()
|
||||
+ " §6hat die Basis von Team " + baseTeam.colored()
|
||||
+ " §6getroffen! §8(" + hp + "/" + maxHp + ")");
|
||||
|
||||
if (hp <= 0) {
|
||||
broadcast(plugin.getConfigManager().getText("base-destroyed",
|
||||
"§c§l💥 Die Basis von Team {team} §c§lwurde ZERSTÖRT!",
|
||||
"team", baseTeam.colored()));
|
||||
int bonus = plugin.getConfigManager().getBaseDestroyBonus();
|
||||
lp.addScore(bonus);
|
||||
teamScore.merge(lp.getTeam(), bonus, Integer::sum);
|
||||
shooter.sendMessage(plugin.getConfigManager().getPrefix()
|
||||
+ "§6§l+" + bonus + " Bonuspunkte für Basis-Zerstörung!");
|
||||
playAll(Sound.ENTITY_ENDER_DRAGON_GROWL, 0.5f, 0.7f);
|
||||
}
|
||||
|
||||
plugin.getScoreboardManager().update(shooter, this);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// SPIELER SETUP
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
private void setupPlayer(Player player, LaserPlayer lp) {
|
||||
player.setGameMode(GameMode.ADVENTURE);
|
||||
player.getInventory().clear();
|
||||
player.setHealth(20); player.setFoodLevel(20); player.setSaturation(20f);
|
||||
for (PotionEffect e : player.getActivePotionEffects())
|
||||
player.removePotionEffect(e.getType());
|
||||
|
||||
int slot = 0;
|
||||
for (WeaponType w : WeaponType.values()) {
|
||||
if (plugin.getConfigManager().isWeaponEnabled(w.getConfigKey())) {
|
||||
player.getInventory().setItem(slot++, WeaponUtil.create(plugin, w));
|
||||
}
|
||||
}
|
||||
player.getInventory().setHeldItemSlot(0);
|
||||
giveArmor(player, lp.getTeam());
|
||||
}
|
||||
|
||||
private void giveArmor(Player player, Team team) {
|
||||
// Helm: farbiger Woll-Block als Kopfbedeckung — auf einen Blick erkennbar
|
||||
player.getInventory().setHelmet (makeHelm(team));
|
||||
player.getInventory().setChestplate(coloredLeather(Material.LEATHER_CHESTPLATE, team));
|
||||
player.getInventory().setLeggings (coloredLeather(Material.LEATHER_LEGGINGS, team));
|
||||
player.getInventory().setBoots (coloredLeather(Material.LEATHER_BOOTS, team));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helm: Leder-Helm mit kräftiger Teamfarbe (RGB).
|
||||
* Enchantment-Glanz macht ihn zusätzlich im Dunkeln erkennbar.
|
||||
*/
|
||||
private ItemStack makeHelm(Team team) {
|
||||
ItemStack item = new ItemStack(Material.LEATHER_HELMET);
|
||||
LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
|
||||
meta.setColor(team.getArmorColor());
|
||||
meta.setDisplayName(team.getChatColor() + "§l" + team.getDisplayName().toUpperCase()
|
||||
+ " §r" + team.getChatColor() + "Helm");
|
||||
meta.setLore(java.util.List.of(
|
||||
"§8Lasertag – " + team.colored() + " §8Team",
|
||||
"§8Rüstung kann nicht abgelegt werden"
|
||||
));
|
||||
// Glanz damit der Helm optisch hervorsticht
|
||||
meta.addEnchant(org.bukkit.enchantments.Enchantment.PROTECTION_ENVIRONMENTAL, 1, true);
|
||||
meta.setUnbreakable(true);
|
||||
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_UNBREAKABLE,
|
||||
ItemFlag.HIDE_ENCHANTS);
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lederrüstung mit kräftiger Teamfarbe (RGB) und Lore.
|
||||
* Brustplatte, Hose und Stiefel sind farbig — zusammen mit dem
|
||||
* Woll-Helm ergibt sich ein eindeutiges Team-Outfit.
|
||||
*/
|
||||
private ItemStack coloredLeather(Material mat, Team team) {
|
||||
String partName = switch (mat) {
|
||||
case LEATHER_CHESTPLATE -> "Brustplatte";
|
||||
case LEATHER_LEGGINGS -> "Hose";
|
||||
case LEATHER_BOOTS -> "Stiefel";
|
||||
default -> "Rüstung";
|
||||
};
|
||||
ItemStack item = new ItemStack(mat);
|
||||
LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
|
||||
meta.setColor(team.getArmorColor());
|
||||
meta.setDisplayName(team.getChatColor() + "Team " + team.getDisplayName()
|
||||
+ " – " + partName);
|
||||
meta.setLore(java.util.List.of(
|
||||
"§8Lasertag – " + team.colored() + " §8Team",
|
||||
"§8Rüstung kann nicht abgelegt werden"
|
||||
));
|
||||
meta.setUnbreakable(true);
|
||||
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_UNBREAKABLE,
|
||||
ItemFlag.HIDE_ENCHANTS);
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
private void restorePlayer(Player player, LaserPlayer lp) {
|
||||
player.getInventory().clear();
|
||||
if (lp.getSavedInventory() != null)
|
||||
player.getInventory().setContents(lp.getSavedInventory());
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
player.setHealth(20); player.setFoodLevel(20);
|
||||
for (PotionEffect e : player.getActivePotionEffects())
|
||||
player.removePotionEffect(e.getType());
|
||||
Location lobby = plugin.getConfigManager().getLobbyLocation();
|
||||
if (lobby != null) player.teleport(lobby);
|
||||
}
|
||||
|
||||
private void sendToSpawn(Player player, Team team) {
|
||||
Location spawn = arena.getRandomSpawn(team);
|
||||
if (spawn != null) player.teleport(spawn);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// BASIS-BLÖCKE
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
private void placeBaseBlocks() {
|
||||
for (Team t : Team.values()) {
|
||||
Location loc = arena.getBase(t);
|
||||
if (loc != null) loc.getBlock().setType(t.getGlassMat());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBaseBlock(Team team, int hp, int maxHp) {
|
||||
Location loc = arena.getBase(team);
|
||||
if (loc == null) return;
|
||||
if (hp <= 0) loc.getBlock().setType(Material.OBSIDIAN);
|
||||
else if (hp < maxHp / 2.0) loc.getBlock().setType(team.getWoolMat());
|
||||
if (plugin.getConfigManager().isParticlesEnabled())
|
||||
loc.getWorld().spawnParticle(Particle.SMOKE_LARGE,
|
||||
loc.clone().add(0.5,1.2,0.5), 5, 0.3,0.3,0.3,0.02);
|
||||
}
|
||||
|
||||
private void removeBaseBlocks() {
|
||||
for (Team t : Team.values()) {
|
||||
Location loc = arena.getBase(t);
|
||||
if (loc == null) continue;
|
||||
Material m = loc.getBlock().getType();
|
||||
if (m == t.getGlassMat() || m == t.getWoolMat() || m == Material.OBSIDIAN)
|
||||
loc.getBlock().setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// HILFSMETHODEN
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
private void drawLaser(Location start, Vector dir, WeaponType weapon, int range) {
|
||||
var particle = plugin.getConfigManager().getWeaponParticle(weapon.getConfigKey());
|
||||
Location cur = start.clone();
|
||||
Vector step = dir.clone().normalize().multiply(0.6);
|
||||
for (int i = 0; i < range * 1.7; i++) {
|
||||
cur.add(step);
|
||||
if (!cur.getBlock().isPassable()) break;
|
||||
cur.getWorld().spawnParticle(particle, cur.clone(), 1, 0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector spreadDir(Player player) {
|
||||
Vector base = player.getEyeLocation().getDirection();
|
||||
double s = 0.12;
|
||||
return base.clone().add(new Vector(
|
||||
(Math.random()-0.5)*s, (Math.random()-0.5)*s*0.7, (Math.random()-0.5)*s
|
||||
)).normalize();
|
||||
}
|
||||
|
||||
private Team pickBalancedTeam() {
|
||||
Map<Team,Integer> counts = new LinkedHashMap<>();
|
||||
for (Team t : Team.values()) counts.put(t, 0);
|
||||
for (LaserPlayer lp : players.values()) counts.merge(lp.getTeam(), 1, Integer::sum);
|
||||
return counts.entrySet().stream().min(Map.Entry.comparingByValue()).map(Map.Entry::getKey).orElse(Team.RED);
|
||||
}
|
||||
|
||||
private Team getLeader() {
|
||||
return teamScore.entrySet().stream().max(Map.Entry.comparingByValue())
|
||||
.map(Map.Entry::getKey).orElse(null);
|
||||
}
|
||||
|
||||
private void cancelTasks() {
|
||||
if (countdownTask != null) countdownTask.cancel();
|
||||
if (gameTask != null) gameTask.cancel();
|
||||
if (healTask != null) healTask.cancel();
|
||||
}
|
||||
|
||||
private void sendActionBar(Player player) {
|
||||
LaserPlayer lp = players.get(player.getUniqueId());
|
||||
if (lp == null) return;
|
||||
if (!lp.isHit()) {
|
||||
int idle = antiCamp.getIdleSeconds(player.getUniqueId());
|
||||
int max = plugin.getConfigManager().getCampMaxIdleSecs();
|
||||
String campBar = idle > 0
|
||||
? " §c| Camp: " + buildBar(1.0 - (double)idle/max, 6)
|
||||
: "";
|
||||
sendActionBarMsg(player, "§7Kills: §a" + lp.getKills()
|
||||
+ " §7Punkte: §6" + lp.getScore()
|
||||
+ " §7Team: " + lp.getTeam().colored()
|
||||
+ " §7Zeit: §b" + formatTime(timeLeft)
|
||||
+ campBar);
|
||||
}
|
||||
// Wenn getroffen: wird in tickHeal() gesetzt
|
||||
}
|
||||
|
||||
private void sendActionBarMsg(Player player, String msg) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(msg));
|
||||
}
|
||||
|
||||
private void broadcastStreak(Player player, String textKey, String fallbackTitle, int streak) {
|
||||
broadcast(plugin.getConfigManager().getText(textKey,
|
||||
fallbackTitle + " §e{player} §7– " + streak + "er Serie!",
|
||||
"player", player.getName()));
|
||||
for (Player p : getOnline())
|
||||
p.sendTitle(fallbackTitle, "§e" + player.getName(), 5, 40, 10);
|
||||
}
|
||||
|
||||
private void showEndStats(Player p, LaserPlayer lp) {
|
||||
if (lp == null) return;
|
||||
p.sendMessage("§8§l══════════════════════════════");
|
||||
p.sendMessage("§b§l ⚡ LASERTAG ERGEBNIS");
|
||||
p.sendMessage("§8§l══════════════════════════════");
|
||||
p.sendMessage("§7Team: " + lp.getTeam().colored());
|
||||
p.sendMessage("§7Kills: §a" + lp.getKills());
|
||||
p.sendMessage("§7Tode: §c" + lp.getDeaths());
|
||||
p.sendMessage("§7Basis-Angriffe: §6" + lp.getBaseAttacks());
|
||||
p.sendMessage("§7Punkte: §6" + lp.getScore());
|
||||
p.sendMessage("§7Beste Serie: §b" + lp.getBestStreak());
|
||||
p.sendMessage("§8──────────────────────────────");
|
||||
p.sendMessage("§7Team-Punkte:");
|
||||
teamScore.entrySet().stream()
|
||||
.sorted((a,b) -> Integer.compare(b.getValue(), a.getValue()))
|
||||
.forEach(e -> p.sendMessage(" " + e.getKey().colored()
|
||||
+ " §7→ §6" + e.getValue() + " Punkte"));
|
||||
p.sendMessage("§8§l══════════════════════════════");
|
||||
}
|
||||
|
||||
private String buildBar(double progress, int length) {
|
||||
int filled = Math.max(0, Math.min(length, (int)Math.round(progress * length)));
|
||||
return "§a" + "█".repeat(filled) + "§8" + "░".repeat(length - filled);
|
||||
}
|
||||
|
||||
private String formatTime(int secs) {
|
||||
return String.format("%d:%02d", secs/60, secs%60);
|
||||
}
|
||||
|
||||
private void broadcast(String msg) {
|
||||
for (Player p : getOnline()) p.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void playAll(Sound sound, float vol, float pitch) {
|
||||
if (sound == null) return;
|
||||
for (Player p : getOnline()) p.playSound(p.getLocation(), sound, vol, pitch);
|
||||
}
|
||||
|
||||
private void playSound(Player p, Sound s, float vol, float pitch) {
|
||||
if (s != null) p.playSound(p.getLocation(), s, vol, pitch);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
// GETTERS
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
public Arena getArena() { return arena; }
|
||||
public GameState getState() { return state; }
|
||||
public Map<UUID, LaserPlayer> getPlayers() { return players; }
|
||||
public Map<Team, Integer> getTeamScore() { return teamScore; }
|
||||
public int getTimeLeft() { return timeLeft; }
|
||||
public LaserPlayer getLP(UUID uid) { return players.get(uid); }
|
||||
public boolean isRunning() { return state == GameState.RUNNING; }
|
||||
public boolean isJoinable() { return state == GameState.WAITING || state == GameState.STARTING; }
|
||||
public int getPlayerCount() { return players.size(); }
|
||||
public int getMaxPlayers() { return plugin.getConfigManager().getMaxPlayersPerTeam() * 4; }
|
||||
public AntiCampManager getAntiCamp() { return antiCamp; }
|
||||
|
||||
public List<Player> getOnline() {
|
||||
List<Player> list = new ArrayList<>();
|
||||
for (UUID uid : players.keySet()) {
|
||||
Player p = Bukkit.getPlayer(uid);
|
||||
if (p != null) list.add(p);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void forceEnd() { endGame(); }
|
||||
public void forceStart() {
|
||||
if (state == GameState.WAITING) startCountdown();
|
||||
else if (state == GameState.STARTING) startGame();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user