Reusable Characters domain library for OpenCore.
This package provides:
- Character CRUD service logic
- Active character selection bound to
Playerruntime metadata - Slot policy abstraction (
CharacterSlotPolicyContract) - Deletion policy abstraction (
CharacterDeletionPolicyContract) - Internal library events through OpenCore Library API
- Optional external bridge events (
emitExternal)
This package intentionally does not include UI, gameplay situations, concrete database adapters, or appearance customization logic.
pnpm add @open-core/characters@open-core/characters/server@open-core/characters/client@open-core/characters/shared
The store is required and must implement CharacterStoreContract.
import { CharacterStoreContract } from '@open-core/characters/shared'
class MyCharacterStore extends CharacterStoreContract {
async listByAccount(accountId) { /* ... */ }
async getById(characterId) { /* ... */ }
async create(character) { /* ... */ }
async update(character) { /* ... */ }
async delete(characterId) { /* ... */ }
}import { Server } from '@open-core/framework/server'
import { charactersServerPlugin } from '@open-core/characters/server'
await Server.init({
mode: 'CORE',
plugins: [
charactersServerPlugin({
store: new MyCharacterStore(),
baseSlots: 3,
bridgeExternalEvents: false,
}),
],
})import { CharactersModule } from '@open-core/characters/server'
const characters = CharactersModule.resolveService()import { CharactersModule } from '@open-core/characters/server'
CharactersModule.setStore(new MyCharacterStore())
CharactersModule.install({
baseSlots: 3,
bridgeExternalEvents: false,
})Event hub: CharactersEvents.
Internal events emitted by the library:
created->{ character }updated->{ character }deleted->{ characterId, accountId }selected->{ player, character }unselected->{ player, characterId }
Example:
import { CharactersEvents } from '@open-core/characters/server'
CharactersEvents.on('created', ({ character }) => {
// internal reaction
})When bridgeExternalEvents: true is used, the module also emits minimal cross-resource events with namespaced event ids:
opencore:characters:createdopencore:characters:updatedopencore:characters:deletedopencore:characters:selectedopencore:characters:unselected
These external payloads are stable and intentionally minimal.
The selected character is stored in player metadata key:
opencore.characters.active
Use CharactersService.getActive(player) and CharactersService.clearActive(player) to manage this state.
Client helper surface is minimal and transport-focused:
CharactersClientrequestCharacterSelect(characterId)requestCharacterCreate(input)
No UI is included.
Additional docs are available in docs/:
For a full practical flow (store + install + create/select/update appearance + event listeners), see the concrete example in docs/server-api.md.