@lisachandra/platform
v1.0.0
Published
Platform integrations (documents, teleporter, centurion, startup glue) for @lisachandra
Downloads
26
Readme
@lisachandra/platform
Platform glue: bootstrap orchestration, Centurion admin commands, document persistence, and player teleportation.
Install
pnpm add @lisachandra/platformPeer dependencies: @lisachandra/types, @lisachandra/matter, @lisachandra/core, @flamework/core, @rbxts/centurion, @rbxts/dataforge, @rbxts/services, @rbxts/log, @rbxts/sift, @rbxts/t, @rbxts/serio, @rbxts/object-utils, @rbxts/rbxts-hashlib, @rbxts/regexp, @rbxts/luau-polyfill, @rbxts/matter, type-fest
Submodule Exports
| Import | Purpose |
| ------------------------------------------ | ------------------------------------------------ |
| @lisachandra/platform | Main: bootstrap, centurion utilities, teleporter |
| @lisachandra/platform/bootstrap | Client/server startup |
| @lisachandra/platform/centurion/type | Centurion type definitions |
| @lisachandra/platform/centurion/guards | Command authorization guards |
| @lisachandra/platform/centurion/commands | Admin commands |
| @lisachandra/platform/centurion/types | Custom Centurion argument types |
| @lisachandra/platform/centurion/utility | Type builder helpers |
| @lisachandra/platform/teleporter | Player teleportation |
| @lisachandra/platform/document | Document-based data |
Bootstrap
The single entry point for starting the game on client or server:
import { bootstrap } from "@lisachandra/platform";
import { configureRuntimeAdapters } from "@lisachandra/matter";
import { collection } from "./documents/playerData";
// Server entry point (main.server.ts)
configureRuntimeAdapters({
document: { collection },
playerLifecycle: {
preSpawn: async (player) => [true],
postSpawn(world, player, entityId) {
print(`Player ${player.Name} spawned!`);
},
},
});
const { world, crate, loop, boundary } = bootstrap({
mode: "development",
systems: mySystems,
modules: {
server: serverSystems, // Flamework barrel module
shared: sharedSystems,
},
hotReload: {
containers: [rewireContainer],
},
});
// Client entry point (main.client.ts)
const { world, crate } = bootstrap({
modules: { client: clientSystems, shared: sharedSystems },
});BootstrapOptions
| Option | Type | Description |
| ------------- | ------------------------------------- | -------------------------------------------------- |
| mode? | "development" \| "production" | Enables Rewire hot reload when development |
| modules? | { client?, server?, shared? } | Flamework barrel modules for auto-system discovery |
| systems? | Array<AnySystem> | Pre-resolved systems from pipeline/registry |
| hotReload? | { containers? } | Hot reload containers (development only) |
| extensions? | { containers?, modules?, systems? } | Ad-hoc extensions merged into boundary |
BootstrapResult
interface BootstrapResult {
world: World;
crate: Crate<ClientState | ServerState>;
loop: Loop<any>;
boundary: BootstrapBoundary;
}Centurion Commands
Pre-built admin commands with authorization:
| Command | Description | Arguments |
| -------------------------- | --------------------------------- | ---------------------------------------- |
| teleport (aliases: tp) | Teleport players to a target | from: Players, target: Player |
| kick | Kick players from the server | players: Players |
| document | Get document info for a player | user: Number |
| set | Set properties on an item by GUID | itemGuid: String, properties: String |
// Commands use @rbxts/centurion decorators
// Importing the commands module auto-registers them
import "@lisachandra/platform/centurion/commands";Custom Argument Types
import { Entity, Entities } from "@lisachandra/platform/centurion/types";
// Single entity by name/@me/@id
// Multi-entity with @all, @others, @query(), @except(), @only() prefixesGuards
import {
configureCenturionGroup,
configureCenturionRoles,
adminOrDeveloper,
} from "@lisachandra/platform/centurion/guards";
configureCenturionGroup(1234567); // Roblox group ID
configureCenturionRoles(["Developer", "Founder"]);
// adminOrDeveloper is used as @Guard on all commandsUtility
import { makeListableType, makeEnumType } from "@lisachandra/platform/centurion/utility";
// Make a single type listable
const ListablePlayer = makeListableType("Players", CenturionType.Player);
// Create an enum type
const GameModeType = makeEnumType("GameMode", ["Survival", "Creative", "Adventure"]);Teleporter
Secure, retryable player teleportation between places:
import {
teleport,
serializeTeleportData,
configureTeleport,
configureTeleportSecret,
isValidTeleport,
} from "@lisachandra/platform/teleporter";
// Configure once at startup
configureTeleport({ expiration: 300, attempts: 3, retry_delay: 1 });
configureTeleportSecret("my-secret-string");
// Serialize data for teleport
const options = serializeTeleportData({/* custom data */});
// Teleport players
const [success, result] = await teleport(placeId, [player], options);
// Validate on arrival
const { success, validHash, unexpired } = isValidTeleport(player);Document
Dataforge-based data persistence with validation:
import { configureRuntimeAdapters } from "@lisachandra/matter";
import dataforge from "@rbxts/dataforge";
// Create a custom store
const store = dataforge.create_store<CollectionData>({
name: "PlayerData",
template: {
banned: false,
hotbar: [],
inventory: [],
},
});
// Pass to matter
configureRuntimeAdapters({ document: { store } });For tests, createTestStore() builds an in-memory store backed by the dataforge memory hook and
virtual scheduler.
