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

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

View file

@ -11,7 +11,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
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;
// Configuration keys
@ -39,12 +39,12 @@ public class AdaptiveConfig {
return;
}
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_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_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_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_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_CONFIDENCE_THRESHOLD, configDouble(KEY_CONFIDENCE_THRESHOLD, DEFAULT_CONFIDENCE_THRESHOLD));
CACHE.put(KEY_NEAR_MISS_DISTANCE, configDouble(KEY_NEAR_MISS_DISTANCE, DEFAULT_NEAR_MISS_DISTANCE));
initialized = true;
}
@ -55,7 +55,7 @@ public class AdaptiveConfig {
*/
public static void reload() {
initialized = false;
cache.clear();
CACHE.clear();
init();
}
@ -66,7 +66,7 @@ public class AdaptiveConfig {
*/
public static boolean isEnabled() {
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() {
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() {
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() {
ensureInitialized();
Object value = cache.get(KEY_RATING_WEIGHT);
Object value = CACHE.get(KEY_RATING_WEIGHT);
if (value instanceof Double) {
return (double) value;
}
@ -110,7 +110,7 @@ public class AdaptiveConfig {
*/
public static double getConfidenceThreshold() {
ensureInitialized();
Object value = cache.get(KEY_CONFIDENCE_THRESHOLD);
Object value = CACHE.get(KEY_CONFIDENCE_THRESHOLD);
if (value instanceof Double) {
return (double) value;
}
@ -124,7 +124,7 @@ public class AdaptiveConfig {
*/
public static double getNearMissDistance() {
ensureInitialized();
Object value = cache.get(KEY_NEAR_MISS_DISTANCE);
Object value = CACHE.get(KEY_NEAR_MISS_DISTANCE);
if (value instanceof Double) {
return (double) value;
}
@ -152,7 +152,7 @@ public class AdaptiveConfig {
public static <T> T get(@NotNull String key, @NotNull T defaultValue) {
ensureInitialized();
@SuppressWarnings("unchecked")
T value = (T) cache.get(key);
T value = (T) CACHE.get(key);
return value != null ? value : defaultValue;
}
}

View file

@ -16,8 +16,11 @@ import java.util.List;
*/
public final class Registry {
private static final LinkedList<Mode> modes = new LinkedList<>();
private static final LinkedList<Style> styles = new LinkedList<>();
private Registry() {
}
private static final LinkedList<Mode> MODES = new LinkedList<>();
private static final LinkedList<Style> STYLES = new LinkedList<>();
/**
* Registers a {@link Mode}.
@ -25,11 +28,11 @@ public final class Registry {
* @param mode The mode.
*/
public static void register(@NotNull Mode mode) {
modes.add(mode);
MODES.add(mode);
}
public static void register(@NotNull Style style) {
styles.add(style);
STYLES.add(style);
}
/**
@ -38,7 +41,7 @@ public final class Registry {
*/
@Nullable
public static Mode getMode(@NotNull String name) {
return modes.stream()
return MODES.stream()
.filter(mode -> mode.getName().equals(name))
.findFirst()
.orElse(null);
@ -46,17 +49,17 @@ public final class Registry {
@Nullable
public static Style getStyle(@NotNull String name) {
return styles.stream()
return STYLES.stream()
.filter(style -> style.getName().equals(name))
.findFirst()
.orElse(null);
}
public static List<Style> getStyles() {
return styles;
return STYLES;
}
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.SingleLineChart;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* 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);
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);
return;
}
@ -98,17 +102,23 @@ public class LoParkourCommand implements CommandExecutor, TabCompleter {
}
SchematicCommandHandler.handleSubcommand(a2, sender, p, player);
}
default -> {
}
}
}
// ── 3-arg routing ──────────────────────────────────────────────────────────
private void handle3(String a1, String a2, String a3, CommandSender sender, @Nullable Player p) {
if (p == null) return;
if (!p.hasPermission(ParkourOption.ADMIN.permission)) return;
if (p == null) {
return;
}
if (!p.hasPermission(ParkourOption.ADMIN.permission)) {
return;
}
if (a1.equalsIgnoreCase("schematic")) {
if (a2.equalsIgnoreCase("create")) {
if ("schematic".equalsIgnoreCase(a1)) {
if ("create".equalsIgnoreCase(a2)) {
SchematicCommandHandler.handleCreateDifficultyOnly(a3, sender, p, player);
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) {
if (p == null) return;
if (!p.hasPermission(ParkourOption.ADMIN.permission)) return;
if (!a1.equalsIgnoreCase("schematic") || !a2.equalsIgnoreCase("create")) return;
if (p == null) {
return;
}
if (!p.hasPermission(ParkourOption.ADMIN.permission)) {
return;
}
if (!"schematic".equalsIgnoreCase(a1) || !"create".equalsIgnoreCase(a2)) {
return;
}
SchematicCommandHandler.handleCreateWithDifficulty(a3, a4, sender, p, player);
}
// ── join logic ─────────────────────────────────────────────────────────────
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);
if (mode != null) { mode.create(p); return; }
if (mode != null) {
mode.create(p);
return;
}
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);
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);
Session session = pp.session;
if (user != null && user.session == session) return;
if (user != null && user.session == session) {
return;
}
if (session.isAcceptingPlayers()) {
Mode sessionMode = session.generator.getMode();

View file

@ -38,18 +38,24 @@ public class AdminCommandHandler {
public void handle(@NotNull String arg1, @NotNull String arg2,
@NotNull CommandSender sender, @Nullable Player player) {
if (!sender.hasPermission(ParkourOption.ADMIN.permission)) return;
if (!sender.hasPermission(ParkourOption.ADMIN.permission)) {
return;
}
switch (arg1.toLowerCase()) {
case "forcejoin" -> handleForceJoin(arg2, sender);
case "forceleave" -> handleForceLeave(arg2, sender);
case "reset" -> handleReset(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);
}
}
@ -57,52 +63,72 @@ public class AdminCommandHandler {
// ── forcejoin ──────────────────────────────────────────────────────────────
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));
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_join_everyone"));
return;
}
if (target.equalsIgnoreCase("nearest")) {
if ("nearest".equalsIgnoreCase(target)) {
Player closest = findNearest(sender);
if (closest == null) return;
if (closest == null) {
return;
}
Modes.DEFAULT.create(closest);
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_join_player").formatted(closest.getName()));
return;
}
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);
}
// ── forceleave ─────────────────────────────────────────────────────────────
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);
send(sender, LoParkour.PREFIX + Locales.getString(sender, "admin.force_leave_everyone"));
return;
}
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);
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);
}
// ── reset ──────────────────────────────────────────────────────────────────
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()
.map(Mode::getLeaderboard)
.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"));
return;
}
@ -113,7 +139,10 @@ public class AdminCommandHandler {
Registry.getModes().stream()
.map(Mode::getLeaderboard)
.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));
}
@ -121,9 +150,14 @@ public class AdminCommandHandler {
// ── recoverinventory ───────────────────────────────────────────────────────
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);
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 -> {
if (result != null) {
@ -140,7 +174,9 @@ public class AdminCommandHandler {
Location from = sender instanceof Player p ? p.getLocation()
: sender instanceof BlockCommandSender b ? b.getBlock().getLocation()
: null;
if (from == null || from.getWorld() == null) return null;
if (from == null || from.getWorld() == null) {
return null;
}
return from.getWorld().getPlayers().stream()
.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)
private UUID resolveUUID(String input) {
Player online = Bukkit.getPlayerExact(input);
if (online != null) return online.getUniqueId();
if (online != null) {
return online.getUniqueId();
}
if (input.contains("-")) {
try {
return UUID.fromString(input);
@ -163,7 +201,9 @@ public class AdminCommandHandler {
private String resolvePlayerName(String input, UUID uuid) {
Player online = Bukkit.getPlayerExact(input);
if (online != null) return online.getName();
if (online != null) {
return online.getName();
}
OfflinePlayer op = Bukkit.getOfflinePlayer(uuid);
return op.getName() != null ? op.getName() : input;
}

View file

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

View file

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

View file

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

View file

@ -17,6 +17,9 @@ import java.util.logging.Logger;
*/
public class ConfigLoader {
private ConfigLoader() {
}
@NotNull
public static FileConfiguration loadConfig(@NotNull File 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.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.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;
/**
@ -80,14 +91,19 @@ public class ConfigUpdater {
}
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 after = trimmed.substring(colon + 1).trim();
int indent = indentOf(line);
while (prevIndent >= 0 && indent <= prevIndent) {
if (!stack.isEmpty()) stack.pop();
if (!stack.isEmpty()) {
stack.pop();
}
prevIndent -= 2;
}
@ -120,17 +136,23 @@ public class ConfigUpdater {
for (String line : lines) {
String trimmed = line.trim();
if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith("-")) continue;
if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith("-")) {
continue;
}
int colon = trimmed.indexOf(':');
if (colon == -1) continue;
if (colon == -1) {
continue;
}
String leaf = trimmed.substring(0, colon).trim();
String after = trimmed.substring(colon + 1).trim();
int indent = indentOf(line);
while (prevIndent >= 0 && indent <= prevIndent) {
if (!stack.isEmpty()) stack.pop();
if (!stack.isEmpty()) {
stack.pop();
}
prevIndent -= 2;
}
@ -150,7 +172,9 @@ public class ConfigUpdater {
private static int indentOf(@NotNull String line) {
int i = 0;
while (i < line.length() && line.charAt(i) == ' ') i++;
while (i < line.length() && line.charAt(i) == ' ') {
i++;
}
return i;
}
@ -181,16 +205,22 @@ public class ConfigUpdater {
@NotNull
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<>();
for (String k : keys) s.add(k.trim().toLowerCase());
for (String k : keys) {
s.add(k.trim().toLowerCase());
}
return s;
}
private static boolean isIgnored(@NotNull String fullPath, @NotNull Set<String> ignored) {
String lower = fullPath.toLowerCase();
for (String ign : ignored) {
if (lower.equals(ign) || lower.startsWith(ign + ".")) return true;
if (lower.equals(ign) || lower.startsWith(ign + ".")) {
return true;
}
}
return false;
}

View file

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

View file

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

View file

@ -13,7 +13,10 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
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.Pattern;
@ -23,14 +26,14 @@ import java.util.regex.Pattern;
*/
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]");
// ── Initialization ────────────────────────────────────────────────────────
public static void init() {
Map<String, FileConfiguration> loaded = LocaleLoader.loadAll();
cache.setLocales(loaded);
CACHE.setLocales(loaded);
dev.loki.loparkour.command.schematic.SchematicCommandHandler.clearWandCache();
LoParkour.log("Locales loaded successfully (" + loaded.size() + " locales)");
}
@ -61,7 +64,7 @@ public class Locales {
@NotNull
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
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() {
return cache.getLocaleCount();
return CACHE.getLocaleCount();
}
@NotNull
public static Set<String> getLocaleKeys() {
return cache.getLocaleKeys();
return CACHE.getLocaleKeys();
}
@NotNull
@ -103,14 +106,14 @@ public class Locales {
@NotNull
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);
return new Item(Material.STONE, "");
}
FileConfiguration config = cache.getLocale(locale);
FileConfiguration config = CACHE.getLocale(locale);
if (config == null) {
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 buildItem(config, path, replace);
@ -147,7 +150,9 @@ public class Locales {
@NotNull
private static String applyReplacements(@NotNull String text, String... replacements) {
if (replacements.length == 0) return text;
if (replacements.length == 0) {
return text;
}
String result = text;
int idx = 0;
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.config.core.Config;
import dev.loki.loparkour.config.options.*;
import dev.loki.loparkour.menu.core.ParkourOption;
import dev.loki.loparkour.style.core.RandomStyle;
import dev.loki.loparkour.style.core.Style;
@ -61,17 +60,34 @@ public class Option {
public static ParticleData<?> PARTICLE_DATA;
// Generation
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS;
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE;
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4;
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2;
public static int MAX_Y, MIN_Y;
public static int BLOCK_CLEANUP_DISTANCE, CLEANUP_INTERVAL, TRAIL_KEEP_BEHIND;
public static double TYPE_NORMAL;
public static double TYPE_SPECIAL;
public static double TYPE_SCHEMATICS;
public static double SPECIAL_ICE;
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;
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 int GHOST_SHOW_TOP;
public static double GHOST_TRANSPARENCY;
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 Map<String, Boolean> JUMP_TYPE_ENABLED;
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.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).
@ -125,7 +129,9 @@ public class OptionGeneral {
throw new IllegalArgumentException("Expected 4 values (x,y,z,world), got " + values.length);
}
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]),
Double.parseDouble(values[1]), Double.parseDouble(values[2]));
} catch (Exception ex) {

View file

@ -12,11 +12,23 @@ import java.util.Map;
public class OptionGeneration {
// ── Block generation probabilities ────────────────────────────────────────
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS;
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE;
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4;
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2;
public static int MAX_Y, MIN_Y;
public static double TYPE_NORMAL;
public static double TYPE_SPECIAL;
public static double TYPE_SCHEMATICS;
public static double SPECIAL_ICE;
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 ──────────────────────────────────────────────────────
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.config.core.Config;
import dev.loki.loparkour.config.options.Option;
import dev.loki.loparkour.util.particle.ParticleData;
import org.bukkit.Particle;
import org.bukkit.Sound;

View file

@ -127,7 +127,9 @@ public class ParkourGenerator {
/** Last generated block, or {@code null} if history is empty. */
public @Nullable Block getLatest() {
if (state.history.isEmpty()) return null;
if (state.history.isEmpty()) {
return null;
}
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 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.

View file

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

View file

@ -25,7 +25,9 @@ public class EffectManager {
* Spawns particles around the given blocks based on the configured shape.
*/
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();
Location max = locations.stream().reduce((a, b) -> {
@ -41,7 +43,9 @@ public class EffectManager {
return new Location(a.getWorld(), x, y, z);
}).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();
@ -64,6 +68,7 @@ public class EffectManager {
org.bukkit.util.BoundingBox.of(min, max), max.getWorld(), Option.PARTICLE_TYPE,
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.
*/
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();
generator.getPlayers().forEach(p ->

View file

@ -51,7 +51,9 @@ public class JumpCalculator {
height = Math.max(-2, Math.min(2, height));
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
Vector offset = calculateJumpOffset(distance, height);

View file

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

View file

@ -79,7 +79,9 @@ public class BlockSelector {
public Material getSlabMaterialFromCurrentStyle() {
try {
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
for (int i = 0; i < 20; i++) {

View file

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

View file

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

View file

@ -1,5 +1,4 @@
package dev.loki.loparkour.ghost.core;
import dev.loki.loparkour.ghost.core.GhostPlayer;
import dev.loki.loparkour.ghost.model.GhostData;
import dev.loki.loparkour.LoParkour;
@ -11,7 +10,12 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
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.
@ -46,10 +50,14 @@ public class GhostManager {
public void loadGhosts(@NotNull String 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"));
if (files == null) return;
if (files == null) {
return;
}
List<GhostData> ghosts = new ArrayList<>();
for (File file : files) {
@ -77,7 +85,9 @@ public class GhostManager {
public void saveGhost(@NotNull String mode, @NotNull GhostData data) {
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<>()));
ghosts.add(data);
@ -88,7 +98,9 @@ public class GhostManager {
GhostData evicted = ghosts.remove(ghosts.size() - 1);
// File is named by UUID — always finds the right file regardless of name changes
File evictedFile = ghostFile(modeFolder, evicted);
if (evictedFile.exists()) evictedFile.delete();
if (evictedFile.exists()) {
evictedFile.delete();
}
}
ghostsByMode.put(mode, ghosts);
@ -107,12 +119,16 @@ public class GhostManager {
public void spawnGhosts(@NotNull String mode, @NotNull Location startLocation,
@NotNull World world) {
if (!Config.CONFIG.getBoolean("ghost-mode.enabled")) return;
if (!Config.CONFIG.getBoolean("ghost-mode.enabled")) {
return;
}
stopAllGhosts();
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());
for (int i = 0; i < showTop; i++) {
@ -137,13 +153,17 @@ public class GhostManager {
public List<GhostData> getTopGhosts(@NotNull String mode, int count) {
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())));
}
public boolean shouldRecordGhost(@NotNull String mode, int score) {
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();
}

View file

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

View file

@ -36,8 +36,12 @@ public class GhostRecorder {
}
public void recordFrame(@NotNull Location currentLocation) {
if (!recording) return;
if (lastLocation.distance(currentLocation) < MIN_MOVEMENT) return;
if (!recording) {
return;
}
if (lastLocation.distance(currentLocation) < MIN_MOVEMENT) {
return;
}
long timestamp = System.currentTimeMillis() - startTime;
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 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.List;
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.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.

View file

@ -3,7 +3,11 @@ import dev.loki.loparkour.leaderboard.model.Score;
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.
@ -60,9 +64,15 @@ public class LeaderboardSorter {
String diff2 = two.getValue().difficulty();
// Handle "?" as lowest difficulty
if ("?".equals(diff1) && "?".equals(diff2)) return 0;
if ("?".equals(diff1)) return 1;
if ("?".equals(diff2)) return -1;
if ("?".equals(diff1) && "?".equals(diff2)) {
return 0;
}
if ("?".equals(diff1)) {
return 1;
}
if ("?".equals(diff2)) {
return -1;
}
try {
return (int) Math.signum(Double.parseDouble(diff2) - Double.parseDouble(diff1));

View file

@ -1,7 +1,6 @@
package dev.loki.loparkour.leaderboard.persistence;
import dev.loki.loparkour.leaderboard.model.Score;
import dev.loki.loparkour.leaderboard.core.LeaderboardSorter;
import dev.loki.loparkour.leaderboard.core.Leaderboard;
import dev.loki.loparkour.LoParkour;
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.inventory.InventoryClickEvent;
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.PlayerInventory;
@ -30,31 +34,45 @@ public class ParkourRestrictionListener implements Listener {
@EventHandler
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();
ParkourUser user = ParkourUser.getUser(player);
if (user == null) return;
if (user == null) {
return;
}
Session session = user.session;
if (session.isMuted(user)) return;
if (session.isMuted(user)) {
return;
}
event.setCancelled(true);
switch (user.chatType) {
case LOBBY_ONLY -> session.getUsers().forEach(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);
case LOBBY_ONLY -> session.getUsers().forEach(
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);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
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());
if (user == null) return;
if (user == null) {
return;
}
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");
event.setCancelled(true);
@ -64,7 +82,9 @@ public class ParkourRestrictionListener implements Listener {
public void onInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
ParkourPlayer pp = ParkourPlayer.getPlayer(player);
if (pp == null) return;
if (pp == null) {
return;
}
// Block container right-click
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
|| event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)
&& event.getHand() == org.bukkit.inventory.EquipmentSlot.HAND;
if (!isRightClick) return;
if (!isRightClick) {
return;
}
ItemStack held = heldItem(player);
event.setCancelled(true);
if (matchesLocaleHotbar(player, "play.item", held)) Menus.PLAY.open(player);
else if (matchesLocaleHotbar(player, "community.item", held)) Menus.COMMUNITY.open(player);
else if (matchesLocaleHotbar(player, "settings.item", held)) 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);
if (matchesLocaleHotbar(player, "play.item", held)) {
Menus.PLAY.open(player);
} else if (matchesLocaleHotbar(player, "community.item", held)) {
Menus.COMMUNITY.open(player);
} else if (matchesLocaleHotbar(player, "settings.item", held)) {
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)
public void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player player)) return;
if (event.getInventory().getType() == InventoryType.CHEST) return; // LoLib GUI
if (event.getInventory().getType() == InventoryType.CRAFTING) return; // own inv
if (!(event.getWhoClicked() instanceof Player player)) {
return;
}
if (event.getInventory().getType() == InventoryType.CHEST) {
return; // LoLib GUI
}
if (event.getInventory().getType() == InventoryType.CRAFTING) {
return; // own inv
}
restrict(player, event);
}
@EventHandler
public void onDrop(PlayerDropItemEvent event) { restrict(event.getPlayer(), event); }
public void onDrop(PlayerDropItemEvent event) {
restrict(event.getPlayer(), event);
}
@EventHandler
public void onPlace(BlockPlaceEvent event) { restrict(event.getPlayer(), event); }
public void onPlace(BlockPlaceEvent event) {
restrict(event.getPlayer(), event);
}
@EventHandler
public void onBreak(BlockBreakEvent event) { restrict(event.getPlayer(), event); }
public void onBreak(BlockBreakEvent event) {
restrict(event.getPlayer(), event);
}
@EventHandler
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)
public void onSpectate(PlayerTeleportEvent event) {
if (event.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE)
if (event.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE) {
restrict(event.getPlayer(), 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) {

View file

@ -34,7 +34,9 @@ public class PlayerConnectionListener implements Listener {
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"));
if (fallback != null) {
@ -52,7 +54,9 @@ public class PlayerConnectionListener implements Listener {
@EventHandler
public void onQuit(PlayerQuitEvent event) {
ParkourUser user = ParkourUser.getUser(event.getPlayer());
if (user == null) return;
if (user == null) {
return;
}
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());
if (op.getName() != null && !op.getName().startsWith(".")) {
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:
* 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.
* 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) {
int[] result = new int[count];
if (count == 0) return result;
if (count == 0) {
return result;
}
for (int i = 0; i < count; i++) {
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.SettingsMenu;
public class Menus {
public final class Menus {
private Menus() {
}
// main
public static MainMenu MAIN = new MainMenu();

View file

@ -45,7 +45,10 @@ public class PlayerManagementMenu extends LPMenu {
if (!ParkourUser.isBedrockPlayer(other.player)
&& other.getName() != null && !other.getName().startsWith(".")) {
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);

View file

@ -45,7 +45,10 @@ public class SpectatorMenu extends LPMenu {
if (!ParkourUser.isBedrockPlayer(player)
&& pp.getName() != null && !pp.getName().startsWith(".")) {
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);
items.add(skull);

View file

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

View file

@ -158,7 +158,10 @@ public class ParkourSettingsMenu extends LPMenu {
ItemStack item = new ItemStack(style.getNext());
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;
gui = gui.setItem(slot++, item, e -> {

View file

@ -1,9 +1,18 @@
package dev.loki.loparkour.mode.base;
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 SpectatorMode SPECTATOR;

View file

@ -93,7 +93,9 @@ public class CoopMode implements MultiMode {
return;
}
if (session.generator == null) return;
if (session.generator == null) {
return;
}
// Register the joining player into the existing session
ParkourPlayer pp = ParkourUser.register(joiningPlayer, session);
@ -132,7 +134,7 @@ public class CoopMode implements MultiMode {
/** Individual block contributions per player UUID. */
private final Map<UUID, Integer> contributions = new HashMap<>();
public CoopGenerator(@NotNull Session session) {
CoopGenerator(@NotNull Session session) {
super(session);
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.mode.base.Mode;
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.player.core.ParkourPlayer;
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.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.
@ -67,7 +72,7 @@ public class GravityShiftMode implements Mode {
private final Random random;
private final Map<UUID, Integer> jumpCounts;
public GravityShiftGenerator(@NotNull Session session) {
GravityShiftGenerator(@NotNull Session session) {
super(session);
this.random = new Random();
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 int particleTick = 0;
public BarrierGenerator(@NotNull Session session) {
BarrierGenerator(@NotNull Session session) {
super(session);
}
@ -114,13 +114,17 @@ public class InvisibleBarrierMode implements Mode {
}
private void convertLastBlockToBarrier() {
if (state.history.isEmpty()) return;
if (state.history.isEmpty()) {
return;
}
convertBlockToBarrier(state.history.get(state.history.size() - 1));
}
private void convertBlockToBarrier(@NotNull Block block) {
Location loc = block.getLocation();
if (block.getType() == Material.BARRIER) return;
if (block.getType() == Material.BARRIER) {
return;
}
block.setType(Material.BARRIER, false);
activeBarriers.add(loc);
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() {
if (activeBarriers.isEmpty()) return;
if (activeBarriers.isEmpty()) {
return;
}
// Self-clean invalid entries
Iterator<Map.Entry<Location, Particle.DustOptions>> it = blockColors.entrySet().iterator();
@ -145,53 +151,70 @@ public class InvisibleBarrierMode implements Mode {
Location playerLoc = player.getLocation();
for (Location loc : activeBarriers) {
if (loc.getWorld() != playerLoc.getWorld()) continue;
if (loc.distanceSquared(playerLoc) > RENDER_DISTANCE * RENDER_DISTANCE) continue;
if (loc.getWorld() != playerLoc.getWorld()) {
continue;
}
if (loc.distanceSquared(playerLoc) > RENDER_DISTANCE * RENDER_DISTANCE) {
continue;
}
Particle.DustOptions options = blockColors.get(loc);
if (options == null) continue;
if (options == null) {
continue;
}
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) {
double x = loc.getX();
double y = loc.getY();
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)
drawEdge(player, x, y, z, x + 1, y, z, options);
drawEdge(player, x + 1, y, z, x + 1, y, z + 1, options);
drawEdge(player, x + 1, y, z + 1, x, y, z + 1, options);
drawEdge(player, x, y, z + 1, x, y, z, options);
drawEdge(player, p, q, options);
drawEdge(player, q, r, options);
drawEdge(player, r, s, options);
drawEdge(player, s, p, options);
// Top edges (y offset = 1)
drawEdge(player, x, y + 1, z, x + 1, y + 1, z, options);
drawEdge(player, x + 1, y + 1, z, x + 1, y + 1, z + 1, options);
drawEdge(player, x + 1, y + 1, z + 1, x, y + 1, z + 1, options);
drawEdge(player, x, y + 1, z + 1, x, y + 1, z, options);
Point pt = new Point(x, y + 1, z);
Point qt = new Point(x + 1, y + 1, z);
Point rt = new Point(x + 1, y + 1, z + 1);
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
drawEdge(player, x, y, z, x, y + 1, z, options);
drawEdge(player, x + 1, y, z, x + 1, y + 1, z, options);
drawEdge(player, x + 1, y, z + 1, x + 1, y + 1, z + 1, options);
drawEdge(player, x, y, z + 1, x, y + 1, z + 1, options);
drawEdge(player, p, pt, options);
drawEdge(player, q, qt, options);
drawEdge(player, r, rt, 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) {
double dx = x2 - x1;
double dy = y2 - y1;
double dz = z2 - z1;
private void drawEdge(@NotNull Player player, @NotNull Point start, @NotNull Point end,
@NotNull Particle.DustOptions options) {
double dx = end.x - start.x;
double dy = end.y - start.y;
double dz = end.z - start.z;
double length = Math.sqrt(dx * dx + dy * dy + dz * dz);
int steps = Math.max(1, (int) (length / PARTICLE_STEP));
for (int i = 0; i <= steps; i++) {
double t = (double) i / steps;
double px = x1 + dx * t;
double py = y1 + dy * t;
double pz = z1 + dz * t;
double px = start.x + dx * t;
double py = start.y + dy * t;
double pz = start.z + dz * t;
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 boolean raceFinished = false;
public RaceGenerator(@NotNull Session session) {
RaceGenerator(@NotNull Session session) {
super(session);
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.Mode;
import dev.loki.loparkour.config.core.Config;
import dev.loki.loparkour.config.locale.Locales;
import dev.loki.loparkour.leaderboard.core.Leaderboard;
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]. */
private final Map<Block, ScheduledTask[]> scheduledTasks = new HashMap<>();
public SpeedrunGenerator(@NotNull Session session) {
SpeedrunGenerator(@NotNull Session 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
// (history.size()-1 is the leading block, size()-2 is where player stands)
int histSize = state.history.size();
if (histSize < 2) return;
if (histSize < 2) {
return;
}
Block stepped = state.history.get(histSize - 2);
if (stepped.getType() == Material.AIR) return;
if (scheduledTasks.containsKey(stepped)) return; // already scheduled
if (stepped.getType() == Material.AIR) {
return;
}
if (scheduledTasks.containsKey(stepped)) {
return;
}
scheduleBlockRemoval(stepped);
}
@ -144,7 +150,9 @@ public class SpeedrunMode implements Mode {
// Cancel every pending warning and removal task
scheduledTasks.values().forEach(tasks -> {
for (ScheduledTask t : tasks) {
if (t != null) t.cancel();
if (t != null) {
t.cancel();
}
}
});
scheduledTasks.clear();

View file

@ -3,11 +3,9 @@ package dev.loki.loparkour.player.core;
import com.google.gson.annotations.Expose;
import dev.loki.loparkour.LoParkour;
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.model.Profile;
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.player.data.PreviousData;
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.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;
/**
@ -48,7 +49,7 @@ public class ParkourPlayer extends ParkourUser {
public @Expose Boolean showScoreboard;
public @Expose Integer selectedTime;
public @Expose String style;
public @Expose String _locale;
public @Expose String locale;
public @Expose List<String> collectedRewards;
/**
* 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) {
super(player, session, previousData);
this._locale = locale;
// generic player settings
player.setFlying(false);
player.setAllowFlight(false);

View file

@ -1,7 +1,6 @@
package dev.loki.loparkour.player.core;
import dev.loki.loparkour.player.service.UserRegistry;
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.options.Option;
@ -112,9 +111,17 @@ public abstract class ParkourUser {
}
}
public UUID getUUID() { return player.getUniqueId(); }
public Location getLocation() { return player.getLocation(); }
public String getName() { return player.getName(); }
public UUID getUUID() {
return player.getUniqueId();
}
public Location getLocation() {
return player.getLocation();
}
public String getName() {
return player.getName();
}
public static boolean isBedrockPlayer(Player 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.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.Map;
import java.util.function.Consumer;
@ -95,7 +98,9 @@ public class InventoryData {
items = (Map<Integer, ItemStack>) stream.readObject();
onFinish.accept(this);
} 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);
}
}
@ -132,7 +137,9 @@ public class InventoryData {
file.getParentFile().mkdirs();
file.createNewFile();
} 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 {
@ -143,7 +150,9 @@ public class InventoryData {
}
yaml.save(file);
} 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) {
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));
else {
} else {
player.teleport(to);
apply(player);

View file

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

View file

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

View file

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

View file

@ -1,5 +1,4 @@
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.ParkourPlayer;
@ -25,7 +24,10 @@ import java.util.stream.Collectors;
*
* @since 5.0.0
*/
public class UserRegistry {
public final class UserRegistry {
private UserRegistry() {
}
private static int joinCount = 0;

View file

@ -61,7 +61,8 @@ public class ParkourSpectator extends ParkourUser {
}
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);
}, 1, 10);
}
@ -71,7 +72,8 @@ public class ParkourSpectator extends ParkourUser {
*/
@SuppressWarnings("deprecation") // Spigot Chat API: action bar via TextComponent
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);
updateScoreboard(session.generator);

View file

@ -62,7 +62,9 @@ public record Reward(@NotNull String string) {
try {
VaultHook.deposit(player.player, Double.parseDouble(string));
} 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 {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), string);

View file

@ -12,6 +12,9 @@ import java.util.Map;
*/
public class Rewards {
private Rewards() {
}
public static boolean REWARDS_ENABLED;
/**
@ -71,13 +74,17 @@ public class Rewards {
int value = Integer.parseInt(score);
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;
}
rewardMap.put(value, rewardStrings);
} 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 {
private Schematics() {
}
private static final File FOLDER = LoParkour.getInFolder("schematics");
public static void init() {

View file

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

View file

@ -22,6 +22,9 @@ import java.util.UUID;
*/
public class StorageDisk {
private StorageDisk() {
}
public static @NotNull Map<UUID, Score> readScores(@NotNull String mode) {
File file = getLeaderboardFile(mode);
@ -43,7 +46,8 @@ public class StorageDisk {
return scores;
} 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<>();
}
}
@ -82,7 +86,8 @@ public class StorageDisk {
ParkourPlayer from = LoParkour.getGson().fromJson(reader, ParkourPlayer.class);
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<>());
return;
}
@ -99,7 +104,7 @@ public class StorageDisk {
settings.put("collectedRewards", from.collectedRewards);
// 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)) {
locale = "en";
}
@ -109,7 +114,8 @@ public class StorageDisk {
player.setSettings(settings);
} 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);
writer.flush();
} 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

@ -16,7 +16,10 @@ import java.util.UUID;
* Maps data between Java objects and SQL result sets.
*/
public class SQLDataMapper {
private SQLDataMapper() {
}
/**
* Map ResultSet to Score objects.
*/

View file

@ -6,7 +6,10 @@ import org.jetbrains.annotations.NotNull;
* Builds SQL queries for parkour storage operations.
*/
public class SQLQueryBuilder {
private SQLQueryBuilder() {
}
/**
* Build CREATE TABLE query for scores.
*/

View file

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

View file

@ -17,8 +17,11 @@ import java.util.logging.Logger;
* Coordinates connection management, query building, and data mapping.
*/
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;
/**
@ -43,7 +46,7 @@ public class StorageSQL {
if (isConnected()) {
callback.run();
} else {
logger.warning("Database not connected, skipping operation");
LOGGER.warning("Database not connected, skipping operation");
}
}
@ -67,9 +70,9 @@ public class StorageSQL {
createTables(mode);
logger.info("Database initialized successfully for mode: " + mode);
LOGGER.info("Database initialized successfully for mode: " + mode);
} 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);
} 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();
}
}
@ -117,10 +120,10 @@ public class StorageSQL {
}
stmt.executeBatch();
logger.info("Wrote " + scores.size() + " scores for mode: " + mode);
LOGGER.info("Wrote " + scores.size() + " scores for mode: " + mode);
} 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) {
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();
} 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
@SuppressWarnings("NoClone")
public Item clone() {
Item cloned = new Item(item.getType(), "");
cloned.item.setItemMeta(item.getItemMeta());

View file

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

View file

@ -7,7 +7,10 @@ import org.bukkit.inventory.meta.SkullMeta;
* Utility for setting player heads
*/
public class SkullSetter {
private SkullSetter() {
}
public static void setPlayerHead(OfflinePlayer player, SkullMeta meta) {
if (meta != null && player != null) {
meta.setOwningPlayer(player);

View file

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

View file

@ -12,6 +12,9 @@ import org.bukkit.util.BoundingBox;
*/
public class ParticleUtil {
private ParticleUtil() {
}
/**
* Shows a box outline with particles
*
@ -89,7 +92,9 @@ public class ParticleUtil {
* @param points Number of 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++) {
double angle = 2 * Math.PI * i / points;

View file

@ -12,6 +12,9 @@ import java.util.regex.Pattern;
*/
public class ColorUtil {
private ColorUtil() {
}
private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})");
/** 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})>");

View file

@ -7,6 +7,9 @@ import org.bukkit.Location;
*/
public class Locations {
private Locations() {
}
/**
* 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 {
private Divider() {
}
/**
* 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.config.core.Config;
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.IOException;
@ -14,6 +18,9 @@ import java.util.stream.Stream;
public class World {
private World() {
}
private static String name;
private static org.bukkit.World world;
@ -35,7 +42,9 @@ public class World {
}
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
}