MetaCore

MetaCore

Core for triggers, conditions and effects providers.

12 downloads 0 followers

MetaCore

A shared Trigger Engine platform for Paper plugins — MetaCore provides the Trigger Engine, its Paper integration layer, and a Kotlin DSL as a centralized library that other plugins (MetaJobs and your own) can depend on without bundling duplicate engine code.


Overview

MetaCore is a utility library plugin that hosts a single, shared instance of the Trigger Engine on your Paper/Folia server. Instead of every plugin embedding its own copy of the engine — wasting memory, duplicating configuration logic, and complicating cross-plugin triggers — plugins register their trigger configurations as modules against MetaCore's shared engine.

Think of it as "Trigger Engine as a Service" for your server.


Why MetaCore?

Problem MetaCore Solution
Multiple plugins each bundle the Trigger Engine → memory bloat, version conflicts Single shared engine instance loaded once
Plugins can't easily reference each other's triggers Cross-module trigger references via shared TriggerHolder IDs
Each plugin reimplements Paper integrations (parsers, elements, properties) Registered once at startup by MetaCore
Configuration reload requires plugin restart Hot-reload individual modules via /metacore reload <module>
Kotlin DSL setup is boilerplate-heavy LoadScope DSL + PaperTriggers.load { } helpers that work on the shared engine

Features

  • Shared Trigger Engine — One DefaultTriggerEngine instance, one event bridge, one placeholder registry
  • Paper Integration Layer — All Paper-specific parsers, elements, properties, lookups, and trigger types registered once
  • External Item Support — Built-in providers for ItemsAdder, Oraxen, Nexo, CraftEngine (auto-detected)
  • PlaceholderAPI Integration — Optional, auto-enabled when PlaceholderAPI is present
  • Persistent Placeholder Storage — SQLite (default) or MySQL with async flush
  • Kotlin DSL — LoadScope DSL + PaperTriggers.load { } / yaml() helpers in io.github.neoramm.triggerengine.kotlin.paper, usable on the shared engine
  • Brigadier Commands — Modern command API with tab completion for module management
  • Folia Compatible — Region-aware, thread-safe engine operation
  • Hot Module Reload — Reload a single plugin's triggers without touching others

Installation

For Server Administrators

  1. Download the latest MetaCore-<version>.jar
  2. Place in plugins/
  3. Start the server — MetaCore creates plugins/MetaCore/config.yml
  4. Configure storage (optional): SQLite (default) or MySQL
  5. Install dependent plugins (MetaJobs, MetaEnchants, or your own)

For Plugin Developers (Gradle)

// build.gradle.kts of your plugin
dependencies {
    compileOnly("io.papermc.paper:paper-api:26.2.build.+")
    compileOnly(files("libs/MetaCore.jar"))
}

paper-plugin.yml (Dependent Plugin)

name: YourPlugin
version: 1.0.0
main: com.your.YourPlugin
api-version: '26.2'
depend: [MetaCore]        # Hard dependency — MetaCore loads first
# Or soft dependency:
# load: BEFORE
# required: false

Quick Start (Plugin Developer)

1. Access the Shared Engine

import io.github.neoramm.metacore.MetaCore;
import io.github.neoramm.triggerengine.paper.PaperTriggers;

public class YourPlugin extends JavaPlugin {
    private PaperTriggers triggers;

    @Override
    public void onEnable() {
        // Get the shared engine (initialized by MetaCore)
        triggers = MetaCore.triggers();
        
        // Register your plugin as a module for reload support
        MetaCore.registerModule("yourplugin", session -> {
            loadTriggers(session);
        });
    }

    private void loadTriggers(LoadSession session) {
        // Load YAML, Kotlin DSL, or programmatic triggers
        ConfigNode root = triggers.read(dataFolder.toPath().resolve("triggers.yml"), session);
        if (root != null) {
            session.add(root.get("triggers"), root.get("placeholders"), TriggerHolder.of("yourplugin", "1.0"));
        }
    }
}

2. Using the Kotlin DSL on the shared engine (Recommended)

The Kotlin DSL does not create an engine. It provides LoadScope builders (paper.load { }, yaml()) that run on any PaperTriggers — including the global instance started by MetaCore:

// In your plugin's Kotlin code
import io.github.neoramm.metacore.MetaCore
import io.github.neoramm.triggerengine.kotlin.holder
import io.github.neoramm.triggerengine.kotlin.paper.load
import io.github.neoramm.triggerengine.kotlin.paper.yaml

class YourPlugin : JavaPlugin() {
    override fun onEnable() {
        // Shared singleton, already initialized + started by MetaCore.
        // Paper elements/parsers/properties were registered once by MetaCore.
        val paper = MetaCore.triggers()
        val holder = holder("yourplugin")

        fun loadAll() = paper.load {
            yaml(dataFolder.toPath().resolve("triggers.yml"), holder)
            // or programmatic triggers in the same session:
            // add(holder, "in-code") { trigger("welcome") { on("player-join") /* ... */ } }
        }

        loadAll()
        // Reuse the same loader for hot-reload (same pattern as MetaJobs).
        // The LoadSession passed by MetaCore is unused here because
        // paper.load{} manages its own session internally.
        MetaCore.registerModule("yourplugin") { loadAll() }
    }
}

Do not call Plugin.triggerEngine() here — that helper creates a new, standalone engine (see below), not the shared one.

3. Shared vs. standalone engine

