miaoda-game-thirteen-water-react
v0.3.3
Published
React DOM bindings for the fixed four-player Thirteen Water rules profile.
Maintainers
Readme
miaoda-game-thirteen-water-react
React bindings and a framework-neutral controller for one four-player Thirteen Water hand.
pnpm add miaoda-game-thirteen-water-reactimport {
createThirteenWaterGame,
ThirteenWaterController,
useThirteenWaterView,
} from 'miaoda-game-thirteen-water-react';
const controller = new ThirteenWaterController(
createThirteenWaterGame({ playerIds: ['a', 'b', 'c', 'd'], seed: 2026 }),
'a',
);
function SubmitPartition({ partition }) {
const view = useThirteenWaterView(controller);
return view.legalActions.canSubmit ? (
<button
onClick={() => controller.dispatch({
type: 'submit-partition',
playerId: view.viewerId,
partition,
})}
>
Submit
</button>
) : null;
}Build partition in your UI or with miaoda-game-thirteen-water-analysis-core, then submit its exact
front/middle/back card ids. Render status and controls from the current view. Opponent hands and every
submitted layout remain hidden until all four submissions commit; the finished view reveals all
partitions, comparisons, scores, and winners together.
Commits and reconnects
const unsubscribe = controller.onCommit(({ revision, view, events }) => {
queueAnimations(events);
persistRevision(revision);
renderHud(view);
});
controller.replaceSnapshot(JSON.parse(savedJson), serverRevision);
controller.setViewerId('b');Only accepted submissions advance revision or publish commits. The first three commit events contain
only the submitting player id. The fourth commit contains that submission event followed by
hand-finished; layouts appear in the finished view, not in events. Invalid viewers, inconsistent
snapshots, and lower revisions throw without partially changing the controller. Authenticate reconnect
snapshots at the host boundary.
Phaser
pnpm add miaoda-game-command-phaserimport { PhaserGameBridge } from 'miaoda-game-command-phaser';
const bridge = new PhaserGameBridge().setup(controller);
bridge.consumeWith((event) => animateThirteenWaterEvent(event));
bridge.dispatch({ type: 'submit-partition', playerId: bridge.view.viewerId, partition });
bridge.destroy();
unsubscribe();The bridge exposes the same player-safe view as React and consumes detached events in commit order. Use the final view change to reveal layouts; do not expect private card ids in the animation queue.
