@idosgames/module-sdk 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { IDosGamesClient } from '@idosgames/core';
1
+ import { RealtimeSession, IDosGamesClient } from '@idosgames/core';
2
2
  export { IDosGamesClient, SdkEvents } from '@idosgames/core';
3
3
  import { ComponentType } from 'react';
4
4
 
@@ -276,6 +276,87 @@ interface FeatureRegistry {
276
276
  setPresenter(presenter: FeaturePresenter): () => void;
277
277
  }
278
278
 
279
+ /** A room setting the host picks when creating a room for the game (guest mode, cheats…). */
280
+ interface MultiplayerSetting {
281
+ /** Key in `MultiplayerRoom.settings`. */
282
+ id: string;
283
+ /** Label, already in the player's language. */
284
+ label: string;
285
+ /** A choice of options, or an on/off switch. */
286
+ kind: "choice" | "toggle";
287
+ /** For `choice`: value + label of every option. */
288
+ options?: Array<{
289
+ value: string;
290
+ label: string;
291
+ }>;
292
+ /** Value when the host does not change it. */
293
+ default: string | boolean;
294
+ }
295
+ /** What a game declares about playing online (`ctx.multiplayer.registerGame`). */
296
+ interface MultiplayerGame {
297
+ /** The game's mode (its route id) — the room's game and where "Play" takes the room. */
298
+ mode: string;
299
+ /** Label of the game in the rooms screen; defaults to the route's label. */
300
+ label?: string;
301
+ /**
302
+ * Who connects to whom: `"Host"` (star — the host links to everyone, the others only to the host)
303
+ * or `"Mesh"` (everyone to everyone). Default `"Mesh"`.
304
+ */
305
+ topology?: "Host" | "Mesh";
306
+ /**
307
+ * `"P2P"` — the game has its own chat over the DataChannels, the lobby draws none;
308
+ * `"ServerRelay"` (default) — the lobby's room chat goes through the server.
309
+ */
310
+ chatMode?: "P2P" | "ServerRelay";
311
+ /** Most players in one room (the title's limit caps it). Default 8. */
312
+ maxPlayers?: number;
313
+ /**
314
+ * A player may join a room whose game is already running — the rooms screen lets them in and
315
+ * `start` gets called for them right away (the game's own "late joiner" path). Default `false`.
316
+ */
317
+ joinInProgress?: boolean;
318
+ /** Room settings the host picks on creation; the game reads them in `room.settings`. */
319
+ settings?: MultiplayerSetting[];
320
+ /**
321
+ * The room goes into this game: switch the game to network play over `room.session`. Called on
322
+ * EVERY member's device (the host's first) — after the app switched to the game's mode.
323
+ */
324
+ start(room: MultiplayerRoom): void | Promise<void>;
325
+ }
326
+ /** The room handed to a game. */
327
+ interface MultiplayerRoom {
328
+ /** The live session — links, messages, members, host changes. Opened by the rooms system. */
329
+ readonly session: RealtimeSession;
330
+ /** The game's mode. */
331
+ readonly mode: string;
332
+ /** Whether this player created the game (the host at start). Live host: `session.hostId`. */
333
+ readonly isHost: boolean;
334
+ /** The room's settings as the host picked them (defaults filled in). */
335
+ readonly settings: Readonly<Record<string, string | boolean>>;
336
+ /**
337
+ * The game joins a running room (`joinInProgress`) rather than starting together with it.
338
+ */
339
+ readonly lateJoin: boolean;
340
+ /** Leave the room for good: closes the session and the rooms screen forgets it. */
341
+ leave(): Promise<void>;
342
+ }
343
+ /** What `ctx.features.open("multiplayer", args)` understands. */
344
+ interface MultiplayerScreenArgs {
345
+ /** Show only this game's rooms and preselect it in "Create a room". */
346
+ mode?: string;
347
+ /** Open straight on "Create a room" (a game's "Open for friends"). */
348
+ create?: boolean;
349
+ }
350
+ /** `ctx.multiplayer` — the host's registry of games that play online, shared by every module. */
351
+ interface MultiplayerRegistry {
352
+ /** A game declares that it plays online. Returns an unregister function. */
353
+ registerGame(game: MultiplayerGame): () => void;
354
+ getGame(mode: string): MultiplayerGame | undefined;
355
+ listGames(): MultiplayerGame[];
356
+ /** Called when a game is registered or removed. */
357
+ subscribe(listener: () => void): () => void;
358
+ }
359
+
279
360
  /** What a module is, for catalog/UI purposes. Not every module is a game. */