Mode How Who owns lifecycle When to use
Shared (default with MetaCore) MetaCore.triggers() MetaCore (createShared() + start() / shutdown() once) MetaJobs, MetaEnchants, any plugin with depend: [MetaCore]. Enables cross-module run_trigger and /metacore reload <module>.
Standalone (opt-in, no MetaCore) Plugin.triggerEngine() (kotlin-dsl) or PaperTriggers.create(plugin, ...) (paper module) Your plugin (start() / shutdown() yourself, own EventBridge) You explicitly don't want the shared instance: isolated tests, separate server, forked behavior. Full Paper defaults (properties, parsers, elements, types) are registered on the new engine.

Creating your own engine while also depending on MetaCore is allowed but discouraged: you pay for two engines, two event bridges, and triggers on the private engine are invisible to other modules.

// Standalone only — no MetaCore dependency:
val isolated: PaperTriggers = triggerEngine {
    // optional DefaultTriggerEngine.Builder customization
}
isolated.start()
// ... isolated.load { ... } ...
// onDisable: isolated.shutdown()

4. Hot Reload Support

Players/ops can reload just your plugin's triggers:

/metacore reload yourplugin

Or programmatically:

MetaCore.reloadModule("yourplugin");

Configuration (config.yml)

storage:
  # sqlite -> file inside plugins/MetaCore (zero setup)
  # mysql  -> external database for multi-server sync
  type: sqlite

  sqlite:
    file: data.db

  mysql:
    host: localhost
    port: 3306
    database: minecraft
    user: root
    password: ""
    properties:
      useSSL: false
      characterEncoding: utf8

  # Flush interval in seconds (min 5). Also saves on shutdown/player quit.
  flush-seconds: 30

Commands

Command Permission Description
/metacore metacore.base Show version and loaded modules
/metacore modules metacore.base List registered module IDs
/metacore reload metacore.admin Reload all modules
/metacore reload <module> metacore.admin Reload a specific module

Tab completion works for module names in /metacore reload <module>.


API Reference

MetaCore (Main Entry Point)

Method Description
static PaperTriggers triggers() Get the shared PaperTriggers instance
static CompositeExternalItemRegistry externalItems() Access the combined external item registry
static ModuleHandle registerModule(String id, ModuleInitializer init) Register a module for hot-reload
static ModuleHandle getModule(String id) Retrieve a module handle
static Set<String> getModuleIds() List all registered module IDs
static void reloadModule(String id) Hot-reload a single module
static void reloadAllModules() Reload all modules
static void unregisterModule(String id) Unregister a module (on plugin disable)

ModuleInitializer (Functional Interface)

@FunctionalInterface
public interface ModuleInitializer {
    void accept(LoadSession session);
}

Receives a fresh LoadSession — add your triggers, placeholders, and configs here.

PaperTriggers (Engine Access)

Key methods you'll use:

// Engine & registries
DefaultTriggerEngine engine();
PaperKeys keys();
PaperTriggerTypes types();
CompositeExternalItemRegistry externalItemRegistry();

// Loading
LoadSession engine().beginLoad();
ConfigNode read(Path file, LoadSession session);
CompileResult loadFile(Path file, String section, TriggerHolder holder);
CompileResult report(CompileResult result);  // Logs diagnostics

// Lifecycle
void start();      // Owner calls once: MetaCore for the shared instance,
                   // your plugin for a standalone PaperTriggers.create() engine
void shutdown();   // Same owner rule as start()

External Item Providers

MetaCore auto-registers providers for these plugins (if present):

Provider Items Requires
ItemsAdder itemsadder: namespace ItemsAdder
Nexo nexo: namespace Nexo
CraftEngine craftengine: namespace CraftEngine

Use in triggers like any vanilla item:

# triggers.yml
triggers:
  give_custom_sword:
    type: player-join
    actions:
      - give_item:
          item: "itemsadder:my_custom_sword"
          amount: 1

Cross-Module Triggers

Since all modules share one engine, triggers can reference each other:

# MetaJobs triggers.yml
triggers:
  miner_level_up:
    type: job-level-up
    conditions:
      - job_id: "miner"
    actions:
      - run_trigger: "namespace:apply_mining_bonus"  # References other plugin trigger
# Other plugin triggers.yml
triggers:
  apply_mining_bonus:
    type: manual  # Only run via run_trigger
    actions:
      - add-enchantment:
          enchantment: "fortune"
          level: 1

Compatibility

Platform Version
Paper 26.2+ (API 26.2+)
Folia Supported (region-aware)
Java 25+
Trigger Engine Bundled (core/paper modules)

License

MIT License — Free for any use, including commercial servers and plugins.


Links


For Plugin Authors: Publishing Your Plugin

When publishing a plugin that depends on MetaCore:

  1. Declare dependency in paper-plugin.yml:

    depend: [MetaCore]
    # Or soft dependency:
    # load: BEFORE
    # required: false
    
  2. Document requirement in your plugin's README:

    Requires MetaCore (provides shared Trigger Engine). Download from releases.

  3. Use MetaCore.registerModule() so server admins can hot-reload your triggers via /metacore reload yourplugin.

  4. Don't shade Trigger Engine classes — use compileOnly / provided scope.

  5. Don't call Plugin.triggerEngine() when you target the shared engine — use MetaCore.triggers() + paper.load { }. Reserve Plugin.triggerEngine() / PaperTriggers.create() for the opt-in standalone mode with no MetaCore dependency.


No gallery available for this project.

Version Minecraft Loader Download

MetaCore 1.0.0

1.0.0

26.2, 26.3
folia, paper
Download