[{"data":1,"prerenderedAt":347},["ShallowReactive",2],{"docs-\u002Fgetting-started\u002Fmigration":3},{"id":4,"title":5,"body":6,"description":337,"extension":338,"meta":339,"navTitle":340,"navigation":341,"path":342,"rawbody":343,"seo":344,"stem":345,"__hash__":346},"docs\u002Fgetting-started\u002Fmigration.md","Migration Guide",{"type":7,"value":8,"toc":319},"minimark",[9,13,17,26,31,34,44,47,53,56,75,79,81,87,89,95,102,106,108,114,116,122,130,133,139,142,148,151,157,160,171,182,185,191,193,199,206,233,239,246,249,255,257,263,266,272,276,278,284,286,292,295,299,302,313],[10,11,5],"h1",{"id":12},"migration-guide",[14,15,16],"p",{},"This page shows how to move from the older manual wiring style to the current\nbootstrap-first setup.",[18,19,21,22],"h2",{"id":20},"_1-manual-bootstrap-buildruntime","1. Manual Bootstrap -> ",[23,24,25],"code",{},"buildRuntime()",[27,28,30],"h3",{"id":29},"bukkitpaper","Bukkit\u002FPaper",[14,32,33],{},"Before:",[35,36,42],"pre",{"className":37,"code":39,"language":40,"meta":41},[38],"language-java","Platform platform = new BukkitPlatformProvider(this);\nConfigManager configManager = new ConfigManager(platform);\nLogger logger = new Logger(platform, this, configManager);\nLanguageManager languageManager = new LanguageManager(this, configManager);\nlanguageManager.init(\"en\");\nlanguageManager.addMagicUtilsMessages();\nlogger.setLanguageManager(languageManager);\nMessages.register(getName(), languageManager);\n","java","",[23,43,39],{"__ignoreMap":41},[14,45,46],{},"After:",[35,48,51],{"className":49,"code":50,"language":40,"meta":41},[38],"BukkitBootstrap.RuntimeResult magic = BukkitBootstrap.forPlugin(this)\n        .buildRuntime();\n",[23,52,50],{"__ignoreMap":41},[14,54,55],{},"What you gain:",[57,58,59,63,66,69],"ul",{},[60,61,62],"li",{},"one managed shutdown handle",[60,64,65],{},"consistent logger\u002Flang\u002Fmessages wiring",[60,67,68],{},"optional command registry integration",[60,70,71,72],{},"easy access through ",[23,73,74],{},"MagicRuntime",[27,76,78],{"id":77},"fabric","Fabric",[14,80,33],{},[35,82,85],{"className":83,"code":84,"language":40,"meta":41},[38],"Platform platform = new FabricPlatformProvider(server);\nConfigManager configManager = new ConfigManager(platform);\nLogger logger = new Logger(platform, configManager, \"MyMod\");\n",[23,86,84],{"__ignoreMap":41},[14,88,46],{},[35,90,93],{"className":91,"code":92,"language":40,"meta":41},[38],"FabricBootstrap.RuntimeResult magic = FabricBootstrap.forMod(\"mymod\", () -> server)\n        .buildRuntime();\n",[23,94,92],{"__ignoreMap":41},[14,96,97,98,101],{},"Important: Fabric command registration still happens inside\n",[23,99,100],{},"CommandRegistrationCallback.EVENT",".",[27,103,105],{"id":104},"velocity","Velocity",[14,107,33],{},[35,109,112],{"className":110,"code":111,"language":40,"meta":41},[38],"Platform platform = new VelocityPlatformProvider(proxy, slf4j, dataDirectory, this);\nConfigManager configManager = new ConfigManager(platform);\nLoggerCore logger = new LoggerCore(platform, configManager, this, \"MyPlugin\");\n",[23,113,111],{"__ignoreMap":41},[14,115,46],{},[35,117,120],{"className":118,"code":119,"language":40,"meta":41},[38],"VelocityBootstrap.RuntimeResult magic = VelocityBootstrap.forPlugin(proxy, this, \"MyPlugin\", dataDirectory)\n        .slf4j(slf4j)\n        .buildRuntime();\n",[23,121,119],{"__ignoreMap":41},[18,123,125,126,129],{"id":124},"_2-initialize-explicit-registry-or-bootstrap","2. ",[23,127,128],{},"initialize(...)"," -> Explicit Registry Or Bootstrap",[14,131,132],{},"Older code often used the static default registry:",[35,134,137],{"className":135,"code":136,"language":40,"meta":41},[38],"CommandRegistry.initialize(plugin, \"myplugin\", logger);\nCommandRegistry.register(plugin, new DonateCommand());\n",[23,138,136],{"__ignoreMap":41},[14,140,141],{},"Preferred now:",[35,143,146],{"className":144,"code":145,"language":40,"meta":41},[38],"CommandRegistry registry = CommandRegistry.create(plugin, \"myplugin\", logger);\nregistry.registerCommand(new DonateCommand());\n",[23,147,145],{"__ignoreMap":41},[14,149,150],{},"Or through bootstrap:",[35,152,155],{"className":153,"code":154,"language":40,"meta":41},[38],"BukkitBootstrap.RuntimeResult magic = BukkitBootstrap.forPlugin(plugin)\n        .permissionPrefix(\"myplugin\")\n        .enableCommands()\n        .configureCommands(registry -> registry.registerCommand(new DonateCommand()))\n        .buildRuntime();\n",[23,156,154],{"__ignoreMap":41},[14,158,159],{},"Why prefer this:",[57,161,162,165,168],{},[60,163,164],{},"easier testing",[60,166,167],{},"fewer hidden globals",[60,169,170],{},"clearer ownership in multi-plugin or multi-mod setups",[18,172,174,175,178,179],{"id":173},"_3-commandspecbuilder-magiccommandbuilder","3. ",[23,176,177],{},"CommandSpec.builder(...)"," -> ",[23,180,181],{},"MagicCommand.builder(...)",[14,183,184],{},"Older builder-based command code often produced a detached spec:",[35,186,189],{"className":187,"code":188,"language":40,"meta":41},[38],"CommandSpec\u003CCommandSender> spec = CommandSpec.\u003CCommandSender>builder(\"donate\")\n        .execute(ctx -> CommandResult.success(\"ok\"))\n        .build();\n\nregistry.registerSpec(spec);\n",[23,190,188],{"__ignoreMap":41},[14,192,141],{},[35,194,197],{"className":195,"code":196,"language":40,"meta":41},[38],"MagicCommand command = MagicCommand.\u003CCommandSender>builder(\"donate\")\n        .execute(ctx -> CommandResult.success(\"ok\"))\n        .build();\n\nregistry.registerCommand(command);\n",[23,198,196],{"__ignoreMap":41},[14,200,201,202,205],{},"This matters because builder-authored commands are now real ",[23,203,204],{},"MagicCommand","\ninstances. They can use the same runtime adaptation API as annotation-based\ncommands:",[57,207,208,213,218,223,228],{},[60,209,210],{},[23,211,212],{},"withName(...)",[60,214,215],{},[23,216,217],{},"addAlias(...)",[60,219,220],{},[23,221,222],{},"addSubCommand(...)",[60,224,225],{},[23,226,227],{},"setExecute(...)",[60,229,230],{},[23,231,232],{},"mount(existingCommand)",[14,234,235,238],{},[23,236,237],{},"registerSpec(...)"," still works for migration, but it is now the compatibility\npath rather than the primary one.",[18,240,242,243,245],{"id":241},"_4-ad-hoc-reload-logic-magicruntime-bindings","4. Ad-Hoc Reload Logic -> ",[23,244,74],{}," Bindings",[14,247,248],{},"Older reload code often looked like this:",[35,250,253],{"className":251,"code":252,"language":40,"meta":41},[38],"if (client != null) {\n    client.close();\n}\nclient = MagicHttpClient.builder(platform, configManager)\n        .baseUrl(config.monitoring.baseUrl)\n        .build();\n",[23,254,252],{"__ignoreMap":41},[14,256,141],{},[35,258,261],{"className":259,"code":260,"language":40,"meta":41},[38],"MagicRuntimeConfigBinding\u003CServiceConfig, MagicHttpClient> binding = runtime.bindConfig(\n        \"http.monitoring\",\n        ServiceConfig.class,\n        config -> MagicHttpClient.builder(runtime.platform(), runtime.configManager())\n                .baseUrl(config.monitoring.baseUrl)\n                .build(),\n        \"monitoring\"\n);\n",[23,262,260],{"__ignoreMap":41},[14,264,265],{},"Or use the higher-level profile wrapper:",[35,267,270],{"className":268,"code":269,"language":40,"meta":41},[38],"MagicHttpClientProfile\u003CServiceConfig> monitoring = MagicHttpClientProfile\n        .builder(runtime, \"http.monitoring\", ServiceConfig.class)\n        .sections(\"monitoring\")\n        .baseUrl(config -> config.monitoring.baseUrl)\n        .build();\n",[23,271,269],{"__ignoreMap":41},[18,273,275],{"id":274},"_5-manual-shutdown-one-runtime-close","5. Manual Shutdown -> One Runtime Close",[14,277,33],{},[35,279,282],{"className":280,"code":281,"language":40,"meta":41},[38],"configManager.shutdown();\nCommandRegistry.shutdown(plugin);\nMessages.unregister(getName());\n",[23,283,281],{"__ignoreMap":41},[14,285,46],{},[35,287,290],{"className":288,"code":289,"language":40,"meta":41},[38],"magic.runtime().close();\n",[23,291,289],{"__ignoreMap":41},[14,293,294],{},"That only works when the services were created through bootstrap or registered\ninside the runtime.",[18,296,298],{"id":297},"_6-when-not-to-migrate","6. When Not To Migrate",[14,300,301],{},"Keep the manual style when:",[57,303,304,307,310],{},[60,305,306],{},"you are integrating MagicUtils into an unusual platform",[60,308,309],{},"you need partial module wiring without the bootstrap defaults",[60,311,312],{},"you intentionally manage service lifecycles yourself",[14,314,315,316,318],{},"Even in those cases, ",[23,317,74],{}," is still useful as a local lifecycle\ncontainer.",{"title":41,"searchDepth":320,"depth":320,"links":321},3,[322,329,331,333,335,336],{"id":20,"depth":323,"text":324,"children":325},2,"1. Manual Bootstrap -> buildRuntime()",[326,327,328],{"id":29,"depth":320,"text":30},{"id":77,"depth":320,"text":78},{"id":104,"depth":320,"text":105},{"id":124,"depth":323,"text":330},"2. initialize(...) -> Explicit Registry Or Bootstrap",{"id":173,"depth":323,"text":332},"3. CommandSpec.builder(...) -> MagicCommand.builder(...)",{"id":241,"depth":323,"text":334},"4. Ad-Hoc Reload Logic -> MagicRuntime Bindings",{"id":274,"depth":323,"text":275},{"id":297,"depth":323,"text":298},"Upgrade MagicUtils between versions: breaking changes, renamed APIs, and step-by-step migration notes for the bootstrap and runtime layers.","md",{},null,true,"\u002Fgetting-started\u002Fmigration","---\ntitle: Migration Guide\ndescription: 'Upgrade MagicUtils between versions: breaking changes, renamed APIs, and step-by-step migration notes for the bootstrap and runtime layers.'\n---\n\n# Migration Guide\n\nThis page shows how to move from the older manual wiring style to the current\nbootstrap-first setup.\n\n## 1. Manual Bootstrap -> `buildRuntime()`\n\n### Bukkit\u002FPaper\n\nBefore:\n\n```java\nPlatform platform = new BukkitPlatformProvider(this);\nConfigManager configManager = new ConfigManager(platform);\nLogger logger = new Logger(platform, this, configManager);\nLanguageManager languageManager = new LanguageManager(this, configManager);\nlanguageManager.init(\"en\");\nlanguageManager.addMagicUtilsMessages();\nlogger.setLanguageManager(languageManager);\nMessages.register(getName(), languageManager);\n```\n\nAfter:\n\n```java\nBukkitBootstrap.RuntimeResult magic = BukkitBootstrap.forPlugin(this)\n        .buildRuntime();\n```\n\nWhat you gain:\n\n- one managed shutdown handle\n- consistent logger\u002Flang\u002Fmessages wiring\n- optional command registry integration\n- easy access through `MagicRuntime`\n\n### Fabric\n\nBefore:\n\n```java\nPlatform platform = new FabricPlatformProvider(server);\nConfigManager configManager = new ConfigManager(platform);\nLogger logger = new Logger(platform, configManager, \"MyMod\");\n```\n\nAfter:\n\n```java\nFabricBootstrap.RuntimeResult magic = FabricBootstrap.forMod(\"mymod\", () -> server)\n        .buildRuntime();\n```\n\nImportant: Fabric command registration still happens inside\n`CommandRegistrationCallback.EVENT`.\n\n### Velocity\n\nBefore:\n\n```java\nPlatform platform = new VelocityPlatformProvider(proxy, slf4j, dataDirectory, this);\nConfigManager configManager = new ConfigManager(platform);\nLoggerCore logger = new LoggerCore(platform, configManager, this, \"MyPlugin\");\n```\n\nAfter:\n\n```java\nVelocityBootstrap.RuntimeResult magic = VelocityBootstrap.forPlugin(proxy, this, \"MyPlugin\", dataDirectory)\n        .slf4j(slf4j)\n        .buildRuntime();\n```\n\n## 2. `initialize(...)` -> Explicit Registry Or Bootstrap\n\nOlder code often used the static default registry:\n\n```java\nCommandRegistry.initialize(plugin, \"myplugin\", logger);\nCommandRegistry.register(plugin, new DonateCommand());\n```\n\nPreferred now:\n\n```java\nCommandRegistry registry = CommandRegistry.create(plugin, \"myplugin\", logger);\nregistry.registerCommand(new DonateCommand());\n```\n\nOr through bootstrap:\n\n```java\nBukkitBootstrap.RuntimeResult magic = BukkitBootstrap.forPlugin(plugin)\n        .permissionPrefix(\"myplugin\")\n        .enableCommands()\n        .configureCommands(registry -> registry.registerCommand(new DonateCommand()))\n        .buildRuntime();\n```\n\nWhy prefer this:\n\n- easier testing\n- fewer hidden globals\n- clearer ownership in multi-plugin or multi-mod setups\n\n## 3. `CommandSpec.builder(...)` -> `MagicCommand.builder(...)`\n\nOlder builder-based command code often produced a detached spec:\n\n```java\nCommandSpec\u003CCommandSender> spec = CommandSpec.\u003CCommandSender>builder(\"donate\")\n        .execute(ctx -> CommandResult.success(\"ok\"))\n        .build();\n\nregistry.registerSpec(spec);\n```\n\nPreferred now:\n\n```java\nMagicCommand command = MagicCommand.\u003CCommandSender>builder(\"donate\")\n        .execute(ctx -> CommandResult.success(\"ok\"))\n        .build();\n\nregistry.registerCommand(command);\n```\n\nThis matters because builder-authored commands are now real `MagicCommand`\ninstances. They can use the same runtime adaptation API as annotation-based\ncommands:\n\n- `withName(...)`\n- `addAlias(...)`\n- `addSubCommand(...)`\n- `setExecute(...)`\n- `mount(existingCommand)`\n\n`registerSpec(...)` still works for migration, but it is now the compatibility\npath rather than the primary one.\n\n## 4. Ad-Hoc Reload Logic -> `MagicRuntime` Bindings\n\nOlder reload code often looked like this:\n\n```java\nif (client != null) {\n    client.close();\n}\nclient = MagicHttpClient.builder(platform, configManager)\n        .baseUrl(config.monitoring.baseUrl)\n        .build();\n```\n\nPreferred now:\n\n```java\nMagicRuntimeConfigBinding\u003CServiceConfig, MagicHttpClient> binding = runtime.bindConfig(\n        \"http.monitoring\",\n        ServiceConfig.class,\n        config -> MagicHttpClient.builder(runtime.platform(), runtime.configManager())\n                .baseUrl(config.monitoring.baseUrl)\n                .build(),\n        \"monitoring\"\n);\n```\n\nOr use the higher-level profile wrapper:\n\n```java\nMagicHttpClientProfile\u003CServiceConfig> monitoring = MagicHttpClientProfile\n        .builder(runtime, \"http.monitoring\", ServiceConfig.class)\n        .sections(\"monitoring\")\n        .baseUrl(config -> config.monitoring.baseUrl)\n        .build();\n```\n\n## 5. Manual Shutdown -> One Runtime Close\n\nBefore:\n\n```java\nconfigManager.shutdown();\nCommandRegistry.shutdown(plugin);\nMessages.unregister(getName());\n```\n\nAfter:\n\n```java\nmagic.runtime().close();\n```\n\nThat only works when the services were created through bootstrap or registered\ninside the runtime.\n\n## 6. When Not To Migrate\n\nKeep the manual style when:\n\n- you are integrating MagicUtils into an unusual platform\n- you need partial module wiring without the bootstrap defaults\n- you intentionally manage service lifecycles yourself\n\nEven in those cases, `MagicRuntime` is still useful as a local lifecycle\ncontainer.\n",{"title":5,"description":337},"getting-started\u002Fmigration","VofEy5jlRXxwuGCg9k1r_YZkpEKIIYaiNfl7EPqa-EM",1783944486999]