Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ tasks {
// dev → Core-1.0.0-dev.jar
archiveBaseName.set("Core")
archiveVersion.set(version.toString())
archiveClassifier.set(if (isDev) "dev" else "")
archiveClassifier.set(if (isDev) "dev-${shortSha}" else "")

// ── Relocation ───────────────────────────────────────────────────────
relocate("com.fasterxml.jackson", "dev.mzcy.core.libs.jackson")
Expand Down
3 changes: 1 addition & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.jvmargs=-Xmx2g -XX:+UseG1GC
kotlin.stdlib.default.dependency=false
version=1.0.1
aaaaaa=b
version=1.0.2
71 changes: 71 additions & 0 deletions src/main/java/dev/mzcy/core/CorePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
import dev.mzcy.core.cache.CacheManager;
import dev.mzcy.core.command.CommandManager;
import dev.mzcy.core.config.ConfigManager;
import dev.mzcy.core.config.migration.ConfigMigrationManager;
import dev.mzcy.core.conversation.ConversationManager;
import dev.mzcy.core.cooldown.CooldownManager;
import dev.mzcy.core.cooldown.PersistentCooldownStore;
import dev.mzcy.core.cutscene.CutsceneManager;
import dev.mzcy.core.data.DataStoreManager;
import dev.mzcy.core.database.DatabaseManager;
import dev.mzcy.core.debug.DebugCommand;
import dev.mzcy.core.debug.DebugOverlay;
import dev.mzcy.core.debug.DebugRegistry;
import dev.mzcy.core.dependency.DependencyCheckResultSet;
import dev.mzcy.core.dependency.DependencyChecker;
import dev.mzcy.core.di.Container;
import dev.mzcy.core.display.ActionbarManager;
import dev.mzcy.core.display.bossbar.BossBarManager;
Expand All @@ -28,7 +33,10 @@
import dev.mzcy.core.npc.NpcManager;
import dev.mzcy.core.placeholder.PlaceholderManager;
import dev.mzcy.core.plugin.settings.CoreSettingsConfig;
import dev.mzcy.core.profiling.ProfilingManager;
import dev.mzcy.core.ratelimit.RateLimitManager;
import dev.mzcy.core.reload.HotReloadManager;
import dev.mzcy.core.retry.RetryManager;
import dev.mzcy.core.scanner.ClassScanner;
import dev.mzcy.core.scanner.ComponentRegistry;
import dev.mzcy.core.scanner.ScanResult;
Expand All @@ -38,6 +46,7 @@
import dev.mzcy.core.task.TaskManager;
import dev.mzcy.core.updater.UpdateChecker;
import dev.mzcy.core.updater.UpdateNotifier;
import dev.mzcy.core.validation.ValidationManager;
import lombok.Getter;
import lombok.extern.java.Log;
import org.bukkit.event.Listener;
Expand Down Expand Up @@ -85,6 +94,8 @@ public final class CorePlugin extends JavaPlugin {
// Framework components
// =========================================================================

@Getter
private DependencyCheckResultSet dependencyCheckResult;
@Getter
private Container container;
@Getter
Expand Down Expand Up @@ -143,6 +154,12 @@ public final class CorePlugin extends JavaPlugin {
private CacheManager cacheManager;
@Getter
private CutsceneManager cutsceneManager;
@Getter
private CooldownManager cooldownManager;
@Getter private ConfigMigrationManager configMigrationManager;
@Getter private ProfilingManager profilingManager;
@Getter private ValidationManager validationManager;
@Getter private RetryManager retryManager;@Getter private RateLimitManager rateLimitManager;

/**
* The scan result from startup — available to dependent plugins post-enable.
Expand All @@ -154,6 +171,30 @@ public final class CorePlugin extends JavaPlugin {
// Enable
// =========================================================================

private void checkDependencies() {
dependencyCheckResult = new DependencyChecker(getServer().getPluginManager())
// Keine required deps für Core selbst — es ist das Framework
.recommend("LuckPerms",
"Permission group support and @RequiresPermission integration")
.recommend("Vault",
"Economy and permissions API fallback")
.recommend("PlaceholderAPI",
"Placeholder support in messages and configs")
.optional("WorldEdit",
"Schematic paste/save support")
.optional("FastAsyncWorldEdit",
"Faster schematic paste/save support")
.check(this);

// Hard stop if a required dep is missing
if (dependencyCheckResult.hasFatal()) {
log.severe("Core cannot start — required dependencies are missing.");
log.severe("Install the missing plugins and restart the server.");
getServer().getPluginManager().disablePlugin(this);
return;
}
}

@Override
public void onEnable() {
instance = this;
Expand All @@ -166,6 +207,9 @@ public void onEnable() {
log.info("\\____/\\____/_/ \\___/ ");
log.info("Framework booting... ");

checkDependencies();
if (!isEnabled()) return;

try {
bootFramework();
} catch (CoreException ex) {
Expand Down Expand Up @@ -202,6 +246,9 @@ public void onDisable() {
safeRun("DataStoreManager.flushAll",
() -> dataStoreManager.flushAll());

safeRun("CooldownManager.shutdown",
() -> cooldownManager.shutdown());

// 5. Save all configs
safeRun("ConfigManager.saveAll",
() -> configManager.saveAll());
Expand Down Expand Up @@ -276,6 +323,8 @@ private void bootFramework() {
step("Scanning classpath", this::initScanner);
step("Wiring database repositories",
() -> databaseManager.discoverAndWire(scanResult));
step("Running config migrations",
() -> configMigrationManager.migrateAll(getDataFolder()));
step("Initializing ConfigManager", this::initConfigs);
step("Initializing DataStoreManager", this::initDataStores);
step("Registering commands", this::initCommands);
Expand All @@ -300,6 +349,7 @@ private void initContainer() {

// Self-register the plugin and server into the container
container.bindInstance(CorePlugin.class, this);

container.bindInstance(
org.bukkit.Server.class,
getServer()
Expand All @@ -313,6 +363,15 @@ private void initContainer() {
getDataFolder().toPath()
);

validationManager = new ValidationManager();
container.bindInstance(ValidationManager.class, validationManager);

configMigrationManager = new ConfigMigrationManager();
container.bindInstance(ConfigMigrationManager.class, configMigrationManager);

profilingManager = new ProfilingManager();
container.bindInstance(ProfilingManager.class, profilingManager);

// Construct and register all framework managers
moduleRegistry = new ModuleRegistry();
configManager = new ConfigManager(
Expand All @@ -324,6 +383,8 @@ private void initContainer() {
getDataFolder().toPath(),
container
);
cooldownManager = new CooldownManager(this);
container.bindInstance(CooldownManager.class, cooldownManager);
commandManager = new CommandManager(getName(), container);
inventoryManager = new InventoryManager(container, this);
placeholderManager = new PlaceholderManager(this, container);
Expand Down Expand Up @@ -353,6 +414,8 @@ private void initContainer() {
mapDisplayManager = new MapDisplayManager(this);
cacheManager = new CacheManager(this);
cutsceneManager = new CutsceneManager(this);
retryManager = new RetryManager();
rateLimitManager = new RateLimitManager(this);

container.bindInstance(ModuleRegistry.class, moduleRegistry);
container.bindInstance(ConfigManager.class, configManager);
Expand Down Expand Up @@ -385,6 +448,8 @@ private void initContainer() {
container.bindInstance(MapDisplayManager.class, mapDisplayManager);
container.bindInstance(CacheManager.class, cacheManager);
container.bindInstance(CutsceneManager.class, cutsceneManager);
container.bindInstance(RetryManager.class, retryManager);
container.bindInstance(RateLimitManager.class, rateLimitManager);

}

Expand Down Expand Up @@ -421,6 +486,12 @@ private void initConfigs() {

private void initDataStores() {
dataStoreManager.initializeAll(scanResult);

// Cooldown
final PersistentCooldownStore cooldownStore =
container.resolve(PersistentCooldownStore.class);
cooldownManager.setPersistentStore(cooldownStore);
cooldownManager.loadPersisted();
}

private void initCommands() {
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/dev/mzcy/core/annotation/Cooldown.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,12 @@
* Always includes {@code core.cooldown.bypass} automatically.
*/
String bypassPermission() default "";

/**
* Whether this cooldown should persist across server restarts.
* Requires a {@link dev.mzcy.core.cooldown.PersistentCooldownStore}
* to be registered.
* Defaults to {@code false} — in-memory only.
*/
boolean persistent() default false;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/mzcy/core/command/CommandManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public final class CommandManager {
public CommandManager(@NotNull String pluginName, @NotNull Container container) {
this.pluginName = pluginName.toLowerCase(Locale.ROOT);
this.container = container;
this.cooldownManager = new CooldownManager();
this.cooldownManager = container.resolve(CooldownManager.class);
container.bindInstance(CooldownManager.class, cooldownManager);
this.commandMap = resolveCommandMap();
}
Expand Down
62 changes: 62 additions & 0 deletions src/main/java/dev/mzcy/core/config/migration/ConfigMigration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package dev.mzcy.core.config.migration;

import com.fasterxml.jackson.databind.node.ObjectNode;
import org.jetbrains.annotations.NotNull;

/**
* A single versioned migration step for a config file.
*
* <p>Receives the raw JSON/YAML data as a Jackson {@link ObjectNode}
* so it can rename, remove, add, or transform fields without needing
* the target config class to be instantiated.
*
* <p>Example — rename {@code homeLimit} to {@code maxHomes} in v2:
* <pre>{@code
* public class V2_RenameHomeLimit implements ConfigMigration {
*
* @Override public int getTargetVersion() { return 2; }
*
* @Override public String getDescription() {
* return "Rename homeLimit → maxHomes";
* }
*
* @Override
* public void migrate(@NotNull ObjectNode node) {
* if (node.has("homeLimit")) {
* node.set("maxHomes", node.get("homeLimit"));
* node.remove("homeLimit");
* }
* }
* }
* }</pre>
*/
public interface ConfigMigration {

/**
* The schema version this migration produces.
*
* <p>A migration with {@code getTargetVersion() = 3} transforms
* a v2 config into a v3 config.
*/
int getTargetVersion();

/**
* Short human-readable description of what this migration does.
* Shown in the console log when the migration runs.
*/
@NotNull
String getDescription();

/**
* Applies this migration to the raw config data.
*
* <p>The node represents the entire config file as a JSON object.
* Mutate it in-place — add, remove, rename or transform fields.
*
* <p>The {@code _version} field is managed automatically by the
* {@link ConfigMigrationRunner} — do not touch it here.
*
* @param node the raw config data to migrate
*/
void migrate(@NotNull ObjectNode node);
}
Loading
Loading