280
361
  type ModuleType = "game" | "app" | "ai-app";
281
362
  /**
@@ -328,10 +409,19 @@ interface ModuleManifest {
328
409
  */
329
410
  type?: "template" | "feature";
330
411
  /**
331
- * Part of the standard set: the platform installs this module into EVERY new project together with
332
- * the base (login + lobby) — the shop, heroes, leaderboards… A creator removes it like any module.
412
+ * Part of the base: the platform installs this system into EVERY new project together with the base
413
+ * (sign-in + the lobby) — only profile, inventory, invite, friends, quests and mailbox (owner's rule
414
+ * 29.09.2026). Every other module is installed only when it is needed: a game brings the ones it
415
+ * `uses`, the AI Coder installs any other one as soon as the task needs what it `provides`. A creator removes it like any module.
333
416
  */
334
417
  inBase?: boolean;
418
+ /**
419
+ * A game's modules: catalog ids of the systems this game plugs into (`ctx.multiplayer` →
420
+ * `"multiplayer"`, `ctx.content` → `"workshop"`, …). The platform installs them together with the game
421
+ * — a new title on this game gets them, and so does a project the AI Coder adds the game to.
422
+ * `npm run check` makes a module that registers in `ctx.multiplayer` / `ctx.content` list them.
423
+ */
424
+ uses?: string[];
335
425
  /** Overrides the catalog display name; defaults to `ModuleMeta.name` from `module.ts`. */
336
426
  name?: string;
337
427
  /** One-line pitch shown on the catalog card. */
