Skip to main content

server-runtime

@bedrock-core/server-runtime is the framework layer addons build on. Where @bedrock-core/sync is the low-level transport, the runtime is the thing you register into: an addon declares its identity and its data once, and that declaration flows into a cross-addon registry — a live directory of every bedrock-core addon present in the world.

Install

npm install @bedrock-core/server-runtime

Most addons install @bedrock-core/server instead, which re-exports everything below and pins a matching @bedrock-core/sync. Both imports are interchangeable:

import { core } from '@bedrock-core/server'; // meta-package (recommended)
import { core } from '@bedrock-core/server-runtime'; // direct

core — the runtime singleton

core is a Runtime instance. Import it, register once, and use it for the rest of the addon's life.

import { core } from '@bedrock-core/server-runtime';

core.register({ creator: 'drav0011', pack: 'economy', packName: 'Economy', version: '1.0.0' });

Every accessor below throws runtime.<name> is unavailable: call register() first until registration has happened.

MemberTypeWhat it is
core.registeredbooleanWhether register() has run. The one member safe to read before it.
core.idstringThis addon's namespace, creator_pack.
core.namespacestringAlias of core.id.
core.manifestAddonManifestThe validated manifest, identity fields only.
core.registryRegistryThe cross-addon directory.
core.featuresFeatureManagerCondition-driven togglable behaviour.
core.hostHostElectionWhich realm does the work only one realm may do.
core.stateScopedStateReplicated state, pre-scoped to this addon's namespace.
core.configConfigRegistrySchema, scopes and cross-addon config access.
core.translationsTranslationsRegistryCross-addon i18n bundles.
core.guidesGuidesRegistryCross-addon compiled guides.
core.rpcRpcRPC, passed through from the sync node.
core.nodeSyncNodeThe raw sync node — bus, discovery, unscoped state.

register()

register<I extends ConfigDefinition>(options: RegisterOptions<I> & { config: I }): Config<I>
register(options: RegisterOptions): void

Declare the addon and bring it online. Call exactly once — there is no separate start(). It throws on an invalid manifest and on a second call.

RegisterOptions is the manifest plus three optional declaration fields. Each is exactly equivalent to the standalone call listed beside it, which stays available for publishing late or replacing data at runtime:

FieldTypeEquivalent to
translationsI18nBundlecore.translations.provide()
guideGuideManifestcore.guides.provideManifest()
configConfigDefinitioncore.config.define()

When config is given, register() returns the typed scope accessors — the same value core.config.define() would return. Without it, the return type is void.

import { core } from '@bedrock-core/server-runtime';
import bundle from '@bedrock-core/generated/i18n';
import guides from '@bedrock-core/generated/guides';
import { configDef } from './example';

const config = core.register({
creator: 'drav0011',
pack: 'economy',
packName: 'Economy',
creatorName: 'DrAv0011',
version: '1.0.0',
description: 'Balances, currency and trading',
dependencies: ['drav0011_core_data'],
optionalDependencies: ['drav0011_leaderboard'],
icon: 'textures/ui/economy/icon',
thumbnail: 'textures/ui/economy/thumbnail',
translations: bundle,
guide: guides,
config: configDef,
});

config.server.get(); // fully typed

Manifest fields

interface AddonManifest {
creator: string;
pack: string;
packName: string;
version: string;
creatorName?: string;
description?: string;
dependencies?: string[];
optionalDependencies?: string[];
icon?: string;
thumbnail?: string;
}
FieldRequiredNotes
creatorCreator/vendor id. Must match /^[a-z0-9_]+$/ — lowercase alphanumeric and underscores.
packAbbreviated pack id, same character rule. Joined as creator_pack to form the namespace.
packNamePack display name. Not part of identity.
versionFree-form, e.g. semver. Announced to peers by discovery.
creatorNameCreator display name.
descriptionShort description.
dependenciesNamespaces (creator_pack) this addon needs. Soft — a missing one logs and fires an event, it never blocks.
optionalDependenciesNamespaces that unlock optional features when present.
iconResource-pack texture path for a registry UI icon, e.g. textures/ui/my_addon_logo.
thumbnailResource-pack texture path for a 16:9 banner.

