Exact API signatures
This page is generated from the SDK declarations in this repository. It documents parameter names, optional arguments, return values, and the types used by the client and server guides. These are type declarations, not runnable examples. Expand the entry you need.
Use the SDK version installed in your project as the final compatibility check. Development-only APIs may appear here before a hosted release supports them. For permissions, behavior, and examples, start with the API map.
Regenerate with node scripts/generate-docs-api.mjs; verify with --check.
Server context
Source: packages/mod-sdk/server/index.ts.
ModServerContext
export interface ModServerContext {
readonly modId: string;
readonly worldId: string;
/** Per-world config resolved against the manifest configSchema. */
readonly config: Record<string, unknown>;
/** Own custom subscriptions/handles that must be released with this runtime instance. */
readonly resources: ModResourceScope;
/** Experimental schema-validated host reads; currently only player.list. */
readonly operations: ModServerOperations;
/** Experimental pinned-contract service composition. Provider code never receives host internals. */
readonly services: {
provide(
serviceId: string,
handlers: Record<string, ModServiceHandler>,
): Promise<ModResult<ModServiceProviderHandle>>;
call(serviceId: string, methodId: string, input: unknown): Promise<ModResult<unknown>>;
};
/**
* Host wall-clock in epoch milliseconds. Prefer this over `Date.now()` for
* anything you store on world state or compare against later: the test
* harness and replay tooling drive this clock, so mod timing stays
* deterministic instead of depending on the machine's real time.
*/
now(): number;
world: {
worldName: string;
terrainSeed: number;
terrainSize: number;
seaLevel: number;
biome: string;
getGroundHeight(x: number, z: number): number;
getTimeOfDay(): number;
getWeather(): { type: string; intensity: number };
/** Requires 'world.entities.read'; player rows additionally require 'players.read'. */
entities: {
get(ref: ModEntityRef): Promise<ModWorldEntitySnapshot | null>;
query(query?: ModWorldEntityQuery): Promise<ModWorldEntitySnapshot[]>;
findNearby(position: ModVec3, radius: number, query?: ModWorldEntityQuery): Promise<ModWorldEntitySnapshot[]>;
};
};
players: {
get(sessionId: string): ModPlayerView | null;
list(): ModPlayerView[];
/** True for world owners / admins — for "override someone else's stuff" checks. */
canEditWorld(sessionId: string): boolean;
/** Teleport a live walking player onto terrain. Requires 'players.teleport'. */
teleport(sessionId: string, destination: { x: number; z: number }): boolean;
/**
* Apply bounded server-authoritative damage to a live, non-dead player.
* Amount is clamped to (0, 100] by the host. Requires 'players.damage'.
*/
applyDamage(sessionId: string, amount: number, label?: string): boolean;
};
/**
* World objects whose preset this mod owns via manifest editorItems
* (claimed or mod:-namespaced). Reads require 'world.objects.read';
* setFarm/setProperties require 'world.objects.write'. setX persists to
* the world database when persist is true (default).
*/
objects: {
list(preset?: string): ModWorldObjectView[];
get(id: string): ModWorldObjectView | null;
setFarm(id: string, farm: Partial<ModObjectFarmState>, opts?: { persist?: boolean }): boolean;
setProperties(id: string, properties: Record<string, unknown>, opts?: { persist?: boolean }): boolean;
};
/**
* Player inventories (persistent, host-owned). Requires the
* 'players.inventory' permission. Mutations push the fresh inventory
* state to the affected client automatically. Item ids must be core
* items or items registered via manifest `items`.
*/
inventory: {
count(sessionId: string, itemId: string): Promise<number>;
/** Every stack the player carries, in one read. */
list(sessionId: string): Promise<ModItemStack[]>;
grant(sessionId: string, itemId: string, quantity?: number): Promise<boolean>;
remove(sessionId: string, itemId: string, quantity?: number): Promise<boolean>;
};
/**
* The world's item catalog — core items and every enabled mod's manifest
* `items` — so a mod can name, price and accept items it does not own.
* No permission needed; `list()` returns mod-contributed items only.
*/
items: {
get(itemId: string): ModItemView | null;
list(): ModItemView[];
};
/** Replicated mod entities. Requires the 'world.entities' permission. */
entities: {
spawn(init: ModEntityInit): string | null;
update(id: string, patch: ModEntityUpdate): boolean;
/** Applies a server-authoritative impulse to this mod's dynamic entity. */
applyImpulse(
id: string,
impulse: ModVec3,
point?: ModVec3,
ownerSessionId?: string,
): boolean;
remove(id: string): boolean;
has(id: string): boolean;
list(): ModEntityView[];
count(): number;
};
/** Engine-neutral authoritative physics actions for mod-owned bodies. */
physics: {
/** Compatibility peer of `ctx.entities.applyImpulse`; requires `physics.colliders`. */
applyImpulse(
id: string,
impulse: ModVec3,
point?: ModVec3,
ownerSessionId?: string,
): boolean;
/** Accumulates a world-space force for the next authoritative solver step. */
applyForce(id: string, force: ModVec3, point?: ModVec3, ownerSessionId?: string): boolean;
applyTorque(id: string, torque: ModVec3, ownerSessionId?: string): boolean;
setVelocity(
id: string,
linearVelocity: ModVec3,
angularVelocity?: ModVec3,
ownerSessionId?: string,
): boolean;
getBodyState(id: string): Promise<ModPhysicsBodyState | null>;
/**
* Grants solver-rate snapshots to one connected participant for a bounded
* interval. Server authority never transfers; renew while control is active.
*/
acquireControl(id: string, sessionId: string, durationMs?: number): Promise<ModPhysicsControlLease | null>;
releaseControl(id: string, sessionId?: string): Promise<boolean>;
getControl(id: string): Promise<ModPhysicsControlLease | null>;
/** Requires `physics.joints`; both endpoints must be this mod's live physics entities. */
createJoint(definition: ModPhysicsJointDefinition): Promise<string | null>;
removeJoint(jointId: string): Promise<boolean>;
getJoint(jointId: string): Promise<ModPhysicsJointView | null>;
listJoints(): Promise<ModPhysicsJointView[]>;
};
/** Host-owned authoritative player zones. Requires `world.zones`. */
zones: {
create(definition: ModZoneDefinition): Promise<string | null>;
remove(zoneId: string): Promise<boolean>;
get(zoneId: string): Promise<ModZoneView | null>;
list(): Promise<ModZoneView[]>;
contains(zoneId: string, sessionId: string): Promise<boolean>;
};
/** Declarative host-validated interaction catalog. Requires `world.interactions`. */
interactions: {
register(definition: ModInteractionDefinition): Promise<string | null>;
remove(interactionId: string): Promise<boolean>;
get(interactionId: string): Promise<ModInteractionView | null>;
list(): Promise<ModInteractionView[]>;
};
/** Host-owned activity graph runtime. Requires `world.activities`. */
activities: {
register(definition: ModActivityDefinition): Promise<string | null>;
unregister(definitionId: string): Promise<boolean>;
create(
definitionId: string,
options: { sessionIds: readonly string[]; variables?: Record<string, unknown> },
): Promise<ModActivityInstance | null>;
get(instanceId: string): Promise<ModActivityInstance | null>;
list(): Promise<ModActivityInstance[]>;
start(instanceId: string): Promise<boolean>;
pause(instanceId: string): Promise<boolean>;
resume(instanceId: string): Promise<boolean>;
cancel(instanceId: string): Promise<boolean>;
completeObjective(instanceId: string, objectiveId: string, patch?: Record<string, unknown>): Promise<boolean>;
resolveCustomNode(instanceId: string, nodeId: string, patch?: Record<string, unknown>): Promise<boolean>;
};
/** Small replicated KV blob, broadcast to every client. */
state: {
set(data: Record<string, unknown>): boolean;
get(): Record<string, unknown> | null;
};
/** Persistent per-mod per-world storage. Requires the 'storage' permission. */
storage: {
get<T = unknown>(key: string): Promise<T | null>;
set(key: string, value: unknown): Promise<boolean>;
delete(key: string): Promise<void>;
};
messages: {
send(sessionId: string, type: string, data?: unknown): void;
broadcast(type: string, data?: unknown): void;
};
/** Requires the 'players.modify' permission. */
rewards: {
grantMoney(sessionId: string, amountCents: number, label?: string): Promise<boolean>;
grantXp(sessionId: string, xp: number, label?: string): Promise<boolean>;
/**
* Atomically debit a live player's money. Resolves false (and changes
* nothing) when the player is gone, dead, signed out or cannot afford it.
* Amount is a positive integer of cents, at most 1 000 000 per call.
*/
spendMoney(sessionId: string, amountCents: number, label?: string): Promise<boolean>;
};
/** Host-owned timers; automatically cleared on dispose/disable. */
schedule: {
interval(ms: number, fn: () => void): () => void;
timeout(ms: number, fn: () => void): () => void;
};
log(...args: unknown[]): void;
}Server hooks
Source: packages/mod-sdk/server/index.ts.
ModServerHooks
export interface ModServerHooks {
/** How often onTick fires. Default 100 ms; clamped by the host to [16, 5000]. */
tickIntervalMs?: number;
onWorldStart?(ctx: ModServerContext): void | Promise<void>;
onPlayerJoin?(ctx: ModServerContext, player: ModPlayerView): void;
onPlayerLeave?(ctx: ModServerContext, sessionId: string): void;
onZoneEnter?(ctx: ModServerContext, event: ModZonePlayerEvent): void;
onZoneExit?(ctx: ModServerContext, event: ModZonePlayerEvent): void;
onInteraction?(ctx: ModServerContext, event: ModInteractionEvent): void | Promise<void>;
onActivityEvent?(ctx: ModServerContext, event: ModActivityEvent): void | Promise<void>;
onPhysicsJointEvent?(ctx: ModServerContext, event: ModPhysicsJointEvent): void | Promise<void>;
onPhysicsCollisionEvent?(ctx: ModServerContext, event: ModPhysicsCollisionEvent): void | Promise<void>;
/**
* A validated weapon shot hit one of this mod's physics entities.
* Requires 'physics.colliders' (the entity must have a physics body).
*/
onEntityWeaponHit?(ctx: ModServerContext, event: ModEntityWeaponHitEvent): void | Promise<void>;
/**
* Gate for this mod's harvestable presets, consulted before every tool hit.
* Must be synchronous and cheap (keep the data it needs cached); return
* false or a player-facing reason to refuse. Only in-process (internal)
* mods are consulted — sandboxed workers are never asked and never block.
*/
canHarvestResource?(ctx: ModServerContext, event: ModResourceHarvestContext): ModGateResult;
/**
* A resource node was depleted and its rewards granted. Fires for every
* enabled mod with 'players.read' (not only the preset owner), so a skills
* mod can reward harvesting other mods' trees or rocks.
*/
onResourceHarvested?(ctx: ModServerContext, event: ModResourceHarvestedEvent): void | Promise<void>;
/** Gate for this mod's recipes; same rules as canHarvestResource. */
canCraftRecipe?(ctx: ModServerContext, event: ModRecipeCraftContext): ModGateResult;
/** One of this mod's recipes was crafted and its ingredients consumed. */
onRecipeCrafted?(ctx: ModServerContext, event: ModRecipeCraftedEvent): void | Promise<void>;
onTick?(ctx: ModServerContext, dtSeconds: number): void;
onMessage?: Record<string, ModMessageHandler>;
/** A player placed one of this mod's editor items in the world. */
onEditorObjectPlaced?(ctx: ModServerContext, event: ModEditorObjectEvent): void;
/** One of this mod's editor-item objects was deleted from the world. */
onEditorObjectRemoved?(ctx: ModServerContext, event: ModEditorObjectEvent): void;
onDispose?(ctx: ModServerContext): void | Promise<void>;
}Client functions
Source: packages/mod-sdk/client/index.d.ts.
ProceduralModel
export declare function ProceduralModel(props: {
createModel: (options?: unknown) => unknown;
options?: unknown;
[key: string]: unknown;
}): any;disposeProceduralModel
export declare function disposeProceduralModel(model: unknown): void;useModResourceScope
export declare function useModResourceScope(label?: string): import('../shared').ModResourceScope;useSignalValue
export declare function useSignalValue<T>(signal: { value: T } | null | undefined): T | undefined;useWorldInfo
export declare function useWorldInfo(): ModWorldInfo;useTerrainSampler
export declare function useTerrainSampler(): ((x: number, z: number) => number) | null;useAtmosphereFrame
export declare function useAtmosphereFrame(): { current: ModAtmosphereFrame };useGraphicsQuality
export declare function useGraphicsQuality(): 'low' | 'balanced' | 'high' | string;useRenderPipeline
/** Active render pipeline; see manifest `rendering.pipelines`. */
export declare function useRenderPipeline(): 'classic' | 'node';useNodeRenderer
/** Host `three/webgpu` module (NodeMaterials + `TSL`) on the node pipeline; null on classic. */
export declare function useNodeRenderer(): (Record<string, any> & { TSL: Record<string, any> }) | null;useNodePointSpriteMaterial
/** Registers a node-pipeline sprite material for a GLSL `THREE.Points` material. */
export declare function useNodePointSpriteMaterial(): <M extends import('three').Material>(
material: M,
create: (ctx: ModNodePointSpriteContext) => import('three').Material,
) => M;useWeather
export declare function useWeather(): { type: string; intensity: number; [key: string]: unknown };useLocalPlayerGetter
export declare function useLocalPlayerGetter(): () => ModPlayerClientView | null;useTimeOfDayGetter
export declare function useTimeOfDayGetter(): () => number;usePlayersLite
export declare function usePlayersLite(): ModPlayerClientView[];usePlayerGetter
export declare function usePlayerGetter(): (sessionId: string) => ModPlayerClientView | null;useWorldSurface
export declare function useWorldSurface(): Record<string, unknown> | null;useWorldEntityQuery
export declare function useWorldEntityQuery(
query?: import('../shared').ModWorldEntityQuery,
options?: { pollMs?: number },
): import('../shared').ModWorldEntitySnapshot[];useWorldEntity
export declare function useWorldEntity(
ref: import('../shared').ModEntityRef | null | undefined,
options?: { pollMs?: number },
): import('../shared').ModWorldEntitySnapshot | null;useModInteractions
export declare function useModInteractions(): import('../shared').ModInteractionView[];useExecuteModInteraction
export declare function useExecuteModInteraction(): (
interactionId: string,
options?: { operationId?: string; autoComplete?: boolean },
) => ModInteractionExecutionHandle;useLocalAvatarPositionGetter
export declare function useLocalAvatarPositionGetter(): () => ModVec3Like | null;distanceSqToBounds2d
export declare function distanceSqToBounds2d(
position: ModVec3Like,
target: ModVec3Like,
halfExtents?: Partial<Pick<ModVec3Like, 'x' | 'z'>>,
): number;useLocalAvatarProximity
export declare function useLocalAvatarProximity(
target: ModVec3Like | null,
options?: ModProximityOptions,
): ModProximityResult | null;useCloudLayerRegistration
export declare function useCloudLayerRegistration(
options?: ModSurfaceLeaseOptions,
): (layer: unknown, options?: ModSurfaceLeaseOptions) => ModSurfaceLease;useFogVolumeRegistration
export declare function useFogVolumeRegistration(
options?: ModSurfaceLeaseOptions,
): (volume: unknown, options?: ModSurfaceLeaseOptions) => ModSurfaceLease;useWorldObjects
export declare function useWorldObjects(preset?: string): ModWorldObjectClientView[];useWorldVegetationClearings
export declare function useWorldVegetationClearings(): Array<{
x: number;
z: number;
yaw?: number;
shape?: 'rect' | 'rounded' | 'circle';
halfX?: number;
halfZ?: number;
radius?: number;
corner?: number;
}>;useNearestWorldObject
export declare function useNearestWorldObject(
preset: string,
options?: ModProximityOptions,
): ModNearestWorldObjectResult | null;useModKeyAction
export declare function useModKeyAction(options: ModKeyActionOptions): void;useModCameraShotRegistration
export declare function useModCameraShotRegistration(
options?: ModSurfaceLeaseOptions,
): (provider: ModCameraShotProvider, options?: ModSurfaceLeaseOptions) => ModSurfaceLease;useModCinematicDirector
/** Requires camera.control; returns a disabled data-only API when denied. */
export declare function useModCinematicDirector(): ModCinematicDirectorApi;useModInputAction
export declare function useModInputAction(options: ModInputActionOptions): void;useModControlSession
export declare function useModControlSession(options?: ModControlSessionOptions): void;useModControlInputAction
export declare function useModControlInputAction(options: ModControlInputActionOptions): void;useModConfig
export declare function useModConfig<T extends Record<string, unknown> = Record<string, unknown>>(): T;useEditorMode
export declare function useEditorMode(): boolean | undefined;useEditorSelectedEntity
export declare function useEditorSelectedEntity(): unknown;useDeterministicRng
export declare function useDeterministicRng(salt?: string): () => number;useModState
export declare function useModState<T extends Record<string, unknown> = Record<string, unknown>>(): T | null;useModEntityList
export declare function useModEntityList<T = Record<string, unknown>>(): T[];useModEntityIds
export declare function useModEntityIds(): string[];useModEntity
export declare function useModEntity<T = Record<string, unknown>>(entityId: string): T | null;useModMessage
export declare function useModMessage<T = unknown>(
type: string,
handler: (data: T) => void,
): void;useSendModMessage
export declare function useSendModMessage(): (
type: string,
data?: unknown,
options?: ModMessageSendOptions,
) => string | void;useTypedModMessage
/** Typed server -> client subscription using a generated message map. */
export declare function useTypedModMessage<
Messages extends ModMessageMap,
Type extends keyof Messages & string,
>(type: Type, handler: (data: Messages[Type]) => void): void;useTypedSendModMessage
/** Typed client -> server sender using a generated message map. */
export declare function useTypedSendModMessage<Messages extends ModMessageMap>(): <
Type extends keyof Messages & string,
>(type: Type, data: Messages[Type], options?: ModMessageSendOptions) => string | void;useModNotifications
export declare function useModNotifications(): ModNotificationApi;useModHudSurfaces
export declare function useModHudSurfaces(): ModHudSurfaceApi;useModDialogs
export declare function useModDialogs(): ModDialogApi;useModPermissions
export declare function useModPermissions(): readonly string[];useModAudio
export declare function useModAudio(): ModAudioApi;useModAudioBus
export declare function useModAudioBus(): GainNode | null;useModSpatialAudio
export declare function useModSpatialAudio(
position: ModVec3Like | null | undefined,
options?: ModSpatialAudioOptions,
): PannerNode | null;useModAssetUrl
export declare function useModAssetUrl(relativePath: string): string;useModGltf
export declare function useModGltf<T = unknown>(relativePath: string): T | null;useModTexture
export declare function useModTexture<T = unknown>(relativePath: string): T | null;useModAudioBuffer
export declare function useModAudioBuffer(relativePath: string): AudioBuffer | null;useModFrame
export declare function useModFrame(
callback: (state: ModFrameState, delta: number, frame?: unknown) => void,
options?: number | ModFrameOptions,
): void;sharedStandardMaterial
/**
* Shared, value-keyed materials. Never dispose or mutate what these return —
* the instance is shared with every other caller asking for the same props.
*/
export declare function sharedStandardMaterial(props: Record<string, unknown>): any;sharedBasicMaterial
export declare function sharedBasicMaterial(props: Record<string, unknown>): any;sharedMaterialForPart
export declare function sharedMaterialForPart(part: InstancedObjectBatchPart): any;mergeBatchParts
/**
* Bakes each part's transform and colour (sRGB hex, multiplied into any
* existing vertex colours) into a vertex `color` attribute and merges parts
* that share material type/props and shadow flags into one geometry, so a
* multi-part prop costs one batch bucket (one draw call). Clones geometry:
* call once per distinct appearance and cache the result. Keys are unique per
* call unless `options.key` is given (it must then be unique per merge).
*/
export declare function mergeBatchParts(
parts: InstancedObjectBatchPart[],
options?: { key?: string },
): MergedBatchPart[];countGeometryTriangles
/** Triangle count of a geometry (indexed or not). */
export declare function countGeometryTriangles(geometry: unknown): number;ObjectPartsMesh
/**
* Renders batch part specs as plain meshes with shared materials, for editor
* ghosts and library previews.
*/
export declare function ObjectPartsMesh(props: {
itemId: string;
properties: Record<string, unknown>;
renderMode?: string;
getParts(args: {
itemId: string;
properties: Record<string, unknown>;
}): InstancedObjectBatchPart[];
name?: string;
/** Prefix for part mesh names; pass an empty string to show only the part key. */
partNamePrefix?: string;
}): any;InstancedObjectBatchRenderer
export declare function InstancedObjectBatchRenderer(props: {
itemId: string;
objects: ModWorldObjectClientView[];
getParts(args: {
itemId: string;
properties: Record<string, unknown>;
object: ModWorldObjectClientView;
}): InstancedObjectBatchPart[];
namePrefix?: string;
}): any;PooledPointLight
export declare function PooledPointLight(props: PooledLightProps & {
follow?: boolean;
handleRef?: import('react').MutableRefObject<PooledPointLightHandle | null>;
}): any;PooledSpotLight
export declare function PooledSpotLight(props: PooledLightProps & {
angle?: number;
penumbra?: number;
lightRef?: import('react').Ref<PooledSpotLightSource>;
}): any;PooledDirectionalLight
/** Directional light from the host's fixed rig; direction runs from the source to its target. No shadows. */
export declare function PooledDirectionalLight(props: PooledEnvironmentLightProps): any;PooledAmbientLight
/** Ambient light from the host's fixed rig; only color and intensity apply. */
export declare function PooledAmbientLight(props: PooledEnvironmentLightProps): any;selectNearestObjects
export declare function selectNearestObjects<T extends ModWorldObjectClientView>(
objects: T[],
origin: { x: number; z: number } | null | undefined,
limit: number,
): T[];PooledObjectPointLights
export declare function PooledObjectPointLights(props: {
objects: ModWorldObjectClientView[];
getLightSpec(
object: ModWorldObjectClientView,
properties: Record<string, unknown>,
): PooledPointLightSpec | null;
/** @deprecated Selection belongs to the host master; ignored. */
limit?: number;
/** @deprecated Static batches update on object changes; ignored. */
pollSeconds?: number;
}): any;defineModClient
export declare function defineModClient<T extends ModClientDefinition>(definition: T): T;useModScreenEffect
/** Returns a request function; its result cancels the effect. Unmount also cancels it. */
export declare function useModScreenEffect(): (definition: ModScreenEffectDefinition) => () => void;Physics components and hooks
Source: packages/mod-sdk/physics/index.d.ts.
ReplicatedDynamicBox
export declare function ReplicatedDynamicBox(
props: ModPhysicsColliderProps & { entityId: string },
): any;ReplicatedDynamicSphere
export declare function ReplicatedDynamicSphere(
props: ModPhysicsColliderProps & { entityId: string },
): any;ReplicatedDynamicBoxInstances
export declare function ReplicatedDynamicBoxInstances(
props: ModPhysicsColliderProps & {
groups: unknown[];
collisionProxyLimit?: number;
preventVisualInterpenetration?: boolean;
presentationGroupProperty?: string;
},
): any;ReplicatedDynamicSphereInstances
export declare function ReplicatedDynamicSphereInstances(
props: ModPhysicsColliderProps & {
groups: unknown[];
collisionProxyLimit?: number;
preventVisualInterpenetration?: boolean;
presentationGroupProperty?: string;
},
): any;usePhysicsRaycast
export declare function usePhysicsRaycast(): (
origin: ModVec3Like,
translation: ModVec3Like,
filter?: Record<string, unknown>,
) => ModRaycastHit | null;Server types and helpers
Source: packages/mod-sdk/server/index.ts.
ModVec3
export interface ModVec3 {
x: number;
y: number;
z: number;
}ModQuat
export interface ModQuat {
x: number;
y: number;
z: number;
w: number;
}ModPlayerView
/** Snapshot view of a player. Never a live schema reference. */
export interface ModPlayerView {
sessionId: string;
userId: string;
name: string;
level: number;
mode: string;
dead: boolean;
position: ModVec3;
}ModEntityView
export interface ModEntityView {
id: string;
kind: string;
position: ModVec3;
rotation: ModQuat;
scale: ModVec3;
velocity: ModVec3;
angularVelocity: ModVec3;
properties: Record<string, unknown>;
/** Manifest-declared component values, keyed by this mod's local component id. */
components: Record<string, unknown>;
ownerSessionId: string;
physicsTick: number;
physics?: ModDynamicPhysics;
}ModEntityInit
export interface ModEntityInit {
/** Optional stable suffix; final id is `<modId>:<suffix>`. Auto-generated when omitted. */
id?: string;
kind: string;
position: ModVec3;
rotation?: ModQuat;
scale?: ModVec3 | number;
velocity?: ModVec3;
angularVelocity?: ModVec3;
properties?: Record<string, unknown>;
/** Initial values for manifest-declared component descriptors. */
components?: Record<string, unknown>;
ownerSessionId?: string;
/**
* Host-owned, server-authoritative physics. Requires both `world.entities`
* and `physics.colliders`; clients render/reconcile the replicated body.
*/
physics?: ModDynamicPhysics;
}ModDynamicPhysics
export type ModDynamicPhysics = ModDynamicBoxPhysics | ModDynamicSpherePhysics;ModDynamicMaterialPhysics
export interface ModDynamicMaterialPhysics {
density?: number;
friction?: number;
restitution?: number;
linearDamping?: number;
angularDamping?: number;
gravityScale?: number;
canSleep?: boolean;
ccd?: boolean;
}ModDynamicBoxPhysics
export interface ModDynamicBoxPhysics extends ModDynamicMaterialPhysics {
type: 'dynamic-box';
halfExtents: ModVec3;
/** Optional host-owned hinge from this body to the static world. */
constraint?: ModHingeConstraint;
}ModDynamicSpherePhysics
export interface ModDynamicSpherePhysics extends ModDynamicMaterialPhysics {
type: 'dynamic-sphere';
radius: number;
}ModHingeConstraint
export interface ModHingeConstraint {
type: 'hinge';
/** Hinge axis in the entity's local space. */
axis: ModVec3;
/** Optional hinge point in the entity's local space. Defaults to the body origin. */
anchor?: ModVec3;
/** Optional lower/upper angular stops, in radians. */
limits?: readonly [number, number];
}ModEntityUpdate
export interface ModEntityUpdate {
kind?: string;
position?: ModVec3;
rotation?: ModQuat;
scale?: ModVec3 | number;
velocity?: ModVec3;
angularVelocity?: ModVec3;
properties?: Record<string, unknown>;
/** Partial component patch. A null value removes that component. */
components?: Record<string, unknown | null>;
ownerSessionId?: string;
}ModEntityGroup
export interface ModEntityGroup {
readonly label: string;
readonly ids: readonly string[];
/** Applies one reset/update patch per member in stable spawn order. */
updateAll(patches: readonly ModEntityUpdate[]): boolean;
/** Idempotently removes every member through the host lifecycle. */
remove(): void;
}ModServiceCallContext
export interface ModServiceCallContext {
readonly originModId: string;
readonly consumerModId: string;
readonly providerModId: string;
readonly serviceId: string;
readonly methodId: string;
readonly depth: number;
call(serviceId: string, methodId: string, input: unknown): Promise<ModResult<unknown>>;
}ModServiceHandler
export type ModServiceHandler = (
input: unknown,
context: ModServiceCallContext,
) => unknown | Promise<unknown>;ModServiceProviderHandle
export interface ModServiceProviderHandle {
readonly serviceId: string;
readonly generation: number;
dispose(): Promise<boolean>;
}createModEntityGroup
/**
* Transactional host-entity group for large authoritative constructions.
* Creation rolls back on quota/body failure and reset order stays stable.
*/
export function createModEntityGroup(
ctx: Pick<ModServerContext, 'entities'>,
label: string,
members: readonly ModEntityInit[],
): ModEntityGroup | null;ModObjectFarmState
/** The generic replicated farm channel on world objects (host-owned fields). */
export interface ModObjectFarmState {
state: 'empty' | 'tilled' | 'planted' | 'ready' | 'withered';
cropId: string;
plantedBy: string;
plantedAt: number;
readyAt: number;
water01: number;
lastWateredAt: number;
}ModWorldObjectView
/** Snapshot view of a world object owned by this mod (claimed/namespaced editor-item presets). */
export interface ModWorldObjectView {
id: string;
preset: string;
position: ModVec3;
rotation: ModQuat;
scale: ModVec3;
properties: Record<string, unknown>;
farm: ModObjectFarmState;
/** Harvestable presets only: whether the node can be worked right now, and its HP. */
resource?: { active: boolean; health: number };
}ModMessageClient
export interface ModMessageClient {
sessionId: string;
/** Present for a client intent sent with an operation id. */
operationId?: string;
}ModMessageMap
/** A generated mod message interface: message name -> JSON payload type. */
export type ModMessageMap = object;ModMessageSender
/** Type-safe server -> client transport derived from manifest messageSchemas. */
export interface ModMessageSender<Messages extends ModMessageMap> {
send<Type extends keyof Messages & string>(
sessionId: string,
type: Type,
data: Messages[Type],
): void;
broadcast<Type extends keyof Messages & string>(type: Type, data: Messages[Type]): void;
}TypedModServerContext
/** ModServerContext with a generated, direction-safe outbound message API. */
export type TypedModServerContext<ServerToClientMessages extends ModMessageMap> =
Omit<ModServerContext, 'messages'> & {
messages: ModMessageSender<ServerToClientMessages>;
};ModNearbyWorldObjectOptions
export interface ModNearbyWorldObjectOptions {
/** Raw object id from a mod message payload. Non-strings are rejected. */
objectId: unknown;
/** Exact world-object preset to accept. Defaults to mod:<modId>:<itemId> when itemId is provided. */
preset?: string;
/** Manifest editorItems id owned by this mod. Used to derive the default mod preset. */
itemId?: string;
/** Horizontal interaction radius in meters. Default 3. */
range?: number;
/** Vertical tolerance in meters. Default 3. */
yRange?: number;
/** Required player mode. Default 'walk'. Set false to allow any mode. */
requireMode?: string | false;
/** Dead players are rejected by default. */
allowDead?: boolean;
}ModNearbyWorldObjectResult
export interface ModNearbyWorldObjectResult {
player: ModPlayerView;
object: ModWorldObjectView;
distanceSq: number;
}ModMessageHandler
export type ModMessageHandler = (
ctx: ModServerContext,
client: ModMessageClient,
data: unknown,
) => void | Promise<void>;TypedModMessageHandlers
export type TypedModMessageHandlers<
ClientToServerMessages extends ModMessageMap,
ServerToClientMessages extends ModMessageMap,
> = {
[Type in keyof ClientToServerMessages & string]?: (
ctx: TypedModServerContext<ServerToClientMessages>,
client: ModMessageClient,
data: ClientToServerMessages[Type],
) => void | Promise<void>;
};ModEditorObjectEvent
/** A world object created from one of this mod's manifest editorItems. */
export interface ModEditorObjectEvent {
/** World-object id (not a mod entity id). */
objectId: string;
/** The manifest editorItems id this object was placed from. */
itemId: string;
position: ModVec3;
rotation: ModQuat;
scale: ModVec3;
/** Merged properties (item defaults + placer overrides). */
properties: Record<string, unknown>;
/** Session of the player who placed/removed it; empty for non-player edits. */
sessionId: string;
}TypedModServerHooks
/**
* Server hooks whose inbound handlers and outbound ctx.messages calls are
* constrained by the TypeScript maps generated from manifest messageSchemas.
*/
export type TypedModServerHooks<
ClientToServerMessages extends ModMessageMap,
ServerToClientMessages extends ModMessageMap,
> = Omit<
ModServerHooks,
| 'onWorldStart'
| 'onPlayerJoin'
| 'onPlayerLeave'
| 'onZoneEnter'
| 'onZoneExit'
| 'onInteraction'
| 'onActivityEvent'
| 'onPhysicsJointEvent'
| 'onPhysicsCollisionEvent'
| 'onEntityWeaponHit'
| 'canHarvestResource'
| 'onResourceHarvested'
| 'canCraftRecipe'
| 'onRecipeCrafted'
| 'onTick'
| 'onMessage'
| 'onEditorObjectPlaced'
| 'onEditorObjectRemoved'
| 'onDispose'
> & {
onWorldStart?(ctx: TypedModServerContext<ServerToClientMessages>): void | Promise<void>;
onPlayerJoin?(ctx: TypedModServerContext<ServerToClientMessages>, player: ModPlayerView): void;
onPlayerLeave?(ctx: TypedModServerContext<ServerToClientMessages>, sessionId: string): void;
onZoneEnter?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModZonePlayerEvent): void;
onZoneExit?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModZonePlayerEvent): void;
onInteraction?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModInteractionEvent): void | Promise<void>;
onActivityEvent?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModActivityEvent): void | Promise<void>;
onPhysicsJointEvent?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModPhysicsJointEvent): void | Promise<void>;
onPhysicsCollisionEvent?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModPhysicsCollisionEvent): void | Promise<void>;
onEntityWeaponHit?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModEntityWeaponHitEvent): void | Promise<void>;
canHarvestResource?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModResourceHarvestContext): ModGateResult;
onResourceHarvested?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModResourceHarvestedEvent): void | Promise<void>;
canCraftRecipe?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModRecipeCraftContext): ModGateResult;
onRecipeCrafted?(ctx: TypedModServerContext<ServerToClientMessages>, event: ModRecipeCraftedEvent): void | Promise<void>;
onTick?(ctx: TypedModServerContext<ServerToClientMessages>, dtSeconds: number): void;
onMessage?: TypedModMessageHandlers<ClientToServerMessages, ServerToClientMessages>;
onEditorObjectPlaced?(
ctx: TypedModServerContext<ServerToClientMessages>,
event: ModEditorObjectEvent,
): void;
onEditorObjectRemoved?(
ctx: TypedModServerContext<ServerToClientMessages>,
event: ModEditorObjectEvent,
): void;
onDispose?(ctx: TypedModServerContext<ServerToClientMessages>): void | Promise<void>;
};defineModServer
export function defineModServer(hooks: ModServerHooks): ModServerHooks;defineTypedModServer
export function defineTypedModServer<
ClientToServerMessages extends ModMessageMap,
ServerToClientMessages extends ModMessageMap,
>(
hooks: TypedModServerHooks<ClientToServerMessages, ServerToClientMessages>,
): ModServerHooks & TypedModServerHooks<ClientToServerMessages, ServerToClientMessages>;findNearbyWorldObject
/**
* Common server-side validator for object interactions initiated by a player:
* object id shape, mod-owned preset, live player, mode/death state, and
* horizontal/vertical range. Returns null on any rejection.
*/
export function findNearbyWorldObject(
ctx: Pick<ModServerContext, 'modId' | 'players' | 'objects'>,
sessionId: string,
options: ModNearbyWorldObjectOptions,
): ModNearbyWorldObjectResult | null;Client types
Source: packages/mod-sdk/client/index.d.ts.
ModComponent
export type ModComponent<Props = Record<string, unknown>> =
(props: Props) => any;ModVec3Like
export interface ModVec3Like {
x: number;
y: number;
z: number;
}ModWorldObjectClientView
export interface ModWorldObjectClientView {
id: string;
preset: string;
label?: string;
position: ModVec3Like;
rotation?: ModVec3Like;
scale?: ModVec3Like | number;
properties?: Record<string, unknown> | string;
[key: string]: unknown;
}ModPlayerClientView
export interface ModPlayerClientView {
sessionId?: string;
id?: string;
userId?: string;
name?: string;
mode?: string;
dead?: boolean;
position: ModVec3Like;
[key: string]: unknown;
}ModWorldInfo
export interface ModWorldInfo {
worldId?: string;
worldSeed?: number;
terrain: {
seed?: number;
size: number;
seaLevel: number;
biome?: string;
[key: string]: unknown;
};
[key: string]: unknown;
}ModAtmosphereFrame
export interface ModAtmosphereFrame {
daylight: number;
weatherIntensity: number;
timeOfDay?: number;
weatherType?: string;
[key: string]: unknown;
}ModCameraShot
export interface ModCameraShot {
position: ModVec3Like;
target: ModVec3Like;
/** The host clamps this to its safe 30–100 degree range. */
fov?: number;
}ModCameraShotProvider
export interface ModCameraShotProvider {
getShot(context: { delta: number }): ModCameraShot | null;
}ModCinematicFps
export type ModCinematicFps = 24 | 30 | 60;ModCinematicJsonValue
export type ModCinematicJsonValue =
| null
| boolean
| number
| string
| ModCinematicJsonValue[]
| { [key: string]: ModCinematicJsonValue };ModCinematicQuaternion
export interface ModCinematicQuaternion extends ModVec3Like {
w: number;
}ModCinematicTrackedTarget
export interface ModCinematicTrackedTarget {
kind: 'player' | 'vehicle' | 'world-object';
id: string;
localOffset?: ModVec3Like;
lookAtOffset?: ModVec3Like;
missingBehavior: 'freeze' | 'baked';
}ModCinematicCameraKeyframe
export interface ModCinematicCameraKeyframe {
id: string;
/** Time in seconds relative to the containing shot. */
time: number;
position: ModVec3Like;
quaternion: ModCinematicQuaternion;
target?: ModVec3Like;
fov: number;
roll?: number;
easing: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
interpolation: 'linear' | 'step';
trackedTarget?: ModCinematicTrackedTarget;
focusDistance?: number;
}ModCinematicCameraShake
export interface ModCinematicCameraShake {
seed: number;
frequency: number;
positionAmplitude: number;
rotationAmplitude: number;
fovAmplitude: number;
}ModCinematicCameraShot
export interface ModCinematicCameraShot {
id: string;
name: string;
start: number;
duration: number;
transition: {
type: 'cut' | 'blend' | 'ease-in-out';
duration: number;
};
keyframes: ModCinematicCameraKeyframe[];
trackedTarget?: ModCinematicTrackedTarget;
shake?: ModCinematicCameraShake;
}ModCinematicCameraTrack
export interface ModCinematicCameraTrack {
type: 'camera';
id: string;
name: string;
enabled: boolean;
shots: ModCinematicCameraShot[];
}ModCinematicMarker
export interface ModCinematicMarker {
id: string;
time: number;
label: string;
color?: string;
}ModCinematicSequence
/** Versioned, JSON-only Director document accepted by the host sanitizer. */
export interface ModCinematicSequence {
version: number;
id: string;
name: string;
duration: number;
fps: ModCinematicFps;
tracks: ModCinematicCameraTrack[];
markers: ModCinematicMarker[];
metadata?: Record<string, ModCinematicJsonValue>;
}ModCinematicSanitizationIssue
export interface ModCinematicSanitizationIssue {
path: string;
code: 'defaulted' | 'invalid' | 'clamped' | 'normalized' | 'truncated' | 'duplicate' | 'unsupported';
message: string;
}ModCinematicLoadResult
export interface ModCinematicLoadResult {
ok: boolean;
error: string;
issues: ModCinematicSanitizationIssue[];
/** Detached sanitized document; null when parsing failed or permission was denied. */
document: ModCinematicSequence | null;
}ModCinematicPlaybackState
export interface ModCinematicPlaybackState {
time: number;
duration: number;
fps: ModCinematicFps;
frame: number;
playing: boolean;
speed: number;
source: 'standalone' | 'game-timeline';
}ModCinematicDirectorState
export interface ModCinematicDirectorState {
available: boolean;
active: boolean;
cameraMode: 'playback' | 'free-fly' | 'orbit';
cleanPreview: boolean;
dirty: boolean;
selection: {
trackId: string | null;
shotId: string | null;
keyframeId: string | null;
};
sequence: Pick<ModCinematicSequence, 'version' | 'id' | 'name' | 'duration' | 'fps'> | null;
playback: ModCinematicPlaybackState;
safeFrame: { id: string; width: number; height: number } | null;
gameTimelineBound: boolean;
}ModCinematicCaptureFrame
/** Data-only capture metadata. Renderer/canvas references are intentionally unavailable. */
export interface ModCinematicCaptureFrame {
sequenceId: string;
sequenceTime: number;
frame: number;
fps: ModCinematicFps;
pose: {
position: ModVec3Like;
quaternion: ModCinematicQuaternion;
fov: number;
};
}ModCinematicDirectorApi
export interface ModCinematicDirectorApi {
/** Reactive snapshot for this render; call getState() in callbacks. */
state: ModCinematicDirectorState;
getState(): ModCinematicDirectorState;
/** Every call returns a detached JSON-only copy. */
getDocument(): ModCinematicSequence | null;
/** Accepts JSON text or data and always passes it through the host sanitizer. */
load(input: unknown, options?: { recordHistory?: boolean }): ModCinematicLoadResult;
enter(): boolean;
exit(): boolean;
play(speed?: number): boolean;
pause(): number | false;
stop(): number | false;
seek(time: number): number | false;
stepFrame(frames?: number): number | false;
subscribeCapture(
listener: (frame: ModCinematicCaptureFrame) => void,
options?: { once?: boolean },
): () => boolean;
}ModRenderMode
export type ModRenderMode = 'world' | 'ghost' | 'library';ModObjectRendererProps
export interface ModObjectRendererProps {
itemId: string;
properties?: Record<string, unknown>;
worldObject?: ModWorldObjectClientView;
renderMode: ModRenderMode;
ghostMaterialProps?: Record<string, unknown>;
}ModObjectBatchRendererProps
export interface ModObjectBatchRendererProps {
itemId: string;
objects: ModWorldObjectClientView[];
}ModClientDefinition
export interface ModClientDefinition {
WorldLayer?: ModComponent;
HudPanel?: ModComponent;
objectRenderers?: Record<string, ModComponent<ModObjectRendererProps>>;
objectBatchRenderers?: Record<string, ModComponent<ModObjectBatchRendererProps>>;
}ModNotification
export interface ModNotification {
tone?: 'success' | 'info' | 'warning' | 'error' | string;
title?: string;
message: string;
}ModNotificationApi
export interface ModNotificationApi {
set(id: string, notification: ModNotification): void;
clear(id: string): void;
notify(
notification: ModNotification,
options?: { durationMs?: number },
): string | void;
dismiss(id: string): void;
}ModHudSurface
/** A data-only mission/status card rendered in the host HUD. */
export interface ModHudSurface {
title?: string;
objective?: string;
marker?: string;
/**
* Longer how-to text under the objective (≤ 400 chars). Wraps; `\n` starts
* a new line. Keep title/objective/marker short and put explanations here.
*/
detail?: string;
/** Normalized by the host to the 0..1 range. Omit to hide the bar. */
progress?: number;
progressLabel?: string;
}ModHudSurfaceApi
export interface ModHudSurfaceApi {
set(id: string, surface: ModHudSurface): void;
clear(id: string): void;
}ModDialogAction
export interface ModDialogAction {
id: string;
label: string;
tone?: 'primary' | 'danger' | 'neutral';
}ModDialog
export interface ModDialog {
kind?: 'dialog' | 'menu';
title: string;
message?: string;
actions?: ModDialogAction[];
}ModDialogApi
export interface ModDialogApi {
open(id: string, dialog: ModDialog, onAction?: (actionId: string) => void): void;
close(id: string): void;
}ModAudioApi
export interface ModAudioApi {
getAudioContext(): AudioContext | null;
getMasterGain(): GainNode | null;
resumeAudioContext(): void | Promise<void>;
isAudioEnabled(): boolean;
}ModSpatialAudioOptions
export interface ModSpatialAudioOptions {
refDistance?: number;
maxDistance?: number;
rolloffFactor?: number;
}ModProximityOptions
export interface ModProximityOptions {
range?: number;
yRange?: number;
requireMode?: string;
pollMs?: number;
halfExtents?: Partial<ModVec3Like>;
}ModProximityResult
export interface ModProximityResult {
position: ModVec3Like;
distanceSq: number;
}ModNearestWorldObjectResult
export interface ModNearestWorldObjectResult {
object: ModWorldObjectClientView;
player: ModPlayerClientView;
distanceSq: number;
}ModKeyActionOptions
export interface ModKeyActionOptions {
code: string;
enabled?: boolean;
onAction: (event: KeyboardEvent) => void;
ignoreTyping?: boolean;
capture?: boolean;
}ModInputActionOptions
export interface ModInputActionOptions {
actionId: string;
defaultCode: string;
enabled?: boolean;
onAction: (event: KeyboardEvent) => void;
priority?: number;
ignoreTyping?: boolean;
/** Button caption on the host touch control bar. Defaults to the action id. */
label?: string;
/** Host touch icon name. Defaults to a generic hand icon. */
icon?: string;
}ModControlSessionOptions
export interface ModControlSessionOptions {
active?: boolean;
/** Advertise an enter-control action without locking movement yet. */
available?: boolean;
label?: string;
priority?: number;
}ModControlInputActionOptions
export interface ModControlInputActionOptions extends ModInputActionOptions {
allowRepeat?: boolean;
/** May exclusively claim the enter-control key while this mod has the active offer. */
activation?: boolean;
}ModSurfaceLeaseOptions
export interface ModSurfaceLeaseOptions {
/** Higher priority wins; same-priority mod ids are ordered lexicographically. */
priority?: number;
/** Optional bounded host-clock duration. Call renew before it expires. */
durationMs?: number;
}ModSurfaceLease
export interface ModSurfaceLease {
(): void;
renew(durationMs: number): boolean;
isActive(): boolean;
}ModFrameState
export interface ModFrameState {
clock: { elapsedTime: number; [key: string]: unknown };
[key: string]: unknown;
}ModNodePointSpriteContext
export type ModNodePointSpriteContext = {
TSL: Record<string, any>;
SpriteNodeMaterial: new () => import('three').Material & Record<string, any>;
source: import('three').Material;
pointPosition: unknown;
pointCoord: unknown;
uniform(name: string, type?: string): unknown;
pixelScale(pixelsAtUnitDepth: number): unknown;
focal: unknown;
};ModInteractionExecutionHandle
export interface ModInteractionExecutionHandle {
operationId: string | null;
complete(): void;
cancel(): void;
}ModMessageSendOptions
export interface ModMessageSendOptions {
/** Reuse the same id only when retrying the same at-most-once intent. */
operationId?: string;
}ModMessageMap
/** A generated mod message interface: message name -> JSON payload type. */
export type ModMessageMap = object;ModFrameOptions
export interface ModFrameOptions {
priority?: number;
/** Defaults to true. False skips the callback with a single boolean test. */
enabled?: boolean;
}InstancedObjectBatchPart
export interface InstancedObjectBatchPart {
key: string;
geometry: unknown;
color?: string;
materialType?: 'standard' | 'basic' | string;
materialProps?: Record<string, unknown>;
position?: ModVec3Like | [number, number, number];
rotation?: ModVec3Like | [number, number, number];
scale?: ModVec3Like | [number, number, number] | number;
/** Defaults to true in the batch path. */
castShadow?: boolean;
/** Opt-in: only `true` makes the instance sample the shadow map. */
receiveShadow?: boolean;
}MergedBatchPart
/** A part produced by `mergeBatchParts`: vertex-coloured, white material. */
export interface MergedBatchPart extends InstancedObjectBatchPart {
key: string;
geometry: any;
color: '#ffffff';
materialType: 'standard' | 'basic' | string;
materialProps: Record<string, unknown> & { vertexColors: true };
castShadow: boolean;
receiveShadow: boolean;
}PooledPointLightSpec
export interface PooledPointLightSpec {
enabled?: boolean;
priority?: number;
color: string;
intensity: number;
distance: number;
decay: number;
/** Object-local offset of the light. */
position: [number, number, number];
}PooledLightProps
export interface PooledLightProps {
position?: [number, number, number];
color?: string | number;
intensity?: number;
distance?: number;
decay?: number;
priority?: number;
enabled?: boolean;
}PooledPointLightHandle
export interface PooledPointLightHandle {
id: string;
intensity: number;
distance: number;
decay: number;
priority: number;
enabled: boolean;
color: string | number | import('three').Color;
position: { x: number; y: number; z: number };
}PooledSpotLightSource
export type PooledSpotLightSource = import('three').Object3D & {
intensity: number;
distance: number;
decay: number;
angle: number;
penumbra: number;
priority: number;
enabled: boolean;
color: import('three').Color;
target: import('three').Object3D;
}PooledEnvironmentLightSource
export type PooledEnvironmentLightSource = import('three').Object3D & {
intensity: number;
priority: number;
enabled: boolean;
color: import('three').Color;
target: import('three').Object3D;
}PooledEnvironmentLightProps
export interface PooledEnvironmentLightProps {
position?: [number, number, number];
color?: string | number;
intensity?: number;
priority?: number;
enabled?: boolean;
lightRef?: import('react').Ref<PooledEnvironmentLightSource>;
}ModScreenEffectDefinition
/** Host-rendered local view effect; requires camera.control; expires in at most 12 seconds. */
export interface ModScreenEffectDefinition {
type: 'psychedelic';
durationMs?: number;
intensity?: number;
}Physics types
Source: packages/mod-sdk/physics/index.d.ts.
ModRaycastHit
export interface ModRaycastHit {
point?: ModVec3Like;
normal?: ModVec3Like;
distance?: number;
colliderId?: string | number;
[key: string]: unknown;
}ModPhysicsColliderProps
export type ModPhysicsColliderProps = Record<string, unknown> & {
position?: ModVec3Like | [number, number, number];
rotation?: ModVec3Like | [number, number, number];
};