@@ -431,6 +521,12 @@ interface ModuleContext {
431
521
  * rather than a mode of its own; `open(id)` opens another module's screen. See `FeatureDefinition`.
432
522
  */
433
523
  features: FeatureRegistry;
524
+ /**
525
+ * Games that play online and the rooms system that runs them (see `MultiplayerGame`). A game
526
+ * registers here (`registerGame`) and takes the room in `start`; it never creates or joins rooms
527
+ * itself. Without the multiplayer system installed nothing ever calls `start`.
528
+ */
529
+ multiplayer: MultiplayerRegistry;
434
530
  /**
435
531
  * The app's modes — every route any module registered, and which one is on screen. The lobby
436
532
  * builds its "Play" buttons from it; a game can tell whether a lobby exists to return to.
@@ -600,4 +696,4 @@ interface SharedEventBus<Events extends Record<string, unknown> = Record<string,
600
696
  /** Identity helper that pins a module literal to the `Module` type for editor help and errors. */
601
697
  declare function defineModule(module: Module): Module;
602
698
 
603
- export { type CapturedContent, type ContentFileData, type ContentRegistry, type ContentTypeHandler, type DownloadedContent, type EngineScene, type FeatureDefinition, type FeatureEntry, type FeatureGroup, type FeaturePresenter, type FeatureRegistry, type FeatureScreenProps, type InferShape, type LocalContentItem, type ModeEntry, type ModeRegistry, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
699
+ export { type CapturedContent, type ContentFileData, type ContentRegistry, type ContentTypeHandler, type DownloadedContent, type EngineScene, type FeatureDefinition, type FeatureEntry, type FeatureGroup, type FeaturePresenter, type FeatureRegistry, type FeatureScreenProps, type InferShape, type LocalContentItem, type ModeEntry, type ModeRegistry, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type MultiplayerGame, type MultiplayerRegistry, type MultiplayerRoom, type MultiplayerScreenArgs, type MultiplayerSetting, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IDosGamesClient } from '@idosgames/core';
1
+ import { RealtimeSession, IDosGamesClient } from '@idosgames/core';
2
2
  export { IDosGamesClient, SdkEvents } from '@idosgames/core';
3
3
  import { ComponentType } from 'react';
4
4
 
@@ -276,6 +276,87 @@ interface FeatureRegistry {
276
276
  setPresenter(presenter: FeaturePresenter): () => void;
277
277
  }
278
278
 
279
+ /** A room setting the host picks when creating a room for the game (guest mode, cheats…). */
280
+ interface MultiplayerSetting {
281
+ /** Key in `MultiplayerRoom.settings`. */
282
+ id: string;
283
+ /** Label, already in the player's language. */
284
+ label: string;
285
+ /** A choice of options, or an on/off switch. */
286
+ kind: "choice" | "toggle";
287
+ /** For `choice`: value + label of every option. */
288
+ options?: Array<{
289
+ value: string;
290
+ label: string;
291
+ }>;
292
+ /** Value when the host does not change it. */
293
+ default: string | boolean;
294
+ }
295
+ /** What a game declares about playing online (`ctx.multiplayer.registerGame`). */
296
+ interface MultiplayerGame {
297
+ /** The game's mode (its route id) — the room's game and where "Play" takes the room. */
298
+ mode: string;
299
+ /** Label of the game in the rooms screen; defaults to the route's label. */
300
+ label?: string;
301
+ /**
302
+ * Who connects to whom: `"Host"` (star — the host links to everyone, the others only to the host)
303
+ * or `"Mesh"` (everyone to everyone). Default `"Mesh"`.
304
+ */
305
+ topology?: "Host" | "Mesh";
306
+ /**
307
+ * `"P2P"` — the game has its own chat over the DataChannels, the lobby draws none;
308
+ * `"ServerRelay"` (default) — the lobby's room chat goes through the server.
309
+ */
310
+ chatMode?: "P2P" | "ServerRelay";
311
+ /** Most players in one room (the title's limit caps it). Default 8. */
312
+ maxPlayers?: number;
313
+ /**
314
+ * A player may join a room whose game is already running — the rooms screen lets them in and
315
+ * `start` gets called for them right away (the game's own "late joiner" path). Default `false`.
316
+ */
317
+ joinInProgress?: boolean;
318
+ /** Room settings the host picks on creation; the game reads them in `room.settings`. */
319
+ settings?: MultiplayerSetting[];
320
+ /**
321
+ * The room goes into this game: switch the game to network play over `room.session`. Called on
322
+ * EVERY member's device (the host's first) — after the app switched to the game's mode.
323
+ */
324
+ start(room: MultiplayerRoom): void | Promise<void>;
325
+ }
326
+ /** The room handed to a game. */
327
+ interface MultiplayerRoom {
328
+ /** The live session — links, messages, members, host changes. Opened by the rooms system. */
329
+ readonly session: RealtimeSession;
330
+ /** The game's mode. */
331
+ readonly mode: string;
332
+ /** Whether this player created the game (the host at start). Live host: `session.hostId`. */
333
+ readonly isHost: boolean;
334
+ /** The room's settings as the host picked them (defaults filled in). */
335
+ readonly settings: Readonly<Record<string, string | boolean>>;
336
+ /**
337
+ * The game joins a running room (`joinInProgress`) rather than starting together with it.
338
+ */
339
+ readonly lateJoin: boolean;
340
+ /** Leave the room for good: closes the session and the rooms screen forgets it. */
341
+ leave(): Promise<void>;
342
+ }
343
+ /** What `ctx.features.open("multiplayer", args)` understands. */
344
+ interface MultiplayerScreenArgs {
345
+ /** Show only this game's rooms and preselect it in "Create a room". */
346
+ mode?: string;
347
+ /** Open straight on "Create a room" (a game's "Open for friends"). */
348
+ create?: boolean;
349
+ }
350
+ /** `ctx.multiplayer` — the host's registry of games that play online, shared by every module. */
351
+ interface MultiplayerRegistry {
352
+ /** A game declares that it plays online. Returns an unregister function. */
353
+ registerGame(game: MultiplayerGame): () => void;
354
+ getGame(mode: string): MultiplayerGame | undefined;
355
+ listGames(): MultiplayerGame[];
356
+ /** Called when a game is registered or removed. */
357
+ subscribe(listener: () => void): () => void;
358
+ }
359
+
279
360
  /** What a module is, for catalog/UI purposes. Not every module is a game. */
280
361
  type ModuleType = "game" | "app" | "ai-app";
281
362
  /**
@@ -328,10 +409,19 @@ interface ModuleManifest {
328
409
  */
329
410
  type?: "template" | "feature";
330
411
  /**
331
- * Part of the standard set: the platform installs this module into EVERY new project together with
332
- * the base (login + lobby) — the shop, heroes, leaderboards… A creator removes it like any module.
412
+ * Part of the base: the platform installs this system into EVERY new project together with the base
413
+ * (sign-in + the lobby) — only profile, inventory, invite, friends, quests and mailbox (owner's rule
414
+ * 29.09.2026). Every other module is installed only when it is needed: a game brings the ones it
415
+ * `uses`, the AI Coder installs any other one as soon as the task needs what it `provides`. A creator removes it like any module.
333
416
  */
334
417
  inBase?: boolean;
418
+ /**
419
+ * A game's modules: catalog ids of the systems this game plugs into (`ctx.multiplayer` →
420
+ * `"multiplayer"`, `ctx.content` → `"workshop"`, …). The platform installs them together with the game
421
+ * — a new title on this game gets them, and so does a project the AI Coder adds the game to.
422
+ * `npm run check` makes a module that registers in `ctx.multiplayer` / `ctx.content` list them.
423
+ */
424
+ uses?: string[];
335
425
  /** Overrides the catalog display name; defaults to `ModuleMeta.name` from `module.ts`. */
336
426
  name?: string;
337
427
  /** One-line pitch shown on the catalog card. */
@@ -431,6 +521,12 @@ interface ModuleContext {
431
521
  * rather than a mode of its own; `open(id)` opens another module's screen. See `FeatureDefinition`.
432
522
  */
433
523
  features: FeatureRegistry;
524
+ /**
525
+ * Games that play online and the rooms system that runs them (see `MultiplayerGame`). A game
526
+ * registers here (`registerGame`) and takes the room in `start`; it never creates or joins rooms
527
+ * itself. Without the multiplayer system installed nothing ever calls `start`.
528
+ */
529
+ multiplayer: MultiplayerRegistry;
434
530
  /**
435
531
  * The app's modes — every route any module registered, and which one is on screen. The lobby
436
532
  * builds its "Play" buttons from it; a game can tell whether a lobby exists to return to.
@@ -600,4 +696,4 @@ interface SharedEventBus<Events extends Record<string, unknown> = Record<string,
600
696
  /** Identity helper that pins a module literal to the `Module` type for editor help and errors. */
601
697
  declare function defineModule(module: Module): Module;
602
698
 
603
- export { type CapturedContent, type ContentFileData, type ContentRegistry, type ContentTypeHandler, type DownloadedContent, type EngineScene, type FeatureDefinition, type FeatureEntry, type FeatureGroup, type FeaturePresenter, type FeatureRegistry, type FeatureScreenProps, type InferShape, type LocalContentItem, type ModeEntry, type ModeRegistry, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
699
+ export { type CapturedContent, type ContentFileData, type ContentRegistry, type ContentTypeHandler, type DownloadedContent, type EngineScene, type FeatureDefinition, type FeatureEntry, type FeatureGroup, type FeaturePresenter, type FeatureRegistry, type FeatureScreenProps, type InferShape, type LocalContentItem, type ModeEntry, type ModeRegistry, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type MultiplayerGame, type MultiplayerRegistry, type MultiplayerRoom, type MultiplayerScreenArgs, type MultiplayerSetting, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idosgames/module-sdk",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "The composable-module contract for the iDosGames host shell: Module / ModuleContext types plus tiny authoring helpers. Framework-neutral at runtime — a module can be a game (Three/Phaser), a plain app, or an AI app.",
5
5
  "type": "module",
6
6
  "license": "MIT",