SDK
Porting Guide from NeoForge to ECHO Native
ECHO Native gives you service-based optional integrations, policy-driven runtime lanes, and built-in RuntimeGuard budgets. Porting is incremental: you can keep NeoForge compatibility while a
Porting Guide from NeoForge to ECHO Native
Why Port?
ECHO Native gives you service-based optional integrations, policy-driven runtime lanes, and built-in RuntimeGuard budgets. Porting is incremental: you can keep NeoForge compatibility while adding Native features.
Porting Checklist
1. Project Setup
- Apply
echo-sdk-gradle-plugininbuild.gradle. - Add
echo-native-contractsasimplementation. - Move NeoForge-only dependencies to
compileOnlyorneoforgeconfiguration.
2. Descriptor
Create META-INF/echo-native-addon.descriptor.json with:
nativePolicy: Start withNEOFORGE_BRIDGEif you want gradual migration.optionalIntegrations: List every cross-mod integration.side: DeclareCLIENT/SERVER/BOTHaccurately.
3. Entry Point Migration
Replace @Mod main class with an EchoNativeAddon entry point:
public class MyNeoForgeMod {
// NeoForge entry point — keep it for NEOFORGE_BRIDGE lane
}
public class MyNativeAddon implements EchoNativeAddon {
@Override
public void onInitialize(EchoNativeAddonRuntime runtime) {
// Register services here
}
}
Register the native entry point in echo-native-addon.descriptor.json:
{
"entryPoints": {
"native": "com.example.MyNativeAddon"
}
}
4. Event Handling
Replace direct NeoForge event bus subscriptions with ECHO Native event contracts where available. For events without a Native wrapper, keep NeoForge subscriptions—they still work in the NEOFORGE_BRIDGE lane.
| NeoForge Event | ECHO Native Equivalent |
|---|---|
| FMLCommonSetupEvent | EchoNativeAddonRuntime.onInitialize() |
| RegisterEvent | EchoCoreServices.registry().register(...) |
| ServerStartingEvent | EchoNativeServerLifecycle.STARTING |
| PlayerEvent.PlayerLoggedInEvent | EchoPlayerService.joinEvent() |
5. Registry Porting
Use EchoCoreServices.contentRegistry() for blocks, items, and entities. If you need raw NeoForge registries, access them through the EchoNeoForgeBridge service.
6. Config
ECHO Native supports datapack-driven config and TOML files in config/<modid>/. For per-world config, use DataCore persistence services.
7. Networking
Replace raw SimpleChannel with echonetcore packet contracts. Define packet descriptors in JSON or Java records, then register with EchoNetService.
8. Testing
Add echo-native-testkit tests alongside NeoForge GameTest fixtures. Run both until you switch fully to NATIVE policy.
9. Validation
./gradlew validateAddon
./gradlew parityReport
Fix any ParityMismatch warnings before switching from NEOFORGE_BRIDGE to NATIVE.
Common Pitfalls
- Direct
ModListchecks in hot paths: Move them to setup or useEchoOptionalServices. - Accessing another addon's saved data: Use
DataCoreservice contracts. - Assuming NeoForge registries exist in Standalone lane: Guard with
EchoNativePolicy.current().hasNeoForgeBackend(). - Missing
sidein descriptor: Client-only code loaded on a server will crash.
Gradual Migration Path
| Stage | Policy | Goal |
|---|---|---|
| 1 | NEOFORGE_BRIDGE | Addon loads via NeoForge; services registered to ECHO. |
| 2 | NEOFORGE_BRIDGE | Replace direct cross-mod calls with service lookups. |
| 3 | NATIVE | Switch policy; verify with testkit + parity report. |
| 4 | STANDALONE (optional) | Strip NeoForge-only code for lightweight deployments. |
See AdapterCore Guide for bridge helpers.