@cfxdevkit/game-engine
Reusable on-chain game state engine.
Install
pnpm
pnpm add @cfxdevkit/game-engineScope: Engine-agnostic, on-chain game primitives.
Responsibilities
- Game state machine abstractions (
GameEngine,GameState,Transition) - Turn / round / action dispatch (
dispatchAction,nextTurn,roundState) - Inventory & character interfaces (
Inventory,Character,Item) - Bridge between chain events and a Zustand-style local store (
createStoreAdapter) - Adapter interfaces for renderer (React, Phaser, …) (
RendererAdapter,RendererContext)
Non-goals
- Specific game rules (those stay in
projects/<game>). - UI/rendering (only defines interfaces to integrate with them).
Origin: chainbrawler/packages/core — extract the truly engine-shaped pieces, leave RPG-specific rules in the project.
Sub-paths
| Sub-path | Exports |
|---|---|
. | GameEngine, GameState, Transition, dispatchAction, nextTurn, roundState, Inventory, Character, Item, createStoreAdapter, RendererAdapter, RendererContext, __packageName |
.
Core Engine Types
export interface GameState {
currentRound: number;
currentPlayerIndex: number;
status: 'idle' | 'active' | 'paused' | 'finished';
}
export type Transition = (state: GameState) => GameState;
export interface GameEngine {
getState(): GameState;
applyTransition(transition: Transition): void;
reset(): void;
}Action Dispatch
export function dispatchAction(action: unknown): void;
export function nextTurn(): void;
export function roundState(): GameState['status'];Inventory & Character
export interface Item {
id: string;
name: string;
quantity: number;
}
export interface Inventory {
items: Item[];
addItem(item: Item): void;
removeItem(itemId: string, quantity: number): void;
}
export interface Character {
id: string;
name: string;
inventory: Inventory;
stats: Record<string, number>;
}Store Bridge
export function createStoreAdapter(store: {
subscribe: (listener: () => void) => () => void;
getState: () => GameState;
dispatch: (action: unknown) => void;
}): {
subscribe: (listener: () => void) => () => void;
getState: () => GameState;
dispatch: (action: unknown) => void;
};Renderer Integration
export interface RendererAdapter {
render(state: GameState): void;
}
export interface RendererContext {
engine: GameEngine;
adapter: RendererAdapter;
}Package Identifier
export declare const __packageName: "@cfxdevkit/game-engine";Usage
import { GameEngine, GameState, dispatchAction, createStoreAdapter } from '@cfxdevkit/game-engine';
// Define initial state
const initialState: GameState = {
currentRound: 1,
currentPlayerIndex: 0,
status: 'idle'
};
// Implement a simple engine
class SimpleEngine implements GameEngine {
private state: GameState = initialState;
getState(): GameState {
return this.state;
}
applyTransition(transition: (state: GameState) => GameState): void {
this.state = transition(this.state);
}
reset(): void {
this.state = initialState;
}
}
// Create engine and adapter
const engine = new SimpleEngine();
const storeAdapter = createStoreAdapter({
subscribe: (listener) => {
// Hook into engine state changes (e.g., via event emitter or polling)
const onChange = () => listener();
// In practice, wire this to engine state updates
return () => {};
},
getState: () => engine.getState(),
dispatch: (action) => dispatchAction(action)
});
// Example: advance round
engine.applyTransition((state) => ({
...state,
status: 'active',
currentRound: state.currentRound + 1
}));API Reference
See API.md for the full public surface.
Tier
Tier 2 — domains — May import Tier 0 and Tier 1 packages.
API Reference
.
Usage
import { __packageName } from "@cfxdevkit/game-engine";// The package name identifier.
export declare const __packageName: "@cfxdevkit/game-engine";Last updated on