Display fields are translation keys

packName, creatorName and description are assumed to be Minecraft translation keys shipped in the addon's resource pack .lang, so a registry UI can render them in each player's language. Plain text still works — Bedrock falls back to the literal string when no .lang entry matches.

import { createI18n } from '@bedrock-core/i18n';
import bundle from '@bedrock-core/generated/i18n';

const i18n = createI18n(bundle);

core.register({
creator: 'drav0011',
pack: 'economy',
packName: i18n.key($ => $.meta.name),
creatorName: i18n.key($ => $.meta.creator),
description: i18n.key($ => $.meta.description),
version: '1.0.0',
translations: bundle,
});

Validation

validateManifest(input) is exported, and register() runs it for you. It throws a descriptive error rather than letting a misconfigured addon misbehave silently:

InputError
Not an objectaddon manifest must be an object
Missing/empty creator, pack, packName or versionaddon manifest '<field>' is required and must be a non-empty string
creator or pack with an illegal characterinvalid <field> '<value>': must be lowercase alphanumeric and underscores only (a-z0-9_)
dependencies that is not a string[]addon manifest '<field>' must be an array of strings

addonNamespace(manifest) is exported too, and simply returns `${manifest.creator}_${manifest.pack}`.


stop()

core.stop();

Take the addon offline and clear every accessor. Safe to call before registering (no-op). Mostly useful in GameTests — a shipped addon registers and stays up.


Several runtimes in one realm

The Runtime class stands alone, so a GameTest can create several runtimes in one script realm. They talk over the real system script-event bus, and each register() brings its runtime online independently.

import { register, type Test } from '@minecraft/server-gametest';
import { Runtime } from '@bedrock-core/server-runtime';

register('core', 'discovery_and_rpc', (test: Test) => {
const a = new Runtime();

a.register({ creator: 'test', pack: 'demo_a', packName: 'A', version: '1.0.0' });

const b = new Runtime();

b.register({ creator: 'test', pack: 'demo_b', packName: 'B', version: '1.0.0' });
b.rpc.onRequest('ping', () => 'pong');

// a.id === 'test_demo_a', b.id === 'test_demo_b'

let reply: unknown;

test.startSequence()
.thenIdle(20)
.thenExecute(() => void a.rpc.request(b.id, 'ping').then((r) => { reply = r; }))
.thenIdle(20)
.thenExecute(() => {
if (!a.registry.has(b.id)) { test.fail('A did not discover B'); }

if (reply !== 'pong') { test.fail(`expected 'pong', got ${String(reply)}`); }

a.stop();
b.stop();
})
.thenSucceed();
}).structureName('core:empty').tag('core').maxTicks(220);

Use core — the singleton — in a real addon. One identity per pack.


Version helpers

import { RUNTIME_VERSION, compareVersions } from '@bedrock-core/server-runtime';
  • RUNTIME_VERSION — the version of @bedrock-core/server-runtime this build was compiled against. It is stamped into the discovery meta blob automatically, surfaces on every registry entry as runtimeVersion, and is what the host election compares. It is generated at release time; addons never set it.
  • compareVersions(a, b) — minimal semver comparison returning -1 / 0 / 1, suitable for Array.prototype.sort. Handles major.minor.patch with an optional -prerelease tail; anything unparseable sorts as 0.0.0 rather than throwing.

In This Section

PageDescription
RegistryEnumerate peers, resolve dependencies, detect namespace collisions
FeatureManagerBehaviour that toggles on a condition over registry and state
HostElectioncore.host — deterministic "who does the shared work"
ScopedStateReplicated key/value scoped to your namespace, with reserved keys
ConfigRegistrySchema, three scopes, persistence, cross-addon access, authorization
TranslationsRegistryPublish and resolve i18n bundles across addons
GuidesRegistryPublish and read compiled guide manifests across addons