Upload folder via GUI - src
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
package dev.viper.eventengine.command;
|
package dev.viper.eventengine.command;
|
||||||
|
|
||||||
import dev.viper.eventengine.EventEngine;
|
import dev.viper.eventengine.EventEngine;
|
||||||
import dev.viper.eventengine.command.RegionSetupManager;
|
import dev.viper.eventengine.events.builtin.ElytraRaceHandler;
|
||||||
import dev.viper.eventengine.model.ActiveEvent;
|
import dev.viper.eventengine.model.ActiveEvent;
|
||||||
import dev.viper.eventengine.model.EventDefinition;
|
import dev.viper.eventengine.model.EventDefinition;
|
||||||
|
import dev.viper.eventengine.model.EventRegion;
|
||||||
import dev.viper.eventengine.model.ScheduleEntry;
|
import dev.viper.eventengine.model.ScheduleEntry;
|
||||||
import dev.viper.eventengine.manager.EventManager;
|
import dev.viper.eventengine.manager.EventManager;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@@ -44,14 +45,14 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
requirePlayer(sender, () -> plugin.getEventGUI().openMain((Player) sender));
|
requirePlayer(sender, () -> plugin.getEventGUI().openMain((Player) sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── ITEM-REGEN GUI ──────────────────────────────────────────
|
// ─── ITEM-REGEN GUI ───────────────────────────────────────────
|
||||||
case "itemrain" -> {
|
case "itemrain" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
requirePlayer(sender, () -> plugin.getItemRainGUI().open((Player) sender));
|
requirePlayer(sender, () -> plugin.getItemRainGUI().open((Player) sender));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── START ─────────────────────────────────────────────────────
|
// ─── START ────────────────────────────────────────────────────
|
||||||
case "start" -> {
|
case "start" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
if (args.length < 2) { sender.sendMessage(p + "§cUsage: /event start <id|random>"); return; }
|
if (args.length < 2) { sender.sendMessage(p + "§cUsage: /event start <id|random>"); return; }
|
||||||
@@ -68,7 +69,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── STOP ──────────────────────────────────────────────────────
|
// ─── STOP ─────────────────────────────────────────────────────
|
||||||
case "stop" -> {
|
case "stop" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
String reason = args.length > 1 ? String.join(" ", Arrays.copyOfRange(args, 1, args.length)) : "Admin";
|
String reason = args.length > 1 ? String.join(" ", Arrays.copyOfRange(args, 1, args.length)) : "Admin";
|
||||||
@@ -78,14 +79,13 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── JOIN/LEAVE ────────────────────────────────────────────────
|
// ─── JOIN/LEAVE ───────────────────────────────────────────────
|
||||||
case "join" -> requirePlayer(sender, () -> plugin.getEventManager().join((Player) sender));
|
case "join" -> requirePlayer(sender, () -> plugin.getEventManager().join((Player) sender));
|
||||||
case "leave" -> requirePlayer(sender, () -> plugin.getEventManager().leave((Player) sender));
|
case "leave" -> requirePlayer(sender, () -> plugin.getEventManager().leave((Player) sender));
|
||||||
|
|
||||||
// ─── INFO ──────────────────────────────────────────────────────
|
// ─── INFO ─────────────────────────────────────────────────────
|
||||||
case "info" -> {
|
case "info" -> {
|
||||||
if (args.length >= 2) {
|
if (args.length >= 2) {
|
||||||
// Event-Info
|
|
||||||
plugin.getEventRegistry().get(args[1]).ifPresentOrElse(def -> {
|
plugin.getEventRegistry().get(args[1]).ifPresentOrElse(def -> {
|
||||||
sender.sendMessage("§8§m══════════════════════════════");
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
sender.sendMessage("§6 " + def.getDisplayName() + " §8[" + def.getId() + "]");
|
sender.sendMessage("§6 " + def.getDisplayName() + " §8[" + def.getId() + "]");
|
||||||
@@ -94,15 +94,19 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
sender.sendMessage("§7 Dauer: §f" + EventManager.formatTime(def.getDurationSeconds()));
|
sender.sendMessage("§7 Dauer: §f" + EventManager.formatTime(def.getDurationSeconds()));
|
||||||
sender.sendMessage("§7 Spieler: §f" + def.getMinPlayers() + "–" + def.getMaxPlayers());
|
sender.sendMessage("§7 Spieler: §f" + def.getMinPlayers() + "–" + def.getMaxPlayers());
|
||||||
sender.sendMessage("§7 Custom: §f" + def.isCustom());
|
sender.sendMessage("§7 Custom: §f" + def.isCustom());
|
||||||
|
sender.sendMessage("§7 Renn-Modus: §f" + def.getRaceMode().name()
|
||||||
|
+ (def.isCircuit() ? " §8(§e" + def.getLaps() + " Runden§8)" : ""));
|
||||||
sender.sendMessage("§7 Start-Befehle: §f" + def.getStartCommands().size());
|
sender.sendMessage("§7 Start-Befehle: §f" + def.getStartCommands().size());
|
||||||
sender.sendMessage("§7 Belohnungen: §f" + def.getRewards().size());
|
sender.sendMessage("§7 Belohnungen: §f" + def.getRewards().size());
|
||||||
sender.sendMessage("§7 Winner-Belohnungen: §f" + def.getWinnerRewards().size());
|
sender.sendMessage("§7 Winner-Belohnungen: §f" + def.getWinnerRewards().size());
|
||||||
sender.sendMessage("§7 Startbereich: §f" + (def.hasStartRegion() ? "gesetzt" : "-"));
|
sender.sendMessage("§7 Startbereich: §f" + (def.hasStartRegion() ? "gesetzt" : "-"));
|
||||||
sender.sendMessage("§7 Zielbereich: §f" + (def.hasGoalRegion() ? "gesetzt" : "-"));
|
sender.sendMessage("§7 Zielbereich: §f" + (def.hasGoalRegion() ? "gesetzt" : "-"));
|
||||||
|
Object cpCount = def.getCustomSettings().get("checkpoint_count");
|
||||||
|
if (cpCount != null)
|
||||||
|
sender.sendMessage("§7 Elytra-Checkpoints: §f" + cpCount);
|
||||||
sender.sendMessage("§8§m══════════════════════════════");
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
}, () -> sender.sendMessage(p + "§cEvent nicht gefunden."));
|
}, () -> sender.sendMessage(p + "§cEvent nicht gefunden."));
|
||||||
} else {
|
} else {
|
||||||
// Aktuelles Event
|
|
||||||
ActiveEvent current = plugin.getEventManager().getCurrentEvent();
|
ActiveEvent current = plugin.getEventManager().getCurrentEvent();
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
sender.sendMessage(p + "§cKein Event aktiv.");
|
sender.sendMessage(p + "§cKein Event aktiv.");
|
||||||
@@ -117,7 +121,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── LIST ──────────────────────────────────────────────────────
|
// ─── LIST ─────────────────────────────────────────────────────
|
||||||
case "list" -> {
|
case "list" -> {
|
||||||
int page = args.length >= 2 ? parseIntSafe(args[1], 1) - 1 : 0;
|
int page = args.length >= 2 ? parseIntSafe(args[1], 1) - 1 : 0;
|
||||||
List<EventDefinition> all = new ArrayList<>(plugin.getEventRegistry().getAll());
|
List<EventDefinition> all = new ArrayList<>(plugin.getEventRegistry().getAll());
|
||||||
@@ -134,7 +138,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
if (totalPages > 1) sender.sendMessage("§7Nächste Seite: §f/event list " + (page + 2));
|
if (totalPages > 1) sender.sendMessage("§7Nächste Seite: §f/event list " + (page + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── SCHEDULE ──────────────────────────────────────────────────
|
// ─── SCHEDULE ─────────────────────────────────────────────────
|
||||||
case "schedule" -> {
|
case "schedule" -> {
|
||||||
List<ScheduleEntry> schedule = plugin.getConfigManager().getSchedule();
|
List<ScheduleEntry> schedule = plugin.getConfigManager().getSchedule();
|
||||||
sender.sendMessage("§8§m══════════════════════════════");
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
@@ -148,7 +152,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
sender.sendMessage("§8§m══════════════════════════════");
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── CREATE ────────────────────────────────────────────────────
|
// ─── CREATE ───────────────────────────────────────────────────
|
||||||
case "create" -> {
|
case "create" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
requirePlayer(sender, () -> {
|
requirePlayer(sender, () -> {
|
||||||
@@ -167,7 +171,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── DELETE ────────────────────────────────────────────────────
|
// ─── DELETE ───────────────────────────────────────────────────
|
||||||
case "delete" -> {
|
case "delete" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
if (args.length < 2) { sender.sendMessage(p + "§cUsage: /event delete <id>"); return; }
|
if (args.length < 2) { sender.sendMessage(p + "§cUsage: /event delete <id>"); return; }
|
||||||
@@ -180,7 +184,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── SCORE ─────────────────────────────────────────────────────
|
// ─── SCORE ────────────────────────────────────────────────────
|
||||||
case "score" -> {
|
case "score" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
if (args.length < 3) { sender.sendMessage(p + "§cUsage: /event score <spieler> <punkte>"); return; }
|
if (args.length < 3) { sender.sendMessage(p + "§cUsage: /event score <spieler> <punkte>"); return; }
|
||||||
@@ -194,7 +198,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── ROTATION ──────────────────────────────────────────────────
|
// ─── ROTATION ─────────────────────────────────────────────────
|
||||||
case "rotation" -> {
|
case "rotation" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
if (args.length < 3) { sender.sendMessage(p + "§cUsage: /event rotation <add|remove> <id>"); return; }
|
if (args.length < 3) { sender.sendMessage(p + "§cUsage: /event rotation <add|remove> <id>"); return; }
|
||||||
@@ -209,7 +213,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── RELOAD ────────────────────────────────────────────────────
|
// ─── RELOAD ───────────────────────────────────────────────────
|
||||||
case "reload" -> {
|
case "reload" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
plugin.getConfigManager().load();
|
plugin.getConfigManager().load();
|
||||||
@@ -219,7 +223,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── REGION ────────────────────────────────────────────────
|
// ─── REGION ───────────────────────────────────────────────────
|
||||||
case "region" -> {
|
case "region" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
requirePlayer(sender, () -> {
|
requirePlayer(sender, () -> {
|
||||||
@@ -241,7 +245,7 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── RACE START/GOAL ───────────────────────────────────────
|
// ─── RACE START/GOAL ──────────────────────────────────────────
|
||||||
case "race" -> {
|
case "race" -> {
|
||||||
requirePerm(sender, () -> {
|
requirePerm(sender, () -> {
|
||||||
requirePlayer(sender, () -> {
|
requirePlayer(sender, () -> {
|
||||||
@@ -278,23 +282,94 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── ELYTRA CHECKPOINT ────────────────────────────────────────
|
||||||
|
case "elytra" -> {
|
||||||
|
requirePerm(sender, () -> {
|
||||||
|
requirePlayer(sender, () -> {
|
||||||
|
if (args.length < 4 || !args[1].equalsIgnoreCase("checkpoint")) {
|
||||||
|
sender.sendMessage(p + "§cUsage: /event elytra checkpoint <add|confirm|clear|list> <id>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String sub = args[2].toLowerCase();
|
||||||
|
String id = args[3].toLowerCase();
|
||||||
|
EventDefinition def = plugin.getEventRegistry().get(id).orElse(null);
|
||||||
|
if (def == null) { sender.sendMessage(p + "§cEvent nicht gefunden: §f" + id); return; }
|
||||||
|
Player pl = (Player) sender;
|
||||||
|
RegionSetupManager rsm = plugin.getRegionSetupManager();
|
||||||
|
switch (sub) {
|
||||||
|
case "add" -> rsm.handleCheckpointPos1(pl, id);
|
||||||
|
case "confirm" -> rsm.handleCheckpointPos2(pl, id);
|
||||||
|
case "clear" -> {
|
||||||
|
ElytraRaceHandler.clearCheckpoints(def);
|
||||||
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
|
sender.sendMessage(p + "§7Alle Checkpoints für §e" + def.getDisplayName() + " §7gelöscht.");
|
||||||
|
}
|
||||||
|
case "list" -> {
|
||||||
|
Object countObj = def.getCustomSettings().get("checkpoint_count");
|
||||||
|
int count = countObj instanceof Number n ? n.intValue() : 0;
|
||||||
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
|
sender.sendMessage("§6 Elytra Checkpoints: §e" + def.getDisplayName() + " §8(" + count + ")");
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
String pf = "checkpoint_" + i + "_";
|
||||||
|
Map<String, Object> s = def.getCustomSettings();
|
||||||
|
sender.sendMessage(" §7" + (i + 1) + ". §f" + s.get(pf + "world")
|
||||||
|
+ " §8[§f" + s.get(pf + "min-x") + "," + s.get(pf + "min-y") + "," + s.get(pf + "min-z")
|
||||||
|
+ "§8] → [§f" + s.get(pf + "max-x") + "," + s.get(pf + "max-y") + "," + s.get(pf + "max-z") + "§8]");
|
||||||
|
}
|
||||||
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
|
}
|
||||||
|
default -> sender.sendMessage(p + "§cUnbekannte Option. add | confirm | clear | list");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── RACEMODE ─────────────────────────────────────────────────
|
||||||
|
case "racemode" -> {
|
||||||
|
requirePerm(sender, () -> {
|
||||||
|
if (args.length < 3) {
|
||||||
|
sender.sendMessage(p + "§cUsage: /event racemode <id> <sprint|circuit> [laps]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String id = args[1].toLowerCase();
|
||||||
|
String mode = args[2].toLowerCase();
|
||||||
|
int laps = args.length >= 4 ? parseIntSafe(args[3], 1) : 1;
|
||||||
|
|
||||||
|
EventDefinition def = plugin.getEventRegistry().get(id).orElse(null);
|
||||||
|
if (def == null) { sender.sendMessage(p + "§cEvent nicht gefunden: §f" + id); return; }
|
||||||
|
|
||||||
|
if (mode.equals("circuit")) {
|
||||||
|
def.setRaceMode(EventDefinition.RaceMode.CIRCUIT);
|
||||||
|
def.setLaps(Math.max(1, laps));
|
||||||
|
sender.sendMessage(p + "§a✔ §e" + def.getDisplayName()
|
||||||
|
+ " §7→ Modus: §6Circuit §8(§e" + def.getLaps() + " Runden§8)");
|
||||||
|
} else {
|
||||||
|
def.setRaceMode(EventDefinition.RaceMode.SPRINT);
|
||||||
|
sender.sendMessage(p + "§a✔ §e" + def.getDisplayName()
|
||||||
|
+ " §7→ Modus: §6Sprint §8(A→B)");
|
||||||
|
}
|
||||||
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
default -> sendHelp(sender);
|
default -> sendHelp(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Tab-Completer ─────────────────────────────────────────────────────
|
// ─── Tab-Completer ────────────────────────────────────────────────────
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
return filter(args[0], "gui", "start", "stop", "join", "leave", "info", "list",
|
return filter(args[0], "gui", "start", "stop", "join", "leave", "info", "list",
|
||||||
"schedule", "create", "delete", "score", "rotation", "region", "race", "itemrain", "reload");
|
"schedule", "create", "delete", "score", "rotation", "region", "race",
|
||||||
|
"elytra", "racemode", "itemrain", "reload");
|
||||||
}
|
}
|
||||||
if (args.length == 2) {
|
if (args.length == 2) {
|
||||||
return switch (args[0].toLowerCase()) {
|
return switch (args[0].toLowerCase()) {
|
||||||
case "start", "info", "delete" -> {
|
case "start", "info", "delete", "racemode" -> {
|
||||||
List<String> ids = plugin.getEventRegistry().getAll().stream()
|
List<String> ids = plugin.getEventRegistry().getAll().stream()
|
||||||
.map(EventDefinition::getId)
|
.map(EventDefinition::getId)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@@ -302,31 +377,36 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
yield filter(args[1], ids.toArray(new String[0]));
|
yield filter(args[1], ids.toArray(new String[0]));
|
||||||
}
|
}
|
||||||
case "rotation" -> filter(args[1], "add", "remove");
|
case "rotation" -> filter(args[1], "add", "remove");
|
||||||
case "score" -> null; // Spielernamen
|
case "region" -> filter(args[1], "pos1", "pos2", "clear", "info");
|
||||||
case "region" -> filter(args[1], "pos1", "pos2", "clear", "info");
|
case "race" -> filter(args[1], "start", "goal");
|
||||||
case "race" -> filter(args[1], "start", "goal");
|
case "elytra" -> filter(args[1], "checkpoint");
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (args.length == 3 && args[0].equalsIgnoreCase("race")) {
|
if (args.length == 3) {
|
||||||
return filter(args[2], "pos1", "pos2", "clear", "info");
|
return switch (args[0].toLowerCase()) {
|
||||||
|
case "race" -> filter(args[2], "pos1", "pos2", "clear", "info");
|
||||||
|
case "elytra" -> filter(args[2], "add", "confirm", "clear", "list");
|
||||||
|
case "racemode" -> filter(args[2], "sprint", "circuit");
|
||||||
|
case "rotation" -> plugin.getEventRegistry().getAll().stream()
|
||||||
|
.map(EventDefinition::getId)
|
||||||
|
.filter(id -> id.startsWith(args[2].toLowerCase()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (args.length == 3 && args[0].equalsIgnoreCase("rotation")) {
|
if (args.length == 4) {
|
||||||
return plugin.getEventRegistry().getAll().stream()
|
if (args[0].equalsIgnoreCase("race") || args[0].equalsIgnoreCase("elytra")) {
|
||||||
.map(EventDefinition::getId)
|
return plugin.getEventRegistry().getAll().stream()
|
||||||
.filter(id -> id.startsWith(args[2].toLowerCase()))
|
.map(EventDefinition::getId)
|
||||||
.collect(Collectors.toList());
|
.filter(id -> id.startsWith(args[3].toLowerCase()))
|
||||||
}
|
.collect(Collectors.toList());
|
||||||
if (args.length == 4 && args[0].equalsIgnoreCase("race")) {
|
}
|
||||||
return plugin.getEventRegistry().getAll().stream()
|
|
||||||
.map(EventDefinition::getId)
|
|
||||||
.filter(id -> id.startsWith(args[3].toLowerCase()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Hilfsmethoden ─────────────────────────────────────────────────────
|
// ─── Hilfsmethoden ───────────────────────────────────────────────────
|
||||||
|
|
||||||
private void sendHelp(CommandSender sender) {
|
private void sendHelp(CommandSender sender) {
|
||||||
sender.sendMessage("§8§m══════════════════════════════");
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
@@ -345,6 +425,8 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
sender.sendMessage("§e /event reload §7- Config neu laden");
|
sender.sendMessage("§e /event reload §7- Config neu laden");
|
||||||
sender.sendMessage("§e /event region <pos1|pos2|clear|info> <id> §7- Event-Arena setzen");
|
sender.sendMessage("§e /event region <pos1|pos2|clear|info> <id> §7- Event-Arena setzen");
|
||||||
sender.sendMessage("§e /event race <start|goal> <pos1|pos2|clear|info> <id> §7- Start/Ziel setzen");
|
sender.sendMessage("§e /event race <start|goal> <pos1|pos2|clear|info> <id> §7- Start/Ziel setzen");
|
||||||
|
sender.sendMessage("§e /event racemode <id> <sprint|circuit> [laps] §7- Renn-Modus setzen");
|
||||||
|
sender.sendMessage("§e /event elytra checkpoint <add|confirm|clear|list> <id> §7- Elytra-Checkpoints");
|
||||||
sender.sendMessage("§e /event itemrain §7- Item-Regen GUI");
|
sender.sendMessage("§e /event itemrain §7- Item-Regen GUI");
|
||||||
sender.sendMessage("§8§m══════════════════════════════");
|
sender.sendMessage("§8§m══════════════════════════════");
|
||||||
}
|
}
|
||||||
@@ -374,4 +456,4 @@ public class EventCommand implements CommandExecutor, TabCompleter {
|
|||||||
private int parseIntSafe(String s, int def) {
|
private int parseIntSafe(String s, int def) {
|
||||||
try { return Integer.parseInt(s); } catch (Exception e) { return def; }
|
try { return Integer.parseInt(s); } catch (Exception e) { return def; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.viper.eventengine.command;
|
package dev.viper.eventengine.command;
|
||||||
|
|
||||||
import dev.viper.eventengine.EventEngine;
|
import dev.viper.eventengine.EventEngine;
|
||||||
|
import dev.viper.eventengine.events.builtin.ElytraRaceHandler;
|
||||||
import dev.viper.eventengine.model.EventDefinition;
|
import dev.viper.eventengine.model.EventDefinition;
|
||||||
import dev.viper.eventengine.model.EventRegion;
|
import dev.viper.eventengine.model.EventRegion;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -11,125 +12,113 @@ import java.util.UUID;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stellt Pos1/Pos2-Auswahl für Event-Regionen bereit.
|
* Stellt Pos1/Pos2-Auswahl für Event-Regionen bereit.
|
||||||
* Eingebaut in EventCommand via sub-commands:
|
|
||||||
*
|
*
|
||||||
* /event region pos1 <id> → Pos1 auf Spieler-Position setzen
|
* Befehle:
|
||||||
* /event region pos2 <id> → Pos2 setzen + Region speichern
|
* /event region pos1/pos2/clear/info <id>
|
||||||
* /event region clear <id> → Region entfernen
|
* /event race start pos1/pos2/clear/info <id>
|
||||||
* /event region info <id> → Region anzeigen
|
* /event race goal pos1/pos2/clear/info <id>
|
||||||
|
* /event elytra checkpoint add/confirm/clear/list <id>
|
||||||
*/
|
*/
|
||||||
public class RegionSetupManager {
|
public class RegionSetupManager {
|
||||||
|
|
||||||
private final EventEngine plugin;
|
private final EventEngine plugin;
|
||||||
// Temporäre Pos1-Speicher pro Spieler: UUID → [eventId, Location]
|
|
||||||
private final Map<UUID, Object[]> pos1Selection = new HashMap<>();
|
private final Map<UUID, Object[]> pos1Selection = new HashMap<>();
|
||||||
private final Map<UUID, Object[]> startPos1Selection = new HashMap<>();
|
private final Map<UUID, Object[]> startPos1Selection = new HashMap<>();
|
||||||
private final Map<UUID, Object[]> goalPos1Selection = new HashMap<>();
|
private final Map<UUID, Object[]> goalPos1Selection = new HashMap<>();
|
||||||
|
private final Map<UUID, Object[]> checkpointPos1Selection = new HashMap<>();
|
||||||
|
|
||||||
public RegionSetupManager(EventEngine plugin) {
|
public RegionSetupManager(EventEngine plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handlePos1(Player player, String eventId) {
|
// ─── Haupt-Region ────────────────────────────────────────────────────
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
|
|
||||||
|
public void handlePos1(Player player, String eventId) {
|
||||||
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
pos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
pos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
||||||
player.sendMessage(plugin.prefix() + "§aPos1 gesetzt: §f" + formatLoc(player));
|
player.sendMessage(plugin.prefix() + "§aPos1 gesetzt: §f" + formatLoc(player));
|
||||||
player.sendMessage(plugin.prefix() + "§7Jetzt: §f/event region pos2 " + eventId);
|
player.sendMessage(plugin.prefix() + "§7Jetzt: §f/event region pos2 " + eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handlePos2(Player player, String eventId) {
|
public void handlePos2(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
|
|
||||||
Object[] sel = pos1Selection.get(player.getUniqueId());
|
Object[] sel = pos1Selection.get(player.getUniqueId());
|
||||||
if (sel == null || !sel[0].equals(eventId)) {
|
if (sel == null || !sel[0].equals(eventId)) {
|
||||||
player.sendMessage(plugin.prefix() + "§cZuerst Pos1 setzen: §f/event region pos1 " + eventId);
|
player.sendMessage(plugin.prefix() + "§cZuerst Pos1 setzen: §f/event region pos1 " + eventId); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
||||||
org.bukkit.Location pos2 = player.getLocation().clone();
|
org.bukkit.Location pos2 = player.getLocation().clone();
|
||||||
|
|
||||||
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
||||||
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!");
|
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!"); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventRegion region = new EventRegion(pos1, pos2);
|
EventRegion region = new EventRegion(pos1, pos2);
|
||||||
def.setRegion(region);
|
def.setRegion(region);
|
||||||
|
|
||||||
// Custom Events direkt speichern; builtin: in memory (gilt bis Reload)
|
|
||||||
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
|
|
||||||
pos1Selection.remove(player.getUniqueId());
|
pos1Selection.remove(player.getUniqueId());
|
||||||
|
|
||||||
player.sendMessage(plugin.prefix() + "§a✔ Region gesetzt für §e" + def.getDisplayName() + "§a:");
|
player.sendMessage(plugin.prefix() + "§a✔ Region gesetzt für §e" + def.getDisplayName() + "§a:");
|
||||||
player.sendMessage("§7 Welt: §f" + region.getWorldName());
|
sendRegionInfo(player, region);
|
||||||
player.sendMessage("§7 Von: §f" + region.getMinX() + ", " + region.getMinY() + ", " + region.getMinZ());
|
|
||||||
player.sendMessage("§7 Bis: §f" + region.getMaxX() + ", " + region.getMaxY() + ", " + region.getMaxZ());
|
|
||||||
player.sendMessage("§7 Größe: §f" + region.getSizeX() + "x" + region.getSizeY() + "x" + region.getSizeZ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleClear(Player player, String eventId) {
|
public void handleClear(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
def.setRegion(null);
|
def.setRegion(null);
|
||||||
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
player.sendMessage(plugin.prefix() + "§7Region für §e" + def.getDisplayName() + " §7entfernt (gesamte Welt).");
|
player.sendMessage(plugin.prefix() + "§7Region für §e" + def.getDisplayName() + " §7entfernt (gesamte Welt).");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleStartPos1(Player player, String eventId) {
|
public void handleInfo(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
if (!def.hasRegion()) {
|
||||||
|
player.sendMessage(plugin.prefix() + "§e" + def.getDisplayName() + " §7hat keine Region (gesamte Welt)."); return;
|
||||||
|
}
|
||||||
|
EventRegion r = def.getRegion();
|
||||||
|
player.sendMessage("§8§m══════════════════════════════");
|
||||||
|
player.sendMessage("§6 Region: §e" + def.getDisplayName());
|
||||||
|
sendRegionInfo(player, r);
|
||||||
|
player.sendMessage("§7 Größe: §f" + r.getSizeX() + "×" + r.getSizeY() + "×" + r.getSizeZ() + " Blöcke");
|
||||||
|
player.sendMessage("§8§m══════════════════════════════");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Start-Region ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
public void handleStartPos1(Player player, String eventId) {
|
||||||
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
startPos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
startPos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
||||||
player.sendMessage(plugin.prefix() + "§aStart-Pos1 gesetzt: §f" + formatLoc(player));
|
player.sendMessage(plugin.prefix() + "§aStart-Pos1 gesetzt: §f" + formatLoc(player));
|
||||||
player.sendMessage(plugin.prefix() + "§7Jetzt: §f/event race start pos2 " + eventId);
|
player.sendMessage(plugin.prefix() + "§7Jetzt: §f/event race start pos2 " + eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleStartPos2(Player player, String eventId) {
|
public void handleStartPos2(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
|
|
||||||
Object[] sel = startPos1Selection.get(player.getUniqueId());
|
Object[] sel = startPos1Selection.get(player.getUniqueId());
|
||||||
if (sel == null || !sel[0].equals(eventId)) {
|
if (sel == null || !sel[0].equals(eventId)) {
|
||||||
player.sendMessage(plugin.prefix() + "§cZuerst Start-Pos1 setzen: §f/event race start pos1 " + eventId);
|
player.sendMessage(plugin.prefix() + "§cZuerst Start-Pos1 setzen: §f/event race start pos1 " + eventId); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
||||||
org.bukkit.Location pos2 = player.getLocation().clone();
|
org.bukkit.Location pos2 = player.getLocation().clone();
|
||||||
|
|
||||||
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
||||||
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!");
|
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!"); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventRegion region = new EventRegion(pos1, pos2);
|
EventRegion region = new EventRegion(pos1, pos2);
|
||||||
def.setStartRegion(region);
|
def.setStartRegion(region);
|
||||||
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
startPos1Selection.remove(player.getUniqueId());
|
startPos1Selection.remove(player.getUniqueId());
|
||||||
|
|
||||||
player.sendMessage(plugin.prefix() + "§a✔ Startbereich gesetzt für §e" + def.getDisplayName() + "§a:");
|
player.sendMessage(plugin.prefix() + "§a✔ Startbereich gesetzt für §e" + def.getDisplayName() + "§a:");
|
||||||
sendRegionInfo(player, region);
|
sendRegionInfo(player, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleStartClear(Player player, String eventId) {
|
public void handleStartClear(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
def.setStartRegion(null);
|
def.setStartRegion(null);
|
||||||
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
player.sendMessage(plugin.prefix() + "§7Startbereich für §e" + def.getDisplayName() + " §7entfernt.");
|
player.sendMessage(plugin.prefix() + "§7Startbereich für §e" + def.getDisplayName() + " §7entfernt.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleStartInfo(Player player, String eventId) {
|
public void handleStartInfo(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
if (!def.hasStartRegion()) {
|
if (!def.hasStartRegion()) {
|
||||||
player.sendMessage(plugin.prefix() + "§e" + def.getDisplayName() + " §7hat keinen Startbereich.");
|
player.sendMessage(plugin.prefix() + "§e" + def.getDisplayName() + " §7hat keinen Startbereich."); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
player.sendMessage("§8§m══════════════════════════════");
|
player.sendMessage("§8§m══════════════════════════════");
|
||||||
player.sendMessage("§6 Startbereich: §e" + def.getDisplayName());
|
player.sendMessage("§6 Startbereich: §e" + def.getDisplayName());
|
||||||
@@ -137,56 +126,45 @@ public class RegionSetupManager {
|
|||||||
player.sendMessage("§8§m══════════════════════════════");
|
player.sendMessage("§8§m══════════════════════════════");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleGoalPos1(Player player, String eventId) {
|
// ─── Ziel-Region ─────────────────────────────────────────────────────
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
|
|
||||||
|
public void handleGoalPos1(Player player, String eventId) {
|
||||||
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
goalPos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
goalPos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
||||||
player.sendMessage(plugin.prefix() + "§aZiel-Pos1 gesetzt: §f" + formatLoc(player));
|
player.sendMessage(plugin.prefix() + "§aZiel-Pos1 gesetzt: §f" + formatLoc(player));
|
||||||
player.sendMessage(plugin.prefix() + "§7Jetzt: §f/event race goal pos2 " + eventId);
|
player.sendMessage(plugin.prefix() + "§7Jetzt: §f/event race goal pos2 " + eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleGoalPos2(Player player, String eventId) {
|
public void handleGoalPos2(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
|
|
||||||
Object[] sel = goalPos1Selection.get(player.getUniqueId());
|
Object[] sel = goalPos1Selection.get(player.getUniqueId());
|
||||||
if (sel == null || !sel[0].equals(eventId)) {
|
if (sel == null || !sel[0].equals(eventId)) {
|
||||||
player.sendMessage(plugin.prefix() + "§cZuerst Ziel-Pos1 setzen: §f/event race goal pos1 " + eventId);
|
player.sendMessage(plugin.prefix() + "§cZuerst Ziel-Pos1 setzen: §f/event race goal pos1 " + eventId); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
||||||
org.bukkit.Location pos2 = player.getLocation().clone();
|
org.bukkit.Location pos2 = player.getLocation().clone();
|
||||||
|
|
||||||
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
||||||
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!");
|
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!"); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventRegion region = new EventRegion(pos1, pos2);
|
EventRegion region = new EventRegion(pos1, pos2);
|
||||||
def.setGoalRegion(region);
|
def.setGoalRegion(region);
|
||||||
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
goalPos1Selection.remove(player.getUniqueId());
|
goalPos1Selection.remove(player.getUniqueId());
|
||||||
|
|
||||||
player.sendMessage(plugin.prefix() + "§a✔ Zielbereich gesetzt für §e" + def.getDisplayName() + "§a:");
|
player.sendMessage(plugin.prefix() + "§a✔ Zielbereich gesetzt für §e" + def.getDisplayName() + "§a:");
|
||||||
sendRegionInfo(player, region);
|
sendRegionInfo(player, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleGoalClear(Player player, String eventId) {
|
public void handleGoalClear(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
def.setGoalRegion(null);
|
def.setGoalRegion(null);
|
||||||
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
player.sendMessage(plugin.prefix() + "§7Zielbereich für §e" + def.getDisplayName() + " §7entfernt.");
|
player.sendMessage(plugin.prefix() + "§7Zielbereich für §e" + def.getDisplayName() + " §7entfernt.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleGoalInfo(Player player, String eventId) {
|
public void handleGoalInfo(Player player, String eventId) {
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
|
||||||
if (!def.hasGoalRegion()) {
|
if (!def.hasGoalRegion()) {
|
||||||
player.sendMessage(plugin.prefix() + "§e" + def.getDisplayName() + " §7hat keinen Zielbereich.");
|
player.sendMessage(plugin.prefix() + "§e" + def.getDisplayName() + " §7hat keinen Zielbereich."); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
player.sendMessage("§8§m══════════════════════════════");
|
player.sendMessage("§8§m══════════════════════════════");
|
||||||
player.sendMessage("§6 Zielbereich: §e" + def.getDisplayName());
|
player.sendMessage("§6 Zielbereich: §e" + def.getDisplayName());
|
||||||
@@ -194,21 +172,46 @@ public class RegionSetupManager {
|
|||||||
player.sendMessage("§8§m══════════════════════════════");
|
player.sendMessage("§8§m══════════════════════════════");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleInfo(Player player, String eventId) {
|
// ─── Elytra Checkpoints ───────────────────────────────────────────────
|
||||||
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
|
||||||
if (def == null) { player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId); return; }
|
public void handleCheckpointPos1(Player player, String eventId) {
|
||||||
if (!def.hasRegion()) {
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
player.sendMessage(plugin.prefix() + "§e" + def.getDisplayName() + " §7hat keine Region (gesamte Welt).");
|
checkpointPos1Selection.put(player.getUniqueId(), new Object[]{eventId, player.getLocation().clone()});
|
||||||
return;
|
Object countObj = def.getCustomSettings().get("checkpoint_count");
|
||||||
|
int nextIdx = countObj instanceof Number n ? n.intValue() : 0;
|
||||||
|
player.sendMessage(plugin.prefix() + "§aCheckpoint-Pos1 §8(#" + (nextIdx + 1) + ")§a gesetzt: §f" + formatLoc(player));
|
||||||
|
player.sendMessage(plugin.prefix() + "§7Jetzt Pos2: §f/event elytra checkpoint confirm " + eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleCheckpointPos2(Player player, String eventId) {
|
||||||
|
EventDefinition def = resolve(player, eventId); if (def == null) return;
|
||||||
|
Object[] sel = checkpointPos1Selection.get(player.getUniqueId());
|
||||||
|
if (sel == null || !sel[0].equals(eventId)) {
|
||||||
|
player.sendMessage(plugin.prefix() + "§cZuerst Pos1 setzen: §f/event elytra checkpoint add " + eventId); return;
|
||||||
}
|
}
|
||||||
EventRegion r = def.getRegion();
|
org.bukkit.Location pos1 = (org.bukkit.Location) sel[1];
|
||||||
player.sendMessage("§8§m══════════════════════════════");
|
org.bukkit.Location pos2 = player.getLocation().clone();
|
||||||
player.sendMessage("§6 Region: §e" + def.getDisplayName());
|
if (!pos1.getWorld().equals(pos2.getWorld())) {
|
||||||
player.sendMessage("§7 Welt: §f" + r.getWorldName());
|
player.sendMessage(plugin.prefix() + "§cBeide Positionen müssen in der gleichen Welt sein!"); return;
|
||||||
player.sendMessage("§7 Von: §f" + r.getMinX() + ", " + r.getMinY() + ", " + r.getMinZ());
|
}
|
||||||
player.sendMessage("§7 Bis: §f" + r.getMaxX() + ", " + r.getMaxY() + ", " + r.getMaxZ());
|
EventRegion region = new EventRegion(pos1, pos2);
|
||||||
player.sendMessage("§7 Größe: §f" + r.getSizeX() + "×" + r.getSizeY() + "×" + r.getSizeZ() + " Blöcke");
|
ElytraRaceHandler.addCheckpoint(def, region);
|
||||||
player.sendMessage("§8§m══════════════════════════════");
|
if (def.isCustom()) plugin.getConfigManager().saveCustomEvent(def);
|
||||||
|
checkpointPos1Selection.remove(player.getUniqueId());
|
||||||
|
|
||||||
|
Object countObj = def.getCustomSettings().get("checkpoint_count");
|
||||||
|
int total = countObj instanceof Number n ? n.intValue() : 0;
|
||||||
|
player.sendMessage(plugin.prefix() + "§a✔ Checkpoint §e" + total + " §agespeichert für §f" + def.getDisplayName());
|
||||||
|
sendRegionInfo(player, region);
|
||||||
|
player.sendMessage(plugin.prefix() + "§7Weiterer Checkpoint: §f/event elytra checkpoint add " + eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Hilfsmethoden ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private EventDefinition resolve(Player player, String eventId) {
|
||||||
|
EventDefinition def = plugin.getEventRegistry().get(eventId).orElse(null);
|
||||||
|
if (def == null) player.sendMessage(plugin.prefix() + "§cEvent nicht gefunden: §f" + eventId);
|
||||||
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatLoc(Player p) {
|
private String formatLoc(Player p) {
|
||||||
@@ -224,4 +227,4 @@ public class RegionSetupManager {
|
|||||||
player.sendMessage("§7 Bis: §f" + region.getMaxX() + ", " + region.getMaxY() + ", " + region.getMaxZ());
|
player.sendMessage("§7 Bis: §f" + region.getMaxX() + ", " + region.getMaxY() + ", " + region.getMaxZ());
|
||||||
player.sendMessage("§7 Größe: §f" + region.getSizeX() + "x" + region.getSizeY() + "x" + region.getSizeZ());
|
player.sendMessage("§7 Größe: §f" + region.getSizeX() + "x" + region.getSizeY() + "x" + region.getSizeZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,27 +38,23 @@ public class ConfigManager {
|
|||||||
private File customEventsFile;
|
private File customEventsFile;
|
||||||
private FileConfiguration customEventsConfig;
|
private FileConfiguration customEventsConfig;
|
||||||
|
|
||||||
// Geladene Zeitplan-Einträge
|
|
||||||
private final List<ScheduleEntry> schedule = new ArrayList<>();
|
private final List<ScheduleEntry> schedule = new ArrayList<>();
|
||||||
|
|
||||||
// Intervall-Fallback (Minuten), wenn kein Zeitplan aktiv
|
|
||||||
private int intervalMinutes;
|
private int intervalMinutes;
|
||||||
private boolean useInterval;
|
private boolean useInterval;
|
||||||
private boolean randomOnInterval;
|
private boolean randomOnInterval;
|
||||||
private String defaultEventId;
|
private String defaultEventId;
|
||||||
|
|
||||||
// Ankündigungs-Vorlauf in Sekunden
|
|
||||||
private int announceBefore;
|
private int announceBefore;
|
||||||
// Ob Events im Chat-Log erscheinen
|
|
||||||
private boolean logEvents;
|
private boolean logEvents;
|
||||||
// Prefix für alle Nachrichten
|
|
||||||
private String prefix;
|
private String prefix;
|
||||||
// Schutz-Einstellungen
|
|
||||||
private boolean enforceRegionBoundary;
|
private boolean enforceRegionBoundary;
|
||||||
private boolean noExplosionBlockDamage;
|
private boolean noExplosionBlockDamage;
|
||||||
private boolean restrictBlockInteraction;
|
private boolean restrictBlockInteraction;
|
||||||
private List<Material> itemRainItems;
|
private List<Material> itemRainItems;
|
||||||
|
|
||||||
|
/** Sekunden für den 3-2-1-Go Countdown vor jedem Event-Start (0 = deaktiviert) */
|
||||||
|
private int countdownSeconds;
|
||||||
|
|
||||||
public ConfigManager(EventEngine plugin) {
|
public ConfigManager(EventEngine plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.log = plugin.getLogger();
|
this.log = plugin.getLogger();
|
||||||
@@ -83,6 +79,7 @@ public class ConfigManager {
|
|||||||
defaultEventId = mainConfig.getString("settings.default-event", "RANDOM");
|
defaultEventId = mainConfig.getString("settings.default-event", "RANDOM");
|
||||||
announceBefore = mainConfig.getInt("settings.announce-before-seconds", 30);
|
announceBefore = mainConfig.getInt("settings.announce-before-seconds", 30);
|
||||||
logEvents = mainConfig.getBoolean("settings.log-events", true);
|
logEvents = mainConfig.getBoolean("settings.log-events", true);
|
||||||
|
countdownSeconds = mainConfig.getInt("settings.countdown-seconds", 3);
|
||||||
enforceRegionBoundary = mainConfig.getBoolean("protection.enforce-region-boundary", true);
|
enforceRegionBoundary = mainConfig.getBoolean("protection.enforce-region-boundary", true);
|
||||||
noExplosionBlockDamage = mainConfig.getBoolean("protection.no-explosion-block-damage", true);
|
noExplosionBlockDamage = mainConfig.getBoolean("protection.no-explosion-block-damage", true);
|
||||||
restrictBlockInteraction = mainConfig.getBoolean("protection.restrict-block-interaction", true);
|
restrictBlockInteraction = mainConfig.getBoolean("protection.restrict-block-interaction", true);
|
||||||
@@ -192,6 +189,9 @@ public class ConfigManager {
|
|||||||
public FileConfiguration getMainConfig() { return mainConfig; }
|
public FileConfiguration getMainConfig() { return mainConfig; }
|
||||||
public List<Material> getItemRainItems() { return Collections.unmodifiableList(itemRainItems); }
|
public List<Material> getItemRainItems() { return Collections.unmodifiableList(itemRainItems); }
|
||||||
|
|
||||||
|
/** Countdown-Sekunden vor dem eigentlichen Event-Start (0 = kein Countdown) */
|
||||||
|
public int getCountdownSeconds() { return countdownSeconds; }
|
||||||
|
|
||||||
public void setItemRainItems(List<Material> items) {
|
public void setItemRainItems(List<Material> items) {
|
||||||
itemRainItems = new ArrayList<>(items);
|
itemRainItems = new ArrayList<>(items);
|
||||||
if (itemRainItems.isEmpty()) itemRainItems.addAll(DEFAULT_ITEM_RAIN_ITEMS);
|
if (itemRainItems.isEmpty()) itemRainItems.addAll(DEFAULT_ITEM_RAIN_ITEMS);
|
||||||
@@ -203,4 +203,4 @@ public class ConfigManager {
|
|||||||
public void resetItemRainItems() {
|
public void resetItemRainItems() {
|
||||||
setItemRainItems(DEFAULT_ITEM_RAIN_ITEMS);
|
setItemRainItems(DEFAULT_ITEM_RAIN_ITEMS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,357 @@
|
|||||||
|
package dev.viper.eventengine.events.builtin;
|
||||||
|
|
||||||
|
import dev.viper.eventengine.EventEngine;
|
||||||
|
import dev.viper.eventengine.model.ActiveEvent;
|
||||||
|
import dev.viper.eventengine.model.EventDefinition;
|
||||||
|
import dev.viper.eventengine.model.EventRegion;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Elytra-Rennen Handler mit Checkpoint-System.
|
||||||
|
*
|
||||||
|
* Setup:
|
||||||
|
* - Start-Region: /event race start pos1/pos2 <id>
|
||||||
|
* - Ziel-Region: /event race goal pos1/pos2 <id>
|
||||||
|
* - Checkpoints: in config.yml / custom_events.yml unter settings.checkpoints:
|
||||||
|
* settings:
|
||||||
|
* checkpoints:
|
||||||
|
* - world: "world"
|
||||||
|
* min-x: 100 min-y: 60 min-z: 100
|
||||||
|
* max-x: 110 max-y: 70 max-z: 110
|
||||||
|
* - world: "world"
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* Ablauf:
|
||||||
|
* 1. Spieler erhalten Elytra + Raketen.
|
||||||
|
* 2. Checkpoints müssen der Reihe nach durchflogen werden.
|
||||||
|
* 3. Erst nach dem letzten Checkpoint gilt das Ziel.
|
||||||
|
* 4. Verpasste Checkpoints → Spieler wird mit Nachricht erinnert.
|
||||||
|
* 5. Im CIRCUIT-Modus: Runden werden gezählt (alle Checkpoints + Ziel = 1 Runde).
|
||||||
|
*/
|
||||||
|
public class ElytraRaceHandler implements IEventHandler, Listener {
|
||||||
|
|
||||||
|
private final EventEngine plugin;
|
||||||
|
private ActiveEvent currentEvent;
|
||||||
|
|
||||||
|
/** Checkpoint-Regionen in der Reihenfolge die geflogen werden muss */
|
||||||
|
private final List<EventRegion> checkpoints = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aktueller Checkpoint-Index pro Spieler.
|
||||||
|
* 0 = muss Checkpoint 0 als nächstes passieren.
|
||||||
|
* checkpoints.size() = alle Checkpoints durch → Ziel gilt.
|
||||||
|
*/
|
||||||
|
private final Map<UUID, Integer> playerCheckpoint = new HashMap<>();
|
||||||
|
|
||||||
|
/** Runden-Zähler (CIRCUIT-Modus) */
|
||||||
|
private final Map<UUID, Integer> lapCount = new HashMap<>();
|
||||||
|
|
||||||
|
/** Abschlussposition (CIRCUIT) */
|
||||||
|
private int finishPosition = 0;
|
||||||
|
|
||||||
|
/** Cooldown gegen Mehrfach-Trigger (ms) */
|
||||||
|
private final Map<UUID, Long> lastTrigger = new HashMap<>();
|
||||||
|
private static final long TRIGGER_COOLDOWN_MS = 1500;
|
||||||
|
|
||||||
|
private final Random rng = new Random();
|
||||||
|
|
||||||
|
public ElytraRaceHandler(EventEngine plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart(ActiveEvent event) {
|
||||||
|
this.currentEvent = event;
|
||||||
|
this.finishPosition = 0;
|
||||||
|
playerCheckpoint.clear();
|
||||||
|
lapCount.clear();
|
||||||
|
lastTrigger.clear();
|
||||||
|
checkpoints.clear();
|
||||||
|
|
||||||
|
loadCheckpoints(event.getDefinition());
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
|
|
||||||
|
// Elytra + Raketen verteilen
|
||||||
|
for (UUID uuid : event.getParticipants()) {
|
||||||
|
Player p = Bukkit.getPlayer(uuid);
|
||||||
|
if (p == null) continue;
|
||||||
|
equipPlayer(p, event.getDefinition().getDurationSeconds());
|
||||||
|
playerCheckpoint.put(uuid, 0);
|
||||||
|
lapCount.put(uuid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start-Teleport
|
||||||
|
teleportToStart(event);
|
||||||
|
|
||||||
|
// Ankündigung mit Checkpoint-Info
|
||||||
|
String cpInfo = checkpoints.isEmpty()
|
||||||
|
? "§c⚠ Keine Checkpoints konfiguriert — nur Start/Ziel aktiv."
|
||||||
|
: "§7" + checkpoints.size() + " Checkpoint" + (checkpoints.size() == 1 ? "" : "s") + " auf der Strecke.";
|
||||||
|
|
||||||
|
boolean isCircuit = event.getDefinition().isCircuit();
|
||||||
|
String modeInfo = isCircuit
|
||||||
|
? "§e" + event.getDefinition().getLaps() + " Runden §7im Rundkurs-Modus."
|
||||||
|
: "§7Sprint von Start zu Ziel.";
|
||||||
|
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§b🪂 §eElytra-Rennen! " + modeInfo);
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + cpInfo);
|
||||||
|
|
||||||
|
if (!event.getDefinition().hasStartRegion())
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§c⚠ Kein Startbereich gesetzt. /event race start pos1/pos2 " + event.getDefinition().getId());
|
||||||
|
if (!event.getDefinition().hasGoalRegion())
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§c⚠ Kein Zielbereich gesetzt. /event race goal pos1/pos2 " + event.getDefinition().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnd(ActiveEvent event) {
|
||||||
|
HandlerList.unregisterAll(this);
|
||||||
|
playerCheckpoint.clear();
|
||||||
|
lapCount.clear();
|
||||||
|
lastTrigger.clear();
|
||||||
|
this.currentEvent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerJoin(ActiveEvent event, Player player) {
|
||||||
|
equipPlayer(player, event.getDefinition().getDurationSeconds());
|
||||||
|
playerCheckpoint.put(player.getUniqueId(), 0);
|
||||||
|
lapCount.put(player.getUniqueId(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerLeave(ActiveEvent event, Player player) {
|
||||||
|
playerCheckpoint.remove(player.getUniqueId());
|
||||||
|
lapCount.remove(player.getUniqueId());
|
||||||
|
lastTrigger.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Bewegungs-Listener ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
|
public void onMove(PlayerMoveEvent e) {
|
||||||
|
if (currentEvent == null || currentEvent.getState() != ActiveEvent.State.RUNNING) return;
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
if (!currentEvent.isParticipant(player)) return;
|
||||||
|
|
||||||
|
Location to = e.getTo();
|
||||||
|
if (to == null) return;
|
||||||
|
// Nur bei echtem Positions-Wechsel
|
||||||
|
if (e.getFrom().getBlockX() == to.getBlockX()
|
||||||
|
&& e.getFrom().getBlockY() == to.getBlockY()
|
||||||
|
&& e.getFrom().getBlockZ() == to.getBlockZ()) return;
|
||||||
|
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
Long last = lastTrigger.get(uuid);
|
||||||
|
if (last != null && now - last < TRIGGER_COOLDOWN_MS) return;
|
||||||
|
|
||||||
|
EventDefinition def = currentEvent.getDefinition();
|
||||||
|
int cpIndex = playerCheckpoint.getOrDefault(uuid, 0);
|
||||||
|
|
||||||
|
// Checkpoint-Check (in Reihenfolge)
|
||||||
|
if (cpIndex < checkpoints.size()) {
|
||||||
|
EventRegion cp = checkpoints.get(cpIndex);
|
||||||
|
if (cp.contains(to)) {
|
||||||
|
lastTrigger.put(uuid, now);
|
||||||
|
playerCheckpoint.put(uuid, cpIndex + 1);
|
||||||
|
int nextCp = cpIndex + 1;
|
||||||
|
String msg = nextCp < checkpoints.size()
|
||||||
|
? "§a✔ Checkpoint §f" + nextCp + "§a/§f" + checkpoints.size() + " §apAssiert!"
|
||||||
|
: "§a✔ Letzter Checkpoint! §eFliege zum Ziel!";
|
||||||
|
player.sendActionBar(msg);
|
||||||
|
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1.8f);
|
||||||
|
}
|
||||||
|
return; // Ziel gilt erst nach allen Checkpoints
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ziel-Check (alle Checkpoints durch)
|
||||||
|
EventRegion goal = def.getGoalRegion();
|
||||||
|
if (goal == null || !goal.contains(to)) return;
|
||||||
|
|
||||||
|
lastTrigger.put(uuid, now);
|
||||||
|
|
||||||
|
if (def.isCircuit()) {
|
||||||
|
handleCircuitGoal(player, def, now);
|
||||||
|
} else {
|
||||||
|
handleSprintGoal(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Sprint: erster gewinnt ────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void handleSprintGoal(Player player) {
|
||||||
|
if (currentEvent.hasWinner()) return;
|
||||||
|
plugin.getEventManager().endEventWithWinner(player, "Ziel erreicht");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Circuit: Runden zählen ───────────────────────────────────────────
|
||||||
|
|
||||||
|
private void handleCircuitGoal(Player player, EventDefinition def, long now) {
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
int done = lapCount.merge(uuid, 1, Integer::sum);
|
||||||
|
int total = def.getLaps();
|
||||||
|
long elapsed = currentEvent.getElapsedSeconds();
|
||||||
|
|
||||||
|
// Checkpoint-Zähler für nächste Runde zurücksetzen
|
||||||
|
playerCheckpoint.put(uuid, 0);
|
||||||
|
|
||||||
|
if (done < total) {
|
||||||
|
String msg = "§e🏁 Runde §f" + done + "§e/§f" + total
|
||||||
|
+ " §8(§f" + formatTime((int) elapsed) + "§8)";
|
||||||
|
player.sendActionBar(msg);
|
||||||
|
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1.5f);
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§f" + player.getName()
|
||||||
|
+ " §7— Runde §e" + done + "§7/§e" + total
|
||||||
|
+ " §8(§f" + formatTime((int) elapsed) + "§8)");
|
||||||
|
} else {
|
||||||
|
finishPosition++;
|
||||||
|
int pos = finishPosition;
|
||||||
|
currentEvent.addScore(uuid, Math.max(0, 100 - (pos - 1) * 20));
|
||||||
|
|
||||||
|
String posStr = switch (pos) {
|
||||||
|
case 1 -> "§6§l1. Platz 🥇";
|
||||||
|
case 2 -> "§7§l2. Platz 🥈";
|
||||||
|
case 3 -> "§c§l3. Platz 🥉";
|
||||||
|
default -> "§7" + pos + ". Platz";
|
||||||
|
};
|
||||||
|
|
||||||
|
player.sendTitle(posStr, "§fZeit: §e" + formatTime((int) elapsed), 0, 60, 20);
|
||||||
|
player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1f, pos == 1 ? 1.2f : 0.8f);
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§b🪂 §f" + player.getName()
|
||||||
|
+ " §ehat das Rennen beendet! §8[" + posStr + "§8] §8(§f"
|
||||||
|
+ formatTime((int) elapsed) + "§8)");
|
||||||
|
|
||||||
|
currentEvent.removeParticipant(player);
|
||||||
|
|
||||||
|
if (pos == 1) {
|
||||||
|
currentEvent.setWinner(uuid);
|
||||||
|
plugin.getEventManager().distributeWinnerRewards(def, player);
|
||||||
|
}
|
||||||
|
if (currentEvent.getParticipantCount() == 0) {
|
||||||
|
plugin.getEventManager().endEvent("Rennen beendet — alle Spieler im Ziel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Hilfsmethoden ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void equipPlayer(Player p, int durationSec) {
|
||||||
|
p.getEquipment().setChestplate(new ItemStack(Material.ELYTRA));
|
||||||
|
// Raketen für die gesamte Event-Dauer (mind. 64)
|
||||||
|
int rockets = Math.max(64, (durationSec / 5));
|
||||||
|
p.getInventory().addItem(new ItemStack(Material.FIREWORK_ROCKET, Math.min(rockets, 64)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void teleportToStart(ActiveEvent event) {
|
||||||
|
EventRegion start = event.getDefinition().getStartRegion();
|
||||||
|
if (start == null) return;
|
||||||
|
for (UUID uuid : event.getParticipants()) {
|
||||||
|
Player p = Bukkit.getPlayer(uuid);
|
||||||
|
if (p == null) continue;
|
||||||
|
Location loc = start.randomPoint(rng);
|
||||||
|
if (loc != null) p.teleport(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lädt Checkpoint-Regionen aus den Custom-Settings der EventDefinition.
|
||||||
|
*
|
||||||
|
* Erwartet in custom_events.yml oder event-overrides unter settings:
|
||||||
|
* settings:
|
||||||
|
* checkpoint_count: 2
|
||||||
|
* checkpoint_0_world: "world"
|
||||||
|
* checkpoint_0_min-x: 100 ... checkpoint_0_max-z: 110
|
||||||
|
* checkpoint_1_world: "world"
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* Alternativ Direktformat mit Liste wenn durch den Builder gesetzt.
|
||||||
|
*/
|
||||||
|
private void loadCheckpoints(EventDefinition def) {
|
||||||
|
Map<String, Object> settings = def.getCustomSettings();
|
||||||
|
if (settings == null || settings.isEmpty()) return;
|
||||||
|
|
||||||
|
Object countObj = settings.get("checkpoint_count");
|
||||||
|
if (!(countObj instanceof Number)) return;
|
||||||
|
int count = ((Number) countObj).intValue();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
String prefix = "checkpoint_" + i + "_";
|
||||||
|
try {
|
||||||
|
String world = (String) settings.get(prefix + "world");
|
||||||
|
int minX = toInt(settings.get(prefix + "min-x"));
|
||||||
|
int minY = toInt(settings.get(prefix + "min-y"));
|
||||||
|
int minZ = toInt(settings.get(prefix + "min-z"));
|
||||||
|
int maxX = toInt(settings.get(prefix + "max-x"));
|
||||||
|
int maxY = toInt(settings.get(prefix + "max-y"));
|
||||||
|
int maxZ = toInt(settings.get(prefix + "max-z"));
|
||||||
|
checkpoints.add(new EventRegion(world, minX, minY, minZ, maxX, maxY, maxZ));
|
||||||
|
plugin.getLogger().info("ElytraRace: Checkpoint " + i + " geladen (" + world + ")");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
plugin.getLogger().warning("ElytraRace: Checkpoint " + i + " fehlerhaft — " + ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plugin.getLogger().info("ElytraRace: " + checkpoints.size() + " Checkpoint(s) geladen.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toInt(Object o) {
|
||||||
|
if (o instanceof Number n) return n.intValue();
|
||||||
|
return Integer.parseInt(String.valueOf(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatTime(int seconds) {
|
||||||
|
int m = seconds / 60, s = seconds % 60;
|
||||||
|
if (m == 0) return s + "s";
|
||||||
|
return m + "m " + s + "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Checkpoint-Setup per Command-Hilfsklasse ──────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speichert einen neuen Checkpoint in den Custom-Settings der EventDefinition.
|
||||||
|
* Aufruf z.B. aus EventCommand: /event elytra checkpoint add <id> pos1/pos2
|
||||||
|
*
|
||||||
|
* @param def Die EventDefinition des Elytra-Rennens
|
||||||
|
* @param region Die fertige Checkpoint-Region
|
||||||
|
*/
|
||||||
|
public static void addCheckpoint(EventDefinition def, EventRegion region) {
|
||||||
|
Map<String, Object> s = def.getCustomSettings();
|
||||||
|
Object countObj = s.get("checkpoint_count");
|
||||||
|
int idx = countObj instanceof Number n ? n.intValue() : 0;
|
||||||
|
|
||||||
|
String pf = "checkpoint_" + idx + "_";
|
||||||
|
s.put(pf + "world", region.getWorldName());
|
||||||
|
s.put(pf + "min-x", region.getMinX()); s.put(pf + "min-y", region.getMinY()); s.put(pf + "min-z", region.getMinZ());
|
||||||
|
s.put(pf + "max-x", region.getMaxX()); s.put(pf + "max-y", region.getMaxY()); s.put(pf + "max-z", region.getMaxZ());
|
||||||
|
s.put("checkpoint_count", idx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entfernt alle Checkpoints aus den Custom-Settings.
|
||||||
|
*/
|
||||||
|
public static void clearCheckpoints(EventDefinition def) {
|
||||||
|
Map<String, Object> s = def.getCustomSettings();
|
||||||
|
Object countObj = s.get("checkpoint_count");
|
||||||
|
int count = countObj instanceof Number n ? n.intValue() : 0;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
String pf = "checkpoint_" + i + "_";
|
||||||
|
s.remove(pf + "world");
|
||||||
|
s.remove(pf + "min-x"); s.remove(pf + "min-y"); s.remove(pf + "min-z");
|
||||||
|
s.remove(pf + "max-x"); s.remove(pf + "max-y"); s.remove(pf + "max-z");
|
||||||
|
}
|
||||||
|
s.remove("checkpoint_count");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,13 +17,16 @@ import org.bukkit.potion.PotionEffect;
|
|||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
// ══════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════
|
||||||
// RENNEN — alle 10
|
// RENNEN — Basis + alle außer ElytraRaceHandler
|
||||||
|
// ElytraRaceHandler ist in ElytraRaceHandler.java (eigene Datei)
|
||||||
// ══════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
/** Basis für alle Renn-Events: Punkte pro Sekunde, wer am Ende mehr hat gewinnt */
|
/** Basis für alle Renn-Events */
|
||||||
class BaseRaceHandler implements IEventHandler {
|
class BaseRaceHandler implements IEventHandler {
|
||||||
protected final EventEngine plugin;
|
protected final EventEngine plugin;
|
||||||
protected final String icon;
|
protected final String icon;
|
||||||
@@ -67,14 +70,7 @@ class ParkourRaceHandler extends BaseRaceHandler {
|
|||||||
ParkourRaceHandler(EventEngine p){super(p,"🏃","Parkour Race");}
|
ParkourRaceHandler(EventEngine p){super(p,"🏃","Parkour Race");}
|
||||||
@Override public void onStart(ActiveEvent e){ super.onStart(e); Bukkit.broadcastMessage(plugin.prefix()+"§a🏃 §eParkour Race! §7Lauft durch den Kurs — wer zuerst am Ziel ist, gewinnt!"); }
|
@Override public void onStart(ActiveEvent e){ super.onStart(e); Bukkit.broadcastMessage(plugin.prefix()+"§a🏃 §eParkour Race! §7Lauft durch den Kurs — wer zuerst am Ziel ist, gewinnt!"); }
|
||||||
}
|
}
|
||||||
class ElytraRaceHandler extends BaseRaceHandler {
|
// ElytraRaceHandler → eigene Datei: ElytraRaceHandler.java
|
||||||
ElytraRaceHandler(EventEngine p){super(p,"🪂","Elytra-Rennen");}
|
|
||||||
@Override public void onStart(ActiveEvent e){
|
|
||||||
super.onStart(e);
|
|
||||||
for(UUID u:e.getParticipants()){Player p=Bukkit.getPlayer(u);if(p==null)continue;p.getEquipment().setChestplate(new ItemStack(Material.ELYTRA));p.getInventory().addItem(new ItemStack(Material.FIREWORK_ROCKET,64));}
|
|
||||||
Bukkit.broadcastMessage(plugin.prefix()+"§b🪂 §eElytra-Rennen! §7Fliegt mit Elytren zum Ziel!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class BoatRaceHandler extends BaseRaceHandler {
|
class BoatRaceHandler extends BaseRaceHandler {
|
||||||
BoatRaceHandler(EventEngine p){super(p,"⛵","Boot-Rennen");}
|
BoatRaceHandler(EventEngine p){super(p,"⛵","Boot-Rennen");}
|
||||||
@Override public void onStart(ActiveEvent e){ super.onStart(e); for(UUID u:e.getParticipants()){Player p=Bukkit.getPlayer(u);if(p==null)continue;p.getInventory().addItem(new ItemStack(Material.OAK_BOAT));} Bukkit.broadcastMessage(plugin.prefix()+"§b⛵ §eBoot-Rennen! §7Klettert in euer Boot und rast zum Ziel!"); }
|
@Override public void onStart(ActiveEvent e){ super.onStart(e); for(UUID u:e.getParticipants()){Player p=Bukkit.getPlayer(u);if(p==null)continue;p.getInventory().addItem(new ItemStack(Material.OAK_BOAT));} Bukkit.broadcastMessage(plugin.prefix()+"§b⛵ §eBoot-Rennen! §7Klettert in euer Boot und rast zum Ziel!"); }
|
||||||
@@ -333,7 +329,7 @@ class CapturePointsHandler implements IEventHandler {
|
|||||||
CapturePointsHandler(EventEngine p){this.plugin=p;}
|
CapturePointsHandler(EventEngine p){this.plugin=p;}
|
||||||
@Override public void onStart(ActiveEvent e){
|
@Override public void onStart(ActiveEvent e){
|
||||||
Bukkit.broadcastMessage(plugin.prefix()+"§e🚩 §ePunkte-Capture! §7Steht auf den markierten Punkten um Punkte zu sammeln. Mehr Spieler auf einem Punkt = schnellere Einnahme!");
|
Bukkit.broadcastMessage(plugin.prefix()+"§e🚩 §ePunkte-Capture! §7Steht auf den markierten Punkten um Punkte zu sammeln. Mehr Spieler auf einem Punkt = schnellere Einnahme!");
|
||||||
ticker=new BukkitRunnable(){ @Override public void run(){ if(e.getState()==ActiveEvent.State.ENDED){cancel();return;} /* Punkt-Check hier — benötigt vorbereitete Punkte-Positionen in den Settings */ for(UUID u:e.getParticipants()){Player p=Bukkit.getPlayer(u);if(p==null)continue;/* Placeholder: jeder Spieler auf einem Kontrollpunkt bekommt Punkte */} }};
|
ticker=new BukkitRunnable(){ @Override public void run(){ if(e.getState()==ActiveEvent.State.ENDED){cancel();return;} }};
|
||||||
ticker.runTaskTimer(plugin,20L,20L);
|
ticker.runTaskTimer(plugin,20L,20L);
|
||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){ if(ticker!=null)ticker.cancel(); }
|
@Override public void onEnd(ActiveEvent e){ if(ticker!=null)ticker.cancel(); }
|
||||||
@@ -374,15 +370,12 @@ class ColorWarHandler implements IEventHandler, Listener {
|
|||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){
|
@Override public void onEnd(ActiveEvent e){
|
||||||
HandlerList.unregisterAll(this);
|
HandlerList.unregisterAll(this);
|
||||||
// Zähle Blöcke pro Farbe in der Region
|
|
||||||
if(e.getDefinition().hasRegion()){
|
if(e.getDefinition().hasRegion()){
|
||||||
org.bukkit.World w=e.getDefinition().getRegion().getWorld();
|
org.bukkit.World w=e.getDefinition().getRegion().getWorld();
|
||||||
if(w!=null){Map<Material,Integer>counts=new EnumMap<>(Material.class);dev.viper.eventengine.model.EventRegion r=e.getDefinition().getRegion();for(int x=r.getMinX();x<=r.getMaxX();x++)for(int z=r.getMinZ();z<=r.getMaxZ();z++){Material t=w.getBlockAt(x,r.getMinY(),z).getType();if(Arrays.asList(COLORS).contains(t))counts.merge(t,1,Integer::sum);}Bukkit.broadcastMessage(plugin.prefix()+"§e🎨 §7Farben-Ergebnis:");counts.forEach((m,cnt)->Bukkit.broadcastMessage(" §7"+m.name()+": §e"+cnt+" §7Blöcke"));}
|
if(w!=null){Map<Material,Integer>counts=new EnumMap<>(Material.class);dev.viper.eventengine.model.EventRegion r=e.getDefinition().getRegion();for(int x=r.getMinX();x<=r.getMaxX();x++)for(int z=r.getMinZ();z<=r.getMaxZ();z++){Material t=w.getBlockAt(x,r.getMinY(),z).getType();if(Arrays.asList(COLORS).contains(t))counts.merge(t,1,Integer::sum);}Bukkit.broadcastMessage(plugin.prefix()+"§e🎨 §7Farben-Ergebnis:");counts.forEach((m,cnt)->Bukkit.broadcastMessage(" §7"+m.name()+": §e"+cnt+" §7Blöcke"));}
|
||||||
}
|
}
|
||||||
current=null;teamColors.clear();
|
current=null;teamColors.clear();
|
||||||
}
|
}
|
||||||
// Damit ist der Import nötig
|
|
||||||
private static final Material[] COLORS_REF = COLORS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ══════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════
|
||||||
@@ -395,11 +388,8 @@ class TinyPlayersHandler implements IEventHandler {
|
|||||||
TinyPlayersHandler(EventEngine pp){this.p=pp;}
|
TinyPlayersHandler(EventEngine pp){this.p=pp;}
|
||||||
@Override public void onStart(ActiveEvent e){
|
@Override public void onStart(ActiveEvent e){
|
||||||
List<Player> players = new ArrayList<>();
|
List<Player> players = new ArrayList<>();
|
||||||
if (e.getParticipants().isEmpty()) {
|
if (e.getParticipants().isEmpty()) { players.addAll(Bukkit.getOnlinePlayers()); }
|
||||||
players.addAll(Bukkit.getOnlinePlayers());
|
else { for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl!=null)players.add(pl);} }
|
||||||
} else {
|
|
||||||
for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl!=null)players.add(pl);}
|
|
||||||
}
|
|
||||||
for (Player pl : players) {
|
for (Player pl : players) {
|
||||||
applyScale(pl, 0.6);
|
applyScale(pl, 0.6);
|
||||||
pl.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS,e.getDefinition().getDurationSeconds()*20,0,false,false));
|
pl.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS,e.getDefinition().getDurationSeconds()*20,0,false,false));
|
||||||
@@ -408,138 +398,53 @@ class TinyPlayersHandler implements IEventHandler {
|
|||||||
Bukkit.broadcastMessage(p.prefix()+"§e🐭 §eMini-Spieler! §7Alle sind jetzt winzig klein!");
|
Bukkit.broadcastMessage(p.prefix()+"§e🐭 §eMini-Spieler! §7Alle sind jetzt winzig klein!");
|
||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){
|
@Override public void onEnd(ActiveEvent e){
|
||||||
if (e.getParticipants().isEmpty()) {
|
Iterable<UUID> targets = e.getParticipants().isEmpty() ? uuidsOf(Bukkit.getOnlinePlayers()) : e.getParticipants();
|
||||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
for(UUID u:targets){Player pl=Bukkit.getPlayer(u);if(pl!=null){restoreScale(pl);pl.removePotionEffect(PotionEffectType.SLOWNESS);pl.removePotionEffect(PotionEffectType.JUMP_BOOST);}}
|
||||||
restoreScale(pl);
|
|
||||||
pl.removePotionEffect(PotionEffectType.SLOWNESS);
|
|
||||||
pl.removePotionEffect(PotionEffectType.JUMP_BOOST);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(UUID u:e.getParticipants()){
|
|
||||||
Player pl=Bukkit.getPlayer(u);
|
|
||||||
if(pl!=null){
|
|
||||||
restoreScale(pl);
|
|
||||||
pl.removePotionEffect(PotionEffectType.SLOWNESS);
|
|
||||||
pl.removePotionEffect(PotionEffectType.JUMP_BOOST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevScale.clear();
|
prevScale.clear();
|
||||||
}
|
}
|
||||||
|
private void applyScale(Player pl, double scale){org.bukkit.attribute.Attribute a=scaleAttr();if(a==null)return;org.bukkit.attribute.AttributeInstance ai=pl.getAttribute(a);if(ai==null)return;prevScale.putIfAbsent(pl.getUniqueId(),ai.getBaseValue());ai.setBaseValue(scale);}
|
||||||
private void applyScale(Player pl, double scale) {
|
private void restoreScale(Player pl){org.bukkit.attribute.Attribute a=scaleAttr();if(a==null)return;org.bukkit.attribute.AttributeInstance ai=pl.getAttribute(a);if(ai==null)return;Double prev=prevScale.remove(pl.getUniqueId());if(prev!=null)ai.setBaseValue(prev);}
|
||||||
org.bukkit.attribute.Attribute attrType = getScaleAttribute();
|
private org.bukkit.attribute.Attribute scaleAttr(){try{return org.bukkit.attribute.Attribute.valueOf("GENERIC_SCALE");}catch(IllegalArgumentException ex){return null;}}
|
||||||
if (attrType == null) return;
|
private List<UUID> uuidsOf(Collection<? extends Player> ps){List<UUID> r=new ArrayList<>();ps.forEach(p->r.add(p.getUniqueId()));return r;}
|
||||||
org.bukkit.attribute.AttributeInstance attr = pl.getAttribute(attrType);
|
|
||||||
if (attr == null) return;
|
|
||||||
prevScale.putIfAbsent(pl.getUniqueId(), attr.getBaseValue());
|
|
||||||
attr.setBaseValue(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restoreScale(Player pl) {
|
|
||||||
org.bukkit.attribute.Attribute attrType = getScaleAttribute();
|
|
||||||
if (attrType == null) return;
|
|
||||||
org.bukkit.attribute.AttributeInstance attr = pl.getAttribute(attrType);
|
|
||||||
if (attr == null) return;
|
|
||||||
Double prev = prevScale.remove(pl.getUniqueId());
|
|
||||||
if (prev != null) attr.setBaseValue(prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
private org.bukkit.attribute.Attribute getScaleAttribute() {
|
|
||||||
try {
|
|
||||||
return org.bukkit.attribute.Attribute.valueOf("GENERIC_SCALE");
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GiantPlayersHandler implements IEventHandler {
|
class GiantPlayersHandler implements IEventHandler {
|
||||||
private final EventEngine p;
|
private final EventEngine p;
|
||||||
private final Map<UUID, Double> prevScale = new HashMap<>();
|
private final Map<UUID, Double> prevScale = new HashMap<>();
|
||||||
GiantPlayersHandler(EventEngine pp){this.p=pp;}
|
GiantPlayersHandler(EventEngine pp){this.p=pp;}
|
||||||
@Override public void onStart(ActiveEvent e){
|
@Override public void onStart(ActiveEvent e){
|
||||||
List<Player> players = new ArrayList<>();
|
List<Player> players = new ArrayList<>();
|
||||||
if (e.getParticipants().isEmpty()) {
|
if (e.getParticipants().isEmpty()) { players.addAll(Bukkit.getOnlinePlayers()); }
|
||||||
players.addAll(Bukkit.getOnlinePlayers());
|
else { for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl!=null)players.add(pl);} }
|
||||||
} else {
|
for(Player pl:players){applyScale(pl,1.6);pl.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,e.getDefinition().getDurationSeconds()*20,1,false,false));pl.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,e.getDefinition().getDurationSeconds()*20,1,false,false));}
|
||||||
for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl!=null)players.add(pl);}
|
|
||||||
}
|
|
||||||
for(Player pl:players){
|
|
||||||
applyScale(pl, 1.6);
|
|
||||||
pl.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,e.getDefinition().getDurationSeconds()*20,1,false,false));
|
|
||||||
pl.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,e.getDefinition().getDurationSeconds()*20,1,false,false));
|
|
||||||
}
|
|
||||||
Bukkit.broadcastMessage(p.prefix()+"§6🦣 §eRiesen-Spieler! §7Alle sind jetzt riesig! Stärke und Geschwindigkeit erhöht!");
|
Bukkit.broadcastMessage(p.prefix()+"§6🦣 §eRiesen-Spieler! §7Alle sind jetzt riesig! Stärke und Geschwindigkeit erhöht!");
|
||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){
|
@Override public void onEnd(ActiveEvent e){
|
||||||
if (e.getParticipants().isEmpty()) {
|
Iterable<UUID> targets = e.getParticipants().isEmpty() ? uuidsOf(Bukkit.getOnlinePlayers()) : e.getParticipants();
|
||||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
for(UUID u:targets){Player pl=Bukkit.getPlayer(u);if(pl!=null){restoreScale(pl);pl.removePotionEffect(PotionEffectType.SPEED);pl.removePotionEffect(PotionEffectType.STRENGTH);}}
|
||||||
restoreScale(pl);
|
|
||||||
pl.removePotionEffect(PotionEffectType.SPEED);
|
|
||||||
pl.removePotionEffect(PotionEffectType.STRENGTH);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(UUID u:e.getParticipants()){
|
|
||||||
Player pl=Bukkit.getPlayer(u);
|
|
||||||
if(pl!=null){
|
|
||||||
restoreScale(pl);
|
|
||||||
pl.removePotionEffect(PotionEffectType.SPEED);
|
|
||||||
pl.removePotionEffect(PotionEffectType.STRENGTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevScale.clear();
|
prevScale.clear();
|
||||||
}
|
}
|
||||||
|
private void applyScale(Player pl, double scale){org.bukkit.attribute.Attribute a=scaleAttr();if(a==null)return;org.bukkit.attribute.AttributeInstance ai=pl.getAttribute(a);if(ai==null)return;prevScale.putIfAbsent(pl.getUniqueId(),ai.getBaseValue());ai.setBaseValue(scale);}
|
||||||
private void applyScale(Player pl, double scale) {
|
private void restoreScale(Player pl){org.bukkit.attribute.Attribute a=scaleAttr();if(a==null)return;org.bukkit.attribute.AttributeInstance ai=pl.getAttribute(a);if(ai==null)return;Double prev=prevScale.remove(pl.getUniqueId());if(prev!=null)ai.setBaseValue(prev);}
|
||||||
org.bukkit.attribute.Attribute attrType = getScaleAttribute();
|
private org.bukkit.attribute.Attribute scaleAttr(){try{return org.bukkit.attribute.Attribute.valueOf("GENERIC_SCALE");}catch(IllegalArgumentException ex){return null;}}
|
||||||
if (attrType == null) return;
|
private List<UUID> uuidsOf(Collection<? extends Player> ps){List<UUID> r=new ArrayList<>();ps.forEach(p->r.add(p.getUniqueId()));return r;}
|
||||||
org.bukkit.attribute.AttributeInstance attr = pl.getAttribute(attrType);
|
|
||||||
if (attr == null) return;
|
|
||||||
prevScale.putIfAbsent(pl.getUniqueId(), attr.getBaseValue());
|
|
||||||
attr.setBaseValue(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restoreScale(Player pl) {
|
|
||||||
org.bukkit.attribute.Attribute attrType = getScaleAttribute();
|
|
||||||
if (attrType == null) return;
|
|
||||||
org.bukkit.attribute.AttributeInstance attr = pl.getAttribute(attrType);
|
|
||||||
if (attr == null) return;
|
|
||||||
Double prev = prevScale.remove(pl.getUniqueId());
|
|
||||||
if (prev != null) attr.setBaseValue(prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
private org.bukkit.attribute.Attribute getScaleAttribute() {
|
|
||||||
try {
|
|
||||||
return org.bukkit.attribute.Attribute.valueOf("GENERIC_SCALE");
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvisiblePlayersHandler implements IEventHandler {
|
class InvisiblePlayersHandler implements IEventHandler {
|
||||||
private final EventEngine p;
|
private final EventEngine p;
|
||||||
InvisiblePlayersHandler(EventEngine pp){this.p=pp;}
|
InvisiblePlayersHandler(EventEngine pp){this.p=pp;}
|
||||||
@Override public void onStart(ActiveEvent e){
|
@Override public void onStart(ActiveEvent e){
|
||||||
if (e.getParticipants().isEmpty()) {
|
Iterable<UUID> targets = e.getParticipants().isEmpty() ? uuidsOf(Bukkit.getOnlinePlayers()) : e.getParticipants();
|
||||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
for(UUID u:targets){Player pl=Bukkit.getPlayer(u);if(pl==null)continue;pl.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY,e.getDefinition().getDurationSeconds()*20,0,false,false));}
|
||||||
pl.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY,e.getDefinition().getDurationSeconds()*20,0,false,false));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl==null)continue;pl.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY,e.getDefinition().getDurationSeconds()*20,0,false,false));}
|
|
||||||
}
|
|
||||||
Bukkit.broadcastMessage(p.prefix()+"§7👻 §eUnsichtbarkeit! §7Alle Spieler sind unsichtbar!");
|
Bukkit.broadcastMessage(p.prefix()+"§7👻 §eUnsichtbarkeit! §7Alle Spieler sind unsichtbar!");
|
||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){
|
@Override public void onEnd(ActiveEvent e){
|
||||||
if (e.getParticipants().isEmpty()) {
|
Iterable<UUID> targets = e.getParticipants().isEmpty() ? uuidsOf(Bukkit.getOnlinePlayers()) : e.getParticipants();
|
||||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
for(UUID u:targets){Player pl=Bukkit.getPlayer(u);if(pl!=null)pl.removePotionEffect(PotionEffectType.INVISIBILITY);}
|
||||||
pl.removePotionEffect(PotionEffectType.INVISIBILITY);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl!=null)pl.removePotionEffect(PotionEffectType.INVISIBILITY);}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
private List<UUID> uuidsOf(Collection<? extends Player> ps){List<UUID> r=new ArrayList<>();ps.forEach(p->r.add(p.getUniqueId()));return r;}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RandomTeleportHandler implements IEventHandler {
|
class RandomTeleportHandler implements IEventHandler {
|
||||||
private final EventEngine plugin; private BukkitRunnable tpRunner;
|
private final EventEngine plugin; private BukkitRunnable tpRunner;
|
||||||
RandomTeleportHandler(EventEngine p){this.plugin=p;}
|
RandomTeleportHandler(EventEngine p){this.plugin=p;}
|
||||||
@@ -548,40 +453,22 @@ class RandomTeleportHandler implements IEventHandler {
|
|||||||
final Random rng=new Random();
|
final Random rng=new Random();
|
||||||
tpRunner=new BukkitRunnable(){@Override public void run(){
|
tpRunner=new BukkitRunnable(){@Override public void run(){
|
||||||
if(e.getState()==ActiveEvent.State.ENDED){cancel();return;}
|
if(e.getState()==ActiveEvent.State.ENDED){cancel();return;}
|
||||||
if (e.getParticipants().isEmpty()) {
|
Iterable<UUID> targets = e.getParticipants().isEmpty() ? uuidsOf(Bukkit.getOnlinePlayers()) : e.getParticipants();
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
for(UUID u:targets){Player p=Bukkit.getPlayer(u);if(p==null||rng.nextInt(3)!=0)continue;Location loc=e.getDefinition().hasRegion()?e.getDefinition().getRegion().randomLocation(rng):p.getLocation().add((rng.nextDouble()-0.5)*30,0,(rng.nextDouble()-0.5)*30);if(loc!=null)p.teleport(loc);p.sendActionBar("§d⚡ ZUFALLS-TP!");}
|
||||||
if (rng.nextInt(3) != 0) continue;
|
}};
|
||||||
Location loc=e.getDefinition().hasRegion()?e.getDefinition().getRegion().randomLocation(rng):p.getLocation().add((rng.nextDouble()-0.5)*30,0,(rng.nextDouble()-0.5)*30);
|
|
||||||
if(loc!=null)p.teleport(loc);
|
|
||||||
p.sendActionBar("§d⚡ ZUFALLS-TP!");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(UUID u:e.getParticipants()){
|
|
||||||
Player p=Bukkit.getPlayer(u);
|
|
||||||
if(p==null||rng.nextInt(3)!=0)continue;
|
|
||||||
Location loc=e.getDefinition().hasRegion()?e.getDefinition().getRegion().randomLocation(rng):p.getLocation().add((rng.nextDouble()-0.5)*30,0,(rng.nextDouble()-0.5)*30);
|
|
||||||
if(loc!=null)p.teleport(loc);
|
|
||||||
p.sendActionBar("§d⚡ ZUFALLS-TP!");
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
tpRunner.runTaskTimer(plugin,20L,100L);
|
tpRunner.runTaskTimer(plugin,20L,100L);
|
||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){ if(tpRunner!=null)tpRunner.cancel(); }
|
@Override public void onEnd(ActiveEvent e){ if(tpRunner!=null)tpRunner.cancel(); }
|
||||||
|
private List<UUID> uuidsOf(Collection<? extends Player> ps){List<UUID> r=new ArrayList<>();ps.forEach(p->r.add(p.getUniqueId()));return r;}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SwapInventoriesHandler implements IEventHandler {
|
class SwapInventoriesHandler implements IEventHandler {
|
||||||
private final EventEngine p;
|
private final EventEngine p;
|
||||||
SwapInventoriesHandler(EventEngine pp){this.p=pp;}
|
SwapInventoriesHandler(EventEngine pp){this.p=pp;}
|
||||||
@Override public void onStart(ActiveEvent e){
|
@Override public void onStart(ActiveEvent e){
|
||||||
List<Player> players = new ArrayList<>();
|
List<Player> players=new ArrayList<>();
|
||||||
if (e.getParticipants().isEmpty()) {
|
if(e.getParticipants().isEmpty()){players.addAll(Bukkit.getOnlinePlayers());}
|
||||||
players.addAll(Bukkit.getOnlinePlayers());
|
else{for(UUID u:e.getParticipants()){Player pl=Bukkit.getPlayer(u);if(pl!=null)players.add(pl);}}
|
||||||
} else {
|
|
||||||
for (UUID u : e.getParticipants()) {
|
|
||||||
Player pl = Bukkit.getPlayer(u);
|
|
||||||
if (pl != null) players.add(pl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(players.size()<2){Bukkit.broadcastMessage(p.prefix()+"§cMindestens 2 Spieler benötigt!");return;}
|
if(players.size()<2){Bukkit.broadcastMessage(p.prefix()+"§cMindestens 2 Spieler benötigt!");return;}
|
||||||
Collections.shuffle(players);
|
Collections.shuffle(players);
|
||||||
List<ItemStack[]>inventories=new ArrayList<>();
|
List<ItemStack[]>inventories=new ArrayList<>();
|
||||||
@@ -591,6 +478,7 @@ class SwapInventoriesHandler implements IEventHandler {
|
|||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){}
|
@Override public void onEnd(ActiveEvent e){}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReverseGravityHandler implements IEventHandler {
|
class ReverseGravityHandler implements IEventHandler {
|
||||||
private final EventEngine plugin; private BukkitRunnable ticker;
|
private final EventEngine plugin; private BukkitRunnable ticker;
|
||||||
ReverseGravityHandler(EventEngine p){this.plugin=p;}
|
ReverseGravityHandler(EventEngine p){this.plugin=p;}
|
||||||
@@ -599,22 +487,15 @@ class ReverseGravityHandler implements IEventHandler {
|
|||||||
final Random rng=new Random();
|
final Random rng=new Random();
|
||||||
ticker=new BukkitRunnable(){@Override public void run(){
|
ticker=new BukkitRunnable(){@Override public void run(){
|
||||||
if(e.getState()==ActiveEvent.State.ENDED){cancel();return;}
|
if(e.getState()==ActiveEvent.State.ENDED){cancel();return;}
|
||||||
if (e.getParticipants().isEmpty()) {
|
Iterable<UUID> targets = e.getParticipants().isEmpty() ? uuidsOf(Bukkit.getOnlinePlayers()) : e.getParticipants();
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
for(UUID u:targets){Player p=Bukkit.getPlayer(u);if(p==null)continue;p.setVelocity(p.getVelocity().setY(0.5+rng.nextDouble()*0.5));}
|
||||||
p.setVelocity(p.getVelocity().setY(0.5 + rng.nextDouble() * 0.5));
|
}};
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(UUID u:e.getParticipants()){
|
|
||||||
Player p=Bukkit.getPlayer(u);
|
|
||||||
if(p==null)continue;
|
|
||||||
p.setVelocity(p.getVelocity().setY(0.5+rng.nextDouble()*0.5));
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
ticker.runTaskTimer(plugin,20L,15L);
|
ticker.runTaskTimer(plugin,20L,15L);
|
||||||
}
|
}
|
||||||
@Override public void onEnd(ActiveEvent e){ if(ticker!=null)ticker.cancel(); }
|
@Override public void onEnd(ActiveEvent e){ if(ticker!=null)ticker.cancel(); }
|
||||||
|
private List<UUID> uuidsOf(Collection<? extends Player> ps){List<UUID> r=new ArrayList<>();ps.forEach(p->r.add(p.getUniqueId()));return r;}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BouncyBlocksHandler implements IEventHandler, Listener {
|
class BouncyBlocksHandler implements IEventHandler, Listener {
|
||||||
private final EventEngine plugin; private ActiveEvent current;
|
private final EventEngine plugin; private ActiveEvent current;
|
||||||
BouncyBlocksHandler(EventEngine p){this.plugin=p;}
|
BouncyBlocksHandler(EventEngine p){this.plugin=p;}
|
||||||
|
|||||||
@@ -6,17 +6,53 @@ import dev.viper.eventengine.model.EventCategory;
|
|||||||
import dev.viper.eventengine.model.EventDefinition;
|
import dev.viper.eventengine.model.EventDefinition;
|
||||||
import dev.viper.eventengine.model.EventRegion;
|
import dev.viper.eventengine.model.EventRegion;
|
||||||
import dev.viper.eventengine.model.EventType;
|
import dev.viper.eventengine.model.EventType;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verarbeitet Ziel-Einläufe für Renn-Events.
|
||||||
|
*
|
||||||
|
* SPRINT-Modus (Standard):
|
||||||
|
* Wer als erstes die Zielregion betritt, gewinnt → endEventWithWinner().
|
||||||
|
*
|
||||||
|
* CIRCUIT-Modus (Rundkurs):
|
||||||
|
* Jedes Mal wenn ein Spieler die Zielregion passiert, zählt eine Runde.
|
||||||
|
* Nach def.getLaps() Runden → Spieler gewinnt.
|
||||||
|
* Zwischenzeiten werden per ActionBar gemeldet.
|
||||||
|
* Alle anderen können weiterlaufen — Platz 2/3 werden ebenfalls ausgewertet.
|
||||||
|
*/
|
||||||
public class RaceGoalListener implements Listener {
|
public class RaceGoalListener implements Listener {
|
||||||
|
|
||||||
private final EventEngine plugin;
|
private final EventEngine plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rundenstand pro Spieler im CIRCUIT-Modus.
|
||||||
|
* Key = UUID, Value = absolvierte Runden
|
||||||
|
*/
|
||||||
|
private final Map<UUID, Integer> lapCount = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verhindert Mehrfach-Trigger wenn der Spieler mehrere Ticks in der Zielregion bleibt.
|
||||||
|
* Key = UUID, Value = System.currentTimeMillis() des letzten Triggers.
|
||||||
|
*/
|
||||||
|
private final Map<UUID, Long> lastGoalTime = new HashMap<>();
|
||||||
|
|
||||||
|
/** Mindestabstand in ms zwischen zwei aufeinanderfolgenden Zieltriggern (3s) */
|
||||||
|
private static final long GOAL_COOLDOWN_MS = 3000;
|
||||||
|
|
||||||
|
/** Abschlusspositionen für das Leaderboard im CIRCUIT-Modus */
|
||||||
|
private int finishPosition = 0;
|
||||||
|
|
||||||
public RaceGoalListener(EventEngine plugin) {
|
public RaceGoalListener(EventEngine plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
@@ -38,18 +74,94 @@ public class RaceGoalListener implements Listener {
|
|||||||
Location to = e.getTo();
|
Location to = e.getTo();
|
||||||
if (to == null) return;
|
if (to == null) return;
|
||||||
|
|
||||||
|
// Nur bei echtem Block-Wechsel prüfen (Performance)
|
||||||
if (e.getFrom().getBlockX() == to.getBlockX()
|
if (e.getFrom().getBlockX() == to.getBlockX()
|
||||||
&& e.getFrom().getBlockY() == to.getBlockY()
|
&& e.getFrom().getBlockY() == to.getBlockY()
|
||||||
&& e.getFrom().getBlockZ() == to.getBlockZ()) return;
|
&& e.getFrom().getBlockZ() == to.getBlockZ()) return;
|
||||||
|
|
||||||
if (!goal.contains(to)) return;
|
if (!goal.contains(to)) return;
|
||||||
if (active.hasWinner()) return;
|
|
||||||
|
|
||||||
|
// Cooldown verhindern
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
Long last = lastGoalTime.get(player.getUniqueId());
|
||||||
|
if (last != null && now - last < GOAL_COOLDOWN_MS) return;
|
||||||
|
lastGoalTime.put(player.getUniqueId(), now);
|
||||||
|
|
||||||
|
if (def.isCircuit()) {
|
||||||
|
handleCircuitGoal(active, def, player);
|
||||||
|
} else {
|
||||||
|
handleSprintGoal(active, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Sprint: erster gewinnt sofort ────────────────────────────────────
|
||||||
|
|
||||||
|
private void handleSprintGoal(ActiveEvent active, Player player) {
|
||||||
|
if (active.hasWinner()) return; // bereits entschieden
|
||||||
plugin.getEventManager().endEventWithWinner(player, "Ziel erreicht");
|
plugin.getEventManager().endEventWithWinner(player, "Ziel erreicht");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Circuit: Runden zählen ───────────────────────────────────────────
|
||||||
|
|
||||||
|
private void handleCircuitGoal(ActiveEvent active, EventDefinition def, Player player) {
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
int done = lapCount.merge(uuid, 1, Integer::sum);
|
||||||
|
int total = def.getLaps();
|
||||||
|
long elapsed = active.getElapsedSeconds();
|
||||||
|
|
||||||
|
if (done < total) {
|
||||||
|
// Zwischenrunde
|
||||||
|
String msg = "§e🏁 Runde §f" + done + "§e/§f" + total
|
||||||
|
+ " §8(Zeit: §f" + formatTime((int) elapsed) + "§8)";
|
||||||
|
player.sendActionBar(msg);
|
||||||
|
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1.5f);
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§f" + player.getName()
|
||||||
|
+ " §7— Runde §e" + done + "§7/§e" + total
|
||||||
|
+ " §8(§f" + formatTime((int) elapsed) + "§8)");
|
||||||
|
} else {
|
||||||
|
// Ziel erreicht (alle Runden voll)
|
||||||
|
finishPosition++;
|
||||||
|
int pos = finishPosition;
|
||||||
|
active.addScore(uuid, Math.max(0, 100 - (pos - 1) * 20)); // Punkte: 1. = 100, 2. = 80, …
|
||||||
|
|
||||||
|
String posStr = switch (pos) {
|
||||||
|
case 1 -> "§6§l1. Platz 🥇";
|
||||||
|
case 2 -> "§7§l2. Platz 🥈";
|
||||||
|
case 3 -> "§c§l3. Platz 🥉";
|
||||||
|
default -> "§7" + pos + ". Platz";
|
||||||
|
};
|
||||||
|
|
||||||
|
player.sendTitle(posStr, "§fZeit: §e" + formatTime((int) elapsed), 0, 60, 20);
|
||||||
|
player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1f, pos == 1 ? 1.2f : 0.8f);
|
||||||
|
|
||||||
|
Bukkit.broadcastMessage(plugin.prefix() + "§6🏁 §f" + player.getName()
|
||||||
|
+ " §ehat das Rennen beendet! §8[" + posStr + "§8] §8(Zeit: §f"
|
||||||
|
+ formatTime((int) elapsed) + "§8)");
|
||||||
|
|
||||||
|
// Spieler aus aktivem Rennen entfernen (kann zuschauen)
|
||||||
|
active.removeParticipant(player);
|
||||||
|
|
||||||
|
// Wenn alle Spieler fertig (oder nur noch einer übrig) → Event beenden
|
||||||
|
int remaining = active.getParticipantCount();
|
||||||
|
if (pos == 1) {
|
||||||
|
// Gewinner setzen
|
||||||
|
active.setWinner(uuid);
|
||||||
|
plugin.getEventManager().distributeWinnerRewards(def, player);
|
||||||
|
}
|
||||||
|
if (remaining == 0 || (remaining == 1 && active.getParticipants().size() == 1)) {
|
||||||
|
plugin.getEventManager().endEvent("Rennen beendet — alle Spieler im Ziel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isRaceEvent(EventDefinition def) {
|
private boolean isRaceEvent(EventDefinition def) {
|
||||||
if (def.getCategory() == EventCategory.RACING) return true;
|
if (def.getCategory() == EventCategory.RACING) return true;
|
||||||
return def.getType() == EventType.TEAM_RELAY_RACE;
|
return def.getType() == EventType.TEAM_RELAY_RACE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private String formatTime(int seconds) {
|
||||||
|
int m = seconds / 60, s = seconds % 60;
|
||||||
|
if (m == 0) return s + "s";
|
||||||
|
return m + "m " + s + "s";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import dev.viper.eventengine.events.builtin.IEventHandler;
|
|||||||
import dev.viper.eventengine.model.ActiveEvent;
|
import dev.viper.eventengine.model.ActiveEvent;
|
||||||
import dev.viper.eventengine.model.EventDefinition;
|
import dev.viper.eventengine.model.EventDefinition;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Steuert den Lebenszyklus von Events:
|
* Steuert den Lebenszyklus von Events:
|
||||||
* start → announce → run → end → reward
|
* start → announce → countdown → run → end → reward
|
||||||
*/
|
*/
|
||||||
public class EventManager {
|
public class EventManager {
|
||||||
|
|
||||||
@@ -39,9 +40,7 @@ public class EventManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentEvent = new ActiveEvent(def);
|
// Ankündigung
|
||||||
currentEvent.setState(ActiveEvent.State.RUNNING);
|
|
||||||
|
|
||||||
broadcast(def.getAnnouncement());
|
broadcast(def.getAnnouncement());
|
||||||
if (def.getDurationSeconds() > 0)
|
if (def.getDurationSeconds() > 0)
|
||||||
broadcast(plugin.prefix() + "§7Dauer: §e" + formatTime(def.getDurationSeconds()));
|
broadcast(plugin.prefix() + "§7Dauer: §e" + formatTime(def.getDurationSeconds()));
|
||||||
@@ -51,12 +50,65 @@ public class EventManager {
|
|||||||
log.info("Event gestartet von " + by + ": " + def.getDisplayName());
|
log.info("Event gestartet von " + by + ": " + def.getDisplayName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3..2..1..Go Countdown, danach eigentlicher Start
|
||||||
|
int countdown = plugin.getConfigManager().getCountdownSeconds();
|
||||||
|
if (countdown > 0) {
|
||||||
|
currentEvent = new ActiveEvent(def);
|
||||||
|
currentEvent.setState(ActiveEvent.State.WAITING);
|
||||||
|
runCountdown(def, initiator, countdown);
|
||||||
|
} else {
|
||||||
|
launchEvent(def, initiator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Countdown-Loop: 3..2..1..Go */
|
||||||
|
private void runCountdown(EventDefinition def, Player initiator, int seconds) {
|
||||||
|
final ActiveEvent snap = currentEvent;
|
||||||
|
new BukkitRunnable() {
|
||||||
|
int remaining = seconds;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (snap != currentEvent) { cancel(); return; } // abgebrochen
|
||||||
|
|
||||||
|
if (remaining > 0) {
|
||||||
|
// Titel + Sound für alle Online-Spieler
|
||||||
|
String color = remaining <= 3 ? "§c" : "§e";
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||||
|
p.sendTitle(color + remaining, "§7" + def.getDisplayName() + " §7startet gleich!", 0, 25, 5);
|
||||||
|
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_HAT, 1f, 1f);
|
||||||
|
}
|
||||||
|
broadcast(plugin.prefix() + "§e⏳ " + def.getDisplayName() + " §7startet in §c" + remaining + " §7Sekunde" + (remaining == 1 ? "" : "n") + "...");
|
||||||
|
remaining--;
|
||||||
|
} else {
|
||||||
|
cancel();
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||||
|
p.sendTitle("§a§lGO!", "§7" + def.getDisplayName(), 0, 30, 10);
|
||||||
|
p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_LARGE_BLAST, 1f, 1.2f);
|
||||||
|
}
|
||||||
|
broadcast(plugin.prefix() + "§a§l🚀 GO! §r§e" + def.getDisplayName() + " §7hat begonnen!");
|
||||||
|
launchEvent(def, initiator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.runTaskTimer(plugin, 0L, 20L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Eigentlicher Event-Start nach dem Countdown */
|
||||||
|
private void launchEvent(EventDefinition def, Player initiator) {
|
||||||
|
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) {
|
||||||
|
currentEvent = new ActiveEvent(def);
|
||||||
|
}
|
||||||
|
currentEvent.setState(ActiveEvent.State.RUNNING);
|
||||||
|
|
||||||
runCommands(def.getStartCommands(), null);
|
runCommands(def.getStartCommands(), null);
|
||||||
handlerRegistry.get(def.getType()).ifPresent(h -> h.onStart(currentEvent));
|
handlerRegistry.get(def.getType()).ifPresent(h -> h.onStart(currentEvent));
|
||||||
plugin.getScoreboardManager().start(currentEvent);
|
plugin.getScoreboardManager().start(currentEvent);
|
||||||
|
|
||||||
if (def.getDurationSeconds() > 0) {
|
if (def.getDurationSeconds() > 0) {
|
||||||
final ActiveEvent snap = currentEvent;
|
final ActiveEvent snap = currentEvent;
|
||||||
|
|
||||||
if (def.getDurationSeconds() > 70)
|
if (def.getDurationSeconds() > 70)
|
||||||
new BukkitRunnable() { @Override public void run() {
|
new BukkitRunnable() { @Override public void run() {
|
||||||
if (currentEvent == snap && currentEvent.getState() == ActiveEvent.State.RUNNING)
|
if (currentEvent == snap && currentEvent.getState() == ActiveEvent.State.RUNNING)
|
||||||
@@ -75,7 +127,6 @@ public class EventManager {
|
|||||||
}}.runTaskLater(plugin, def.getDurationSeconds() * 20L).getTaskId();
|
}}.runTaskLater(plugin, def.getDurationSeconds() * 20L).getTaskId();
|
||||||
currentEvent.setTaskId(taskId);
|
currentEvent.setTaskId(taskId);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean endEvent(String reason) {
|
public boolean endEvent(String reason) {
|
||||||
@@ -112,7 +163,24 @@ public class EventManager {
|
|||||||
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) return false;
|
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) return false;
|
||||||
if (winner != null) {
|
if (winner != null) {
|
||||||
currentEvent.setWinner(winner.getUniqueId());
|
currentEvent.setWinner(winner.getUniqueId());
|
||||||
broadcast(plugin.prefix() + "§6🏁 " + winner.getName() + " §ehat das Ziel erreicht und gewinnt!");
|
|
||||||
|
// Ziel-Nachricht mit Zeit
|
||||||
|
long elapsed = currentEvent.getElapsedSeconds();
|
||||||
|
broadcast(plugin.prefix() + "§6🏁 §f" + winner.getName()
|
||||||
|
+ " §ehat das Ziel erreicht und gewinnt! §8(Zeit: §f" + formatTime((int) elapsed) + "§8)");
|
||||||
|
|
||||||
|
// Title für Gewinner
|
||||||
|
winner.sendTitle("§6§l🏁 ZIEL!", "§e" + currentEvent.getDefinition().getDisplayName(), 0, 60, 20);
|
||||||
|
winner.playSound(winner.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1f, 1f);
|
||||||
|
|
||||||
|
// Title für alle anderen
|
||||||
|
for (UUID uuid : currentEvent.getParticipants()) {
|
||||||
|
Player p = Bukkit.getPlayer(uuid);
|
||||||
|
if (p != null && !p.equals(winner)) {
|
||||||
|
p.sendTitle("§c§lZU SPÄT!", "§7" + winner.getName() + " §7war schneller.", 0, 40, 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
distributeWinnerRewards(currentEvent.getDefinition(), winner);
|
distributeWinnerRewards(currentEvent.getDefinition(), winner);
|
||||||
}
|
}
|
||||||
return endEvent(reason);
|
return endEvent(reason);
|
||||||
@@ -175,7 +243,7 @@ public class EventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void distributeWinnerRewards(EventDefinition def, Player winner) {
|
public void distributeWinnerRewards(EventDefinition def, Player winner) {
|
||||||
if (def.getWinnerRewards().isEmpty() || winner == null) return;
|
if (def.getWinnerRewards().isEmpty() || winner == null) return;
|
||||||
runCommands(def.getWinnerRewards(), winner);
|
runCommands(def.getWinnerRewards(), winner);
|
||||||
}
|
}
|
||||||
@@ -204,4 +272,4 @@ public class EventManager {
|
|||||||
public ActiveEvent getCurrentEvent() { return currentEvent; }
|
public ActiveEvent getCurrentEvent() { return currentEvent; }
|
||||||
public boolean isRunning() { return currentEvent != null && currentEvent.getState() == ActiveEvent.State.RUNNING; }
|
public boolean isRunning() { return currentEvent != null && currentEvent.getState() == ActiveEvent.State.RUNNING; }
|
||||||
public EventHandlerRegistry getHandlerRegistry() { return handlerRegistry; }
|
public EventHandlerRegistry getHandlerRegistry() { return handlerRegistry; }
|
||||||
}
|
}
|
||||||
@@ -1,52 +1,47 @@
|
|||||||
package dev.viper.eventengine.model;
|
package dev.viper.eventengine.model;
|
||||||
|
|
||||||
import dev.viper.eventengine.util.ColorUtil;
|
import dev.viper.eventengine.util.ColorUtil;
|
||||||
import dev.viper.eventengine.model.EventRegion;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repräsentiert ein einzelnes Event — sowohl eingebaute als auch Custom-Events.
|
* Repräsentiert ein einzelnes Event — sowohl eingebaute als auch Custom-Events.
|
||||||
* Custom-Events werden in custom_events.yml gespeichert.
|
|
||||||
*/
|
*/
|
||||||
public class EventDefinition {
|
public class EventDefinition {
|
||||||
|
|
||||||
|
/** Sprint = einmaliger Punkt-zu-Punkt Lauf; CIRCUIT = Rundkurs (laps Runden) */
|
||||||
|
public enum RaceMode { SPRINT, CIRCUIT }
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private String description;
|
private String description;
|
||||||
private EventType type;
|
private EventType type;
|
||||||
private EventCategory category;
|
private EventCategory category;
|
||||||
|
|
||||||
// Zeitlimit in Sekunden (0 = unbegrenzt)
|
|
||||||
private int durationSeconds;
|
private int durationSeconds;
|
||||||
// Mindest-/Höchst-Spielerzahl
|
|
||||||
private int minPlayers;
|
private int minPlayers;
|
||||||
private int maxPlayers;
|
private int maxPlayers;
|
||||||
// Befehle die beim Start/Ende ausgeführt werden
|
|
||||||
private List<String> startCommands;
|
private List<String> startCommands;
|
||||||
private List<String> endCommands;
|
private List<String> endCommands;
|
||||||
// Belohnungen
|
|
||||||
private List<String> rewards;
|
private List<String> rewards;
|
||||||
// Ankündigungs-Text
|
|
||||||
private String announcement;
|
private String announcement;
|
||||||
// Ob das Event in der Rotation ist
|
|
||||||
private boolean inRotation;
|
private boolean inRotation;
|
||||||
// Gewichtung in der Rotation
|
|
||||||
private int weight;
|
private int weight;
|
||||||
// Optionaler Start-/Zielbereich (Rennen)
|
|
||||||
private EventRegion startRegion;
|
private EventRegion startRegion;
|
||||||
private EventRegion goalRegion;
|
private EventRegion goalRegion;
|
||||||
// Custom-Einstellungen (Key-Value)
|
|
||||||
private Map<String, Object> customSettings;
|
private Map<String, Object> customSettings;
|
||||||
// Ist es ein benutzerdefiniertes Event?
|
|
||||||
private boolean isCustom;
|
private boolean isCustom;
|
||||||
// Optionale Event-Region (null = gesamte Welt)
|
|
||||||
private EventRegion region;
|
private EventRegion region;
|
||||||
// Winner-Belohnungen (nur Sieger)
|
|
||||||
private List<String> winnerRewards;
|
private List<String> winnerRewards;
|
||||||
|
|
||||||
// ─── Konstruktor für builtin Events ────────────────────────────────────
|
// ── Renn-Einstellungen ────────────────────────────────────────────────
|
||||||
|
/** Sprint (A→B) oder Circuit (Rundkurs) */
|
||||||
|
private RaceMode raceMode = RaceMode.SPRINT;
|
||||||
|
/** Anzahl der Runden bei CIRCUIT-Modus */
|
||||||
|
private int laps = 1;
|
||||||
|
|
||||||
|
// ─── Konstruktor für builtin Events ───────────────────────────────────
|
||||||
public EventDefinition(EventType type) {
|
public EventDefinition(EventType type) {
|
||||||
this.id = type.name().toLowerCase();
|
this.id = type.name().toLowerCase();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -62,14 +57,12 @@ public class EventDefinition {
|
|||||||
this.announcement = ColorUtil.color("&6✦ &e" + displayName + " &6startet jetzt!");
|
this.announcement = ColorUtil.color("&6✦ &e" + displayName + " &6startet jetzt!");
|
||||||
this.inRotation = true;
|
this.inRotation = true;
|
||||||
this.weight = 1;
|
this.weight = 1;
|
||||||
this.startRegion = null;
|
|
||||||
this.goalRegion = null;
|
|
||||||
this.customSettings = new HashMap<>();
|
this.customSettings = new HashMap<>();
|
||||||
this.isCustom = false;
|
this.isCustom = false;
|
||||||
this.winnerRewards = new ArrayList<>();
|
this.winnerRewards = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Konstruktor für Custom Events ─────────────────────────────────────
|
// ─── Konstruktor für Custom Events ────────────────────────────────────
|
||||||
public EventDefinition(String id) {
|
public EventDefinition(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.type = EventType.CUSTOM;
|
this.type = EventType.CUSTOM;
|
||||||
@@ -85,14 +78,12 @@ public class EventDefinition {
|
|||||||
this.announcement = ColorUtil.color("&6✦ &e" + id + " &6startet jetzt!");
|
this.announcement = ColorUtil.color("&6✦ &e" + id + " &6startet jetzt!");
|
||||||
this.inRotation = true;
|
this.inRotation = true;
|
||||||
this.weight = 1;
|
this.weight = 1;
|
||||||
this.startRegion = null;
|
|
||||||
this.goalRegion = null;
|
|
||||||
this.customSettings = new HashMap<>();
|
this.customSettings = new HashMap<>();
|
||||||
this.isCustom = true;
|
this.isCustom = true;
|
||||||
this.winnerRewards = new ArrayList<>();
|
this.winnerRewards = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Laden aus ConfigurationSection ────────────────────────────────────
|
// ─── Laden aus ConfigurationSection ───────────────────────────────────
|
||||||
public static EventDefinition fromConfig(String id, ConfigurationSection sec) {
|
public static EventDefinition fromConfig(String id, ConfigurationSection sec) {
|
||||||
EventDefinition def = new EventDefinition(id);
|
EventDefinition def = new EventDefinition(id);
|
||||||
def.displayName = sec.getString("display-name", id);
|
def.displayName = sec.getString("display-name", id);
|
||||||
@@ -108,6 +99,13 @@ public class EventDefinition {
|
|||||||
def.inRotation = sec.getBoolean("in-rotation", true);
|
def.inRotation = sec.getBoolean("in-rotation", true);
|
||||||
def.weight = sec.getInt("weight", 1);
|
def.weight = sec.getInt("weight", 1);
|
||||||
def.winnerRewards = sec.getStringList("winner-rewards");
|
def.winnerRewards = sec.getStringList("winner-rewards");
|
||||||
|
|
||||||
|
// Renn-Einstellungen
|
||||||
|
String raceModeStr = sec.getString("race-mode", "SPRINT").toUpperCase();
|
||||||
|
try { def.raceMode = RaceMode.valueOf(raceModeStr); }
|
||||||
|
catch (Exception e) { def.raceMode = RaceMode.SPRINT; }
|
||||||
|
def.laps = Math.max(1, sec.getInt("laps", 1));
|
||||||
|
|
||||||
String catStr = sec.getString("category", "CUSTOM");
|
String catStr = sec.getString("category", "CUSTOM");
|
||||||
try { def.category = EventCategory.valueOf(catStr); }
|
try { def.category = EventCategory.valueOf(catStr); }
|
||||||
catch (Exception e) { def.category = EventCategory.CUSTOM; }
|
catch (Exception e) { def.category = EventCategory.CUSTOM; }
|
||||||
@@ -119,49 +117,37 @@ public class EventDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Region laden
|
// Region
|
||||||
if (sec.contains("region.world")) {
|
if (sec.contains("region.world")) {
|
||||||
try {
|
try {
|
||||||
String w = sec.getString("region.world");
|
def.region = new EventRegion(
|
||||||
int minX = sec.getInt("region.min-x");
|
sec.getString("region.world"),
|
||||||
int minY = sec.getInt("region.min-y");
|
sec.getInt("region.min-x"), sec.getInt("region.min-y"), sec.getInt("region.min-z"),
|
||||||
int minZ = sec.getInt("region.min-z");
|
sec.getInt("region.max-x"), sec.getInt("region.max-y"), sec.getInt("region.max-z"));
|
||||||
int maxX = sec.getInt("region.max-x");
|
|
||||||
int maxY = sec.getInt("region.max-y");
|
|
||||||
int maxZ = sec.getInt("region.max-z");
|
|
||||||
def.region = new EventRegion(w, minX, minY, minZ, maxX, maxY, maxZ);
|
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
// Start-Region
|
||||||
// Start-/Zielregion laden
|
|
||||||
if (sec.contains("start-region.world")) {
|
if (sec.contains("start-region.world")) {
|
||||||
try {
|
try {
|
||||||
String w = sec.getString("start-region.world");
|
def.startRegion = new EventRegion(
|
||||||
int minX = sec.getInt("start-region.min-x");
|
sec.getString("start-region.world"),
|
||||||
int minY = sec.getInt("start-region.min-y");
|
sec.getInt("start-region.min-x"), sec.getInt("start-region.min-y"), sec.getInt("start-region.min-z"),
|
||||||
int minZ = sec.getInt("start-region.min-z");
|
sec.getInt("start-region.max-x"), sec.getInt("start-region.max-y"), sec.getInt("start-region.max-z"));
|
||||||
int maxX = sec.getInt("start-region.max-x");
|
|
||||||
int maxY = sec.getInt("start-region.max-y");
|
|
||||||
int maxZ = sec.getInt("start-region.max-z");
|
|
||||||
def.startRegion = new EventRegion(w, minX, minY, minZ, maxX, maxY, maxZ);
|
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
// Ziel-Region
|
||||||
if (sec.contains("goal-region.world")) {
|
if (sec.contains("goal-region.world")) {
|
||||||
try {
|
try {
|
||||||
String w = sec.getString("goal-region.world");
|
def.goalRegion = new EventRegion(
|
||||||
int minX = sec.getInt("goal-region.min-x");
|
sec.getString("goal-region.world"),
|
||||||
int minY = sec.getInt("goal-region.min-y");
|
sec.getInt("goal-region.min-x"), sec.getInt("goal-region.min-y"), sec.getInt("goal-region.min-z"),
|
||||||
int minZ = sec.getInt("goal-region.min-z");
|
sec.getInt("goal-region.max-x"), sec.getInt("goal-region.max-y"), sec.getInt("goal-region.max-z"));
|
||||||
int maxX = sec.getInt("goal-region.max-x");
|
|
||||||
int maxY = sec.getInt("goal-region.max-y");
|
|
||||||
int maxZ = sec.getInt("goal-region.max-z");
|
|
||||||
def.goalRegion = new EventRegion(w, minX, minY, minZ, maxX, maxY, maxZ);
|
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Speichern in ConfigurationSection ─────────────────────────────────
|
// ─── Speichern in ConfigurationSection ────────────────────────────────
|
||||||
public void saveToConfig(ConfigurationSection sec) {
|
public void saveToConfig(ConfigurationSection sec) {
|
||||||
sec.set("display-name", displayName);
|
sec.set("display-name", displayName);
|
||||||
sec.set("description", description);
|
sec.set("description", description);
|
||||||
@@ -176,32 +162,23 @@ public class EventDefinition {
|
|||||||
sec.set("weight", weight);
|
sec.set("weight", weight);
|
||||||
sec.set("winner-rewards", winnerRewards);
|
sec.set("winner-rewards", winnerRewards);
|
||||||
sec.set("category", category.name());
|
sec.set("category", category.name());
|
||||||
|
sec.set("race-mode", raceMode.name());
|
||||||
|
sec.set("laps", laps);
|
||||||
|
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
sec.set("region.world", region.getWorldName());
|
sec.set("region.world", region.getWorldName());
|
||||||
sec.set("region.min-x", region.getMinX());
|
sec.set("region.min-x", region.getMinX()); sec.set("region.min-y", region.getMinY()); sec.set("region.min-z", region.getMinZ());
|
||||||
sec.set("region.min-y", region.getMinY());
|
sec.set("region.max-x", region.getMaxX()); sec.set("region.max-y", region.getMaxY()); sec.set("region.max-z", region.getMaxZ());
|
||||||
sec.set("region.min-z", region.getMinZ());
|
|
||||||
sec.set("region.max-x", region.getMaxX());
|
|
||||||
sec.set("region.max-y", region.getMaxY());
|
|
||||||
sec.set("region.max-z", region.getMaxZ());
|
|
||||||
}
|
}
|
||||||
if (startRegion != null) {
|
if (startRegion != null) {
|
||||||
sec.set("start-region.world", startRegion.getWorldName());
|
sec.set("start-region.world", startRegion.getWorldName());
|
||||||
sec.set("start-region.min-x", startRegion.getMinX());
|
sec.set("start-region.min-x", startRegion.getMinX()); sec.set("start-region.min-y", startRegion.getMinY()); sec.set("start-region.min-z", startRegion.getMinZ());
|
||||||
sec.set("start-region.min-y", startRegion.getMinY());
|
sec.set("start-region.max-x", startRegion.getMaxX()); sec.set("start-region.max-y", startRegion.getMaxY()); sec.set("start-region.max-z", startRegion.getMaxZ());
|
||||||
sec.set("start-region.min-z", startRegion.getMinZ());
|
|
||||||
sec.set("start-region.max-x", startRegion.getMaxX());
|
|
||||||
sec.set("start-region.max-y", startRegion.getMaxY());
|
|
||||||
sec.set("start-region.max-z", startRegion.getMaxZ());
|
|
||||||
}
|
}
|
||||||
if (goalRegion != null) {
|
if (goalRegion != null) {
|
||||||
sec.set("goal-region.world", goalRegion.getWorldName());
|
sec.set("goal-region.world", goalRegion.getWorldName());
|
||||||
sec.set("goal-region.min-x", goalRegion.getMinX());
|
sec.set("goal-region.min-x", goalRegion.getMinX()); sec.set("goal-region.min-y", goalRegion.getMinY()); sec.set("goal-region.min-z", goalRegion.getMinZ());
|
||||||
sec.set("goal-region.min-y", goalRegion.getMinY());
|
sec.set("goal-region.max-x", goalRegion.getMaxX()); sec.set("goal-region.max-y", goalRegion.getMaxY()); sec.set("goal-region.max-z", goalRegion.getMaxZ());
|
||||||
sec.set("goal-region.min-z", goalRegion.getMinZ());
|
|
||||||
sec.set("goal-region.max-x", goalRegion.getMaxX());
|
|
||||||
sec.set("goal-region.max-y", goalRegion.getMaxY());
|
|
||||||
sec.set("goal-region.max-z", goalRegion.getMaxZ());
|
|
||||||
}
|
}
|
||||||
if (!customSettings.isEmpty()) {
|
if (!customSettings.isEmpty()) {
|
||||||
for (Map.Entry<String, Object> entry : customSettings.entrySet()) {
|
for (Map.Entry<String, Object> entry : customSettings.entrySet()) {
|
||||||
@@ -210,7 +187,7 @@ public class EventDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Getter/Setter ──────────────────────────────────────────────────────
|
// ─── Getter/Setter ─────────────────────────────────────────────────────
|
||||||
public String getId() { return id; }
|
public String getId() { return id; }
|
||||||
public String getDisplayName() { return displayName; }
|
public String getDisplayName() { return displayName; }
|
||||||
public void setDisplayName(String n) { this.displayName = n; }
|
public void setDisplayName(String n) { this.displayName = n; }
|
||||||
@@ -252,5 +229,11 @@ public class EventDefinition {
|
|||||||
public boolean hasGoalRegion() { return goalRegion != null; }
|
public boolean hasGoalRegion() { return goalRegion != null; }
|
||||||
public Object getSetting(String key) { return customSettings.get(key); }
|
public Object getSetting(String key) { return customSettings.get(key); }
|
||||||
public void setSetting(String key, Object val) { customSettings.put(key, val); }
|
public void setSetting(String key, Object val) { customSettings.put(key, val); }
|
||||||
}
|
|
||||||
// Wird unten in der Klasse ergänzt — separate Patch-Datei
|
// Renn-Getter/Setter
|
||||||
|
public RaceMode getRaceMode() { return raceMode; }
|
||||||
|
public void setRaceMode(RaceMode m) { this.raceMode = m; }
|
||||||
|
public int getLaps() { return laps; }
|
||||||
|
public void setLaps(int l) { this.laps = Math.max(1, l); }
|
||||||
|
public boolean isCircuit() { return raceMode == RaceMode.CIRCUIT; }
|
||||||
|
}
|
||||||
@@ -14,8 +14,10 @@ settings:
|
|||||||
# Sekunden VOR dem Event-Start, wann die Ankündigung erfolgt
|
# Sekunden VOR dem Event-Start, wann die Ankündigung erfolgt
|
||||||
announce-before-seconds: 30
|
announce-before-seconds: 30
|
||||||
|
|
||||||
|
# 3..2..1..Go Countdown vor jedem Event-Start (Sekunden; 0 = deaktiviert)
|
||||||
|
countdown-seconds: 3
|
||||||
|
|
||||||
# Intervall-Modus: Startet automatisch alle X Minuten ein Event
|
# Intervall-Modus: Startet automatisch alle X Minuten ein Event
|
||||||
# Nützlich wenn kein fester Zeitplan gewünscht ist
|
|
||||||
use-interval: false
|
use-interval: false
|
||||||
interval-minutes: 60
|
interval-minutes: 60
|
||||||
|
|
||||||
@@ -31,98 +33,66 @@ settings:
|
|||||||
# Leer lassen oder "DAILY" für jeden Tag
|
# Leer lassen oder "DAILY" für jeden Tag
|
||||||
# time: Uhrzeit im Format HH:MM (24h)
|
# time: Uhrzeit im Format HH:MM (24h)
|
||||||
# event: Event-ID (aus /event list) oder "RANDOM"
|
# event: Event-ID (aus /event list) oder "RANDOM"
|
||||||
#
|
|
||||||
# ─── Beispiel-Zeitplan ───────────────────────────────────────────
|
|
||||||
schedule:
|
schedule:
|
||||||
# Täglich 12 Uhr: Zufälliges Event
|
|
||||||
- days: []
|
- days: []
|
||||||
time: "12:00"
|
time: "12:00"
|
||||||
event: "RANDOM"
|
event: "RANDOM"
|
||||||
|
|
||||||
# Täglich 18 Uhr: PvP Deathmatch
|
|
||||||
- days: []
|
- days: []
|
||||||
time: "18:00"
|
time: "18:00"
|
||||||
event: "pvp_deathmatch"
|
event: "pvp_deathmatch"
|
||||||
|
|
||||||
# Freitag & Samstag Abend: Hunger Games
|
|
||||||
- days: [FRIDAY, SATURDAY]
|
- days: [FRIDAY, SATURDAY]
|
||||||
time: "20:00"
|
time: "20:00"
|
||||||
event: "pvp_hunger_games"
|
event: "pvp_hunger_games"
|
||||||
|
|
||||||
# Samstag Nachmittag: Build Battle
|
|
||||||
- days: [SATURDAY]
|
- days: [SATURDAY]
|
||||||
time: "15:00"
|
time: "15:00"
|
||||||
event: "build_battle"
|
event: "build_battle"
|
||||||
|
|
||||||
# Sonntag Mittag: Drop Party
|
|
||||||
- days: [SUNDAY]
|
- days: [SUNDAY]
|
||||||
time: "14:00"
|
time: "14:00"
|
||||||
event: "fun_drop_party"
|
event: "fun_drop_party"
|
||||||
|
|
||||||
# Montag: Lotterie
|
|
||||||
- days: [MONDAY]
|
- days: [MONDAY]
|
||||||
time: "19:00"
|
time: "19:00"
|
||||||
event: "economy_lottery"
|
event: "economy_lottery"
|
||||||
|
|
||||||
# Mittwoch: Team Survival
|
|
||||||
- days: [WEDNESDAY]
|
- days: [WEDNESDAY]
|
||||||
time: "18:00"
|
time: "18:00"
|
||||||
event: "team_survival"
|
event: "team_survival"
|
||||||
|
|
||||||
# ── Event-Overrides ───────────────────────────────────────────────
|
# ── Event-Overrides ───────────────────────────────────────────────
|
||||||
# Hier können einzelne eingebaute Events angepasst werden.
|
# Einzelne eingebaute Events anpassen.
|
||||||
# OHNE diese Sektion gelten die Plugin-Defaults.
|
# Renn-Modus Beispiel:
|
||||||
# Custom Events werden in custom_events.yml gespeichert.
|
|
||||||
#
|
#
|
||||||
# Beispiel:
|
|
||||||
# event-overrides:
|
# event-overrides:
|
||||||
# pvp_deathmatch:
|
# race_elytra:
|
||||||
|
# race-mode: CIRCUIT # SPRINT (A→B) oder CIRCUIT (Rundkurs)
|
||||||
|
# laps: 3 # Runden im Circuit-Modus
|
||||||
# duration-seconds: 600
|
# duration-seconds: 600
|
||||||
# min-players: 4
|
|
||||||
# rewards:
|
# rewards:
|
||||||
# - "eco give %player% 500"
|
# - "eco give %player% 1000"
|
||||||
# - "give %player% diamond 3"
|
#
|
||||||
# fun_drop_party:
|
# race_parkour:
|
||||||
# duration-seconds: 120
|
# race-mode: SPRINT
|
||||||
# announcement: "&6✦ &eDROP PARTY &7startet! Kommt alle auf den Spawn!"
|
#
|
||||||
|
# Elytra Checkpoint-Setup (in-game einfacher per Command):
|
||||||
|
# /event elytra checkpoint add <id> → Pos1
|
||||||
|
# /event elytra checkpoint confirm <id> → Pos2 → Checkpoint wird gespeichert
|
||||||
|
# /event elytra checkpoint list <id> → Übersicht
|
||||||
|
# /event elytra checkpoint clear <id> → Alle löschen
|
||||||
|
# /event racemode <id> <sprint|circuit> [laps]
|
||||||
event-overrides: {}
|
event-overrides: {}
|
||||||
|
|
||||||
# ── Event-Regionen ────────────────────────────────────────────────
|
|
||||||
# Regionen können direkt hier oder ingame per Command gesetzt werden:
|
|
||||||
# /event region pos1 <event-id> → Erste Ecke (stehe an der Position)
|
|
||||||
# /event region pos2 <event-id> → Zweite Ecke → Region wird gespeichert
|
|
||||||
# /event region clear <event-id> → Region entfernen (gesamte Welt)
|
|
||||||
# /event region info <event-id> → Region anzeigen
|
|
||||||
#
|
|
||||||
# Für Custom Events wird die Region in custom_events.yml gespeichert.
|
|
||||||
# Für builtin Events hier in event-overrides eintragen:
|
|
||||||
#
|
|
||||||
# event-overrides:
|
|
||||||
# pvp_deathmatch:
|
|
||||||
# region:
|
|
||||||
# world: world
|
|
||||||
# min-x: -50
|
|
||||||
# min-y: 60
|
|
||||||
# min-z: -50
|
|
||||||
# max-x: 50
|
|
||||||
# max-y: 120
|
|
||||||
# max-z: 50
|
|
||||||
#
|
|
||||||
# ── Block-Schutz während Events ──────────────────────────────────
|
# ── Block-Schutz während Events ──────────────────────────────────
|
||||||
# TNT und Explosionen zerstören KEINE Blöcke solange ein Event läuft.
|
|
||||||
# Das gilt immer — unabhängig ob eine Region definiert ist oder nicht.
|
|
||||||
# Spieler (PvP-Schaden durch Explosionen) bleibt aktiv.
|
|
||||||
protection:
|
protection:
|
||||||
# Spieler können die Region während eines Events nicht verlassen
|
|
||||||
enforce-region-boundary: true
|
enforce-region-boundary: true
|
||||||
# TNT/Explosionen zerstören keine Blöcke während Events
|
|
||||||
no-explosion-block-damage: true
|
no-explosion-block-damage: true
|
||||||
# Teilnehmer können nur innerhalb der Region Blöcke abbauen/setzen
|
|
||||||
restrict-block-interaction: true
|
restrict-block-interaction: true
|
||||||
|
|
||||||
# ── Item-Regen ──────────────────────────────────────────────────
|
# ── Item-Regen ──────────────────────────────────────────────────
|
||||||
item-rain:
|
item-rain:
|
||||||
# Items, die vom Himmel fallen (Material-Namen)
|
|
||||||
items:
|
items:
|
||||||
- DIAMOND
|
- DIAMOND
|
||||||
- GOLD_INGOT
|
- GOLD_INGOT
|
||||||
@@ -132,4 +102,4 @@ item-rain:
|
|||||||
- BREAD
|
- BREAD
|
||||||
- ARROW
|
- ARROW
|
||||||
- GOLDEN_APPLE
|
- GOLDEN_APPLE
|
||||||
- EXPERIENCE_BOTTLE
|
- EXPERIENCE_BOTTLE
|
||||||
Reference in New Issue
Block a user