Logger

Logger

Bukkit/Paper BungeeCord Velocity Fabric NeoForge

MagicUtils logger builds on Adventure components and provides a consistent API for console and chat output, with optional localisation, internal placeholders, and external placeholder engines.

Why a logger built on Adventure

Every platform speaks a different dialect of "styled text": Bukkit has legacy &/§ colour codes and ChatColor, Fabric/NeoForge use Minecraft's own Text, Velocity and BungeeCord have their own component types. Writing colourful output that works everywhere normally means branching per platform.

MagicUtils logs in Kyori Adventure components. You can author them with MiniMessage, the modern tag syntax (<green>, <gradient>, <hover>), or with familiar legacy colour codes (&a, &l, &#ff8800) — both are accepted and legacy codes are converted to MiniMessage automatically, so you can mix styles or paste existing coloured strings:

java
logger.info("<green>New</green> and <gold>old</gold> styles");logger.info("&aNew&r and &6old&r styles");   // same result

One string renders correctly on every platform, in chat and in the console, and the same call can localise, resolve placeholders, and honour per-logger prefixes.

Before (raw Bukkit, colour codes, console vs player split):

java
String msg = ChatColor.translateAlternateColorCodes('&', "&aReady&r, &e" + count + "&r loaded");Bukkit.getConsoleSender().sendMessage(msg);player.sendMessage(msg);

After (MagicUtils, one call, MiniMessage, any platform):

java
logger.info()        .toAll()        .args(count)        .send("<green>Ready</green>, <yellow>{0}</yellow> loaded");

Setup

The recommended path is to obtain the logger from a bootstrap result or MagicRuntime.

Bukkit/Paper

java
BukkitBootstrap.RuntimeResult magic = BukkitBootstrap.forPlugin(plugin)        .buildRuntime();Logger logger = magic.logger();

Fabric

java
FabricBootstrap.RuntimeResult magic = FabricBootstrap.forMod("mymod", () -> server)        .buildRuntime();Logger logger = magic.logger();

Velocity

Velocity bootstrap returns LoggerCore directly:

java
VelocityBootstrap.RuntimeResult magic = VelocityBootstrap.forPlugin(proxy, plugin, "MyPlugin", dataDirectory)        .buildRuntime();LoggerCore logger = magic.logger();

NeoForge / Custom Platforms

NeoForge and custom platforms typically wire LoggerCore manually:

java
Platform platform = new NeoForgePlatformProvider();ConfigManager configManager = new ConfigManager(platform);LoggerCore logger = new LoggerCore(platform, configManager, this, "MyMod");

Basic Usage

java
logger.info("<green>Ready.</green>");logger.warn("Slow query detected");logger.error("Database unavailable");logger.success("Migration complete");logger.debug("Cache miss for {key}");

Each level also has form-string overloads (info(format, args...)) and variants that target the console (infoConsole(...)) or every audience (infoAll(...)). The logger accepts MiniMessage markup and can target console, chat, or both.

Send a plain broadcast to every online player and the console:

java
logger.broadcast("<gold>Server restarting in 60s</gold>");

Log Builder

Start a builder with log(), noPrefix(), or any level (info(), success(), ...), chain the targeting/formatting calls, then send(...):

java
logger.info()        .toConsole()        .noPrefix()        .send("<yellow>Reloaded</yellow>");logger.log()        .to(playerAudience)        .args(playerName, count)        .send("<green>{0} claimed {1} rewards</green>");

Builder methods:

  • target(LogTarget.CHAT | CONSOLE | BOTH), toConsole(), toAll()
  • to(audience), toAudiences(collection), recipient(audience)
  • noPrefix(), prefixMode(PrefixMode.FULL | SHORT | CUSTOM | NONE)
  • args(Object...) for {0}, {1}, ... substitution
  • placeholders(Map) for named {key} tokens
  • withResolvers(TagResolver...) for custom MiniMessage tags
  • send(message, placeholders...) to render and dispatch

Prefixed Loggers

java
PrefixedLogger db = logger.withPrefix("database", "[DB]");db.info("Connected");

Each prefixed logger gets its own entry under sub-loggers in logger.{ext} for enable or disable toggles.

Prefix Modes

Prefix rendering is controlled by PrefixMode:

  • FULL -> full plugin/mod name
  • SHORT -> short name from config
  • CUSTOM -> setCustomPrefix(...)
  • NONE -> no prefix

Logger delegates these controls to the underlying LoggerCore.

Runtime Integration

When you already have MagicRuntime, the logger is a shared typed component:

java
MagicRuntime runtime = magic.runtime();LoggerCore loggerCore = runtime.requireComponent(LoggerCore.class);

That makes it easy to pass the logger into reloadable services or register named runtime resources that log through the same config and placeholder setup.

Logger Configuration

LoggerConfig is stored as logger.{ext}.

  • Bukkit: plugin config directory
  • Fabric: config/<modid>/ by default
  • Velocity / custom platforms: resolved through the active Platform

See Logger Config for a full key reference.

Key sections:

  • prefix
  • defaults
  • chat / console
  • help
  • sub-loggers

Localisation

Attach a LanguageManager to enable @key lookups:

java
logger.setLanguageManager(languageManager);logger.info("@myplugin.ready");

The logger resolves the key through the attached LanguageManager and then renders the result as MiniMessage.

Bootstrap helpers bind the language manager automatically when language support is enabled.

Internal And External Placeholders

Logger messages pass through both:

  1. MagicPlaceholders for {key} and {namespace:key} tokens.
  2. Platform-specific external placeholder engines.

Examples:

java
logger.info("Balance: {economy:balance}");logger.info("Hello {player}");

Platform integrations:

  • Bukkit logger installs the PlaceholderAPI bridge and a Bukkit external placeholder engine.
  • Fabric logger installs Text Placeholder API / MiniPlaceholders / PB4 support when those mods are present.
  • LoggerCore also supports a custom ExternalPlaceholderEngine for custom platforms.