272 lines
9.4 KiB
Java
272 lines
9.4 KiB
Java
package dev.loki.loparkour;
|
|
|
|
import dev.loki.loparkour.api.Registry;
|
|
import dev.loki.loparkour.config.Config;
|
|
import dev.loki.loparkour.config.Locales;
|
|
import dev.loki.loparkour.config.Option;
|
|
import dev.loki.loparkour.hook.HoloHook;
|
|
import dev.loki.loparkour.hook.PAPIHook;
|
|
import dev.loki.loparkour.mode.DefaultMode;
|
|
import dev.loki.loparkour.mode.ElytraMode;
|
|
import dev.loki.loparkour.mode.GravityShiftMode;
|
|
import dev.loki.loparkour.mode.HardcoreMode;
|
|
import dev.loki.loparkour.mode.Modes;
|
|
import dev.loki.loparkour.mode.SpectatorMode;
|
|
import dev.loki.loparkour.mode.SpeedrunMode;
|
|
import dev.loki.loparkour.mode.RaceMode;
|
|
import dev.loki.loparkour.mode.CoopMode;
|
|
import dev.loki.loparkour.player.ParkourUser;
|
|
import dev.loki.loparkour.player.UserRegistry;
|
|
import dev.loki.loparkour.reward.Rewards;
|
|
import dev.loki.loparkour.schematic.lpschem.LPSchematicManager;
|
|
import dev.loki.loparkour.storage.Storage;
|
|
import dev.loki.loparkour.world.World;
|
|
import dev.lolib.core.LoPlugin;
|
|
import dev.lolib.scheduler.Scheduler;
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.GsonBuilder;
|
|
import org.bstats.bukkit.Metrics;
|
|
import org.bstats.charts.SimplePie;
|
|
import org.bstats.charts.SingleLineChart;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Main class of LoParkour
|
|
*
|
|
* @author loki
|
|
*/
|
|
public final class LoParkour extends LoPlugin {
|
|
|
|
public static final String NAME = "&#FF6464<bold>LoParkour<reset>";
|
|
public static final String PREFIX = NAME + " 񢩈» &#A0A0A0";
|
|
|
|
private static final Gson gson = new GsonBuilder()
|
|
.setPrettyPrinting()
|
|
.excludeFieldsWithoutExposeAnnotation()
|
|
.create();
|
|
|
|
public static Gson getGson() {
|
|
return gson;
|
|
}
|
|
private static LoParkour instance;
|
|
private static LPSchematicManager schematicManager;
|
|
|
|
@Nullable
|
|
private static PAPIHook placeholderHook;
|
|
|
|
public static void log(String message) {
|
|
if (Config.CONFIG.getBoolean("debug")) {
|
|
LoParkour.getPlugin().getLogger().info("[Debug] " + message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param child The file name.
|
|
* @return A file from within the plugin folder.
|
|
*/
|
|
public static File getInFolder(String child) {
|
|
return new File(instance.getDataFolder(), child);
|
|
}
|
|
|
|
/**
|
|
* @return This plugin's {@link Logging} instance.
|
|
*/
|
|
|
|
|
|
/**
|
|
* @return The plugin instance.
|
|
*/
|
|
public static LoParkour getPlugin() {
|
|
return instance;
|
|
}
|
|
|
|
@Nullable
|
|
public static PAPIHook getPlaceholderHook() {
|
|
return placeholderHook;
|
|
}
|
|
|
|
public static LPSchematicManager getSchematicManager() {
|
|
return schematicManager;
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
public void enable() {
|
|
instance = this; // must be first — Config enum accesses instance inside reload()
|
|
loadConfigs();
|
|
loadSchematics();
|
|
registerModes();
|
|
registerHooks();
|
|
setupWorld();
|
|
registerEventsAndCommands();
|
|
setupMetrics();
|
|
}
|
|
|
|
private void loadConfigs() {
|
|
Config.reload(true);
|
|
}
|
|
|
|
private void loadSchematics() {
|
|
schematicManager = new LPSchematicManager();
|
|
|
|
// Create default island schematic if it doesn't exist
|
|
File schematicsFolder = getInFolder("schematics-new");
|
|
File islandFile = new File(schematicsFolder, "island.lpschem");
|
|
|
|
if (!islandFile.exists()) {
|
|
try {
|
|
createDefaultIslandSchematic(islandFile);
|
|
getLogger().info("Created default island schematic");
|
|
} catch (Exception ex) {
|
|
getLogger().severe("Failed to create default island schematic: " + ex.getMessage());
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
schematicManager.loadAll();
|
|
}
|
|
|
|
private void createDefaultIslandSchematic(File file) throws Exception {
|
|
// Create a larger 9x5x9 island for better visibility and safety
|
|
List<String> palette = new ArrayList<>();
|
|
palette.add("minecraft:air");
|
|
palette.add("minecraft:stone");
|
|
palette.add("minecraft:diamond_block");
|
|
palette.add("minecraft:emerald_block");
|
|
|
|
int width = 9, height = 5, length = 9;
|
|
int[] blocks = new int[width * height * length];
|
|
|
|
// Fill everything with air first
|
|
for (int i = 0; i < blocks.length; i++) {
|
|
blocks[i] = 0;
|
|
}
|
|
|
|
// Create a solid stone platform at y=1 (7x7 platform)
|
|
for (int z = 1; z < 8; z++) {
|
|
for (int x = 1; x < 8; x++) {
|
|
int index = x + (z * width) + (1 * width * length);
|
|
blocks[index] = 1; // stone
|
|
}
|
|
}
|
|
|
|
// Place diamond block (player spawn) at center
|
|
int centerX = 4, centerZ = 4;
|
|
int diamondIndex = centerX + (centerZ * width) + (1 * width * length);
|
|
blocks[diamondIndex] = 2; // diamond_block - player spawns here
|
|
|
|
// Place emerald block (parkour start) to the right of spawn
|
|
int emeraldIndex = (centerX + 1) + (centerZ * width) + (1 * width * length);
|
|
blocks[emeraldIndex] = 3; // emerald_block - parkour starts here
|
|
|
|
dev.loki.loparkour.schematic.lpschem.SchematicMetadata metadata =
|
|
new dev.loki.loparkour.schematic.lpschem.SchematicMetadata("island", "LoParkour", 0.0);
|
|
metadata.addTag("spawn");
|
|
metadata.addTag("island");
|
|
|
|
dev.loki.loparkour.schematic.lpschem.SchematicDimensions dimensions =
|
|
new dev.loki.loparkour.schematic.lpschem.SchematicDimensions(width, height, length);
|
|
|
|
// Markers point to the blocks where player spawns and parkour begins
|
|
dev.loki.loparkour.schematic.lpschem.SchematicMarkers markers =
|
|
new dev.loki.loparkour.schematic.lpschem.SchematicMarkers(
|
|
new dev.loki.loparkour.schematic.lpschem.SchematicMarkers.Vector3i(centerX, 1, centerZ),
|
|
new dev.loki.loparkour.schematic.lpschem.SchematicMarkers.Vector3i(centerX + 1, 1, centerZ)
|
|
);
|
|
|
|
dev.loki.loparkour.schematic.lpschem.LPSchematic schematic =
|
|
new dev.loki.loparkour.schematic.lpschem.LPSchematic(metadata, dimensions, palette, blocks, markers);
|
|
|
|
schematic.save(file);
|
|
}
|
|
|
|
private void registerModes() {
|
|
Registry.register(new DefaultMode());
|
|
Registry.register(new SpectatorMode());
|
|
Registry.register(new SpeedrunMode());
|
|
Registry.register(new GravityShiftMode());
|
|
Registry.register(new HardcoreMode());
|
|
Registry.register(new ElytraMode());
|
|
Registry.register(new RaceMode());
|
|
Registry.register(new CoopMode());
|
|
Modes.init();
|
|
}
|
|
|
|
private void registerHooks() {
|
|
if (getServer().getPluginManager().isPluginEnabled("HolographicDisplays")) {
|
|
getLogger().info("Registered Holographic Displays hook");
|
|
HoloHook.init();
|
|
}
|
|
if (getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
|
getLogger().info("Registered PlaceholderAPI hook");
|
|
placeholderHook = new PAPIHook();
|
|
placeholderHook.register();
|
|
}
|
|
if (Config.CONFIG.getBoolean("bungeecord.enabled")) {
|
|
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
|
|
getLogger().info("Registered BungeeCord hook");
|
|
}
|
|
}
|
|
|
|
private void setupWorld() {
|
|
if (!Config.CONFIG.getBoolean("joining")) {
|
|
return;
|
|
}
|
|
|
|
// World creation MUST happen on the main thread (Bukkit API requirement)
|
|
try {
|
|
loLogger().info("Creating parkour world...");
|
|
World.create();
|
|
loLogger().info("Parkour world created successfully!");
|
|
} catch (Exception ex) {
|
|
loLogger().error("Failed to create parkour world", ex);
|
|
}
|
|
}
|
|
|
|
private void registerEventsAndCommands() {
|
|
dev.lolib.gui.GUIManager.init(this); // required for LoLib GUI click handling
|
|
|
|
var pm = getServer().getPluginManager();
|
|
pm.registerEvents(new dev.loki.loparkour.listener.PlayerConnectionListener(), this);
|
|
pm.registerEvents(new dev.loki.loparkour.listener.ParkourRestrictionListener(), this);
|
|
pm.registerEvents(new dev.loki.loparkour.listener.SchematicWandListener(), this);
|
|
|
|
LoParkourCommand cmd = new LoParkourCommand();
|
|
getCommand("LoParkour").setExecutor(cmd);
|
|
getCommand("LoParkour").setTabCompleter(cmd);
|
|
}
|
|
|
|
private void setupMetrics() {
|
|
Metrics metrics = new Metrics(this, 29754);
|
|
metrics.addCustomChart(new SimplePie("using_sql", () -> Boolean.toString(Option.SQL)));
|
|
metrics.addCustomChart(new SimplePie("using_rewards", () -> Boolean.toString(Rewards.REWARDS_ENABLED)));
|
|
metrics.addCustomChart(new SimplePie("locale_count", () -> Integer.toString(Locales.locales.size())));
|
|
metrics.addCustomChart(new SingleLineChart("player_joins", () -> {
|
|
int joins = UserRegistry.getJoinCount();
|
|
return joins;
|
|
}));
|
|
}
|
|
|
|
@Override
|
|
public void disable() {
|
|
try {
|
|
for (ParkourUser user : ParkourUser.getUsers()) {
|
|
ParkourUser.leave(user);
|
|
}
|
|
|
|
// write all LoParkour gamemodes
|
|
Modes.DEFAULT.getLeaderboard().write(false);
|
|
|
|
Storage.close();
|
|
World.delete();
|
|
} catch (Throwable ignored) {
|
|
|
|
}
|
|
}
|
|
}
|