Skip to content

Module System (bootstrap package)

Navigation: Documentation Home · Contents · Core Concepts · API Overview · Toolkit · Glossary · Diagnostic Codes

QinhCoreLib (QCL) splits its capabilities into Modules, which the ModuleManager registers uniformly, loads by priority, reports health for, and isolates via degradation. This page covers the module lifecycle, the 22 core modules, the degradation mechanism, how to write custom modules, plus the accompanying diagnostic model and startup probing.


The Module Interface

MemberDescription
nameModule name
priorityPriority, defaults to 0, loaded in ascending order
load()Load phase
enable()Enable phase
disable()Disable phase
unload()Unload phase

AbstractModule(name) provides default empty implementations of the above methods, so you only need to override the hooks you care about.

kotlin
class MyModule : AbstractModule("MyModule") {
    override val priority: Int = 50

    override fun load() {
        // Prepare resources, read configuration
    }

    override fun enable() {
        // Register listeners and commands
    }

    override fun disable() {
        // Unregister listeners
    }

    override fun unload() {
        // Release resources
    }
}

ModuleManager

MethodDescription
register(module)Register a module
unregister(module)Unregister a module
getModule(name)Get a module by name
statuses(): List<ModuleStatus>Get the status of all modules
healthReport(): HealthReportHealth report
loadAll()load then enable all modules in ascending priority order
unloadAll()Unload all modules
reloadAll()Reload all modules

Load Order and Degradation

  • loadAll() runs in ascending priority order: it first loads all modules, then enables all modules.
  • Degradation isolation: when a single module throws an exception, only that module is marked available = false / enabled = false; other modules are not affected. This means that if a bridge (such as scripting or economy) is missing or errors out, the core does not crash entirely but degrades locally.
  • Modules can be toggled on/off via the config's modules.* switches.

CoreModules.registerAll registers all 22 core modules to the ModuleManager in one go.

The 22 Core Modules (loaded in ascending priority order)

Modules are registered uniformly by CoreModules.registerAll and go through loadenable in ascending priority order. Infrastructure types (database, config, text) have the lowest priority and load first; the bridges and business types that depend on them load afterward. The table below is a conceptual layering (the actual numbers follow the source CoreModules) to help you understand the load order and dependencies.

LayerTypical module responsibilities
Infrastructure (first)Config, database, debug/logging, text
Unified pipelinesItem source management, attribute pipeline, economy, placeholders
External bridgesCraftEngine block bridge, ModelEngine model bridge, various item source bridges (MMOItems/NeigeItems/QinhItems/MythicMobs/CustomFishing/MagicGem/ItemsAdder/Nexo, etc.)
ScriptingScript engine (GraalVM)
Business/UI (last)GUI, commands, startup report, etc.

Tip: if a bridge module's corresponding soft dependency is not installed, it is skipped via a reflection bridge and marked NO_HOOK. This is normal degradation, not an error. See Diagnostic Codes for details.


The Correct Way to Integrate Sub-Plugins

Although developers can implement a custom Module and register it to QinhCoreLib.moduleManager, this is usually not recommended.

Sub-plugins should generally use their own plugin main class (JavaPlugin), initialize in their own onEnable, and collaborate with QCL's public APIs and services (item sources, attribute pipeline, scheduling, text, etc.). Only when a capability truly needs to be brought into QCL's unified lifecycle / health reporting should you consider registering it as a QCL module.

kotlin
// Recommended: a sub-plugin uses its own main class
class MySubPlugin : JavaPlugin() {
    override fun onEnable() {
        // Call QCL's public APIs / tools directly
    }
}
kotlin
// Optional: register as a module when it really must be part of the QCL lifecycle
QinhCoreLib.moduleManager.register(MyModule())

Diagnostic Model

QCL's diagnostic model provides structured status and result objects, making troubleshooting and health reporting easier.

ModuleStatus

FieldDescription
nameModule name
enabledWhether enabled
availableWhether available
messageStatus message

BridgeStatus

FieldDescription
nameBridge name
availableWhether available
enabledWhether enabled
sourceSource
messageMessage
recoverableWhether recoverable

HealthReport

Field / MethodDescription
okWhether healthy
codeHealth code (OK / NO_HOOK / DEGRADED)
messageMessage
suggestionSuggestion
healthy()Build a healthy report
degraded(code, message, suggestion)Build a degraded report

DiagnosticResult<T>

A unified diagnostic result container.

Field / MethodDescription
successWhether successful
valueResult value
codeResult code
messageMessage
sourceSource
recoverableWhether recoverable
suggestionSuggestion
traceIdTrace ID
ok(...)Build a success result
fail(...)Build a failure result
kotlin
val result: DiagnosticResult<ItemStack> = parseItem(ref)
if (result.success) {
    val item = result.value
} else {
    logger.warning("解析失败[${result.code}]:${result.message},建议:${result.suggestion}")
}

Trace* (debug tracing)

TraceModels provides: TraceEvent, TraceReport, TraceBuilder, DebugTraceRegistry, used to record and replay the internal steps of an operation, making deep troubleshooting easier.


BridgeStatusRegistry

Centrally records the current status of each external bridge; commands such as /qcl status aggregate from this.

MethodDescription
register(status)Record a bridge status
unregister(name)Remove
get(name)Get the status of a bridge
all()Get all
clear()Clear

Startup Probing and Reporting

EcosystemStartupProbe

At startup, probes the available item sources, economies, and plugin hooks, and builds a platform status summary.

MethodDescription
availableItemSources()Available item sources
availableEconomies()Available economies
probePluginHooks()Probe plugin hooks
buildPlatformStatus()Build platform status
formatSummary()Format the summary

StartupReporter

Aggregates and prints the startup summary.

MethodDescription
reset()Reset
setGuiCount(n)Set the GUI count
hookedItemSource(...)Record a hooked item source
hookedBridge(...)Record a hooked bridge
hookedEconomy(...)Record a hooked economy
printSummary()Print the summary

Continue Reading