fix: resolve 266/375 checkstyle violations, add lolib jar

This commit is contained in:
loki5512344 2026-07-12 11:52:54 +02:00
parent 7df0c13ac4
commit bfeecb0866
Signed by: boba
GPG key ID: 253067914055423B
79 changed files with 773 additions and 292 deletions

View file

@ -174,7 +174,7 @@ checkstyle {
configFile = file("config/checkstyle/checkstyle.xml") configFile = file("config/checkstyle/checkstyle.xml")
isIgnoreFailures = true isIgnoreFailures = true
maxErrors = 0 maxErrors = 0
maxWarnings = 400 maxWarnings = 200
} }
tasks.withType<Checkstyle>().configureEach { tasks.withType<Checkstyle>().configureEach {

View file

@ -29,7 +29,7 @@ public final class LoParkour extends LoPlugin {
public static final String NAME = "&#FF6464&lLoParkour&r"; public static final String NAME = "&#FF6464&lLoParkour&r";
public static final String PREFIX = NAME + " &#404040» &#A0A0A0"; public static final String PREFIX = NAME + " &#404040» &#A0A0A0";
private static final Gson gson = new GsonBuilder() private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting() .setPrettyPrinting()
.excludeFieldsWithoutExposeAnnotation() .excludeFieldsWithoutExposeAnnotation()
.create(); .create();
@ -41,7 +41,7 @@ public final class LoParkour extends LoPlugin {
private static PAPIHook placeholderHook; private static PAPIHook placeholderHook;
public static Gson getGson() { public static Gson getGson() {
return gson; return GSON;
} }
public static void log(String message) { public static void log(String message) {

View file

@ -11,7 +11,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/ */
public class AdaptiveConfig { public class AdaptiveConfig {
private static final ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String, Object> CACHE = new ConcurrentHashMap<>();
private static volatile boolean initialized = false; private static volatile boolean initialized = false;
// Configuration keys // Configuration keys
@ -39,12 +39,12 @@ public class AdaptiveConfig {
return; return;
} }
cache.put(KEY_ENABLED, Config.CONFIG.getBoolean(KEY_ENABLED, DEFAULT_ENABLED)); CACHE.put(KEY_ENABLED, Config.CONFIG.getBoolean(KEY_ENABLED, DEFAULT_ENABLED));
cache.put(KEY_MIN_SESSIONS, Config.CONFIG.getInt(KEY_MIN_SESSIONS, DEFAULT_MIN_SESSIONS)); CACHE.put(KEY_MIN_SESSIONS, Config.CONFIG.getInt(KEY_MIN_SESSIONS, DEFAULT_MIN_SESSIONS));
cache.put(KEY_UPDATE_INTERVAL, Config.CONFIG.getInt(KEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL)); CACHE.put(KEY_UPDATE_INTERVAL, Config.CONFIG.getInt(KEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL));
cache.put(KEY_RATING_WEIGHT, configDouble(KEY_RATING_WEIGHT, DEFAULT_RATING_WEIGHT)); CACHE.put(KEY_RATING_WEIGHT, configDouble(KEY_RATING_WEIGHT, DEFAULT_RATING_WEIGHT));
cache.put(KEY_CONFIDENCE_THRESHOLD, configDouble(KEY_CONFIDENCE_THRESHOLD, DEFAULT_CONFIDENCE_THRESHOLD)); CACHE.put(KEY_CONFIDENCE_THRESHOLD, configDouble(KEY_CONFIDENCE_THRESHOLD, DEFAULT_CONFIDENCE_THRESHOLD));
cache.put(KEY_NEAR_MISS_DISTANCE, configDouble(KEY_NEAR_MISS_DISTANCE, DEFAULT_NEAR_MISS_DISTANCE)); CACHE.put(KEY_NEAR_MISS_DISTANCE, configDouble(KEY_NEAR_MISS_DISTANCE, DEFAULT_NEAR_MISS_DISTANCE));
initialized = true; initialized = true;
} }
@ -55,7 +55,7 @@ public class AdaptiveConfig {
*/ */
public static void reload() { public static void reload() {
initialized = false; initialized = false;
cache.clear(); CACHE.clear();
init(); init();
} }
@ -66,7 +66,7 @@ public class AdaptiveConfig {
*/ */
public static boolean isEnabled() { public static boolean isEnabled() {
ensureInitialized(); ensureInitialized();
return (boolean) cache.getOrDefault(KEY_ENABLED, DEFAULT_ENABLED); return (boolean) CACHE.getOrDefault(KEY_ENABLED, DEFAULT_ENABLED);
} }
/** /**
@ -76,7 +76,7 @@ public class AdaptiveConfig {
*/ */
public static int getMinSessions() { public static int getMinSessions() {
ensureInitialized(); ensureInitialized();
return (int) cache.getOrDefault(KEY_MIN_SESSIONS, DEFAULT_MIN_SESSIONS); return (int) CACHE.getOrDefault(KEY_MIN_SESSIONS, DEFAULT_MIN_SESSIONS);
} }
/** /**
@ -86,7 +86,7 @@ public class AdaptiveConfig {
*/ */
public static int getUpdateInterval() { public static int getUpdateInterval() {
ensureInitialized(); ensureInitialized();
return (int) cache.getOrDefault(KEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL); return (int) CACHE.getOrDefault(KEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL);
} }
/** /**
@ -96,7 +96,7 @@ public class AdaptiveConfig {
*/ */
public static double getRatingWeight() { public static double getRatingWeight() {
ensureInitialized(); ensureInitialized();
Object value = cache.get(KEY_RATING_WEIGHT); Object value = CACHE.get(KEY_RATING_WEIGHT);
if (value instanceof Double) { if (value instanceof Double) {
return (double) value; return (double) value;
} }
@ -110,7 +110,7 @@ public class AdaptiveConfig {
*/ */
public static double getConfidenceThreshold() { public static double getConfidenceThreshold() {
ensureInitialized(); ensureInitialized();
Object value = cache.get(KEY_CONFIDENCE_THRESHOLD); Object value = CACHE.get(KEY_CONFIDENCE_THRESHOLD);
if (value instanceof Double) { if (value instanceof Double) {
return (double) value; return (double) value;
} }
@ -124,7 +124,7 @@ public class AdaptiveConfig {
*/ */
public static double getNearMissDistance() { public static double getNearMissDistance() {
ensureInitialized(); ensureInitialized();
Object value = cache.get(KEY_NEAR_MISS_DISTANCE); Object value = CACHE.get(KEY_NEAR_MISS_DISTANCE);
if (value instanceof Double) { if (value instanceof Double) {
return (double) value; return (double) value;
} }
@ -152,7 +152,7 @@ public class AdaptiveConfig {
public static <T> T get(@NotNull String key, @NotNull T defaultValue) { public static <T> T get(@NotNull String key, @NotNull T defaultValue) {
ensureInitialized(); ensureInitialized();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T value = (T) cache.get(key); T value = (T) CACHE.get(key);
return value != null ? value : defaultValue; return value != null ? value : defaultValue;
} }
} }

View file

@ -16,8 +16,11 @@ import java.util.List;
*/ */
public final class Registry { public final class Registry {
private static final LinkedList<Mode> modes = new LinkedList<>(); private Registry() {
private static final LinkedList<Style> styles = new LinkedList<>(); }
private static final LinkedList<Mode> MODES = new LinkedList<>();
private static final LinkedList<Style> STYLES = new LinkedList<>();
/** /**
* Registers a {@link Mode}. * Registers a {@link Mode}.
@ -25,11 +28,11 @@ public final class Registry {
* @param mode The mode. * @param mode The mode.
*/ */
public static void register(@NotNull Mode mode) { public static void register(@NotNull Mode mode) {
modes.add(mode); MODES.add(mode);
} }
public static void register(@NotNull Style style) { public static void register(@NotNull Style style) {
styles.add(style); STYLES.add(style);
} }
/** /**
@ -38,7 +41,7 @@ public final class Registry {
*/ */
@Nullable @Nullable
public static Mode getMode(@NotNull String name) { public static Mode getMode(@NotNull String name) {
return modes.stream() return MODES.stream()
.filter(mode -> mode.getName().equals(name)) .filter(mode -> mode.getName().equals(name))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
@ -46,17 +49,17 @@ public final class Registry {
@Nullable @Nullable
public static Style getStyle(@NotNull String name) { public static Style getStyle(@NotNull String name) {
return styles.stream() return STYLES.stream()
.filter(style -> style.getName().equals(name)) .filter(style -> style.getName().equals(name))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
public static List<Style> getStyles() { public static List<Style> getStyles() {
return styles; return STYLES;
} }
public static List<Mode> getModes() { public static List<Mode> getModes() {
return modes; return MODES;
} }
} }

View file

@ -27,7 +27,6 @@ import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie; import org.bstats.charts.SimplePie;
import org.bstats.charts.SingleLineChart; import org.bstats.charts.SingleLineChart;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/** /**
* Wires plugin subsystems during {@link LoParkour#enable()} and {@link LoParkour#disable()}. * Wires plugin subsystems during {@link LoParkour#enable()} and {@link LoParkour#disable()}.

View file

@ -79,11 +79,15 @@ public class LoParkourCommand implements CommandExecutor, TabCompleter {
admin.handle(a1, a2, sender, p); admin.handle(a1, a2, sender, p);
return; return;
} }
default -> {
}
} }
if (p == null) return; if (p == null) {
return;
}
if (a1.equalsIgnoreCase("create") && p.hasPermission(ParkourOption.ADMIN.permission)) { if ("create".equalsIgnoreCase(a1) && p.hasPermission(ParkourOption.ADMIN.permission)) {
SchematicCommandHandler.handleCreateDifficultyOnly(a2, sender, p, player); SchematicCommandHandler.handleCreateDifficultyOnly(a2, sender, p, player);
return; return;
} }
@ -98,17 +102,23 @@ public class LoParkourCommand implements CommandExecutor, TabCompleter {
} }
SchematicCommandHandler.handleSubcommand(a2, sender, p, player); SchematicCommandHandler.handleSubcommand(a2, sender, p, player);
} }
default -> {
}
} }
} }
// ── 3-arg routing ────────────────────────────────────────────────────────── // ── 3-arg routing ──────────────────────────────────────────────────────────
private void handle3(String a1, String a2, String a3, CommandSender sender, @Nullable Player p) { private void handle3(String a1, String a2, String a3, CommandSender sender, @Nullable Player p) {
if (p == null) return; if (p == null) {
if (!p.hasPermission(ParkourOption.ADMIN.permission)) return; return;
}
if (!p.hasPermission(ParkourOption.ADMIN.permission)) {
return;
}
if (a1.equalsIgnoreCase("schematic")) { if ("schematic".equalsIgnoreCase(a1)) {
if (a2.equalsIgnoreCase("create")) { if ("create".equalsIgnoreCase(a2)) {
SchematicCommandHandler.handleCreateDifficultyOnly(a3, sender, p, player); SchematicCommandHandler.handleCreateDifficultyOnly(a3, sender, p, player);
return; return;
} }
@ -117,29 +127,48 @@ public class LoParkourCommand implements CommandExecutor, TabCompleter {
} }
private void handle4(String a1, String a2, String a3, String a4, CommandSender sender, @Nullable Player p) { private void handle4(String a1, String a2, String a3, String a4, CommandSender sender, @Nullable Player p) {
if (p == null) return; if (p == null) {
if (!p.hasPermission(ParkourOption.ADMIN.permission)) return; return;
if (!a1.equalsIgnoreCase("schematic") || !a2.equalsIgnoreCase("create")) return; }
if (!p.hasPermission(ParkourOption.ADMIN.permission)) {
return;
}
if (!"schematic".equalsIgnoreCase(a1) || !"create".equalsIgnoreCase(a2)) {
return;
}
SchematicCommandHandler.handleCreateWithDifficulty(a3, a4, sender, p, player); SchematicCommandHandler.handleCreateWithDifficulty(a3, a4, sender, p, player);
} }
// ── join logic ───────────────────────────────────────────────────────────── // ── join logic ─────────────────────────────────────────────────────────────
private void handleJoin(String arg, CommandSender sender, Player p) { private void handleJoin(String arg, CommandSender sender, Player p) {
if (!player.cooldown(sender, "join", 2500) || !ParkourOption.JOIN.mayPerform(p)) return; if (!player.cooldown(sender, "join", 2500) || !ParkourOption.JOIN.mayPerform(p)) {
return;
}
Mode mode = Registry.getMode(arg); Mode mode = Registry.getMode(arg);
if (mode != null) { mode.create(p); return; } if (mode != null) {
mode.create(p);
return;
}
Player other = Bukkit.getPlayer(arg); Player other = Bukkit.getPlayer(arg);
if (other == null) { send(sender, LoParkour.PREFIX + Locales.getString(sender, "commands.unknown_player")); return; } if (other == null) {
send(sender, LoParkour.PREFIX + Locales.getString(sender, "commands.unknown_player"));
return;
}
ParkourPlayer pp = ParkourPlayer.getPlayer(other); ParkourPlayer pp = ParkourPlayer.getPlayer(other);
if (pp == null) { send(sender, LoParkour.PREFIX + Locales.getString(sender, "commands.not_playing")); return; } if (pp == null) {
send(sender, LoParkour.PREFIX + Locales.getString(sender, "commands.not_playing"));
return;
}
ParkourUser user = ParkourUser.getUser(p); ParkourUser user = ParkourUser.getUser(p);
Session session = pp.session; Session session = pp.session;
if (user != null && user.session == session) return; if (user != null && user.session == session) {
return;
}
if (session.isAcceptingPlayers()) { if (session.isAcceptingPlayers()) {
Mode sessionMode = session.generator.getMode(); Mode sessionMode = session.generator.getMode();

View file

@ -38,18 +38,24 @@ public class AdminCommandHandler {
public void handle(@NotNull String arg1, @NotNull String arg2, public void handle(@NotNull String arg1, @NotNull String arg2,
@NotNull CommandSender sender, @Nullable Player player) { @NotNull CommandSender sender, @Nullable Player player) {
if (!sender.hasPermission(ParkourOption.ADMIN.permission)) return; if (!sender.hasPermission(ParkourOption.ADMIN.permission)) {
return;
}
switch (arg1.toLowerCase()) { switch (arg1.toLowerCase()) {
case "forcejoin" -> handleForceJoin(arg2, sender); case "forcejoin" -> handleForceJoin(arg2, sender);
case "forceleave" -> handleForceLeave(arg2, sender); case "forceleave" -> handleForceLeave(arg2, sender);
case "reset" -> handleReset(arg2, sender); case "reset" -> handleReset(arg2, sender);
case "recoverinventory" -> handleRecoverInventory(arg2, sender); case "recoverinventory" -> handleRecoverInventory(arg2, sender);
default -> {
}
} }
if (player == null) return; if (player == null) {
return;
}
if (arg1.equals("schematic")) { if ("schematic".equals(arg1)) {
SchematicCommandHandler.handleSubcommand(arg2, sender, player, base); SchematicCommandHandler.handleSubcommand(arg2, sender, player, base);
} }
} }
@ -57,52 +63,72 @@ public class AdminCommandHandler {
// ── forcejoin ────────────────────────────────────────────────────────────── // ── forcejoin ──────────────────────────────────────────────────────────────
private void handleForceJoin(String target, CommandSender sender) { private void handleForceJoin(String target, CommandSender sender) {
if (!base.cooldown(sender, "forcejoin", 2500, Locales.getString(sender, "admin.cooldown"))) return; if (!base.cooldown(sender, "forcejoin", 2500, Locales.getString(sender, "admin.cooldown"))) {
return;
}
if (target.equalsIgnoreCase("everyone")) { if ("everyone".equalsIgnoreCase(target)) {
Bukkit.getOnlinePlayers().forEach(p -> Modes.DEFAULT.create(p)); Bukkit.getOnlinePlayers().forEach(p -> Modes.DEFAULT.create(p));
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_join_everyone")); send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_join_everyone"));
return; return;
} }
if (target.equalsIgnoreCase("nearest")) { if ("nearest".equalsIgnoreCase(target)) {
Player closest = findNearest(sender); Player closest = findNearest(sender);
if (closest == null) return; if (closest == null) {
return;
}
Modes.DEFAULT.create(closest); Modes.DEFAULT.create(closest);
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_join_player").formatted(closest.getName())); send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_join_player").formatted(closest.getName()));
return; return;
} }
Player other = Bukkit.getPlayer(target); Player other = Bukkit.getPlayer(target);
if (other == null) { send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_online")); return; } if (other == null) {
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_online"));
return;
}
Modes.DEFAULT.create(other); Modes.DEFAULT.create(other);
} }
// ── forceleave ───────────────────────────────────────────────────────────── // ── forceleave ─────────────────────────────────────────────────────────────
private void handleForceLeave(String target, CommandSender sender) { private void handleForceLeave(String target, CommandSender sender) {
if (!base.cooldown(sender, "forceleave", 2500, Locales.getString(sender, "admin.cooldown"))) return; if (!base.cooldown(sender, "forceleave", 2500, Locales.getString(sender, "admin.cooldown"))) {
return;
}
if (target.equalsIgnoreCase("everyone")) { if ("everyone".equalsIgnoreCase(target)) {
ParkourPlayer.getPlayers().forEach(ParkourUser::leave); ParkourPlayer.getPlayers().forEach(ParkourUser::leave);
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_leave_everyone")); send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_leave_everyone"));
return; return;
} }
Player other = Bukkit.getPlayer(target); Player other = Bukkit.getPlayer(target);
if (other == null) { send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_online")); return; } if (other == null) {
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_online"));
return;
}
ParkourUser user = ParkourUser.getUser(other); ParkourUser user = ParkourUser.getUser(other);
if (user == null) { send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_playing")); return; } if (user == null) {
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_playing"));
return;
}
ParkourUser.leave(user); ParkourUser.leave(user);
} }
// ── reset ────────────────────────────────────────────────────────────────── // ── reset ──────────────────────────────────────────────────────────────────
private void handleReset(String target, CommandSender sender) { private void handleReset(String target, CommandSender sender) {
if (!base.cooldown(sender, "reset", 2500, Locales.getString(sender, "admin.cooldown"))) return; if (!base.cooldown(sender, "reset", 2500, Locales.getString(sender, "admin.cooldown"))) {
return;
}
if (target.equalsIgnoreCase("everyone")) { if ("everyone".equalsIgnoreCase(target)) {
Registry.getModes().stream() Registry.getModes().stream()
.map(Mode::getLeaderboard) .map(Mode::getLeaderboard)
.filter(lb -> lb != null) .filter(lb -> lb != null)
.forEach(lb -> { lb.resetAll(); lb.write(true); }); .forEach(lb -> {
lb.resetAll();
lb.write(true);
});
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.reset_all")); send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.reset_all"));
return; return;
} }
@ -113,7 +139,10 @@ public class AdminCommandHandler {
Registry.getModes().stream() Registry.getModes().stream()
.map(Mode::getLeaderboard) .map(Mode::getLeaderboard)
.filter(lb -> lb != null) .filter(lb -> lb != null)
.forEach(lb -> { lb.remove(uuid); lb.write(true); }); .forEach(lb -> {
lb.remove(uuid);
lb.write(true);
});
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.reset_player").formatted(name)); send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.reset_player").formatted(name));
} }
@ -121,9 +150,14 @@ public class AdminCommandHandler {
// ── recoverinventory ─────────────────────────────────────────────────────── // ── recoverinventory ───────────────────────────────────────────────────────
private void handleRecoverInventory(String target, CommandSender sender) { private void handleRecoverInventory(String target, CommandSender sender) {
if (!base.cooldown(sender, "recoverinventory", 2500, Locales.getString(sender, "admin.cooldown"))) return; if (!base.cooldown(sender, "recoverinventory", 2500, Locales.getString(sender, "admin.cooldown"))) {
return;
}
Player other = Bukkit.getPlayer(target); Player other = Bukkit.getPlayer(target);
if (other == null) { send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_online")); return; } if (other == null) {
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.player_not_online"));
return;
}
new InventoryData(other).load(result -> { new InventoryData(other).load(result -> {
if (result != null) { if (result != null) {
@ -140,7 +174,9 @@ public class AdminCommandHandler {
Location from = sender instanceof Player p ? p.getLocation() Location from = sender instanceof Player p ? p.getLocation()
: sender instanceof BlockCommandSender b ? b.getBlock().getLocation() : sender instanceof BlockCommandSender b ? b.getBlock().getLocation()
: null; : null;
if (from == null || from.getWorld() == null) return null; if (from == null || from.getWorld() == null) {
return null;
}
return from.getWorld().getPlayers().stream() return from.getWorld().getPlayers().stream()
.min((a, b) -> Double.compare(a.getLocation().distance(from), b.getLocation().distance(from))) .min((a, b) -> Double.compare(a.getLocation().distance(from), b.getLocation().distance(from)))
@ -150,7 +186,9 @@ public class AdminCommandHandler {
@SuppressWarnings("deprecation") // Bukkit: name-based OfflinePlayer lookup (admin-only) @SuppressWarnings("deprecation") // Bukkit: name-based OfflinePlayer lookup (admin-only)
private UUID resolveUUID(String input) { private UUID resolveUUID(String input) {
Player online = Bukkit.getPlayerExact(input); Player online = Bukkit.getPlayerExact(input);
if (online != null) return online.getUniqueId(); if (online != null) {
return online.getUniqueId();
}
if (input.contains("-")) { if (input.contains("-")) {
try { try {
return UUID.fromString(input); return UUID.fromString(input);
@ -163,7 +201,9 @@ public class AdminCommandHandler {
private String resolvePlayerName(String input, UUID uuid) { private String resolvePlayerName(String input, UUID uuid) {
Player online = Bukkit.getPlayerExact(input); Player online = Bukkit.getPlayerExact(input);
if (online != null) return online.getName(); if (online != null) {
return online.getName();
}
OfflinePlayer op = Bukkit.getOfflinePlayer(uuid); OfflinePlayer op = Bukkit.getOfflinePlayer(uuid);
return op.getName() != null ? op.getName() : input; return op.getName() != null ? op.getName() : input;
} }

View file

@ -37,29 +37,43 @@ public class PlayerCommandHandler {
switch (arg.toLowerCase()) { switch (arg.toLowerCase()) {
case "help" -> sendHelp(sender); case "help" -> sendHelp(sender);
case "reload" -> handleReload(sender, player); case "reload" -> handleReload(sender, player);
default -> {
}
} }
if (player == null) return; if (player == null) {
return;
}
switch (arg.toLowerCase()) { switch (arg.toLowerCase()) {
case "join" -> { case "join" -> {
if (!cooldown(sender, "join", 2500)) return; if (!cooldown(sender, "join", 2500)) {
return;
}
if (!ParkourOption.JOIN.mayPerform(player)) { if (!ParkourOption.JOIN.mayPerform(player)) {
send(sender, Locales.getString(player, "other.no_do")); send(sender, Locales.getString(player, "other.no_do"));
return; return;
} }
if (ParkourUser.getUser(player) != null) return; if (ParkourUser.getUser(player) != null) {
return;
}
Modes.DEFAULT.create(player); Modes.DEFAULT.create(player);
} }
case "leave" -> { case "leave" -> {
if (!cooldown(sender, "leave", 2500)) return; if (!cooldown(sender, "leave", 2500)) {
return;
}
ParkourUser.leave(player); ParkourUser.leave(player);
} }
case "play" -> { case "play" -> {
if (ParkourOption.PLAY.mayPerform(player)) Menus.PLAY.open(player); if (ParkourOption.PLAY.mayPerform(player)) {
Menus.PLAY.open(player);
}
} }
case "menu", "main" -> { case "menu", "main" -> {
if (ParkourOption.MAIN.mayPerform(player)) Menus.MAIN.open(player); if (ParkourOption.MAIN.mayPerform(player)) {
Menus.MAIN.open(player);
}
} }
case "leaderboard" -> { case "leaderboard" -> {
if (!ParkourOption.LEADERBOARDS.mayPerform(player)) { if (!ParkourOption.LEADERBOARDS.mayPerform(player)) {
@ -75,11 +89,15 @@ public class PlayerCommandHandler {
} }
SchematicCommandHandler.sendHelp(player); SchematicCommandHandler.sendHelp(player);
} }
default -> {
}
} }
} }
private void handleReload(@NotNull CommandSender sender, @Nullable Player player) { private void handleReload(@NotNull CommandSender sender, @Nullable Player player) {
if (!cooldown(sender, "reload", 2500)) return; if (!cooldown(sender, "reload", 2500)) {
return;
}
if (!sender.hasPermission(ParkourOption.ADMIN.permission)) { if (!sender.hasPermission(ParkourOption.ADMIN.permission)) {
send(sender, Locales.getString(sender, "other.no_do")); send(sender, Locales.getString(sender, "other.no_do"));
return; return;

View file

@ -32,7 +32,10 @@ import java.util.Map;
*/ */
public class SchematicCommandHandler { public class SchematicCommandHandler {
public static final Map<Player, Location[]> selections = new HashMap<>(); private SchematicCommandHandler() {
}
public static final Map<Player, Location[]> SELECTIONS = new HashMap<>();
public static final NamespacedKey WAND_KEY = new NamespacedKey(LoParkour.getPlugin(), "schematic_wand"); public static final NamespacedKey WAND_KEY = new NamespacedKey(LoParkour.getPlugin(), "schematic_wand");
private static ItemStack cachedWand; private static ItemStack cachedWand;
@ -53,10 +56,10 @@ public class SchematicCommandHandler {
@NotNull @NotNull
public static Location[] getSelection(@NotNull Player player) { public static Location[] getSelection(@NotNull Player player) {
Location[] sel = selections.get(player); Location[] sel = SELECTIONS.get(player);
if (sel == null) { if (sel == null) {
sel = new Location[]{null, null}; sel = new Location[]{null, null};
selections.put(player, sel); SELECTIONS.put(player, sel);
} }
return sel; return sel;
} }
@ -64,7 +67,7 @@ public class SchematicCommandHandler {
public static void setPos(@NotNull Player player, @NotNull Location loc, int index) { public static void setPos(@NotNull Player player, @NotNull Location loc, int index) {
Location[] updated = getSelection(player).clone(); Location[] updated = getSelection(player).clone();
updated[index] = loc.clone(); updated[index] = loc.clone();
selections.put(player, updated); SELECTIONS.put(player, updated);
} }
public static void clearWandCache() { public static void clearWandCache() {
@ -161,7 +164,7 @@ public class SchematicCommandHandler {
CommandSender sender, CommandSender sender,
Player player Player player
) { ) {
Location[] sel = selections.get(player); Location[] sel = SELECTIONS.get(player);
if (sel == null || sel[0] == null || sel[1] == null) { if (sel == null || sel[0] == null || sel[1] == null) {
send(player, LoParkour.PREFIX + Locales.getString(player, "schematic.selection_incomplete")); send(player, LoParkour.PREFIX + Locales.getString(player, "schematic.selection_incomplete"));
return; return;

View file

@ -52,7 +52,9 @@ public enum Config {
* Load this configuration file from disk. * Load this configuration file from disk.
*/ */
public void load() { public void load() {
if (path == null) return; if (path == null) {
return;
}
this.fileConfiguration = ConfigLoader.loadConfig(path); this.fileConfiguration = ConfigLoader.loadConfig(path);
this.accessor = new ConfigAccessor(fileConfiguration, fileName); this.accessor = new ConfigAccessor(fileConfiguration, fileName);

View file

@ -17,6 +17,9 @@ import java.util.logging.Logger;
*/ */
public class ConfigLoader { public class ConfigLoader {
private ConfigLoader() {
}
@NotNull @NotNull
public static FileConfiguration loadConfig(@NotNull File configFile) { public static FileConfiguration loadConfig(@NotNull File configFile) {
return YamlConfiguration.loadConfiguration(configFile); return YamlConfiguration.loadConfiguration(configFile);

View file

@ -3,10 +3,21 @@ package dev.loki.loparkour.config.core;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.*; import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.*; import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
@ -80,14 +91,19 @@ public class ConfigUpdater {
} }
int colon = trimmed.indexOf(':'); int colon = trimmed.indexOf(':');
if (colon == -1) { result.add(line); continue; } if (colon == -1) {
result.add(line);
continue;
}
String leaf = trimmed.substring(0, colon).trim(); String leaf = trimmed.substring(0, colon).trim();
String after = trimmed.substring(colon + 1).trim(); String after = trimmed.substring(colon + 1).trim();
int indent = indentOf(line); int indent = indentOf(line);
while (prevIndent >= 0 && indent <= prevIndent) { while (prevIndent >= 0 && indent <= prevIndent) {
if (!stack.isEmpty()) stack.pop(); if (!stack.isEmpty()) {
stack.pop();
}
prevIndent -= 2; prevIndent -= 2;
} }
@ -120,17 +136,23 @@ public class ConfigUpdater {
for (String line : lines) { for (String line : lines) {
String trimmed = line.trim(); String trimmed = line.trim();
if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith("-")) continue; if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith("-")) {
continue;
}
int colon = trimmed.indexOf(':'); int colon = trimmed.indexOf(':');
if (colon == -1) continue; if (colon == -1) {
continue;
}
String leaf = trimmed.substring(0, colon).trim(); String leaf = trimmed.substring(0, colon).trim();
String after = trimmed.substring(colon + 1).trim(); String after = trimmed.substring(colon + 1).trim();
int indent = indentOf(line); int indent = indentOf(line);
while (prevIndent >= 0 && indent <= prevIndent) { while (prevIndent >= 0 && indent <= prevIndent) {
if (!stack.isEmpty()) stack.pop(); if (!stack.isEmpty()) {
stack.pop();
}
prevIndent -= 2; prevIndent -= 2;
} }
@ -150,7 +172,9 @@ public class ConfigUpdater {
private static int indentOf(@NotNull String line) { private static int indentOf(@NotNull String line) {
int i = 0; int i = 0;
while (i < line.length() && line.charAt(i) == ' ') i++; while (i < line.length() && line.charAt(i) == ' ') {
i++;
}
return i; return i;
} }
@ -181,16 +205,22 @@ public class ConfigUpdater {
@NotNull @NotNull
private static Set<String> normalizeIgnored(@Nullable List<String> keys) { private static Set<String> normalizeIgnored(@Nullable List<String> keys) {
if (keys == null) return Set.of(); if (keys == null) {
return Set.of();
}
Set<String> s = new HashSet<>(); Set<String> s = new HashSet<>();
for (String k : keys) s.add(k.trim().toLowerCase()); for (String k : keys) {
s.add(k.trim().toLowerCase());
}
return s; return s;
} }
private static boolean isIgnored(@NotNull String fullPath, @NotNull Set<String> ignored) { private static boolean isIgnored(@NotNull String fullPath, @NotNull Set<String> ignored) {
String lower = fullPath.toLowerCase(); String lower = fullPath.toLowerCase();
for (String ign : ignored) { for (String ign : ignored) {
if (lower.equals(ign) || lower.startsWith(ign + ".")) return true; if (lower.equals(ign) || lower.startsWith(ign + ".")) {
return true;
}
} }
return false; return false;
} }

View file

@ -3,7 +3,10 @@ package dev.loki.loparkour.config.locale;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -28,9 +31,13 @@ public class LocaleCache {
public synchronized <T> T cachedValue(@NotNull String locale, public synchronized <T> T cachedValue(@NotNull String locale,
@NotNull Function<FileConfiguration, T> extractor, @NotNull Function<FileConfiguration, T> extractor,
@NotNull T defaultValue) { @NotNull T defaultValue) {
if (locales.isEmpty()) return defaultValue; if (locales.isEmpty()) {
return defaultValue;
}
FileConfiguration config = locales.get(locale); FileConfiguration config = locales.get(locale);
if (config == null) return defaultValue; if (config == null) {
return defaultValue;
}
try { try {
T result = extractor.apply(config); T result = extractor.apply(config);
return result != null ? result : defaultValue; return result != null ? result : defaultValue;

View file

@ -13,7 +13,11 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
@ -48,7 +52,9 @@ public class LocaleLoader {
try (Stream<Path> stream = Files.list(folder.toPath())) { try (Stream<Path> stream = Files.list(folder.toPath())) {
stream.forEach(path -> { stream.forEach(path -> {
File file = path.toFile(); File file = path.toFile();
if (!file.getName().endsWith(".yml")) return; if (!file.getName().endsWith(".yml")) {
return;
}
String locale = file.getName().split("\\.")[0]; String locale = file.getName().split("\\.")[0];
LoParkour.log("Found locale " + locale); LoParkour.log("Found locale " + locale);

View file

@ -13,7 +13,10 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -23,14 +26,14 @@ import java.util.regex.Pattern;
*/ */
public class Locales { public class Locales {
private static final LocaleCache cache = new LocaleCache(); private static final LocaleCache CACHE = new LocaleCache();
private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("%[a-z]"); private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("%[a-z]");
// ── Initialization ──────────────────────────────────────────────────────── // ── Initialization ────────────────────────────────────────────────────────
public static void init() { public static void init() {
Map<String, FileConfiguration> loaded = LocaleLoader.loadAll(); Map<String, FileConfiguration> loaded = LocaleLoader.loadAll();
cache.setLocales(loaded); CACHE.setLocales(loaded);
dev.loki.loparkour.command.schematic.SchematicCommandHandler.clearWandCache(); dev.loki.loparkour.command.schematic.SchematicCommandHandler.clearWandCache();
LoParkour.log("Locales loaded successfully (" + loaded.size() + " locales)"); LoParkour.log("Locales loaded successfully (" + loaded.size() + " locales)");
} }
@ -61,7 +64,7 @@ public class Locales {
@NotNull @NotNull
public static String getString(@NotNull String locale, @NotNull String path) { public static String getString(@NotNull String locale, @NotNull String path) {
return cache.cachedValue(locale, c -> c.getString(path), ""); return CACHE.cachedValue(locale, c -> c.getString(path), "");
} }
/** /**
@ -84,16 +87,16 @@ public class Locales {
@NotNull @NotNull
public static List<String> getStringList(@NotNull String locale, @NotNull String path) { public static List<String> getStringList(@NotNull String locale, @NotNull String path) {
return cache.cachedValue(locale, c -> c.getStringList(path), Collections.emptyList()); return CACHE.cachedValue(locale, c -> c.getStringList(path), Collections.emptyList());
} }
public static int getLocaleCount() { public static int getLocaleCount() {
return cache.getLocaleCount(); return CACHE.getLocaleCount();
} }
@NotNull @NotNull
public static Set<String> getLocaleKeys() { public static Set<String> getLocaleKeys() {
return cache.getLocaleKeys(); return CACHE.getLocaleKeys();
} }
@NotNull @NotNull
@ -103,14 +106,14 @@ public class Locales {
@NotNull @NotNull
public static Item getItem(@NotNull String locale, @NotNull String path, String... replace) { public static Item getItem(@NotNull String locale, @NotNull String path, String... replace) {
if (cache.isEmpty()) { if (CACHE.isEmpty()) {
LoParkour.getPlugin().getLogger().warning("Locales are empty! Returning STONE item for path: " + path); LoParkour.getPlugin().getLogger().warning("Locales are empty! Returning STONE item for path: " + path);
return new Item(Material.STONE, ""); return new Item(Material.STONE, "");
} }
FileConfiguration config = cache.getLocale(locale); FileConfiguration config = CACHE.getLocale(locale);
if (config == null) { if (config == null) {
LoParkour.getPlugin().getLogger().warning( LoParkour.getPlugin().getLogger().warning(
"Locale '" + locale + "' not found! Available: " + cache.getLocaleKeys() + ". Returning STONE for path: " + path); "Locale '" + locale + "' not found! Available: " + CACHE.getLocaleKeys() + ". Returning STONE for path: " + path);
return new Item(Material.STONE, ""); return new Item(Material.STONE, "");
} }
return buildItem(config, path, replace); return buildItem(config, path, replace);
@ -147,7 +150,9 @@ public class Locales {
@NotNull @NotNull
private static String applyReplacements(@NotNull String text, String... replacements) { private static String applyReplacements(@NotNull String text, String... replacements) {
if (replacements.length == 0) return text; if (replacements.length == 0) {
return text;
}
String result = text; String result = text;
int idx = 0; int idx = 0;
Matcher matcher = REPLACEMENT_PATTERN.matcher(result); Matcher matcher = REPLACEMENT_PATTERN.matcher(result);

View file

@ -2,7 +2,6 @@ package dev.loki.loparkour.config.options;
import dev.loki.loparkour.api.core.Registry; import dev.loki.loparkour.api.core.Registry;
import dev.loki.loparkour.config.core.Config; import dev.loki.loparkour.config.core.Config;
import dev.loki.loparkour.config.options.*;
import dev.loki.loparkour.menu.core.ParkourOption; import dev.loki.loparkour.menu.core.ParkourOption;
import dev.loki.loparkour.style.core.RandomStyle; import dev.loki.loparkour.style.core.RandomStyle;
import dev.loki.loparkour.style.core.Style; import dev.loki.loparkour.style.core.Style;
@ -61,17 +60,34 @@ public class Option {
public static ParticleData<?> PARTICLE_DATA; public static ParticleData<?> PARTICLE_DATA;
// Generation // Generation
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS; public static double TYPE_NORMAL;
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE; public static double TYPE_SPECIAL;
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4; public static double TYPE_SCHEMATICS;
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2; public static double SPECIAL_ICE;
public static int MAX_Y, MIN_Y; public static double SPECIAL_SLAB;
public static int BLOCK_CLEANUP_DISTANCE, CLEANUP_INTERVAL, TRAIL_KEEP_BEHIND; public static double SPECIAL_PANE;
public static double SPECIAL_FENCE;
public static double NORMAL_DISTANCE_1;
public static double NORMAL_DISTANCE_2;
public static double NORMAL_DISTANCE_3;
public static double NORMAL_DISTANCE_4;
public static double NORMAL_HEIGHT_1;
public static double NORMAL_HEIGHT_0;
public static double NORMAL_HEIGHT_NEG1;
public static double NORMAL_HEIGHT_NEG2;
public static int MAX_Y;
public static int MIN_Y;
public static int BLOCK_CLEANUP_DISTANCE;
public static int CLEANUP_INTERVAL;
public static int TRAIL_KEEP_BEHIND;
public static boolean GHOST_MODE_ENABLED; public static boolean GHOST_MODE_ENABLED;
public static int GHOST_SHOW_TOP; public static int GHOST_SHOW_TOP;
public static double GHOST_TRANSPARENCY; public static double GHOST_TRANSPARENCY;
public static boolean JUMP_VALIDATION_ENABLED; public static boolean JUMP_VALIDATION_ENABLED;
public static double MAX_JUMP_DISTANCE, MAX_HORIZONTAL_DISTANCE, MAX_VERTICAL_UP, MAX_VERTICAL_DOWN; public static double MAX_JUMP_DISTANCE;
public static double MAX_HORIZONTAL_DISTANCE;
public static double MAX_VERTICAL_UP;
public static double MAX_VERTICAL_DOWN;
public static boolean JUMP_TYPES_ENABLED; public static boolean JUMP_TYPES_ENABLED;
public static Map<String, Boolean> JUMP_TYPE_ENABLED; public static Map<String, Boolean> JUMP_TYPE_ENABLED;
public static Map<String, Double> JUMP_TYPE_CHANCE; public static Map<String, Double> JUMP_TYPE_CHANCE;

View file

@ -8,7 +8,11 @@ import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* General configuration options (heading, border, leads, go-back location, parkour options). * General configuration options (heading, border, leads, go-back location, parkour options).
@ -125,7 +129,9 @@ public class OptionGeneral {
throw new IllegalArgumentException("Expected 4 values (x,y,z,world), got " + values.length); throw new IllegalArgumentException("Expected 4 values (x,y,z,world), got " + values.length);
} }
World world = Bukkit.getWorld(values[3]); World world = Bukkit.getWorld(values[3]);
if (world == null) world = Bukkit.getWorlds().get(0); if (world == null) {
world = Bukkit.getWorlds().get(0);
}
return new Location(world, Double.parseDouble(values[0]), return new Location(world, Double.parseDouble(values[0]),
Double.parseDouble(values[1]), Double.parseDouble(values[2])); Double.parseDouble(values[1]), Double.parseDouble(values[2]));
} catch (Exception ex) { } catch (Exception ex) {

View file

@ -12,11 +12,23 @@ import java.util.Map;
public class OptionGeneration { public class OptionGeneration {
// ── Block generation probabilities ──────────────────────────────────────── // ── Block generation probabilities ────────────────────────────────────────
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS; public static double TYPE_NORMAL;
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE; public static double TYPE_SPECIAL;
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4; public static double TYPE_SCHEMATICS;
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2; public static double SPECIAL_ICE;
public static int MAX_Y, MIN_Y; public static double SPECIAL_SLAB;
public static double SPECIAL_PANE;
public static double SPECIAL_FENCE;
public static double NORMAL_DISTANCE_1;
public static double NORMAL_DISTANCE_2;
public static double NORMAL_DISTANCE_3;
public static double NORMAL_DISTANCE_4;
public static double NORMAL_HEIGHT_1;
public static double NORMAL_HEIGHT_0;
public static double NORMAL_HEIGHT_NEG1;
public static double NORMAL_HEIGHT_NEG2;
public static int MAX_Y;
public static int MIN_Y;
// ── Memory / cleanup ────────────────────────────────────────────────────── // ── Memory / cleanup ──────────────────────────────────────────────────────
public static int BLOCK_CLEANUP_DISTANCE; public static int BLOCK_CLEANUP_DISTANCE;

View file

@ -2,7 +2,6 @@ package dev.loki.loparkour.config.options;
import dev.loki.loparkour.LoParkour; import dev.loki.loparkour.LoParkour;
import dev.loki.loparkour.config.core.Config; import dev.loki.loparkour.config.core.Config;
import dev.loki.loparkour.config.options.Option;
import dev.loki.loparkour.util.particle.ParticleData; import dev.loki.loparkour.util.particle.ParticleData;
import org.bukkit.Particle; import org.bukkit.Particle;
import org.bukkit.Sound; import org.bukkit.Sound;

View file

@ -127,7 +127,9 @@ public class ParkourGenerator {
/** Last generated block, or {@code null} if history is empty. */ /** Last generated block, or {@code null} if history is empty. */
public @Nullable Block getLatest() { public @Nullable Block getLatest() {
if (state.history.isEmpty()) return null; if (state.history.isEmpty()) {
return null;
}
return state.history.get(state.history.size() - 1); return state.history.get(state.history.size() - 1);
} }

View file

@ -7,7 +7,10 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Holds all state data for parkour generation. * Holds all state data for parkour generation.

View file

@ -41,14 +41,16 @@ public class Profile {
* @return true when the string value is "true", else "false". * @return true when the string value is "true", else "false".
*/ */
public boolean asBoolean() { public boolean asBoolean() {
return value.equals("true"); // save parsing return "true".equals(value); // save parsing
} }
/** /**
* @return The value as a double. Returns 0.0 if the value is empty. * @return The value as a double. Returns 0.0 if the value is empty.
*/ */
public double asDouble() { public double asDouble() {
if (value.isEmpty()) return 0.0; if (value.isEmpty()) {
return 0.0;
}
return Double.parseDouble(value); return Double.parseDouble(value);
} }
@ -56,7 +58,9 @@ public class Profile {
* @return The value as an int. Returns 0 if the value is empty. * @return The value as an int. Returns 0 if the value is empty.
*/ */
public int asInt() { public int asInt() {
if (value.isEmpty()) return 0; if (value.isEmpty()) {
return 0;
}
return Integer.parseInt(value); return Integer.parseInt(value);
} }
} }

View file

@ -25,7 +25,9 @@ public class EffectManager {
* Spawns particles around the given blocks based on the configured shape. * Spawns particles around the given blocks based on the configured shape.
*/ */
public void particles(List<Block> blocks) { public void particles(List<Block> blocks) {
if (!generator.profile.get("particles").asBoolean()) return; if (!generator.profile.get("particles").asBoolean()) {
return;
}
List<Location> locations = blocks.stream().map(Block::getLocation).toList(); List<Location> locations = blocks.stream().map(Block::getLocation).toList();
Location max = locations.stream().reduce((a, b) -> { Location max = locations.stream().reduce((a, b) -> {
@ -41,7 +43,9 @@ public class EffectManager {
return new Location(a.getWorld(), x, y, z); return new Location(a.getWorld(), x, y, z);
}).orElse(null); }).orElse(null);
if (max == null || min == null || max.getWorld() == null) return; if (max == null || min == null || max.getWorld() == null) {
return;
}
List<ParkourPlayer> viewers = generator.getPlayers(); List<ParkourPlayer> viewers = generator.getPlayers();
@ -64,6 +68,7 @@ public class EffectManager {
org.bukkit.util.BoundingBox.of(min, max), max.getWorld(), Option.PARTICLE_TYPE, org.bukkit.util.BoundingBox.of(min, max), max.getWorld(), Option.PARTICLE_TYPE,
viewers.isEmpty() ? null : viewers.get(0).player, 0.3 viewers.isEmpty() ? null : viewers.get(0).player, 0.3
); );
default -> {}
} }
} }
@ -71,7 +76,9 @@ public class EffectManager {
* Plays the configured sound at the first block's location. * Plays the configured sound at the first block's location.
*/ */
public void sound(List<Block> blocks) { public void sound(List<Block> blocks) {
if (!generator.profile.get("sound").asBoolean() || blocks.isEmpty()) return; if (!generator.profile.get("sound").asBoolean() || blocks.isEmpty()) {
return;
}
Location loc = blocks.get(0).getLocation(); Location loc = blocks.get(0).getLocation();
generator.getPlayers().forEach(p -> generator.getPlayers().forEach(p ->

View file

@ -51,7 +51,9 @@ public class JumpCalculator {
height = Math.max(-2, Math.min(2, height)); height = Math.max(-2, Math.min(2, height));
distance = Math.max(1, Math.min(4, distance)); distance = Math.max(1, Math.min(4, distance));
if (height > 0) distance = Math.max(distance - height, 1); if (height > 0) {
distance = Math.max(distance - height, 1);
}
// Calculate offset // Calculate offset
Vector offset = calculateJumpOffset(distance, height); Vector offset = calculateJumpOffset(distance, height);

View file

@ -115,13 +115,17 @@ public class BlockPlacer {
private void placeNormalBlock() { private void placeNormalBlock() {
BlockData blockData = blockSelector.selectBlockData(); BlockData blockData = blockSelector.selectBlockData();
if (blockData == null) return; if (blockData == null) {
return;
}
Material mat = blockData.getMaterial(); Material mat = blockData.getMaterial();
boolean tall = isTallMaterial(mat); boolean tall = isTallMaterial(mat);
List<Block> blocks = tall ? selectBlocks(-1) : selectBlocks(); List<Block> blocks = tall ? selectBlocks(-1) : selectBlocks();
if (blocks.isEmpty()) return; if (blocks.isEmpty()) {
return;
}
Block selectedBlock = blocks.get(0); Block selectedBlock = blocks.get(0);
placeBlockData(selectedBlock, blockData); placeBlockData(selectedBlock, blockData);
@ -139,7 +143,9 @@ public class BlockPlacer {
boolean tall = isTallMaterial(mat); boolean tall = isTallMaterial(mat);
List<Block> blocks = tall ? selectBlocks(-1) : selectBlocks(); List<Block> blocks = tall ? selectBlocks(-1) : selectBlocks();
if (blocks.isEmpty()) return; if (blocks.isEmpty()) {
return;
}
Block selectedBlock = blocks.get(0); Block selectedBlock = blocks.get(0);
placeBlockData(selectedBlock, specialBlockData); placeBlockData(selectedBlock, specialBlockData);

View file

@ -79,7 +79,9 @@ public class BlockSelector {
public Material getSlabMaterialFromCurrentStyle() { public Material getSlabMaterialFromCurrentStyle() {
try { try {
Style style = Registry.getStyle(generator.profile.get("style").value()); Style style = Registry.getStyle(generator.profile.get("style").value());
if (style == null) return null; if (style == null) {
return null;
}
// Try to get a slab material from the style multiple times // Try to get a slab material from the style multiple times
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {

View file

@ -28,12 +28,16 @@ public class GeneratorCleanup {
*/ */
public void cleanupDistantBlocks() { public void cleanupDistantBlocks() {
List<Block> history = generator.state.history; List<Block> history = generator.state.history;
if (history.isEmpty()) return; if (history.isEmpty()) {
return;
}
int minStandingIndex = Integer.MAX_VALUE; int minStandingIndex = Integer.MAX_VALUE;
for (ParkourPlayer pp : generator.getPlayers()) { for (ParkourPlayer pp : generator.getPlayers()) {
Block below = blockBelowPlayer(pp); Block below = blockBelowPlayer(pp);
if (below == null) continue; if (below == null) {
continue;
}
int idx = indexOfBlock(history, below); int idx = indexOfBlock(history, below);
if (idx >= 0) { if (idx >= 0) {
minStandingIndex = Math.min(minStandingIndex, idx); minStandingIndex = Math.min(minStandingIndex, idx);
@ -45,7 +49,9 @@ public class GeneratorCleanup {
int keepBehind = Math.max(0, Option.TRAIL_KEEP_BEHIND); int keepBehind = Math.max(0, Option.TRAIL_KEEP_BEHIND);
int removeCount = minStandingIndex - keepBehind; int removeCount = minStandingIndex - keepBehind;
if (removeCount <= 0) return; if (removeCount <= 0) {
return;
}
List<Block> head = new ArrayList<>(history.subList(0, removeCount)); List<Block> head = new ArrayList<>(history.subList(0, removeCount));
for (Block block : head) { for (Block block : head) {
@ -77,7 +83,9 @@ public class GeneratorCleanup {
* Remove trail blocks behind player at specified index. * Remove trail blocks behind player at specified index.
*/ */
public void removeTrailBlocks(int startIndex) { public void removeTrailBlocks(int startIndex) {
if (startIndex < 0 || startIndex >= generator.state.history.size()) return; if (startIndex < 0 || startIndex >= generator.state.history.size()) {
return;
}
int endIndex = Math.min(startIndex + Option.BLOCK_CLEANUP_DISTANCE, generator.state.history.size()); int endIndex = Math.min(startIndex + Option.BLOCK_CLEANUP_DISTANCE, generator.state.history.size());
@ -133,6 +141,7 @@ public class GeneratorCleanup {
case SOUTH -> blockSpawn.add(0, 0, 6); case SOUTH -> blockSpawn.add(0, 0, 6);
case WEST -> blockSpawn.add(-6, 0, 0); case WEST -> blockSpawn.add(-6, 0, 0);
case EAST -> blockSpawn.add(6, 0, 0); case EAST -> blockSpawn.add(6, 0, 0);
default -> {}
} }
generator.generateFirst(spawn, blockSpawn); generator.generateFirst(spawn, blockSpawn);

View file

@ -54,7 +54,9 @@ public class PlayerInteractionHandler {
/** Check if history contains a block by coordinates, not reference. */ /** Check if history contains a block by coordinates, not reference. */
private static boolean historyContains(@NotNull List<Block> history, @NotNull Block block) { private static boolean historyContains(@NotNull List<Block> history, @NotNull Block block) {
for (Block b : history) { for (Block b : history) {
if (isSameBlock(b, block)) return true; if (isSameBlock(b, block)) {
return true;
}
} }
return false; return false;
} }

View file

@ -1,5 +1,4 @@
package dev.loki.loparkour.ghost.core; package dev.loki.loparkour.ghost.core;
import dev.loki.loparkour.ghost.core.GhostPlayer;
import dev.loki.loparkour.ghost.model.GhostData; import dev.loki.loparkour.ghost.model.GhostData;
import dev.loki.loparkour.LoParkour; import dev.loki.loparkour.LoParkour;
@ -11,7 +10,12 @@ import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Loads, saves, and spawns ghost runs per mode. * Loads, saves, and spawns ghost runs per mode.
@ -46,10 +50,14 @@ public class GhostManager {
public void loadGhosts(@NotNull String mode) { public void loadGhosts(@NotNull String mode) {
File modeFolder = new File(ghostFolder, sanitizeMode(mode)); File modeFolder = new File(ghostFolder, sanitizeMode(mode));
if (!modeFolder.exists()) return; if (!modeFolder.exists()) {
return;
}
File[] files = modeFolder.listFiles((dir, name) -> name.endsWith(".ghost")); File[] files = modeFolder.listFiles((dir, name) -> name.endsWith(".ghost"));
if (files == null) return; if (files == null) {
return;
}
List<GhostData> ghosts = new ArrayList<>(); List<GhostData> ghosts = new ArrayList<>();
for (File file : files) { for (File file : files) {
@ -77,7 +85,9 @@ public class GhostManager {
public void saveGhost(@NotNull String mode, @NotNull GhostData data) { public void saveGhost(@NotNull String mode, @NotNull GhostData data) {
File modeFolder = new File(ghostFolder, sanitizeMode(mode)); File modeFolder = new File(ghostFolder, sanitizeMode(mode));
if (!modeFolder.exists()) modeFolder.mkdirs(); if (!modeFolder.exists()) {
modeFolder.mkdirs();
}
List<GhostData> ghosts = new ArrayList<>(ghostsByMode.getOrDefault(mode, new ArrayList<>())); List<GhostData> ghosts = new ArrayList<>(ghostsByMode.getOrDefault(mode, new ArrayList<>()));
ghosts.add(data); ghosts.add(data);
@ -88,7 +98,9 @@ public class GhostManager {
GhostData evicted = ghosts.remove(ghosts.size() - 1); GhostData evicted = ghosts.remove(ghosts.size() - 1);
// File is named by UUID — always finds the right file regardless of name changes // File is named by UUID — always finds the right file regardless of name changes
File evictedFile = ghostFile(modeFolder, evicted); File evictedFile = ghostFile(modeFolder, evicted);
if (evictedFile.exists()) evictedFile.delete(); if (evictedFile.exists()) {
evictedFile.delete();
}
} }
ghostsByMode.put(mode, ghosts); ghostsByMode.put(mode, ghosts);
@ -107,12 +119,16 @@ public class GhostManager {
public void spawnGhosts(@NotNull String mode, @NotNull Location startLocation, public void spawnGhosts(@NotNull String mode, @NotNull Location startLocation,
@NotNull World world) { @NotNull World world) {
if (!Config.CONFIG.getBoolean("ghost-mode.enabled")) return; if (!Config.CONFIG.getBoolean("ghost-mode.enabled")) {
return;
}
stopAllGhosts(); stopAllGhosts();
List<GhostData> ghosts = ghostsByMode.get(mode); List<GhostData> ghosts = ghostsByMode.get(mode);
if (ghosts == null || ghosts.isEmpty()) return; if (ghosts == null || ghosts.isEmpty()) {
return;
}
int showTop = Math.min(Config.CONFIG.getInt("ghost-mode.show-top"), ghosts.size()); int showTop = Math.min(Config.CONFIG.getInt("ghost-mode.show-top"), ghosts.size());
for (int i = 0; i < showTop; i++) { for (int i = 0; i < showTop; i++) {
@ -137,13 +153,17 @@ public class GhostManager {
public List<GhostData> getTopGhosts(@NotNull String mode, int count) { public List<GhostData> getTopGhosts(@NotNull String mode, int count) {
List<GhostData> ghosts = ghostsByMode.get(mode); List<GhostData> ghosts = ghostsByMode.get(mode);
if (ghosts == null || ghosts.isEmpty()) return Collections.emptyList(); if (ghosts == null || ghosts.isEmpty()) {
return Collections.emptyList();
}
return Collections.unmodifiableList(ghosts.subList(0, Math.min(count, ghosts.size()))); return Collections.unmodifiableList(ghosts.subList(0, Math.min(count, ghosts.size())));
} }
public boolean shouldRecordGhost(@NotNull String mode, int score) { public boolean shouldRecordGhost(@NotNull String mode, int score) {
List<GhostData> ghosts = ghostsByMode.get(mode); List<GhostData> ghosts = ghostsByMode.get(mode);
if (ghosts == null || ghosts.size() < MAX_GHOSTS_PER_MODE) return true; if (ghosts == null || ghosts.size() < MAX_GHOSTS_PER_MODE) {
return true;
}
return score > ghosts.get(ghosts.size() - 1).getScore(); return score > ghosts.get(ghosts.size() - 1).getScore();
} }

View file

@ -36,7 +36,9 @@ public class GhostPlayer {
} }
public void spawn(@NotNull Location startLocation) { public void spawn(@NotNull Location startLocation) {
if (data.getFrames().isEmpty()) return; if (data.getFrames().isEmpty()) {
return;
}
entity = (ArmorStand) world.spawnEntity(startLocation, EntityType.ARMOR_STAND); entity = (ArmorStand) world.spawnEntity(startLocation, EntityType.ARMOR_STAND);
entity.setVisible(false); entity.setVisible(false);
@ -61,17 +63,27 @@ public class GhostPlayer {
while (currentFrame < data.getFrames().size()) { while (currentFrame < data.getFrames().size()) {
GhostFrame frame = data.getFrames().get(currentFrame); GhostFrame frame = data.getFrames().get(currentFrame);
if (frame.getTimestamp() > elapsed) break; if (frame.getTimestamp() > elapsed) {
break;
}
entity.teleport(frame.toLocation(world)); entity.teleport(frame.toLocation(world));
currentFrame++; currentFrame++;
} }
if (currentFrame >= data.getFrames().size()) stop(); if (currentFrame >= data.getFrames().size()) {
stop();
}
} }
public void stop() { public void stop() {
if (task != null) { task.cancel(); task = null; } if (task != null) {
if (entity != null) { entity.remove(); entity = null; } task.cancel();
task = null;
}
if (entity != null) {
entity.remove();
entity = null;
}
} }
public boolean isActive() { return entity != null && entity.isValid(); } public boolean isActive() { return entity != null && entity.isValid(); }

View file

@ -36,8 +36,12 @@ public class GhostRecorder {
} }
public void recordFrame(@NotNull Location currentLocation) { public void recordFrame(@NotNull Location currentLocation) {
if (!recording) return; if (!recording) {
if (lastLocation.distance(currentLocation) < MIN_MOVEMENT) return; return;
}
if (lastLocation.distance(currentLocation) < MIN_MOVEMENT) {
return;
}
long timestamp = System.currentTimeMillis() - startTime; long timestamp = System.currentTimeMillis() - startTime;
frames.add(new GhostFrame(timestamp, currentLocation.clone())); frames.add(new GhostFrame(timestamp, currentLocation.clone()));

View file

@ -2,7 +2,14 @@ package dev.loki.loparkour.ghost.model;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.*; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;

View file

@ -5,7 +5,12 @@ import dev.loki.loparkour.leaderboard.model.Score;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* Facade for leaderboard: CRUD operations with automatic sorting. * Facade for leaderboard: CRUD operations with automatic sorting.

View file

@ -3,7 +3,11 @@ import dev.loki.loparkour.leaderboard.model.Score;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* Sorting logic for leaderboard scores. * Sorting logic for leaderboard scores.
@ -60,9 +64,15 @@ public class LeaderboardSorter {
String diff2 = two.getValue().difficulty(); String diff2 = two.getValue().difficulty();
// Handle "?" as lowest difficulty // Handle "?" as lowest difficulty
if ("?".equals(diff1) && "?".equals(diff2)) return 0; if ("?".equals(diff1) && "?".equals(diff2)) {
if ("?".equals(diff1)) return 1; return 0;
if ("?".equals(diff2)) return -1; }
if ("?".equals(diff1)) {
return 1;
}
if ("?".equals(diff2)) {
return -1;
}
try { try {
return (int) Math.signum(Double.parseDouble(diff2) - Double.parseDouble(diff1)); return (int) Math.signum(Double.parseDouble(diff2) - Double.parseDouble(diff1));

View file

@ -1,7 +1,6 @@
package dev.loki.loparkour.leaderboard.persistence; package dev.loki.loparkour.leaderboard.persistence;
import dev.loki.loparkour.leaderboard.model.Score; import dev.loki.loparkour.leaderboard.model.Score;
import dev.loki.loparkour.leaderboard.core.LeaderboardSorter; import dev.loki.loparkour.leaderboard.core.LeaderboardSorter;
import dev.loki.loparkour.leaderboard.core.Leaderboard;
import dev.loki.loparkour.LoParkour; import dev.loki.loparkour.LoParkour;
import dev.loki.loparkour.config.core.Config; import dev.loki.loparkour.config.core.Config;

View file

@ -18,7 +18,11 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.*; import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.PlayerInventory;
@ -30,31 +34,45 @@ public class ParkourRestrictionListener implements Listener {
@EventHandler @EventHandler
public void onChat(AsyncPlayerChatEvent event) { public void onChat(AsyncPlayerChatEvent event) {
if (!Option.OPTIONS_ENABLED.get(ParkourOption.CHAT)) return; if (!Option.OPTIONS_ENABLED.get(ParkourOption.CHAT)) {
return;
}
Player player = event.getPlayer(); Player player = event.getPlayer();
ParkourUser user = ParkourUser.getUser(player); ParkourUser user = ParkourUser.getUser(player);
if (user == null) return; if (user == null) {
return;
}
Session session = user.session; Session session = user.session;
if (session.isMuted(user)) return; if (session.isMuted(user)) {
return;
}
event.setCancelled(true); event.setCancelled(true);
switch (user.chatType) { switch (user.chatType) {
case LOBBY_ONLY -> session.getUsers().forEach(u -> u.sendTranslated("settings.chat.formats.lobby", player.getName(), event.getMessage())); case LOBBY_ONLY -> session.getUsers().forEach(
case PLAYERS_ONLY -> session.getPlayers().forEach(u -> u.sendTranslated("settings.chat.formats.players", player.getName(), event.getMessage())); u -> u.sendTranslated("settings.chat.formats.lobby", player.getName(), event.getMessage()));
case PLAYERS_ONLY -> session.getPlayers().forEach(
u -> u.sendTranslated("settings.chat.formats.players", player.getName(), event.getMessage()));
default -> event.setCancelled(false); default -> event.setCancelled(false);
} }
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onCommand(PlayerCommandPreprocessEvent event) { public void onCommand(PlayerCommandPreprocessEvent event) {
if (!Config.CONFIG.getBoolean("focus-mode.enabled")) return; if (!Config.CONFIG.getBoolean("focus-mode.enabled")) {
return;
}
ParkourUser user = ParkourUser.getUser(event.getPlayer()); ParkourUser user = ParkourUser.getUser(event.getPlayer());
if (user == null) return; if (user == null) {
return;
}
String cmd = event.getMessage().toLowerCase(); String cmd = event.getMessage().toLowerCase();
if (Config.CONFIG.getStringList("focus-mode.whitelist").stream().anyMatch(cmd::contains)) return; if (Config.CONFIG.getStringList("focus-mode.whitelist").stream().anyMatch(cmd::contains)) {
return;
}
user.sendTranslated("other.no_do"); user.sendTranslated("other.no_do");
event.setCancelled(true); event.setCancelled(true);
@ -64,7 +82,9 @@ public class ParkourRestrictionListener implements Listener {
public void onInteract(PlayerInteractEvent event) { public void onInteract(PlayerInteractEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
ParkourPlayer pp = ParkourPlayer.getPlayer(player); ParkourPlayer pp = ParkourPlayer.getPlayer(player);
if (pp == null) return; if (pp == null) {
return;
}
// Block container right-click // Block container right-click
boolean isContainer = event.getClickedBlock() != null && switch (event.getClickedBlock().getType()) { boolean isContainer = event.getClickedBlock() != null && switch (event.getClickedBlock().getType()) {
@ -81,47 +101,75 @@ public class ParkourRestrictionListener implements Listener {
boolean isRightClick = (event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_AIR boolean isRightClick = (event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_AIR
|| event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK) || event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)
&& event.getHand() == org.bukkit.inventory.EquipmentSlot.HAND; && event.getHand() == org.bukkit.inventory.EquipmentSlot.HAND;
if (!isRightClick) return; if (!isRightClick) {
return;
}
ItemStack held = heldItem(player); ItemStack held = heldItem(player);
event.setCancelled(true); event.setCancelled(true);
if (matchesLocaleHotbar(player, "play.item", held)) Menus.PLAY.open(player); if (matchesLocaleHotbar(player, "play.item", held)) {
else if (matchesLocaleHotbar(player, "community.item", held)) Menus.COMMUNITY.open(player); Menus.PLAY.open(player);
else if (matchesLocaleHotbar(player, "settings.item", held)) Menus.SETTINGS.open(player); } else if (matchesLocaleHotbar(player, "community.item", held)) {
else if (matchesLocaleHotbar(player, "lobby.item", held)) Menus.LOBBY.open(player); Menus.COMMUNITY.open(player);
else if (matchesLocaleHotbar(player, "other.quit", held)) ParkourUser.leave(player); } else if (matchesLocaleHotbar(player, "settings.item", held)) {
else if (!Config.CONFIG.getBoolean("options.disable-inventory-blocks")) event.setCancelled(false); Menus.SETTINGS.open(player);
} else if (matchesLocaleHotbar(player, "lobby.item", held)) {
Menus.LOBBY.open(player);
} else if (matchesLocaleHotbar(player, "other.quit", held)) {
ParkourUser.leave(player);
} else if (!Config.CONFIG.getBoolean("options.disable-inventory-blocks")) {
event.setCancelled(false);
}
} }
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW)
public void onInventoryClick(InventoryClickEvent event) { public void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player player)) return; if (!(event.getWhoClicked() instanceof Player player)) {
if (event.getInventory().getType() == InventoryType.CHEST) return; // LoLib GUI return;
if (event.getInventory().getType() == InventoryType.CRAFTING) return; // own inv }
if (event.getInventory().getType() == InventoryType.CHEST) {
return; // LoLib GUI
}
if (event.getInventory().getType() == InventoryType.CRAFTING) {
return; // own inv
}
restrict(player, event); restrict(player, event);
} }
@EventHandler @EventHandler
public void onDrop(PlayerDropItemEvent event) { restrict(event.getPlayer(), event); } public void onDrop(PlayerDropItemEvent event) {
restrict(event.getPlayer(), event);
}
@EventHandler @EventHandler
public void onPlace(BlockPlaceEvent event) { restrict(event.getPlayer(), event); } public void onPlace(BlockPlaceEvent event) {
restrict(event.getPlayer(), event);
}
@EventHandler @EventHandler
public void onBreak(BlockBreakEvent event) { restrict(event.getPlayer(), event); } public void onBreak(BlockBreakEvent event) {
restrict(event.getPlayer(), event);
}
@EventHandler @EventHandler
public void onDamage(EntityDamageEvent event) { public void onDamage(EntityDamageEvent event) {
if (event.getEntity() instanceof Player p) restrict(p, event); if (event.getEntity() instanceof Player p) {
restrict(p, event);
}
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onSpectate(PlayerTeleportEvent event) { public void onSpectate(PlayerTeleportEvent event) {
if (event.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE) if (event.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE) {
restrict(event.getPlayer(), event); restrict(event.getPlayer(), event);
} }
}
private void restrict(Player player, Cancellable event) { private void restrict(Player player, Cancellable event) {
if (ParkourUser.isUser(player)) event.setCancelled(true); if (ParkourUser.isUser(player)) {
event.setCancelled(true);
}
} }
private ItemStack heldItem(Player player) { private ItemStack heldItem(Player player) {

View file

@ -34,7 +34,9 @@ public class PlayerConnectionListener implements Listener {
return; return;
} }
if (!player.getWorld().equals(World.getWorld())) return; if (!player.getWorld().equals(World.getWorld())) {
return;
}
org.bukkit.World fallback = Bukkit.getWorld(Config.CONFIG.getString("world.fall-back")); org.bukkit.World fallback = Bukkit.getWorld(Config.CONFIG.getString("world.fall-back"));
if (fallback != null) { if (fallback != null) {
@ -52,7 +54,9 @@ public class PlayerConnectionListener implements Listener {
@EventHandler @EventHandler
public void onQuit(PlayerQuitEvent event) { public void onQuit(PlayerQuitEvent event) {
ParkourUser user = ParkourUser.getUser(event.getPlayer()); ParkourUser user = ParkourUser.getUser(event.getPlayer());
if (user == null) return; if (user == null) {
return;
}
ParkourUser.unregister(user, true, false, true); ParkourUser.unregister(user, true, false, true);
} }

View file

@ -51,7 +51,10 @@ public class SingleLeaderboardMenu extends LPMenu {
OfflinePlayer op = org.bukkit.Bukkit.getOfflinePlayer(entry.getKey()); OfflinePlayer op = org.bukkit.Bukkit.getOfflinePlayer(entry.getKey());
if (op.getName() != null && !op.getName().startsWith(".")) { if (op.getName() != null && !op.getName().startsWith(".")) {
SkullMeta meta = (SkullMeta) skull.getItemMeta(); SkullMeta meta = (SkullMeta) skull.getItemMeta();
if (meta != null) { meta.setOwningPlayer(op); skull.setItemMeta(meta); } if (meta != null) {
meta.setOwningPlayer(op);
skull.setItemMeta(meta);
}
} }
} }

View file

@ -15,7 +15,8 @@ import org.jetbrains.annotations.NotNull;
* *
* Real LoLib API: * Real LoLib API:
* InventoryGUI.create().title(String).rows(n).fill(item).setItem(slot, item, Consumer<InventoryClickEvent>).open(player) * InventoryGUI.create().title(String).rows(n).fill(item).setItem(slot, item, Consumer<InventoryClickEvent>).open(player)
* ScrollableGUI.create().title(String).rows(n).addItem(item, Consumer<InventoryClickEvent>).scrollUpButton(item,slot).scrollDownButton(item,slot).open(player) * ScrollableGUI.create().title(String).rows(n).addItem(item, Consumer&lt;InventoryClickEvent&gt;)
* .scrollUpButton(item,slot).scrollDownButton(item,slot).open(player)
* *
* cancelAllClicks = true by default — items cannot be taken out automatically. * cancelAllClicks = true by default — items cannot be taken out automatically.
* Handlers receive Consumer<InventoryClickEvent>, event is already cancelled before handler runs. * Handlers receive Consumer<InventoryClickEvent>, event is already cancelled before handler runs.
@ -81,7 +82,9 @@ public abstract class LPMenu {
protected int[] distributeEvenly(int count, int start, int end) { protected int[] distributeEvenly(int count, int start, int end) {
int[] result = new int[count]; int[] result = new int[count];
if (count == 0) return result; if (count == 0) {
return result;
}
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
result[i] = start + Math.round((float) i * (end - start) / Math.max(count - 1, 1)); result[i] = start + Math.round((float) i * (end - start) / Math.max(count - 1, 1));
} }

View file

@ -12,7 +12,10 @@ import dev.loki.loparkour.menu.settings.LangMenu;
import dev.loki.loparkour.menu.settings.ParkourSettingsMenu; import dev.loki.loparkour.menu.settings.ParkourSettingsMenu;
import dev.loki.loparkour.menu.settings.SettingsMenu; import dev.loki.loparkour.menu.settings.SettingsMenu;
public class Menus { public final class Menus {
private Menus() {
}
// main // main
public static MainMenu MAIN = new MainMenu(); public static MainMenu MAIN = new MainMenu();

View file

@ -45,7 +45,10 @@ public class PlayerManagementMenu extends LPMenu {
if (!ParkourUser.isBedrockPlayer(other.player) if (!ParkourUser.isBedrockPlayer(other.player)
&& other.getName() != null && !other.getName().startsWith(".")) { && other.getName() != null && !other.getName().startsWith(".")) {
SkullMeta meta = (SkullMeta) skull.getItemMeta(); SkullMeta meta = (SkullMeta) skull.getItemMeta();
if (meta != null) { meta.setOwningPlayer(other.player); skull.setItemMeta(meta); } if (meta != null) {
meta.setOwningPlayer(other.player);
skull.setItemMeta(meta);
}
} }
boolean muted = session.isMuted(other); boolean muted = session.isMuted(other);

View file

@ -45,7 +45,10 @@ public class SpectatorMenu extends LPMenu {
if (!ParkourUser.isBedrockPlayer(player) if (!ParkourUser.isBedrockPlayer(player)
&& pp.getName() != null && !pp.getName().startsWith(".")) { && pp.getName() != null && !pp.getName().startsWith(".")) {
SkullMeta meta = (SkullMeta) skull.getItemMeta(); SkullMeta meta = (SkullMeta) skull.getItemMeta();
if (meta != null) { meta.setOwningPlayer(pp.player); skull.setItemMeta(meta); } if (meta != null) {
meta.setOwningPlayer(pp.player);
skull.setItemMeta(meta);
}
} }
sessions.add(session); sessions.add(session);
items.add(skull); items.add(skull);

View file

@ -45,7 +45,7 @@ public class LangMenu extends LPMenu {
} }
gui = gui.setItem(10 + i, item, e -> { gui = gui.setItem(10 + i, item, e -> {
pp.locale = lang; pp.locale = lang;
pp._locale = lang; pp.locale = lang;
pp.updateHotbar(); // Update hotbar with new language pp.updateHotbar(); // Update hotbar with new language
Menus.SETTINGS.open(player); Menus.SETTINGS.open(player);
}); });

View file

@ -158,7 +158,10 @@ public class ParkourSettingsMenu extends LPMenu {
ItemStack item = new ItemStack(style.getNext()); ItemStack item = new ItemStack(style.getNext());
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
if (meta != null) { meta.setDisplayName(ColorUtil.color("&#A020F0" + name)); item.setItemMeta(meta); } if (meta != null) {
meta.setDisplayName(ColorUtil.color("&#A020F0" + name));
item.setItemMeta(meta);
}
final Style s = style; final Style s = style;
gui = gui.setItem(slot++, item, e -> { gui = gui.setItem(slot++, item, e -> {

View file

@ -1,9 +1,18 @@
package dev.loki.loparkour.mode.base; package dev.loki.loparkour.mode.base;
import dev.loki.loparkour.api.core.Registry; import dev.loki.loparkour.api.core.Registry;
import dev.loki.loparkour.mode.impl.*; import dev.loki.loparkour.mode.impl.CoopMode;
import dev.loki.loparkour.mode.impl.DefaultMode;
import dev.loki.loparkour.mode.impl.GravityShiftMode;
import dev.loki.loparkour.mode.impl.InvisibleBarrierMode;
import dev.loki.loparkour.mode.impl.RaceMode;
import dev.loki.loparkour.mode.impl.SpectatorMode;
import dev.loki.loparkour.mode.impl.SpeedrunMode;
public class Modes { public final class Modes {
private Modes() {
}
public static DefaultMode DEFAULT; public static DefaultMode DEFAULT;
public static SpectatorMode SPECTATOR; public static SpectatorMode SPECTATOR;

View file

@ -93,7 +93,9 @@ public class CoopMode implements MultiMode {
return; return;
} }
if (session.generator == null) return; if (session.generator == null) {
return;
}
// Register the joining player into the existing session // Register the joining player into the existing session
ParkourPlayer pp = ParkourUser.register(joiningPlayer, session); ParkourPlayer pp = ParkourUser.register(joiningPlayer, session);
@ -132,7 +134,7 @@ public class CoopMode implements MultiMode {
/** Individual block contributions per player UUID. */ /** Individual block contributions per player UUID. */
private final Map<UUID, Integer> contributions = new HashMap<>(); private final Map<UUID, Integer> contributions = new HashMap<>();
public CoopGenerator(@NotNull Session session) { CoopGenerator(@NotNull Session session) {
super(session); super(session);
session.getPlayers().forEach(pp -> contributions.put(pp.getUUID(), 0)); session.getPlayers().forEach(pp -> contributions.put(pp.getUUID(), 0));
} }

View file

@ -4,7 +4,6 @@ import dev.loki.loparkour.config.locale.Locales;
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator; import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
import dev.loki.loparkour.mode.base.Mode; import dev.loki.loparkour.mode.base.Mode;
import dev.loki.loparkour.mode.base.ModeMessages; import dev.loki.loparkour.mode.base.ModeMessages;
import dev.loki.loparkour.util.item.Item;
import dev.loki.loparkour.leaderboard.core.Leaderboard; import dev.loki.loparkour.leaderboard.core.Leaderboard;
import dev.loki.loparkour.player.core.ParkourPlayer; import dev.loki.loparkour.player.core.ParkourPlayer;
import dev.loki.loparkour.session.core.Session; import dev.loki.loparkour.session.core.Session;

View file

@ -16,7 +16,12 @@ import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
/** /**
* Gravity Shift Mode — random potion effects applied every N jumps. * Gravity Shift Mode — random potion effects applied every N jumps.
@ -67,7 +72,7 @@ public class GravityShiftMode implements Mode {
private final Random random; private final Random random;
private final Map<UUID, Integer> jumpCounts; private final Map<UUID, Integer> jumpCounts;
public GravityShiftGenerator(@NotNull Session session) { GravityShiftGenerator(@NotNull Session session) {
super(session); super(session);
this.random = new Random(); this.random = new Random();
this.jumpCounts = new HashMap<>(); this.jumpCounts = new HashMap<>();

View file

@ -72,7 +72,7 @@ public class InvisibleBarrierMode implements Mode {
private final Map<Location, Particle.DustOptions> blockColors = new HashMap<>(); private final Map<Location, Particle.DustOptions> blockColors = new HashMap<>();
private int particleTick = 0; private int particleTick = 0;
public BarrierGenerator(@NotNull Session session) { BarrierGenerator(@NotNull Session session) {
super(session); super(session);
} }
@ -114,13 +114,17 @@ public class InvisibleBarrierMode implements Mode {
} }
private void convertLastBlockToBarrier() { private void convertLastBlockToBarrier() {
if (state.history.isEmpty()) return; if (state.history.isEmpty()) {
return;
}
convertBlockToBarrier(state.history.get(state.history.size() - 1)); convertBlockToBarrier(state.history.get(state.history.size() - 1));
} }
private void convertBlockToBarrier(@NotNull Block block) { private void convertBlockToBarrier(@NotNull Block block) {
Location loc = block.getLocation(); Location loc = block.getLocation();
if (block.getType() == Material.BARRIER) return; if (block.getType() == Material.BARRIER) {
return;
}
block.setType(Material.BARRIER, false); block.setType(Material.BARRIER, false);
activeBarriers.add(loc); activeBarriers.add(loc);
Color color = Color.fromRGB(random.nextInt(256), random.nextInt(256), random.nextInt(256)); Color color = Color.fromRGB(random.nextInt(256), random.nextInt(256), random.nextInt(256));
@ -128,7 +132,9 @@ public class InvisibleBarrierMode implements Mode {
} }
private void renderOutlines() { private void renderOutlines() {
if (activeBarriers.isEmpty()) return; if (activeBarriers.isEmpty()) {
return;
}
// Self-clean invalid entries // Self-clean invalid entries
Iterator<Map.Entry<Location, Particle.DustOptions>> it = blockColors.entrySet().iterator(); Iterator<Map.Entry<Location, Particle.DustOptions>> it = blockColors.entrySet().iterator();
@ -145,53 +151,70 @@ public class InvisibleBarrierMode implements Mode {
Location playerLoc = player.getLocation(); Location playerLoc = player.getLocation();
for (Location loc : activeBarriers) { for (Location loc : activeBarriers) {
if (loc.getWorld() != playerLoc.getWorld()) continue; if (loc.getWorld() != playerLoc.getWorld()) {
if (loc.distanceSquared(playerLoc) > RENDER_DISTANCE * RENDER_DISTANCE) continue; continue;
}
if (loc.distanceSquared(playerLoc) > RENDER_DISTANCE * RENDER_DISTANCE) {
continue;
}
Particle.DustOptions options = blockColors.get(loc); Particle.DustOptions options = blockColors.get(loc);
if (options == null) continue; if (options == null) {
continue;
}
drawBlockOutline(player, loc, options); drawBlockOutline(player, loc, options);
} }
} }
} }
private record Point(double x, double y, double z) {}
private void drawBlockOutline(@NotNull Player player, @NotNull Location loc, @NotNull Particle.DustOptions options) { private void drawBlockOutline(@NotNull Player player, @NotNull Location loc, @NotNull Particle.DustOptions options) {
double x = loc.getX(); double x = loc.getX();
double y = loc.getY(); double y = loc.getY();
double z = loc.getZ(); double z = loc.getZ();
Point p = new Point(x, y, z);
Point q = new Point(x + 1, y, z);
Point r = new Point(x + 1, y, z + 1);
Point s = new Point(x, y, z + 1);
// Bottom edges (y offset = 0) // Bottom edges (y offset = 0)
drawEdge(player, x, y, z, x + 1, y, z, options); drawEdge(player, p, q, options);
drawEdge(player, x + 1, y, z, x + 1, y, z + 1, options); drawEdge(player, q, r, options);
drawEdge(player, x + 1, y, z + 1, x, y, z + 1, options); drawEdge(player, r, s, options);
drawEdge(player, x, y, z + 1, x, y, z, options); drawEdge(player, s, p, options);
// Top edges (y offset = 1) // Top edges (y offset = 1)
drawEdge(player, x, y + 1, z, x + 1, y + 1, z, options); Point pt = new Point(x, y + 1, z);
drawEdge(player, x + 1, y + 1, z, x + 1, y + 1, z + 1, options); Point qt = new Point(x + 1, y + 1, z);
drawEdge(player, x + 1, y + 1, z + 1, x, y + 1, z + 1, options); Point rt = new Point(x + 1, y + 1, z + 1);
drawEdge(player, x, y + 1, z + 1, x, y + 1, z, options); Point st = new Point(x, y + 1, z + 1);
drawEdge(player, pt, qt, options);
drawEdge(player, qt, rt, options);
drawEdge(player, rt, st, options);
drawEdge(player, st, pt, options);
// Vertical edges // Vertical edges
drawEdge(player, x, y, z, x, y + 1, z, options); drawEdge(player, p, pt, options);
drawEdge(player, x + 1, y, z, x + 1, y + 1, z, options); drawEdge(player, q, qt, options);
drawEdge(player, x + 1, y, z + 1, x + 1, y + 1, z + 1, options); drawEdge(player, r, rt, options);
drawEdge(player, x, y, z + 1, x, y + 1, z + 1, options); drawEdge(player, s, st, options);
} }
private void drawEdge(@NotNull Player player, double x1, double y1, double z1, double x2, double y2, double z2, @NotNull Particle.DustOptions options) { private void drawEdge(@NotNull Player player, @NotNull Point start, @NotNull Point end,
double dx = x2 - x1; @NotNull Particle.DustOptions options) {
double dy = y2 - y1; double dx = end.x - start.x;
double dz = z2 - z1; double dy = end.y - start.y;
double dz = end.z - start.z;
double length = Math.sqrt(dx * dx + dy * dy + dz * dz); double length = Math.sqrt(dx * dx + dy * dy + dz * dz);
int steps = Math.max(1, (int) (length / PARTICLE_STEP)); int steps = Math.max(1, (int) (length / PARTICLE_STEP));
for (int i = 0; i <= steps; i++) { for (int i = 0; i <= steps; i++) {
double t = (double) i / steps; double t = (double) i / steps;
double px = x1 + dx * t; double px = start.x + dx * t;
double py = y1 + dy * t; double py = start.y + dy * t;
double pz = z1 + dz * t; double pz = start.z + dz * t;
player.spawnParticle(Particle.REDSTONE, px, py, pz, 1, options); player.spawnParticle(Particle.REDSTONE, px, py, pz, 1, options);
} }
} }

View file

@ -79,7 +79,7 @@ public class RaceMode implements Mode {
private final int targetScore; private final int targetScore;
private boolean raceFinished = false; private boolean raceFinished = false;
public RaceGenerator(@NotNull Session session) { RaceGenerator(@NotNull Session session) {
super(session); super(session);
this.targetScore = Config.CONFIG.getInt("modes.race.target-score"); this.targetScore = Config.CONFIG.getInt("modes.race.target-score");
} }

View file

@ -2,7 +2,6 @@ package dev.loki.loparkour.mode.impl;
import dev.loki.loparkour.mode.base.ModeMessages; import dev.loki.loparkour.mode.base.ModeMessages;
import dev.loki.loparkour.mode.base.Mode; import dev.loki.loparkour.mode.base.Mode;
import dev.loki.loparkour.config.core.Config;
import dev.loki.loparkour.config.locale.Locales; import dev.loki.loparkour.config.locale.Locales;
import dev.loki.loparkour.leaderboard.core.Leaderboard; import dev.loki.loparkour.leaderboard.core.Leaderboard;
import dev.loki.loparkour.menu.core.Menus; import dev.loki.loparkour.menu.core.Menus;

View file

@ -84,7 +84,7 @@ public class SpeedrunMode implements Mode {
/** Tracks scheduled tasks per block. Key = block, value = [warningTask, removalTask]. */ /** Tracks scheduled tasks per block. Key = block, value = [warningTask, removalTask]. */
private final Map<Block, ScheduledTask[]> scheduledTasks = new HashMap<>(); private final Map<Block, ScheduledTask[]> scheduledTasks = new HashMap<>();
public SpeedrunGenerator(@NotNull Session session) { SpeedrunGenerator(@NotNull Session session) {
super(session); super(session);
} }
@ -100,11 +100,17 @@ public class SpeedrunMode implements Mode {
// The block the player just landed on is the previous-to-last in history // The block the player just landed on is the previous-to-last in history
// (history.size()-1 is the leading block, size()-2 is where player stands) // (history.size()-1 is the leading block, size()-2 is where player stands)
int histSize = state.history.size(); int histSize = state.history.size();
if (histSize < 2) return; if (histSize < 2) {
return;
}
Block stepped = state.history.get(histSize - 2); Block stepped = state.history.get(histSize - 2);
if (stepped.getType() == Material.AIR) return; if (stepped.getType() == Material.AIR) {
if (scheduledTasks.containsKey(stepped)) return; // already scheduled return;
}
if (scheduledTasks.containsKey(stepped)) {
return;
}
scheduleBlockRemoval(stepped); scheduleBlockRemoval(stepped);
} }
@ -144,7 +150,9 @@ public class SpeedrunMode implements Mode {
// Cancel every pending warning and removal task // Cancel every pending warning and removal task
scheduledTasks.values().forEach(tasks -> { scheduledTasks.values().forEach(tasks -> {
for (ScheduledTask t : tasks) { for (ScheduledTask t : tasks) {
if (t != null) t.cancel(); if (t != null) {
t.cancel();
}
} }
}); });
scheduledTasks.clear(); scheduledTasks.clear();

View file

@ -3,11 +3,9 @@ package dev.loki.loparkour.player.core;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import dev.loki.loparkour.LoParkour; import dev.loki.loparkour.LoParkour;
import dev.loki.loparkour.config.core.Config; import dev.loki.loparkour.config.core.Config;
import dev.loki.loparkour.config.options.Option;
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator; import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
import dev.loki.loparkour.generator.core.model.Profile; import dev.loki.loparkour.generator.core.model.Profile;
import dev.loki.loparkour.menu.core.ParkourOption; import dev.loki.loparkour.menu.core.ParkourOption;
import dev.loki.loparkour.config.locale.Locales;
import dev.loki.loparkour.mode.base.MultiMode; import dev.loki.loparkour.mode.base.MultiMode;
import dev.loki.loparkour.player.data.PreviousData; import dev.loki.loparkour.player.data.PreviousData;
import dev.loki.loparkour.player.service.ParkourHotbar; import dev.loki.loparkour.player.service.ParkourHotbar;
@ -24,7 +22,10 @@ import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
/** /**
@ -48,7 +49,7 @@ public class ParkourPlayer extends ParkourUser {
public @Expose Boolean showScoreboard; public @Expose Boolean showScoreboard;
public @Expose Integer selectedTime; public @Expose Integer selectedTime;
public @Expose String style; public @Expose String style;
public @Expose String _locale; public @Expose String locale;
public @Expose List<String> collectedRewards; public @Expose List<String> collectedRewards;
/** /**
* Creates a new instance of a ParkourPlayer<br> * Creates a new instance of a ParkourPlayer<br>
@ -57,8 +58,6 @@ public class ParkourPlayer extends ParkourUser {
public ParkourPlayer(@NotNull Player player, @NotNull Session session, @Nullable PreviousData previousData) { public ParkourPlayer(@NotNull Player player, @NotNull Session session, @Nullable PreviousData previousData) {
super(player, session, previousData); super(player, session, previousData);
this._locale = locale;
// generic player settings // generic player settings
player.setFlying(false); player.setFlying(false);
player.setAllowFlight(false); player.setAllowFlight(false);

View file

@ -1,7 +1,6 @@
package dev.loki.loparkour.player.core; package dev.loki.loparkour.player.core;
import dev.loki.loparkour.player.service.UserRegistry; import dev.loki.loparkour.player.service.UserRegistry;
import dev.loki.loparkour.player.service.ScoreboardManager; import dev.loki.loparkour.player.service.ScoreboardManager;
import dev.loki.loparkour.player.core.ParkourPlayer;
import dev.loki.loparkour.config.locale.Locales; import dev.loki.loparkour.config.locale.Locales;
import dev.loki.loparkour.config.options.Option; import dev.loki.loparkour.config.options.Option;
@ -112,9 +111,17 @@ public abstract class ParkourUser {
} }
} }
public UUID getUUID() { return player.getUniqueId(); } public UUID getUUID() {
public Location getLocation() { return player.getLocation(); } return player.getUniqueId();
public String getName() { return player.getName(); } }
public Location getLocation() {
return player.getLocation();
}
public String getName() {
return player.getName();
}
public static boolean isBedrockPlayer(Player player) { public static boolean isBedrockPlayer(Player player) {
return Bukkit.getPluginManager().isPluginEnabled("floodgate") && FloodgateHook.isBedrockPlayer(player); return Bukkit.getPluginManager().isPluginEnabled("floodgate") && FloodgateHook.isBedrockPlayer(player);

View file

@ -11,7 +11,10 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.util.io.BukkitObjectInputStream; import org.bukkit.util.io.BukkitObjectInputStream;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.*; import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -95,7 +98,9 @@ public class InventoryData {
items = (Map<Integer, ItemStack>) stream.readObject(); items = (Map<Integer, ItemStack>) stream.readObject();
onFinish.accept(this); onFinish.accept(this);
} catch (IOException | ClassNotFoundException ex) { } catch (IOException | ClassNotFoundException ex) {
LoParkour.getPlugin().getLogger().severe("Error while reading inventory of %s from file %s".formatted(player.getName(), file.getName()) + " - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while reading inventory of %s from file %s".formatted(player.getName(), file.getName())
+ " - " + ex.getMessage());
onFinish.accept(null); onFinish.accept(null);
} }
} }
@ -132,7 +137,9 @@ public class InventoryData {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
file.createNewFile(); file.createNewFile();
} catch (IOException ex) { } catch (IOException ex) {
LoParkour.getPlugin().getLogger().severe("Error while creating file to save inventory of %s to file %s".formatted(player.getName(), file.getName()) + " - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while creating file to save inventory of %s to file %s".formatted(player.getName(), file.getName())
+ " - " + ex.getMessage());
} }
try { try {
@ -143,7 +150,9 @@ public class InventoryData {
} }
yaml.save(file); yaml.save(file);
} catch (IOException ex) { } catch (IOException ex) {
LoParkour.getPlugin().getLogger().severe("Error while saving inventory of %s to file %s".formatted(player.getName(), file.getName()) + " - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while saving inventory of %s to file %s".formatted(player.getName(), file.getName())
+ " - " + ex.getMessage());
} }
} }
} }

View file

@ -58,9 +58,9 @@ public class PreviousData {
public void apply(Player player, boolean urgent) { public void apply(Player player, boolean urgent) {
var to = Config.CONFIG.getBoolean("bungeecord.go-back-enabled") ? Option.GO_BACK_LOC : location; var to = Config.CONFIG.getBoolean("bungeecord.go-back-enabled") ? Option.GO_BACK_LOC : location;
if (!urgent) if (!urgent) {
PaperLib.teleportAsync(player, to).thenRun(() -> apply(player)); PaperLib.teleportAsync(player, to).thenRun(() -> apply(player));
else { } else {
player.teleport(to); player.teleport(to);
apply(player); apply(player);

View file

@ -12,7 +12,10 @@ import org.bukkit.plugin.messaging.ChannelNotRegisteredException;
* *
* @since 5.0.0 * @since 5.0.0
*/ */
class BungeeUtil { final class BungeeUtil {
private BungeeUtil() {
}
public static void sendPlayerToServer(Player player, String server) { public static void sendPlayerToServer(Player player, String server) {
ByteArrayDataOutput out = ByteStreams.newDataOutput(); ByteArrayDataOutput out = ByteStreams.newDataOutput();

View file

@ -15,7 +15,10 @@ import java.util.function.BiConsumer;
* *
* @since 5.0.0 * @since 5.0.0
*/ */
public class PlayerSettingsManager { public final class PlayerSettingsManager {
private PlayerSettingsManager() {
}
private static final Map<String, OptionContainer> COLUMN_MAPPINGS = new HashMap<>(); private static final Map<String, OptionContainer> COLUMN_MAPPINGS = new HashMap<>();
@ -41,7 +44,6 @@ public class PlayerSettingsManager {
if ("true".equals(v) || "false".equals(v)) { if ("true".equals(v) || "false".equals(v)) {
sanitized = Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.LANG, "en"); sanitized = Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.LANG, "en");
} }
p._locale = sanitized;
p.locale = sanitized; p.locale = sanitized;
})); }));
COLUMN_MAPPINGS.put("schematicDifficulty", new OptionContainer(ParkourOption.SCHEMATICS, (p, v) -> COLUMN_MAPPINGS.put("schematicDifficulty", new OptionContainer(ParkourOption.SCHEMATICS, (p, v) ->
@ -73,7 +75,7 @@ public class PlayerSettingsManager {
} }
private static boolean parseBoolean(String string) { private static boolean parseBoolean(String string) {
return string == null || string.equals("1") || string.equalsIgnoreCase("true"); return string == null || "1".equals(string) || "true".equalsIgnoreCase(string);
} }
private static int defaultBlockLead() { private static int defaultBlockLead() {

View file

@ -53,13 +53,17 @@ public class ScoreboardManager {
} }
private Score getTopScore(Leaderboard leaderboard) { private Score getTopScore(Leaderboard leaderboard) {
if (leaderboard == null) return createDefaultScore(); if (leaderboard == null) {
return createDefaultScore();
}
Score score = leaderboard.getScoreAtRank(1); Score score = leaderboard.getScoreAtRank(1);
return score != null ? score : createDefaultScore(); return score != null ? score : createDefaultScore();
} }
private Score getHighScore(Leaderboard leaderboard) { private Score getHighScore(Leaderboard leaderboard) {
if (leaderboard == null) return createDefaultScore(); if (leaderboard == null) {
return createDefaultScore();
}
Score score = leaderboard.get(playerUUID); Score score = leaderboard.get(playerUUID);
return score != null ? score : createDefaultScore(); return score != null ? score : createDefaultScore();
} }
@ -83,7 +87,9 @@ public class ScoreboardManager {
private void updateLines(Score top, Score high, ParkourGenerator generator) { private void updateLines(Score top, Score high, ParkourGenerator generator) {
Objective obj = board.getObjective("lp_sidebar"); Objective obj = board.getObjective("lp_sidebar");
if (obj == null) return; if (obj == null) {
return;
}
List<String> lines = Locales.getStringList(locale, "scoreboard.lines").stream() List<String> lines = Locales.getStringList(locale, "scoreboard.lines").stream()
.map(line -> replacePlaceholders(line, top, high, generator)) .map(line -> replacePlaceholders(line, top, high, generator))

View file

@ -1,5 +1,4 @@
package dev.loki.loparkour.player.service; package dev.loki.loparkour.player.service;
import dev.loki.loparkour.player.spectator.ParkourSpectator;
import dev.loki.loparkour.player.core.ParkourUser; import dev.loki.loparkour.player.core.ParkourUser;
import dev.loki.loparkour.player.core.ParkourPlayer; import dev.loki.loparkour.player.core.ParkourPlayer;
@ -25,7 +24,10 @@ import java.util.stream.Collectors;
* *
* @since 5.0.0 * @since 5.0.0
*/ */
public class UserRegistry { public final class UserRegistry {
private UserRegistry() {
}
private static int joinCount = 0; private static int joinCount = 0;

View file

@ -61,7 +61,8 @@ public class ParkourSpectator extends ParkourUser {
} }
closest = session.getPlayers().stream() closest = session.getPlayers().stream()
.min(Comparator.comparing(other -> other.getLocation().distanceSquared(player.getLocation()))) // x or x^2 doesn't matter in getting smallest .min(Comparator.comparing(
other -> other.getLocation().distanceSquared(player.getLocation()))) // x or x^2 doesn't matter in getting smallest
.orElse(closest); .orElse(closest);
}, 1, 10); }, 1, 10);
} }
@ -71,7 +72,8 @@ public class ParkourSpectator extends ParkourUser {
*/ */
@SuppressWarnings("deprecation") // Spigot Chat API: action bar via TextComponent @SuppressWarnings("deprecation") // Spigot Chat API: action bar via TextComponent
public void update() { public void update() {
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(ColorUtil.color(Locales.getString(player, "play.spectator.action_bar")))); String actionBar = ColorUtil.color(Locales.getString(player, "play.spectator.action_bar"));
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(actionBar));
player.setGameMode(GameMode.SPECTATOR); player.setGameMode(GameMode.SPECTATOR);
updateScoreboard(session.generator); updateScoreboard(session.generator);

View file

@ -62,7 +62,9 @@ public record Reward(@NotNull String string) {
try { try {
VaultHook.deposit(player.player, Double.parseDouble(string)); VaultHook.deposit(player.player, Double.parseDouble(string));
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
LoParkour.getPlugin().getLogger().severe("Error while trying to process Vault reward - check your rewards file for incorrect numbers - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while trying to process Vault reward - check your rewards file for incorrect numbers - "
+ ex.getMessage());
} }
} else { } else {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), string); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), string);

View file

@ -12,6 +12,9 @@ import java.util.Map;
*/ */
public class Rewards { public class Rewards {
private Rewards() {
}
public static boolean REWARDS_ENABLED; public static boolean REWARDS_ENABLED;
/** /**
@ -71,13 +74,17 @@ public class Rewards {
int value = Integer.parseInt(score); int value = Integer.parseInt(score);
if (value < 1) { if (value < 1) {
LoParkour.getPlugin().getLogger().severe("Error while trying to read rewards - check the rewards file for incorrect numbers - " + value + " is not a valid score"); LoParkour.getPlugin().getLogger().severe(
"Error while trying to read rewards - check the rewards file for incorrect numbers - "
+ value + " is not a valid score");
continue; continue;
} }
rewardMap.put(value, rewardStrings); rewardMap.put(value, rewardStrings);
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
LoParkour.getPlugin().getLogger().severe("Error while trying to read rewards - check the rewards file for incorrect numbers - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while trying to read rewards - check the rewards file for incorrect numbers - "
+ ex.getMessage());
} }
} }

View file

@ -11,6 +11,9 @@ import java.io.File;
*/ */
public class Schematics { public class Schematics {
private Schematics() {
}
private static final File FOLDER = LoParkour.getInFolder("schematics"); private static final File FOLDER = LoParkour.getInFolder("schematics");
public static void init() { public static void init() {

View file

@ -18,6 +18,9 @@ import java.util.UUID;
*/ */
public class Storage { public class Storage {
private Storage() {
}
public static void init(String mode) { public static void init(String mode) {
if (Option.SQL) { if (Option.SQL) {
StorageSQL.init(mode); StorageSQL.init(mode);

View file

@ -22,6 +22,9 @@ import java.util.UUID;
*/ */
public class StorageDisk { public class StorageDisk {
private StorageDisk() {
}
public static @NotNull Map<UUID, Score> readScores(@NotNull String mode) { public static @NotNull Map<UUID, Score> readScores(@NotNull String mode) {
File file = getLeaderboardFile(mode); File file = getLeaderboardFile(mode);
@ -43,7 +46,8 @@ public class StorageDisk {
return scores; return scores;
} catch (IOException ex) { } catch (IOException ex) {
LoParkour.getPlugin().getLogger().severe("Error while trying to read leaderboard file %s".formatted(mode) + " - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while trying to read leaderboard file %s".formatted(mode) + " - " + ex.getMessage());
return new HashMap<>(); return new HashMap<>();
} }
} }
@ -82,7 +86,8 @@ public class StorageDisk {
ParkourPlayer from = LoParkour.getGson().fromJson(reader, ParkourPlayer.class); ParkourPlayer from = LoParkour.getGson().fromJson(reader, ParkourPlayer.class);
if (from == null) { if (from == null) {
LoParkour.getPlugin().getLogger().warning("Player data file for %s is empty or corrupted, using defaults".formatted(player.getName())); LoParkour.getPlugin().getLogger().warning(
"Player data file for %s is empty or corrupted, using defaults".formatted(player.getName()));
player.setSettings(new HashMap<>()); player.setSettings(new HashMap<>());
return; return;
} }
@ -99,7 +104,7 @@ public class StorageDisk {
settings.put("collectedRewards", from.collectedRewards); settings.put("collectedRewards", from.collectedRewards);
// Sanitize legacy Boolean locale values // Sanitize legacy Boolean locale values
String locale = from._locale; String locale = from.locale;
if (locale == null || "true".equals(locale) || "false".equals(locale) || "1".equals(locale) || "0".equals(locale)) { if (locale == null || "true".equals(locale) || "false".equals(locale) || "1".equals(locale) || "0".equals(locale)) {
locale = "en"; locale = "en";
} }
@ -109,7 +114,8 @@ public class StorageDisk {
player.setSettings(settings); player.setSettings(settings);
} catch (IOException ex) { } catch (IOException ex) {
LoParkour.getPlugin().getLogger().severe("Error while trying to read disk data of %s".formatted(player.getName()) + " - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while trying to read disk data of %s".formatted(player.getName()) + " - " + ex.getMessage());
} }
} }
@ -122,7 +128,9 @@ public class StorageDisk {
LoParkour.getGson().toJson(player, writer); LoParkour.getGson().toJson(player, writer);
writer.flush(); writer.flush();
} catch (IOException ex) { } catch (IOException ex) {
LoParkour.getPlugin().getLogger().severe("Error while trying to write disk data of %s to file %s".formatted(player.getName(), file) + " - " + ex.getMessage()); LoParkour.getPlugin().getLogger().severe(
"Error while trying to write disk data of %s to file %s".formatted(player.getName(), file)
+ " - " + ex.getMessage());
} }
} }

View file

@ -17,6 +17,9 @@ import java.util.UUID;
*/ */
public class SQLDataMapper { public class SQLDataMapper {
private SQLDataMapper() {
}
/** /**
* Map ResultSet to Score objects. * Map ResultSet to Score objects.
*/ */

View file

@ -7,6 +7,9 @@ import org.jetbrains.annotations.NotNull;
*/ */
public class SQLQueryBuilder { public class SQLQueryBuilder {
private SQLQueryBuilder() {
}
/** /**
* Build CREATE TABLE query for scores. * Build CREATE TABLE query for scores.
*/ */

View file

@ -42,7 +42,9 @@ class SQLQueryExecutor {
connectionManager.validateConnection(); connectionManager.validateConnection();
try (Connection conn = connectionManager.getConnection(); try (Connection conn = connectionManager.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) { PreparedStatement stmt = conn.prepareStatement(sql)) {
if (stmt != null) stmt.executeUpdate(); if (stmt != null) {
stmt.executeUpdate();
}
} catch (SQLException ex) { } catch (SQLException ex) {
if (!suppressErrors) { if (!suppressErrors) {
LoParkour.getPlugin().getLogger().severe( LoParkour.getPlugin().getLogger().severe(
@ -62,7 +64,9 @@ class SQLQueryExecutor {
connectionManager.validateConnection(); connectionManager.validateConnection();
try (Connection conn = connectionManager.getConnection(); try (Connection conn = connectionManager.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) { PreparedStatement stmt = conn.prepareStatement(sql)) {
if (stmt == null) return; if (stmt == null) {
return;
}
bindParams(stmt, params); bindParams(stmt, params);
stmt.executeUpdate(); stmt.executeUpdate();
} catch (SQLException ex) { } catch (SQLException ex) {

View file

@ -18,7 +18,10 @@ import java.util.logging.Logger;
*/ */
public class StorageSQL { public class StorageSQL {
private static final Logger logger = Logger.getLogger(StorageSQL.class.getName()); private StorageSQL() {
}
private static final Logger LOGGER = Logger.getLogger(StorageSQL.class.getName());
private static SQLConnectionManager connectionManager; private static SQLConnectionManager connectionManager;
/** /**
@ -43,7 +46,7 @@ public class StorageSQL {
if (isConnected()) { if (isConnected()) {
callback.run(); callback.run();
} else { } else {
logger.warning("Database not connected, skipping operation"); LOGGER.warning("Database not connected, skipping operation");
} }
} }
@ -67,9 +70,9 @@ public class StorageSQL {
createTables(mode); createTables(mode);
logger.info("Database initialized successfully for mode: " + mode); LOGGER.info("Database initialized successfully for mode: " + mode);
} catch (SQLException e) { } catch (SQLException e) {
logger.severe("Failed to initialize database: " + e.getMessage()); LOGGER.severe("Failed to initialize database: " + e.getMessage());
} }
} }
@ -92,7 +95,7 @@ public class StorageSQL {
return SQLDataMapper.mapScores(rs); return SQLDataMapper.mapScores(rs);
} catch (SQLException e) { } catch (SQLException e) {
logger.severe("Failed to read scores for mode " + mode + ": " + e.getMessage()); LOGGER.severe("Failed to read scores for mode " + mode + ": " + e.getMessage());
return Map.of(); return Map.of();
} }
} }
@ -117,10 +120,10 @@ public class StorageSQL {
} }
stmt.executeBatch(); stmt.executeBatch();
logger.info("Wrote " + scores.size() + " scores for mode: " + mode); LOGGER.info("Wrote " + scores.size() + " scores for mode: " + mode);
} catch (SQLException e) { } catch (SQLException e) {
logger.severe("Failed to write scores for mode " + mode + ": " + e.getMessage()); LOGGER.severe("Failed to write scores for mode " + mode + ": " + e.getMessage());
} }
} }
@ -147,7 +150,7 @@ public class StorageSQL {
} }
} catch (SQLException e) { } catch (SQLException e) {
logger.severe("Failed to read player data: " + e.getMessage()); LOGGER.severe("Failed to read player data: " + e.getMessage());
} }
} }
@ -168,7 +171,7 @@ public class StorageSQL {
stmt.executeUpdate(); stmt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
logger.severe("Failed to write player data: " + e.getMessage()); LOGGER.severe("Failed to write player data: " + e.getMessage());
} }
} }

View file

@ -94,6 +94,7 @@ public class Item {
} }
@Override @Override
@SuppressWarnings("NoClone")
public Item clone() { public Item clone() {
Item cloned = new Item(item.getType(), ""); Item cloned = new Item(item.getType(), "");
cloned.item.setItemMeta(item.getItemMeta()); cloned.item.setItemMeta(item.getItemMeta());

View file

@ -9,6 +9,9 @@ import java.util.concurrent.ThreadLocalRandom;
*/ */
public class Probs { public class Probs {
private Probs() {
}
/** /**
* Selects a random key from a map based on weighted probabilities * Selects a random key from a map based on weighted probabilities
* *

View file

@ -8,6 +8,9 @@ import org.bukkit.inventory.meta.SkullMeta;
*/ */
public class SkullSetter { public class SkullSetter {
private SkullSetter() {
}
public static void setPlayerHead(OfflinePlayer player, SkullMeta meta) { public static void setPlayerHead(OfflinePlayer player, SkullMeta meta) {
if (meta != null && player != null) { if (meta != null && player != null) {
meta.setOwningPlayer(player); meta.setOwningPlayer(player);

View file

@ -1,7 +1,5 @@
package dev.loki.loparkour.util.particle; package dev.loki.loparkour.util.particle;
import dev.loki.loparkour.util.particle.ParticleData;
import org.bukkit.Particle; import org.bukkit.Particle;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View file

@ -12,6 +12,9 @@ import org.bukkit.util.BoundingBox;
*/ */
public class ParticleUtil { public class ParticleUtil {
private ParticleUtil() {
}
/** /**
* Shows a box outline with particles * Shows a box outline with particles
* *
@ -89,7 +92,9 @@ public class ParticleUtil {
* @param points Number of points * @param points Number of points
*/ */
public static void circle(Location center, Particle particle, int radius, int points) { public static void circle(Location center, Particle particle, int radius, int points) {
if (center.getWorld() == null) return; if (center.getWorld() == null) {
return;
}
for (int i = 0; i < points; i++) { for (int i = 0; i < points; i++) {
double angle = 2 * Math.PI * i / points; double angle = 2 * Math.PI * i / points;

View file

@ -12,6 +12,9 @@ import java.util.regex.Pattern;
*/ */
public class ColorUtil { public class ColorUtil {
private ColorUtil() {
}
private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})"); private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})");
/** Legacy fallback for old strings; do not use in new code. */ /** Legacy fallback for old strings; do not use in new code. */
private static final Pattern MINIMESSAGE_HEX_PATTERN = Pattern.compile("<#([A-Fa-f0-9]{6})>"); private static final Pattern MINIMESSAGE_HEX_PATTERN = Pattern.compile("<#([A-Fa-f0-9]{6})>");

View file

@ -7,6 +7,9 @@ import org.bukkit.Location;
*/ */
public class Locations { public class Locations {
private Locations() {
}
/** /**
* Gets the maximum location from two locations (highest x, y, z) * Gets the maximum location from two locations (highest x, y, z)
* *

View file

@ -17,6 +17,9 @@ import java.util.stream.IntStream;
*/ */
public class Divider { public class Divider {
private Divider() {
}
/** /**
* Map with all session ids map to the session instances. * Map with all session ids map to the session instances.
*/ */

View file

@ -3,7 +3,11 @@ package dev.loki.loparkour.world.core;
import dev.loki.loparkour.LoParkour; import dev.loki.loparkour.LoParkour;
import dev.loki.loparkour.config.core.Config; import dev.loki.loparkour.config.core.Config;
import dev.lolib.worlds.VoidGenerator; import dev.lolib.worlds.VoidGenerator;
import org.bukkit.*; import org.bukkit.Bukkit;
import org.bukkit.Difficulty;
import org.bukkit.GameRule;
import org.bukkit.WorldCreator;
import org.bukkit.WorldType;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -14,6 +18,9 @@ import java.util.stream.Stream;
public class World { public class World {
private World() {
}
private static String name; private static String name;
private static org.bukkit.World world; private static org.bukkit.World world;
@ -35,7 +42,9 @@ public class World {
} }
if (world != null) { if (world != null) {
LoParkour.getPlugin().getLogger().warning("Crash detected! The parkour world loading twice is not usual behaviour. This only happens after a server crash."); LoParkour.getPlugin().getLogger().warning(
"Crash detected! The parkour world loading twice is not usual behaviour. " +
"This only happens after a server crash.");
World.world = world; // ensure static field is populated World.world = world; // ensure static field is populated
} }