### Install World SDK using npm, yarn, pnpm, or bun Source: https://world.dev/javascript/quickstart Installs the World SDK package using various package managers. Ensure you have Node.js version 22 or higher and a package manager installed. ```bash npm install @argus-labs/sdk ``` ```bash yarn add @argus-labs/sdk ``` ```bash pnpm add @argus-labs/sdk ``` ```bash bun add @argus-labs/sdk ``` -------------------------------- ### Player Spawn Command Structure in Go Source: https://world.dev/javascript/quickstart Defines the structure for a 'player-spawn' command in Go, used on the Cardinal shard. This includes base command details and specific payload fields like authentication IDs, names, and coordinates. This is an example system component for handling the command sent by the SDK. ```go type PlayerSpawnCommand struct { cardinal.BaseCommand ArgusAuthID string `json:"argus_auth_id"` ArgusAuthName string `json:"argus_auth_name"` X uint32 `json:"x"` Y uint32 `json:"y"` } func (a PlayerSpawnCommand) Name() string { return "player-spawn" } func PlayerSpawnSystem(state *SpawnPlayerSystemState) error { // ... code omitted for brevity } ``` -------------------------------- ### Query API - Where Clause Examples Source: https://world.dev/cardinal/build/query-api Provides examples of using the 'where' clause for filtering query results based on component properties and logical conditions. Supports comparison, logical operators, and built-in functions from the Expr language. ```APIDOC ## POST /query (With Where Clause Examples) ### Description Demonstrates various filtering capabilities using the 'where' clause in queries. ### Method POST ### Endpoint /query ### Parameters #### Query Parameters None #### Request Body - **find** (array of strings) - Required - A list of component names to search for. - **match** (string) - Required - How to match components ('exact' or 'contains'). - **where** (string) - Required - An expression string for filtering results. ### Request Examples **By Online Status:** ```json { "find": ["PlayerTag", "OnlineStatus"], "match": "contains", "where": "OnlineStatus.Online == true" } ``` **By Name:** ```json { "find": ["PlayerTag", "Position"], "match": "contains", "where": "PlayerTag.Name == \"Alice\"" } ``` **By Nickname:** ```json { "find": ["PlayerTag"], "match": "contains", "where": "PlayerTag.Nickname contains \"admin\"" } ``` **By Online Status and Position:** ```json { "find": ["PlayerTag", "Position", "OnlineStatus"], "match": "contains", "where": "Position.X > 100 && Position.Y < 200 && OnlineStatus.Online == true" } ``` **By PlayerTag ID:** ```json { "find": ["PlayerTag"], "match": "contains", "where": "PlayerTag.ID in [\"user1\", \"user2\", \"user3\"]" } ``` **By Nickname Length and Position:** ```json { "find": ["PlayerTag", "Position"], "match": "contains", "where": "len(PlayerTag.Nickname) > 5 && Position.X + Position.Y < 500" } ``` ### Response #### Success Response (200) - **entities** (array of objects) - A list of entities matching the query criteria. #### Response Example ```json { "entities": [ { "id": "entityABC", "PlayerTag": {"name": "AdminPlayer", "Nickname": "SuperAdmin", "ID": "user1"}, "Position": {"x": 50, "y": 50}, "OnlineStatus": {"Online": true} } ] } ``` ``` -------------------------------- ### Set up SDK instance in TypeScript/JavaScript Source: https://world.dev/javascript/quickstart Initializes the Argus Labs SDK by creating a configuration and then an SDK instance. This code is typically placed in a central file like `src/lib/sdk.ts` or `src/lib/sdk.js`. TypeScript is optional but recommended. ```typescript import { createConfig, createSDK } from '@argus-labs/sdk' // Basic configuration export const config = createConfig() // Create the SDK instance export const world = createSDK(config) ``` -------------------------------- ### Cardinal Command Struct Example Source: https://world.dev/javascript/guides/command Provides an example of a Go struct that defines a 'player-spawn' command. This Go struct serves as the backend definition, and its structure should be mirrored by the TypeScript interfaces used in the SDK for commands to ensure consistency and correct data transfer. ```go type PlayerSpawnCommand struct { cardinal.BaseCommand ArgusAuthID string `json:"argus_auth_id"` ArgusAuthName string `json:"argus_auth_name"` Position struct { X int `json:"x"` Y int `json:"y"` } `json:"position"` } func (c PlayerSpawnCommand) Name() string { return "player-spawn" } ``` -------------------------------- ### Registering Cardinal Systems Source: https://world.dev/cardinal/build/system/overview Demonstrates how to register game systems with the Cardinal world. Systems can be registered to run at initialization (Init hook) or every game tick (default Update hook). This example shows spawning a player once and registering a player movement system. ```go package main import ( "github.com\/avage-d\/cardinal\/v2" "path\/to\/your\/project\/system" ) func main() { world := cardinal.NewWorld() // Spawn player at tick 0 (only once) cardinal.RegisterSystem(world, system.PlayerSpawnerSystem, cardinal.WithHook(cardinal.Init)) // Register player movement system (runs every tick) cardinal.RegisterSystem(world, system.PlayerMoveSystem) world.StartGame() } ``` -------------------------------- ### Schema Validation Example with Valibot Source: https://world.dev/javascript/guides/query Provides an example of using the Valibot schema library for validating query responses. Similar to Zod, Valibot can be used to define expected data structures, ensuring the data returned from the SDK query conforms to the specified schema. ```typescript import * as v from 'valibot' const playersSchema = v.array( v.object({ _id: v.number(), playertag: v.object({ argus_auth_id: v.string(), argus_auth_name: v.string(), }), position: v.object({ x: v.number(), y: v.number(), }), }) ) const { data } = await shard.query({ find: ['playertag', 'position'] }, { schema: playersSchema }) ``` -------------------------------- ### Register a Shard Client with Argus Labs SDK Source: https://world.dev/javascript/quickstart Registers a shard client to connect to a specific Cardinal shard, enabling command sending, state querying, and event listening. This requires the SDK instance created previously. ```typescript import { world } from './sdk' export const shard = world.shard.register({ organization: 'argus', project: 'demo', shardId: 'cardinal-demo-game-1', }) ``` -------------------------------- ### Initialize Cardinal World and Register Systems (Go) Source: https://world.dev/cardinal/build/world/overview Demonstrates the basic structure of a main.go file for a Cardinal game shard. It shows how to initialize a new world, register various systems (like PlayerSetUpdater, PlayerSpawnSystem, MovePlayerSystem, PlayerLeaveSystem, OnlineStatusUpdater), and optionally attach systems to specific hooks (e.g., PreUpdate). ```go package main import ( "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/demo-game/system" ) func main() { world := cardinal.NewWorld() // Example of using a hook. This hook runs before the main update phase. // There are also other hooks: // - Init (runs only once, at tick 0) // - PreUpdate (runs before the main update phase) // - Update (runs during the main update phase) // - PostUpdate (runs after the main update phase) cardinal.RegisterSystem(world, system.PlayerSetUpdater, cardinal.WithHook(cardinal.PreUpdate)) cardinal.RegisterSystem(world, system.PlayerSpawnSystem) cardinal.RegisterSystem(world, system.MovePlayerSystem) cardinal.RegisterSystem(world, system.PlayerLeaveSystem) cardinal.RegisterSystem(world, system.OnlineStatusUpdater) world.StartGame() } ``` -------------------------------- ### Position Component Definition (Go) Source: https://world.dev/javascript/quickstart This Go code defines the 'Position' component for World Engine, representing a player's coordinates in the game world. It includes X and Y integer fields and implements the Name() method, essential for component identification within World Engine. ```go package component type Position struct { X int `json:"x"` Y int `json:"y"` } func (Position) Name() string { return "position" } ``` -------------------------------- ### Send Player Spawn Command using Argus Labs SDK Source: https://world.dev/javascript/quickstart Defines and sends a 'player-spawn' command to a registered Cardinal shard. This function takes command details as an argument and optionally logs any errors. It requires a pre-registered shard client and a defined command interface. ```typescript import { shard } from './shard' interface SpawnPlayerCommand { name: 'player-spawn' payload: { argus_auth_id: string argus_auth_name: string x: number y: number } } // Call the following function from an event handler, e.g. a button export async function spawnPlayer() { const { error } = await shard.sendCommand({ name: 'player-spawn', payload: { argus_auth_id: 'abc123', argus_auth_name: 'John Doe', x: 100, y: 200, }, } satisfies SpawnPlayerCommand) if (error) console.error(error) } ``` -------------------------------- ### Get Position Component from Entity in Cardinal (Go) Source: https://world.dev/cardinal/build/system/component Demonstrates how to retrieve a 'Position' component from an entity using the `Get` method in a Cardinal system. This function iterates through players, fetches their position, and logs the coordinates. It requires the `cardinal` and specific component packages. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/demo-game/component" ) type GetPositionSystemState struct { cardinal.BaseSystemState Players PlayerSearch } func GetPositionSystem(state *GetPositionSystemState) error { for entity, player := range state.Players.Iter() { position := player.Position.Get() state.Logger().Info(). Uint32("entity", uint32(entity.ID)). Msgf("Player is at position X: %d, Y: %d", position.X, position.Y) } return nil } ``` -------------------------------- ### PlayerTag Component Definition (Go) Source: https://world.dev/javascript/quickstart This Go code defines the 'PlayerTag' component, used in World Engine to represent a player's unique identifier. It includes fields for Argus authentication ID and name, and implements the Name() method required by World Engine components. ```go package component type PlayerTag struct { ArgusAuthID string `json:"argus_auth_id"` ArgusAuthName string `json:"argus_auth_name"` } func (PlayerTag) Name() string { return "playertag" } ``` -------------------------------- ### Query Player Data with World Engine SDK (TypeScript) Source: https://world.dev/javascript/quickstart This TypeScript function demonstrates how to query the world state to find player data, specifically their 'playertag' and 'position'. It uses the `shard.query` method from the Argus Labs SDK. The function handles potential errors and returns the retrieved data or null. ```typescript import { Match } from '@argus-labs/sdk' import { shard } from './shard' export async function playerQuery() { const { error, data } = await shard.query({ find: ['playertag', 'position'], match: Match.CONTAINS, }) if (error) { console.error(error) return null } return data } ``` -------------------------------- ### JSON Query using 'exact' Match Type Source: https://world.dev/cardinal/build/query-api Shows an example of the 'exact' match type in a JSON query. This method strictly returns entities that have precisely the listed components and no others. ```json { "find": ["PlayerTag", "Position"], "match": "exact" } ``` -------------------------------- ### ECS Contains Match Type Example in Go Source: https://world.dev/cardinal/build/system/search Illustrates the 'ecs.Contains' match type in Go, which finds entities having at least the specified components. The example shows a search requiring 'PlayerTag' and 'Position', matching entities with these and potentially others. ```go type PlayerSearch = ecs.Exact[struct { Tag ecs.Ref[component.PlayerTag] Position ecs.Ref[component.Position] }] ``` -------------------------------- ### Pattern Matching ConnectError Codes in TypeScript Source: https://world.dev/javascript/guides/error-handling Shows how to handle specific error types by matching against `ConnectError.code`. This example uses a switch statement to execute different logic based on the error code, such as redirecting to login for unauthenticated errors or scheduling a retry for unavailable services. It requires importing `ConnectError` and `Code` from '@argus-labs/sdk'. ```typescript import { ConnectError, Code } from '@argus-labs/sdk' const { error, data } = await shard.query({ // your query parameters }) if (error) { switch (error.code) { case Code.Unauthenticated: // Redirect to login redirectToLogin() break case Code.PermissionDenied: // Show access denied message showAccessDeniedError() break case Code.NotFound: // Handle missing resource showNotFoundError() break case Code.Unavailable: // Retry logic for temporary issues scheduleRetry() break default: // Handle other errors showGenericError(error.message) } } else { // Handle successful response processData(data) } ``` -------------------------------- ### Configure Multiple Regions for SDK (TypeScript) Source: https://world.dev/javascript/guides/multiple-regions Configure multiple regions for the SDK by providing gateway URLs, display names, and optional latency simulation. This setup allows the SDK to automatically select the best region based on latency. ```typescript import { createConfig, createSDK } from '@argus-labs/sdk' const config = createConfig({ regions: { 'us-west-2': { gatewayUrl: 'http://localhost:8080', displayName: 'US West (Oregon)', simulateLatencyCheckMs: 100, // optional, for development only }, 'eu-central-1': { gatewayUrl: 'http://localhost:8081', displayName: 'Europe (Frankfurt)', simulateLatencyCheckMs: 300, }, 'ap-southeast-1': { gatewayUrl: 'http://localhost:8082', displayName: 'Asia Pacific (Singapore)', simulateLatencyCheckMs: 200, }, }, }) export const world = createSDK(config) ``` -------------------------------- ### JSON Query with Length and Arithmetic Conditions Source: https://world.dev/cardinal/build/query-api An example of a JSON query that uses both a string length check and an arithmetic comparison within the 'where' clause to filter entities. ```json { "find": ["PlayerTag", "Position"], "match": "contains", "where": "len(PlayerTag.Nickname) > 5 && Position.X + Position.Y < 500" } ``` -------------------------------- ### Set Position Component on Entity in Cardinal (Go) Source: https://world.dev/cardinal/build/system/component Illustrates how to update a 'Position' component for an entity using the `Set` method in a Cardinal system. This example iterates through players and assigns a new `component.Position` with updated X and Y coordinates, logging the change. It depends on the `cardinal` and component packages. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/demo-game/component" ) type SetPositionSystemState struct { cardinal.BaseSystemState Players PlayerSearch } func SetPositionSystem(state *SetPositionSystemState) error { for entity, player := range state.Players.Iter() { player.Position.Set(component.Position{X: 100, Y: 200}) state.Logger().Info(). Uint32("entity", uint32(entity.ID)). Msg("Updated player position to X: 100, Y: 200") } return nil } ``` -------------------------------- ### JSON Query filtering by Online Status Source: https://world.dev/cardinal/build/query-api Provides a JSON query example that filters entities based on their online status, specifically looking for entities where 'OnlineStatus.Online' is true. ```json { "find": ["PlayerTag", "OnlineStatus"], "match": "contains", "where": "OnlineStatus.Online == true" } ``` -------------------------------- ### Create Basic SDK Configuration (TypeScript) Source: https://world.dev/javascript/guides/configuration Initializes the SDK configuration using `createConfig` and then creates the SDK instance with `createSDK`. This sets up the basic connection parameters for your application. ```typescript import { createConfig, createSDK } from '@argus-labs/sdk' const config = createConfig({ // Configuration options go here }) export const world = createSDK(config) ``` -------------------------------- ### JSON Query filtering by Nickname Substring Source: https://world.dev/cardinal/build/query-api An example of a JSON query that filters entities based on a substring match within their nickname, using the 'contains' operator in the 'where' clause. ```json { "find": ["PlayerTag"], "match": "contains", "where": "PlayerTag.Nickname contains \"admin\"" } ``` -------------------------------- ### Get Current User with Argus Auth (TypeScript) Source: https://world.dev/javascript/guides/authentication Retrieves the currently authenticated user using `world.auth.getUser()`. Returns an AuthUser object if logged in, otherwise null. This is typically called in the main menu. ```typescript import { world } from './sdk' export function mainMenu() { const user = world.auth.getUser() console.log(user) } ``` -------------------------------- ### Basic useQuery Usage in React Source: https://world.dev/javascript/react/use-query Demonstrates the fundamental use of the useQuery hook to fetch player data from a World Engine shard. It handles different query states (idle, loading, error, success) and renders the player list. Requires the 'shard' client and basic query configuration. ```tsx import { useQuery } from '@argus-labs/sdk/react' import { Match } from '@argus-labs/sdk' import { shard } from './shard' function PlayerList() { const { status, data, error } = useQuery({ shardClient: shard, query: { find: ['playertag', 'position'], match: Match.CONTAINS, }, }) if (status === 'idle') return null if (status === 'loading') return
Loading players…
if (status === 'error') return
Error: {error?.message}
return ( ) } ``` -------------------------------- ### Pattern Matching with Error Codes Source: https://world.dev/javascript/guides/error-handling Illustrates how to handle different types of errors by matching against specific `ConnectError.code` values using a switch statement. ```APIDOC ## Pattern Matching with Error Codes ### Description This example demonstrates advanced error handling by using a `switch` statement to identify specific `ConnectError.code` values (e.g., `Unauthenticated`, `PermissionDenied`, `NotFound`, `Unavailable`) and executing distinct logic for each. A default case handles any other unexpected errors. ### Method N/A (Client-side code snippet) ### Endpoint N/A (Client-side code snippet) ### Parameters N/A ### Request Example ```typescript import { ConnectError, Code } from '@argus-labs/sdk'; const { error, data } = await shard.query({ // your query parameters }); ``` ### Response #### Success Response (200) - **data** (any) - The data payload upon successful request. #### Error Response - **error** (ConnectError) - An object containing detailed error information, specifically the `code` property is used for matching. ### Response Example **Success:** ```json { "data": { "processed": true } } ``` **Error Handling Logic (Conceptual):** ```typescript if (error) { switch (error.code) { case Code.Unauthenticated: // Redirect to login redirectToLogin(); break; case Code.PermissionDenied: // Show access denied message showAccessDeniedError(); break; case Code.NotFound: // Handle missing resource showNotFoundError(); break; case Code.Unavailable: // Retry logic for temporary issues scheduleRetry(); break; default: // Handle other errors showGenericError(error.message); } } else { // Handle successful response processData(data); } ``` ``` -------------------------------- ### Basic JSON Query Structure Source: https://world.dev/cardinal/build/query-api Demonstrates the fundamental structure of a query to the Cardinal state, specifying components to find and a condition for filtering. ```json { "find": ["PlayerTag", "Health"], "match": "contains", "where": "Health.HP > 50" } ``` -------------------------------- ### Unsubscribing from Events in TypeScript Source: https://world.dev/javascript/guides/subscribe-events Provides an example of how to manage event subscriptions and unsubscribe from them when no longer needed. This pattern is typically used within a class managing resources, ensuring cleanup to prevent memory leaks. It relies on the `subscribeToPlayerEvents` function and the `UnsubscribeEventsResult` type from '@argus-labs/sdk'. ```typescript import type { UnsubscribeEventsResult } from '@argus-labs/sdk' // Assume subscribeToPlayerEvents is imported from elsewhere // import { subscribeToPlayerEvents } from './eventSubscriptions' class Game { private unsubscribe: (() => Promise) | null = null constructor() {} async create() { // this.unsubscribe = await subscribeToPlayerEvents() } async destroy() { if (!this.unsubscribe) return const { error } = await this.unsubscribe() if (error) { console.error('Failed to unsubscribe from events:', error) } } } // Placeholder for the actual subscribe function if not imported directly async function subscribeToPlayerEvents() { // Mock implementation for demonstration console.log('Subscribing to events...'); return async () => { console.log('Unsubscribing from events...'); return { error: null }; }; } ``` -------------------------------- ### Create Entity with Components in Go Source: https://world.dev/cardinal/build/system/entity This Go code snippet demonstrates how to create multiple entities with associated components using the Cardinal engine. It iterates to create 10 players, assigning them a nickname and initial position. Ensure the 'github.com/argus-labs/monorepo/pkg/cardinal' package is available. ```go package system import ( "fmt" "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/demo-game/component" ) type CreatePlayerSystemState struct { cardinal.BaseSystemState Players PlayerSearch } func CreatePlayerSystem(state *CreatePlayerSystemState) error { for i := range 10 { name := fmt.Sprintf("default-%d", i) id, err := state.Players.Create( component.PlayerTag{Nickname: name}, component.Position{X: 0, Y: 0}, ) if err != nil { return err } state.Logger().Info().Uint32("entity", uint32(id)).Msgf("Created player %s", name) } return nil } ``` -------------------------------- ### Configure Production Multi-Regions (TypeScript) Source: https://world.dev/javascript/guides/configuration Sets up multiple regions for a production environment, specifying gateway URLs and display names for different geographical locations. This is crucial for global connectivity and performance. ```typescript const config = createConfig({ regions: { 'us-west-2': { gatewayUrl: 'https://us-west-2.gateway.example.com', displayName: 'US West (Oregon)', }, 'eu-central-1': { gatewayUrl: 'https://eu-central-1.gateway.example.com', displayName: 'Europe (Frankfurt)', }, }, }) ``` -------------------------------- ### Receive Player Death System Event in Go Source: https://world.dev/cardinal/build/system/event This Go code demonstrates how to receive system events, specifically player death events, within the Cardinal framework. It defines a system state that includes a `WithSystemEventReceiver` for `systemevent.PlayerDeath`. The `GraveyardSystem` function iterates over received player death events and creates a gravestone for each. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/basic/component" systemevent "github.com/argus-labs/monorepo/pkg/cardinal/examples/basic/system_event" ) type GraveyardSystemState struct { cardinal.BaseSystemState PlayerDeathSystemEvents cardinal.WithSystemEventReceiver[systemevent.PlayerDeath] Graves GraveSearch } func GraveyardSystem(state *GraveyardSystemState) error { // Iterate over all player-death system events received in the tick. for event := range state.PlayerDeathSystemEvents.Iter() { _, _ = state.Graves.Create(component.Gravestone{Nickname: event.Nickname}) } return nil } ``` -------------------------------- ### Basic Error Handling Source: https://world.dev/javascript/guides/error-handling Demonstrates the fundamental approach to checking for and handling errors returned by an API call using the `{ error, data }` pattern. ```APIDOC ## Basic Error Handling ### Description This example shows how to check the `error` field in the response object. If an error exists, its properties like `code`, `message`, and `rawMessage` are logged. Otherwise, the successful `data` is processed. ### Method N/A (Client-side code snippet) ### Endpoint N/A (Client-side code snippet) ### Parameters N/A ### Request Example ```typescript const { error, data } = await shard.query({ // your query parameters }); ``` ### Response #### Success Response (200) - **data** (any) - The data payload upon successful request. #### Error Response - **error** (ConnectError) - An object containing detailed error information. - **code** (number) - The specific error code. - **message** (string) - The full error message, potentially including status code. - **rawMessage** (string) - The error message without any prefix. - **metadata** (object) - Response headers and trailers. - **details** (any) - Additional error details. - **cause** (Error) - The underlying cause of the error. ### Response Example **Success:** ```json { "data": { "key": "value" } } ``` **Error:** ```json { "error": { "code": 3, "message": "InvalidArgument: Invalid input provided.", "rawMessage": "Invalid input provided.", "metadata": {}, "details": null, "cause": null } } ``` ``` -------------------------------- ### Error Handling for Subscriptions and Events in React with useSubscribeEvents Source: https://world.dev/javascript/react/use-subscribe-events Details how to implement comprehensive error handling for both the subscription itself and individual event callbacks using the `onError` prop within the `useSubscribeEvents` hook. This example manages connection status based on subscription and event processing errors. ```tsx import { useSubscribeEvents } from '@argus-labs/sdk/react' import { playerSpawnEvent } from './events' import { shard } from './shard' function GameEventsWithErrorHandling() { const [connectionStatus, setConnectionStatus] = useState<'connected' | 'error' | 'connecting'>( 'connecting' ) useSubscribeEvents({ shardClient: shard, events: [ playerSpawnEvent({ onSuccess: (payload) => { setConnectionStatus('connected') console.log('Player spawned:', payload) }, onError: (error) => { console.error('Event processing error:', error) }, }), ], onError: (error) => { console.error('Subscription error:', error) setConnectionStatus('error') }, }) return (
Connection: {connectionStatus}
{connectionStatus === 'error' &&
Failed to connect to game events
}
) } ``` -------------------------------- ### Multiple Event Subscriptions in React with useSubscribeEvents Source: https://world.dev/javascript/react/use-subscribe-events Shows how to subscribe to multiple different events simultaneously using a single `useSubscribeEvents` hook call. This example combines player spawn and movement events, demonstrating efficient handling of various real-time game updates within one component. ```tsx import { useSubscribeEvents } from '@argus-labs/sdk/react' import { playerSpawnEvent, playerMovementEvent } from './events' import { shard } from './shard' function GameEventHandler() { const [notifications, setNotifications] = useState([]) const addNotification = (message: string) => { setNotifications((prev) => [...prev.slice(-4), message]) // Keep last 5 } useSubscribeEvents({ shardClient: shard, events: [ playerSpawnEvent({ onSuccess: (payload) => { addNotification(`${payload.argus_auth_name} spawned`) }, onError: console.error, }), playerMovementEvent({ onSuccess: (payload) => { addNotification(`${payload.argus_auth_name} moved`) }, onError: console.error, }), ], }) return (
{notifications.map((notification, index) => (
{notification}
))}
) } ``` -------------------------------- ### Query API - Basic Query Source: https://world.dev/cardinal/build/query-api This endpoint allows clients to query the Cardinal state. Queries are read-only and retrieve information about entities, components, and world state. The 'find' field specifies the components to search for, 'match' defines how components are matched ('exact' or 'contains'), and the optional 'where' field allows for complex filtering using the Expr expression language. ```APIDOC ## POST /query ### Description Allows clients to query the Cardinal state for entities based on specified components and filtering criteria. ### Method POST ### Endpoint /query ### Parameters #### Query Parameters None #### Request Body - **find** (array of strings) - Required - A list of component names to search for. - **match** (string) - Required - How to match components. Accepts 'exact' or 'contains'. - **where** (string) - Optional - An expression string for filtering results. ### Request Example ```json { "find": ["PlayerTag", "Health"], "match": "contains", "where": "Health.HP > 50" } ``` ### Response #### Success Response (200) - **entities** (array of objects) - A list of entities matching the query criteria. Each entity object may contain component data. #### Response Example ```json { "entities": [ { "id": "entity123", "PlayerTag": {"name": "Player1"}, "Health": {"HP": 75} } ] } ``` ``` -------------------------------- ### Send Basic Player Spawn Command Source: https://world.dev/javascript/guides/command Demonstrates the simplest way to send a command to the shard to modify game state. This function sends a 'player-spawn' command with player details and coordinates. It checks for and logs any errors returned by the command. ```typescript import { shard } from './shard' export async function spawnPlayer() { const { error } = await shard.sendCommand({ name: 'player-spawn', payload: { // TODO: when persona is implemented, we might not need to send auth id and name argus_auth_id: 'abc123', argus_auth_name: 'John Doe', x: 100, y: 200, }, }) if (error) { console.error(error) return { error } } return { success: true } } ``` -------------------------------- ### Configure Development Server Region (TypeScript) Source: https://world.dev/javascript/guides/configuration Configures a specific region for a development server, typically running on localhost. This allows for targeted development testing. ```typescript const config = createConfig({ regions: { 'dev-server': { gatewayUrl: 'http://localhost:8080', displayName: 'Development Server', }, }, }) ``` -------------------------------- ### Initialize Region Manager and Auto-Selection (TypeScript) Source: https://world.dev/javascript/guides/multiple-regions Initialize the region manager to perform latency checks and automatically select the best region. The `initialize()` method returns an unsubscribe function for cleanup. ```typescript import { world } from './sdk' // Initialize and get cleanup function const unsubscribe = world.regions.initialize() // Clean up when done (e.g., game exits) unsubscribe() ``` -------------------------------- ### Iterate Entities Using Defined Search in Go Source: https://world.dev/cardinal/build/system/search Demonstrates how to use a defined search, 'PlayerSearch', to iterate over entities that have both 'PlayerTag' and 'Position' components. It retrieves and logs the nickname and position of each matched player entity. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" ) type PlayerSystemState struct { cardinal.BaseSystemState Players PlayerSearch } func PlayerSystem(state *PlayerSystemState) error { for entity, player := range state.Players.Iter() { tag := player.Tag.Get() position := player.Position.Get() state.Logger().Info().Msgf("Player %s is at %d, %d", tag.Nickname, position.X, position.Y) } return nil } ``` -------------------------------- ### Integrate React Devtool Component Source: https://world.dev/javascript/react/devtool This snippet shows how to import and use the Devtool component in a React application. It takes a `defaultOpen` prop to control its initial state. The Devtool is conditionally bundled for development environments only. ```typescript import { Devtool } from '@argus-labs/sdk/react-devtool' function App() { return (
{/* Your other app content */}
) } ``` -------------------------------- ### Configure Default Localhost Region (TypeScript) Source: https://world.dev/javascript/guides/configuration Sets up the SDK configuration to default to a single `localhost` region if no specific regions are provided. This is useful for local development environments. ```typescript const config = createConfig({ // No regions specified - defaults to localhost:8080 }) ``` -------------------------------- ### Handle Player Movement Command in Go System Source: https://world.dev/cardinal/build/system/command This Go code demonstrates how to handle the MovePlayerCommand within a Cardinal system. It uses MovePlayerCommands.Iter() to process incoming commands and accesses payload data and the command's originating persona. This is a fundamental pattern for game logic. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" ) type MovePlayerCommand struct { cardinal.BaseCommand // The payload of the command. X uint32 `json:"x"` Y uint32 `json:"y"` } func (MovePlayerCommand) Name() string { // The name of the command. Clients specify the name when sending the command. return "move-player" } type MovePlayerSystemState struct { cardinal.BaseSystemState MovePlayerCommands cardinal.WithCommand[MovePlayerCommand] Players PlayerSearch } func MovePlayerSystem(state *MovePlayerSystemState) error { // Iterate over all move-player commands received in the tick. for cmd := range state.MovePlayerCommands.Iter() { payload := cmd.Payload() state.Logger().Info().Msgf("Player moved to %d, %d", payload.X, payload.Y) // You can also access the persona associated with the command. persona := cmd.Persona() state.Logger().Info().Msgf("Command sent by persona %s", persona) } return nil } ``` -------------------------------- ### Emit Player Death System Event in Go Source: https://world.dev/cardinal/build/system/event This Go code demonstrates how to emit a player death system event. It defines an attack command and a system state that includes a player death event emitter. The `AttackPlayerSystem` function processes attack commands, and if a player's health drops to zero or below, it emits a `systemevent.PlayerDeath`. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/basic/component" systemevent "github.com/argus-labs/monorepo/pkg/cardinal/examples/basic/system_event" ) type AttackPlayerCommand struct { cardinal.BaseCommand Target string Damage uint32 } func (a AttackPlayerCommand) Name() string { return "attack-player" } type AttackPlayerSystemState struct { cardinal.BaseSystemState AttackPlayerCommands cardinal.WithCommand[AttackPlayerCommand] PlayerDeathSystemEvents cardinal.WithSystemEventEmitter[systemevent.PlayerDeath] Players PlayerSearch } func AttackPlayerSystem(state *AttackPlayerSystemState) error { // This is a contrived example for demonstration purposes. // In a real implementation, you would want to avoid the nested loop // by using a more efficient lookup mechanism (e.g., a map or index). // Iterate over all attack-player commands received in the tick. for msg := range state.AttackPlayerCommands.Iter() { // Iterate over all players in the state. for entity, player := range state.Players.Iter() { tag := player.Tag.Get() if msg.Target != tag.Nickname { continue } newHealth := player.Health.Get().HP - int(msg.Damage) if newHealth > 0 { player.Health.Set(component.Health{HP: newHealth}) } else { entity.Destroy() state.PlayerDeathSystemEvents.Emit(systemevent.PlayerDeath{Nickname: tag.Nickname}) } } } return nil } ``` -------------------------------- ### Explicitly Define Localhost Region (TypeScript) Source: https://world.dev/javascript/guides/configuration Explicitly defines the `localhost` region with its gateway URL and display name. This provides a more detailed configuration than the default. ```typescript const config = createConfig({ regions: { localhost: { gatewayUrl: 'http://localhost:8080', displayName: 'Localhost', }, }, }) ``` -------------------------------- ### Query API - Match Type: Exact Source: https://world.dev/cardinal/build/query-api Demonstrates the 'exact' match type, which returns entities possessing only the specified components. No additional components are allowed for a match. ```APIDOC ## POST /query (Match Type: Exact) ### Description Queries entities that contain exactly the specified components, with no additional components present. ### Method POST ### Endpoint /query ### Parameters #### Query Parameters None #### Request Body - **find** (array of strings) - Required - A list of component names to search for. - **match** (string) - Required - Must be 'exact'. - **where** (string) - Optional - An expression string for filtering results. ### Request Example ```json { "find": ["PlayerTag", "Position"], "match": "exact" } ``` ### Response #### Success Response (200) - **entities** (array of objects) - A list of entities matching the query criteria. #### Response Example ```json { "entities": [ { "id": "entity789", "PlayerTag": {"name": "Player3"}, "Position": {"x": 30, "y": 40} } ] } ``` ``` -------------------------------- ### Define Player Movement Command in Go Source: https://world.dev/cardinal/build/system/command This Go code defines a command for player movement, embedding cardinal.BaseCommand and implementing the Name() method. It includes X and Y coordinates as the command's payload. This structure is essential for clients to send movement requests. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" ) type MovePlayerCommand struct { cardinal.BaseCommand // The payload of the command. X uint32 `json:"x"` Y uint32 `json:"y"` } func (MovePlayerCommand) Name() string { // The name of the command. Clients specify the name when sending the command. return "move-player" } ``` -------------------------------- ### Emit PlayerMovement Event in Go System Source: https://world.dev/cardinal/build/system/event Implements a system that processes `MovePlayerCommand` and emits a `PlayerMovement` event. This Go code demonstrates how to set player position and use the `Emit` method from a `cardinal.WithEvent` field within system state. ```go package system import ( "github.com/argus-labs/monorepo/pkg/cardinal" "github.com/argus-labs/monorepo/pkg/cardinal/examples/demo-game/component" "github.com/argus-labs/monorepo/pkg/cardinal/examples/demo-game/event" ) type MovePlayerCommand struct { cardinal.BaseCommand Nickname string `json:"nickname"` X uint32 `json:"x"` Y uint32 `json:"y"` } func (a MovePlayerCommand) Name() string { return "move-player" } type MovePlayerSystemState struct { cardinal.BaseSystemState MovePlayerCommands cardinal.WithCommand[MovePlayerCommand] PlayerMovementEvent cardinal.WithEvent[event.PlayerMovement] Players PlayerSearch } func MovePlayerSystem(state *MovePlayerSystemState) error { // This is a contrived example for demonstration purposes. // In a real implementation, you would want to avoid the nested loop // by using a more efficient lookup mechanism (e.g., a map or index). // Iterate over all move-player commands received in the tick. for msg := range state.MovePlayerCommands.Iter() { // Iterate over all players in the state. for entity, player := range state.Players.Iter() { tag := player.Tag.Get() if msg.Nickname != tag.Nickname { continue } player.Position.Set(component.Position{X: int(msg.X), Y: int(msg.Y)}) state.PlayerMovementEvent.Emit(event.PlayerMovement{ Nickname: tag.Nickname, X: msg.X, Y: msg.Y, }) } } return nil } ``` -------------------------------- ### Handle Command Errors Source: https://world.dev/javascript/guides/command Illustrates how to handle errors returned from sending a command. The function executes a 'player-spawn' command and checks the response for an `error` object. If an error is present, it's logged to the console; otherwise, a success message is returned. ```typescript export async function handleCommand() { const { error } = await shard.sendCommand({ name: 'player-spawn', payload: { argus_auth_id: 'abc123', argus_auth_name: 'John Doe', x: 100, y: 200, }, }) if (error) { console.error('Command failed:', error) return { error } } return { success: true } } ``` -------------------------------- ### Register Shard Client (TypeScript) Source: https://world.dev/javascript/guides/shard-client Registers a shard client to connect to a specific World Engine shard. Requires organization, project, and shard ID. This client can then be used to send commands, query game state, and subscribe to events. ```typescript import { world } from './sdk' const shard = world.shard.register({ organization: 'argus', // corresponds to CARDINAL_ORG project: 'demo', // corresponds to CARDINAL_PROJECT shardId: 'cardinal-demo-game-1', // corresponds to CARDINAL_SHARD_ID }) // You can create shard clients for different shards ``` -------------------------------- ### Querying Entities Based on Match Types (CONTAINS, EXACT) Source: https://world.dev/javascript/guides/query Demonstrates how to use different 'match' types in queries. 'Match.CONTAINS' returns entities with at least the specified components, while 'Match.EXACT' returns entities with only the specified components. These options allow for precise entity selection based on component sets. ```typescript // Returns entities with playertag + position + any other components const { data } = await shard.query({ find: ['playertag', 'position'], match: Match.CONTAINS, // Default behavior }) ``` ```typescript // Returns entities with only playertag + position components const { data } = await shard.query({ find: ['playertag', 'position'], match: Match.EXACT, }) ``` -------------------------------- ### Basic Event Subscription in TypeScript Source: https://world.dev/javascript/guides/subscribe-events Demonstrates how to subscribe to a specific event type, 'player-spawn', using the World Engine SDK. It includes basic success and error handlers for received event payloads. Requires '@argus-labs/sdk' and a configured 'shard' object. ```typescript import { createEventDefinition } from '@argus-labs/sdk' import { shard } from './shard' // Create event definition const playerSpawnEvent = createEventDefinition({ name: 'player-spawn', }) export async function subscribeToPlayerSpawn() { const { error, unsubscribe } = await shard.subscribeEvents([ playerSpawnEvent({ onSuccess: (payload) => { console.log('Player spawned:', payload) }, onError: (error) => { console.error('Event error:', error) }, }), ]) if (error) { console.error('Failed to subscribe:', error) return null } return unsubscribe } ``` -------------------------------- ### Configure World Forge SDK for Development Source: https://world.dev/javascript/guides/world-forge Sets up the World Forge SDK with a development-specific region preset. This preset is optimized for development testing, typically including the 'us-west-2' region. It relies on the '@argus-labs/sdk' package. ```typescript import { createConfig, createSDK, worldForgePresetDevelopment } from '@argus-labs/sdk' const config = createConfig({ regions: worldForgePresetDevelopment, }) export const world = createSDK(config) ``` -------------------------------- ### Configure World Forge SDK for Production Source: https://world.dev/javascript/guides/world-forge Sets up the World Forge SDK with a production-ready region preset. This preset includes multiple regions across different continents (e.g., US West, US East, Asia Pacific, Europe) for global connectivity and high availability. It depends on the '@argus-labs/sdk' package. ```typescript import { createConfig, createSDK, worldForgePresetProduction } from '@argus-labs/sdk' const config = createConfig({ regions: worldForgePresetProduction, }) export const world = createSDK(config) ```