Package Exports
- @memizy/multiplayer-sdk
Readme
Memizy Multiplayer SDK
TypeScript SDK for Memizy multiplayer plugins. It provides a declarative postMessage bridge for host and player plugins, plus manifest and sandbox helpers for standalone development.
Version: 0.3.0 (API 0.3)
What changed in v0.3
- Split-Lobby lifecycle is now first-class with 3 phases:
Init -> Prepare -> Start. context.runModenow indicates one ofhost-settings,host-game, orclient-game.- New incoming events:
PREPARE_GAMEandSTART_GAME. - New outgoing event:
MULTI_READYviasdk.postReadyToStart(). - SDK now injects package version automatically into
PLUGIN_READY. - Rich text helpers are available on the SDK instance via
sdk.parseTextTokens()andsdk.renderHtml().
Core APIs
createMultiplayerPlugin()creates the host/player bridge.loadManifestFromDataIsland()reads an OQSE manifest from<script type="application/oqse-manifest+json">.renderLandingPageIfNeeded()renders a standalone landing page when the plugin is opened outside an iframe.createLocalSandbox()mounts a local host/player preview for development.
Minimal plugin flow (3-Phase Start)
The SDK uses a "Split-Lobby" architecture. The Host app (Memizy) manages the network lobby and waiting screens. The plugin operates in 3 distinct modes provided via context.runMode:
host-settings: Renders a setup form on the teacher's screen before the game starts.host-game: Renders the main game board on the teacher's screen.client-game: Renders the controller on the students' devices.
import { createMultiplayerPlugin } from '@memizy/multiplayer-sdk'
const sdk = createMultiplayerPlugin()
// 1. Host Logic (Teacher's Screen)
sdk.defineHost({
onInit(context) {
if (context.runMode === 'host-settings') {
console.log('Render setup form (e.g., Round Time, Difficulty)')
} else if (context.runMode === 'host-game') {
console.log('Render main game board')
}
},
onPrepareGame(players) {
console.log('Final players received. Downloading 3D models/assets...', players)
// Signal Memizy that we are done loading so it can hide the "Get Ready" screen
sdk.postReadyToStart()
},
onStartGame() {
console.log('Memizy gave the green light. START!')
},
onPlayerAction(action, playerId) {
console.log('Player performed action', playerId, action)
}
})
// 2. Player Logic (Student's Phone)
sdk.definePlayer({
onInit(context) {
if (context.runMode === 'client-game') {
console.log('Render mobile controller (A/B/C/D buttons)')
}
},
onPrepareGame(players) {
sdk.postReadyToStart()
},
onStartGame() {
console.log('Enable buttons, start playing!')
}
})
sdk.start()Rich text helpers
For OQSE content, the SDK now exposes:
sdk.parseTextTokens(rawText)to parse OQSE tags/tokens.sdk.renderHtml(rawText, options?)to render safe HTML with asset and blank replacement.
Manifest data island
<script type="application/oqse-manifest+json">
{
"version": "0.1",
"id": "https://example.com/plugins/my-plugin/",
"appName": "My Plugin",
"description": "Standalone Memizy plugin",
"capabilities": {
"actions": ["render"],
"types": ["mcq-single", "short-answer"]
}
}
</script>For multiplayer host behavior, declare Memizy-specific flags in appSpecific.memizy.multiplayer (instead of extending universal OQSE fields):
{
"appSpecific": {
"memizy": {
"multiplayer": {
"apiVersion": "0.3",
"players": {
"min": 2,
"max": 60,
"recommended": 30
},
"supportsLateJoin": true,
"supportsReconnect": true,
"supportsTeams": false,
"requiresHostScreen": true,
"clientOrientation": "portrait"
}
}
}
}Standalone usage
When the plugin is opened directly in the browser, renderLandingPageIfNeeded() shows a lightweight landing page with manifest details and links to the docs and sandbox.
Local sandbox
Use createLocalSandbox({ mount, pluginUrl }) to mount a host and player iframe side by side and test the handshake locally.
Standalone quiz example: https://github.com/memizy/multiplayer-quiz