### Install Dependencies and Run Development Server Source: https://github.com/instructa/viber3d/blob/main/CONTRIBUTE.md Install project dependencies using pnpm and start the development server. The server will be accessible at http://localhost:5173. ```bash pnpm install pnpm run dev ``` -------------------------------- ### Initialize a new Viber3D project using the CLI Source: https://context7.com/instructa/viber3d/llms.txt Use the `viber3d init` command to create a new project. Interactive setup is recommended. You can also use flags for non-interactive setup, custom templates, or to skip dependency installation. ```bash npx viber3d@latest init ``` ```bash npx viber3d@latest init my-game --defaults ``` ```bash npx viber3d@latest init my-game --template username/my-template ``` ```bash npx viber3d@latest init my-game --template next ``` ```bash npx viber3d@latest init my-game --yes --packageManager pnpm --gitInit ``` -------------------------------- ### Start Development Server Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md Start the development server on http://localhost:3000 using npm, pnpm, yarn, or bun. ```bash # npm npm run dev # pnpm pnpm dev # yarn yarn dev # bun bun run dev ``` -------------------------------- ### Install viber3d Project with CLI Source: https://github.com/instructa/viber3d/blob/main/templates/starter/README.md Use this command to create a new viber3d project. Do not install the package directly; the CLI ensures a complete setup. ```bash npx viber3d@latest my-project ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md Install all necessary project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Install Dependencies Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md Install project dependencies using npm, pnpm, yarn, or bun. ```bash # npm npm install # pnpm pnpm install # yarn yarn install # bun bun install ``` -------------------------------- ### Install Viber3D Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/index.md Install the Viber3D package using npm. This command installs the latest version of the library. ```bash npm install @instructa/viber3d ``` -------------------------------- ### Run Development Server Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md Start your development server using npm or yarn to see your Viber3D application in action. ```bash npm run dev # or yarn dev ``` -------------------------------- ### Install Dependencies for Viber3D Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md Install the necessary libraries for Viber3D, React, Three.js, and optionally a physics engine like Jolt. ```bash yarn add react react-dom three @react-three/fiber @react-three/drei koota ``` ```bash yarn add jolt-physics ``` -------------------------------- ### Example MDC File for React Component Rules Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/3.cursor-rules.md This example shows the front matter and Markdown content for an .mdc file defining rules for React components, including guidelines for functional components, ECS data flow with Koota, and system logic placement. ```markdown --- description: React Component Rules globs: *.tsx --- # React Component Guidelines - Use functional components - Implement ECS data flow with Koota (no direct game logic in components) - Keep all game logic in systems, not `useFrame` ``` -------------------------------- ### Install Viber3D CLI with npx Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md Use npx to run the Viber3D CLI without global installation. This is useful for executing commands directly. ```bash npx viber3d@latest [command] ``` -------------------------------- ### Run viber3d Project Source: https://github.com/instructa/viber3d/blob/main/README.md Commands to start the development server for your viber3d project. Access the app at http://localhost:5173. ```bash npm run dev # or pnpm run dev ``` -------------------------------- ### Start Development Server with Hot Reload Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/1.running-dev-server.md Run this command in your terminal to start the development server. It enables hot module replacement (HMR) and provides real-time error feedback. ```bash npm run dev ``` -------------------------------- ### Viber3D Project Structure Example Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/3.project-structure.md This Bash snippet illustrates a typical directory and file layout for a Viber3D project, including common subdirectories for assets, components, systems, traits, and utilities, as well as core application files. ```bash viber3d/ ├── src │ ├── assets/ # 3D models, textures, images │ ├── components/ # React components for rendering 3D objects/UI │ ├── systems/ # ECS Systems for game logic updates │ ├── traits/ # ECS Traits (components) describing entity data │ ├── utils/ # Utility functions (math, sorting, spatial hashing) │ ├── actions.ts # Central actions to spawn or modify entities │ ├── app.tsx # Main React component (root of your 3D scene) │ ├── frameloop.ts # Main ECS update loop │ ├── index.css # Global CSS or Tailwind CSS (if used) │ ├── main.tsx # React app root, renders │ ├── startup.tsx # Startup logic (initial spawns, intervals) │ └── world.ts # Creates the ECS world with default traits ├── index.html # Basic HTML page with root div ├── package.json # Project dependencies and scripts └── tsconfig.json # TypeScript configuration ``` -------------------------------- ### Create Alpha Release Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/2.releases.md Generate an alpha release, which is published with the 'alpha' tag on npm and not installed by default. ```bash pnpm tsx scripts/release.ts --alpha ``` -------------------------------- ### Game Loop System Execution Order Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/4.systems.md Example of how to organize and call systems in sequence within a game loop. Ensure systems are called in a logical order for correct game state updates. ```typescript export function GameLoop(world: World) { // Possibly in a requestAnimationFrame or React useFrame timeSystem(world) inputSystem(world) movementSystem(world) collisionSystem(world) cleanupSystem(world) } ``` -------------------------------- ### Define Traits, Create World, Spawn Entity, and Query Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/1.ecs-overview.md This snippet demonstrates the basic setup of an ECS world using koota. It shows how to define traits (data structures), create a world, spawn an entity with specific traits, and then query for entities possessing multiple traits to update them. ```typescript import { trait, createWorld } from 'koota' // 1. Define traits (data) export const Position = trait({ x: 0, y: 0, z: 0 }) export const Health = trait({ amount: 100 }) // 2. Create a world and spawn an entity const world = createWorld() world.spawn(Position({ x: 10, y: 5 }), Health({ amount: 50 })) // 3. Query and update entities world.query(Position, Health).updateEach(([pos, hp]) => { // game logic that modifies position or health }) ``` -------------------------------- ### Query and Render Entities with useQuery Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md Use the useQuery hook to fetch entities that possess specific traits. This example demonstrates how to retrieve all entities marked as 'IsEnemy' and having a 'Position' trait for rendering. ```tsx // EnemyRenderer.tsx import { useQuery } from 'koota/react' import { IsEnemy, Position } from '../ecs/traits' export function EnemyRenderer() { const enemies = useQuery(IsEnemy, Position) return ( <> {enemies.map((entity) => ( ))} ) } // Basic visualization function EnemyVisual({ entity }) { const position = entity.get(Position) if (!position) return null return ( ) } ``` -------------------------------- ### Implement Game Logic with Systems Source: https://context7.com/instructa/viber3d/llms.txt Systems are functions that execute game logic by querying entities and performing updates. They can be event-driven or run on a fixed schedule. Includes examples for movement, health regeneration, cleanup, and event emission. ```typescript import { World } from 'koota' import { Transform, Velocity, Health, Time, IsEnemy } from './traits' // Movement system — runs every frame export function movementSystem({ world, delta }: { world: World; delta: number }) { world.query(Transform, Velocity).updateEach(([transform, vel]) => { transform.position.x += vel.x * delta transform.position.y += vel.y * delta transform.position.z += vel.z * delta }) } // Health regen system — uses a Time singleton trait export function healthRegenSystem(world: World) { const time = world.get(Time)! world.query(Health).updateEach(([health]) => { health.amount = Math.min(health.max, health.amount + 5 * time.delta) }) } // Cleanup system — removes dead entities export function cleanupSystem(world: World) { world.query(Health).removeIf(([health]) => health.amount <= 0) } // Event-driven system world.on('entityDamaged', ({ entity, amount }) => { // spawn a hit-effect entity, play audio, etc. }) // Apply damage and emit event function applyDamage(entity: Entity, damage: number) { entity.set(Health, (h) => { const newAmount = Math.max(0, h.amount - damage) world.emit('entityDamaged', { entity, amount: damage }) return { ...h, amount: newAmount } }) } // Unit test for a system describe('movementSystem', () => { it('updates position based on velocity', () => { const testWorld = createWorld() testWorld.add(Time({ delta: 1, current: 0 })) const ent = testWorld.spawn( Transform(), Velocity({ x: 1, y: 0, z: 0 }) ) movementSystem({ world: testWorld, delta: 1 }) expect(ent.get(Transform)!.position.x).toBe(1) }) }) ``` -------------------------------- ### ECS System with `useFrame` Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/5.components.md Integrate ECS logic into React Three Fiber's render loop using `useFrame`. This example demonstrates a 'MovementSystem' that updates entity positions based on velocity and delta time. ```tsx import { useFrame } from '@react-three/fiber' import { useWorld } from 'koota/react' import { Movement, Transform } from '../traits' function MovementSystem() { // This component acts as a "system" in React const world = useWorld() useFrame(() => { const time = world.get(Time) if (!time) return const { delta } = time world.query(Transform, Movement).updateEach(([t, m]) => { t.position.add(m.velocity.clone().multiplyScalar(delta)) }) }) return null } ``` -------------------------------- ### Create a new project with the default template Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md Initializes a new Viber3D project using the default 'starter' template in the 'my-game' directory. ```bash npx viber3d@latest init my-game ``` -------------------------------- ### Create a new project with the 'next' template Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md Initializes a new Viber3D project using the experimental 'next' template in the 'my-game' directory. ```bash npx viber3d@latest init my-game -t next ``` -------------------------------- ### Create Production Build Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/2.production-build.md Run this command to compile, bundle, and optimize your project for production. The output will be placed in the `dist/` directory. ```bash npm run build ``` -------------------------------- ### viber3d CLI Initialization with Options Source: https://github.com/instructa/viber3d/blob/main/packages/viber3d/README.md This command shows the general structure for initializing a viber3d project with a project name and various command-line options. Refer to the CLI Options section for a full list of available flags. ```bash npx viber3d@latest init [project-name] [options] ``` -------------------------------- ### viber3d CLI Options Source: https://github.com/instructa/viber3d/blob/main/README.md Available command-line options for the viber3d initialization tool. Customize project creation with these flags. ```bash npx viber3d@latest [project-name] [options] Options: --cwd, -c The working directory. Defaults to the current directory --name Project name --force, -f Override existing directory --install Skip installing dependencies (default: true) --gitInit Initialize git repository --packageManager Package manager choice (npm, pnpm, yarn) --yes, -y Skip confirmation prompt (default: false) --defaults, -d Use default configuration (default: false) --silent, -s Mute output (default: false) --help, -h Display help for command ``` -------------------------------- ### Initialize a new Viber3D project Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md Initialize a new Viber3D project in a specified directory. Options can be used to customize the initialization process. ```bash npx viber3d@latest init [dir] [options] ``` -------------------------------- ### Create a new project with default settings Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md Initializes a new Viber3D project and skips all confirmation prompts by using the '-y' flag. ```bash npx viber3d@latest init my-game -y ``` -------------------------------- ### Initialize Callback-Based Trait Instance Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/3.traits.md Spawn an entity with a callback-based trait, ensuring each entity gets its own instance. ```typescript const Model = trait(() => new THREE.Mesh()) const entity = world.spawn(Model()) ``` -------------------------------- ### Preview Production Build Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md Locally preview the production build using npm, pnpm, yarn, or bun. ```bash # npm npm run preview # pnpm pnpm preview # yarn yarn preview # bun bun run preview ``` -------------------------------- ### Build for Production Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md Build the application for production using npm, pnpm, yarn, or bun. ```bash # npm npm run build # pnpm pnpm build # yarn yarn build # bun bun run build ``` -------------------------------- ### Retrieve and Modify Trait Snapshot Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/3.traits.md Get a snapshot of a trait's data from an entity and modify it directly. Note that this does not trigger events. ```typescript // Retrieve a trait snapshot const health = entity.get(Health) health.amount -= 10 ``` -------------------------------- ### Create a new project with a custom GitHub template Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md Initializes a new Viber3D project using a template from a specified GitHub repository. ```bash npx viber3d@latest init my-game -t username/repo ``` -------------------------------- ### Adding, Removing, and Checking Traits in Koota Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt Provides examples for adding a trait with custom data, removing a trait from an entity, and checking for the presence of a trait. ```typescript // Add trait entity.add(Health({ amount: 100 })) // Remove trait entity.remove(Health) // Check if a trait is present if (entity.has(Health)) { // ... } ``` -------------------------------- ### Initializing Trait Data in Koota Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt Provides examples of initializing trait data, overriding defaults when adding traits to an entity, including callback-based traits. ```typescript entity.add(Health()) // uses defaults entity.add(Health({ amount: 50 })) // custom amount const Model = trait(() => new THREE.Mesh()) const entity = world.spawn(Model()) // Each entity gets its own mesh instance ``` -------------------------------- ### Initialize a New viber3d Project Source: https://github.com/instructa/viber3d/blob/main/packages/viber3d/README.md Use this command to create a new viber3d project. You can specify a project name or let it default to the current directory. ```bash npx viber3d@latest init ``` ```bash npx viber3d@latest init myGame ``` -------------------------------- ### Compose Actions for Complex Flows Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/6.actions.md Actions can call other actions, allowing for the creation of complex sequences of operations. This example shows `spawnEnemyWave` calling `spawnEnemy`. ```typescript export const actions = createActions((world) => ({ spawnEnemy: (position) => { return world.spawn(IsEnemy(), Transform({ position }), Health({ amount: 50 })) }, spawnEnemyWave: (count) => { for (let i = 0; i < count; i++) { const position = getRandomPosition() actions.spawnEnemy(position) // calling another action } } })) ``` -------------------------------- ### Filter Query Results Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/2.entities.md Apply standard array filters to refine query results. This example filters enemies with health below 50. Requires 'World' from 'koota'. ```typescript const lowHealthEnemies = world .query(IsEnemy, Health) .filter(([_, health]) => health.amount < 50) ``` -------------------------------- ### Initialize Viber3D Project Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/2.installation.md Run this command in your terminal to create a new project using the latest version of Viber3D. ```bash npx viber3d@latest init ``` -------------------------------- ### Commit Changes with Conventional Commits Source: https://github.com/instructa/viber3d/blob/main/CONTRIBUTE.md Commit your changes following the Conventional Commits specification. Use a descriptive message that starts with a type (e.g., 'feat', 'fix') and a brief description of the change. ```bash git commit -m "feat: add your feature description" ``` -------------------------------- ### Initialize Project with a Specific Template Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md Initialize a new Viber3D project using a specific template, such as the experimental 'next' template. This command uses the latest version of the CLI. ```bash npx viber3d@latest init my-game --template next ``` -------------------------------- ### Conditional Updates within Actions Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/6.actions.md Implement conditional logic within actions, such as checking for traits before modifying them or triggering other actions based on conditions. This example handles entity damage and destruction. ```typescript export const actions = createActions((world) => ({ damageEntity: (entity, amount) => { if (entity.has(Health)) { entity.set(Health, (h) => { const newAmount = Math.max(0, h.amount - amount) if (newAmount <= 0) { actions.destroyEntity(entity) } return { ...h, amount: newAmount } }) } }, destroyEntity: (entity) => entity.destroy() })) ``` -------------------------------- ### Testing a Movement System Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/4.systems.md Unit test for the movement system, verifying that entity positions are updated correctly based on velocity and time delta. Requires a test world setup and trait mocks. ```typescript describe('movementSystem', () => { it('updates position based on velocity', () => { const world = createWorld() const ent = world.spawn(Transform(), Movement({ velocity: new Vector3(1, 0, 0) })) world.add(Time({ delta: 1 })) // simulate 1 second movementSystem(world) expect(ent.get(Transform)!.position.x).toBe(1) }) }) ``` -------------------------------- ### Test Production Build Locally Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/2.production-build.md Serve your built files locally to test the production build before deployment. This command defaults to serving at http://localhost:4173. ```bash npm run preview ``` -------------------------------- ### Run Release Script with Minor Version Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/2.releases.md Publish a new release by bumping the minor version using the release script. ```bash pnpm tsx scripts/release.ts minor ``` -------------------------------- ### Hypothetical Collision Handling Logic Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/5.addons/1.physics.md This is a conceptual example of how collision events might be handled. It assumes a hypothetical `GetCollisionEvents` API on the JoltWorld and demonstrates iterating through collisions to find corresponding entities. A map of `BodyID -> Entity` is recommended for efficient lookups. ```typescript function handleCollisions(world: World) { const joltWorld = world.get(JoltWorld) // some hypothetical API const collisions = joltWorld.physicsSystem.GetCollisionEvents() for (const c of collisions) { const bodyA = c.bodyA const bodyB = c.bodyB // find which entities correspond to bodyA, bodyB, then apply logic } } ``` -------------------------------- ### Viber3D Project Rule Files Source: https://context7.com/instructa/viber3d/llms.txt Lists the default rule files included in the Viber3D starter template for organizing coding standards. ```bash # Project rule files included in the starter template: .cursor/rules/ ├── 001-base.mdc # Overarching ECS + R3F principles ├── 002-components.mdc # React component guidelines ├── 003-systems.mdc # System structure rules ├── 004-actions.mdc # Action pattern guidelines ├── 005-traits.mdc # Trait definition conventions ├── 006-utils.mdc # Utility module best practices ├── 007-tailwind.mdc # Tailwind CSS usage └── 900-game-agent.mdc # AI game-agent persona ``` -------------------------------- ### Project Rules Directory Structure Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/3.cursor-rules.md Illustrates the typical directory structure for project-specific Cursor Rules (.mdc files) within a project's .cursor/rules directory. ```bash .cursor/ └── rules/ ├── base.mdc ├── components.mdc ├── systems.mdc ├── traits.mdc └── utils.mdc ``` -------------------------------- ### Use Centralized Actions in React with useActions Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt Demonstrates how to use the centralized actions defined with createActions within a React component. The useActions hook binds the action functions to the current ECS world, allowing them to be called directly. This example spawns a player on mount and cleans up by destroying all players on unmount. ```tsx import { useEffect } from 'react' import { useActions } from 'koota/react' import { actions } from '../actions' function GameController() { const { spawnPlayer, destroyAllPlayers } = useActions(actions) useEffect(() => { // Spawn a player on mount spawnPlayer({ x: 0, y: 0, z: 0 }) // Cleanup on unmount return () => destroyAllPlayers() }, []) return null } ``` -------------------------------- ### Build Project Packages Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md Build all packages within the monorepo using the pnpm build script. ```bash pnpm build:packages ``` -------------------------------- ### Run Release Script Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/2.releases.md Execute the automated release script with an optional version type and options. ```bash pnpm tsx scripts/release.ts [version-type] [options] ``` -------------------------------- ### Create ECS World and Schedule Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md Initialize the ECS world and define a system schedule for managing game logic updates. ```typescript import { createWorld } from 'koota' import { Schedule } from 'directed' import type { World } from 'koota' export const world = createWorld() // Build a system schedule export const schedule = new Schedule<{ world: World; delta: number }>() // Add systems in order schedule.add(movementSystem) schedule.add(collisionSystem, { after: movementSystem }) schedule.add(aiSystem, { after: collisionSystem }) schedule.build() ``` -------------------------------- ### Initialize Jolt Physics World Source: https://context7.com/instructa/viber3d/llms.txt Initializes the Jolt physics world. This action should be called once at application startup. ```typescript export const useJoltActions = createActions((world) => ({ async initWorld() { if (world.has(JoltWorld)) return const joltInit = await import('jolt-physics') JoltWorldImpl.JOLT_NATIVE = await joltInit.default() world.add(JoltWorld()) }, })) ``` -------------------------------- ### Initialize Jolt Physics World Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt Loads the Jolt WASM library and initializes the physics world. This should be called once during application startup. Stores the Jolt WASM reference globally for later use. ```typescript // traits/jolt-world.ts import { trait } from 'koota' import type Jolt from 'jolt-physics' export const JoltWorld = trait(() => new JoltWorldImpl()) export class JoltWorldImpl { static JOLT_NATIVE: typeof Jolt joltInterface: Jolt.JoltInterface = null! bodyInterface: Jolt.BodyInterface = null! physicsSystem: Jolt.PhysicsSystem = null! initialized = false constructor() { if (!JoltWorldImpl.JOLT_NATIVE) { throw new Error("Jolt not loaded yet.") } // Create the JoltInterface with default settings const J = JoltWorldImpl.JOLT_NATIVE const settings = new J.JoltSettings() this._setupCollisionFiltering(settings) const jolt = new J.JoltInterface(settings) J.destroy(settings) this.physicsSystem = jolt.GetPhysicsSystem() this.bodyInterface = this.physicsSystem.GetBodyInterface() this.joltInterface = jolt this.initialized = true } stepPhysics(dt: number) { // E.g., do multiple substeps if dt is large const steps = dt > 1/55 ? 2 : 1 this.joltInterface.Step(dt, steps) } _setupCollisionFiltering(settings: Jolt.JoltSettings) { // your collision layers, etc. } } ``` ```typescript // actions/use-jolt-actions.ts import { createActions } from 'koota/react' import { JoltWorld, JoltWorldImpl } from '../traits/jolt-world' export const useJoltActions = createActions((world) => ({ async initWorld() { if (world.has(JoltWorld)) { // already initialized return } // Load the Jolt WASM const joltInit = await import('jolt-physics') // Store the reference globally JoltWorldImpl.JOLT_NATIVE = await joltInit.default() // Add the JoltWorld trait to ECS world.add(JoltWorld()) console.log("Jolt world created.") } })) ``` -------------------------------- ### Spawn and Manage Entities with world.spawn and entity Source: https://context7.com/instructa/viber3d/llms.txt Use world.spawn() to create entities with initial traits. Entities can be updated with entity.set(), have traits added/removed with add()/remove(), and destroyed with destroy(). Relationships can also be defined and queried. ```typescript import { World, trait, relation } from 'koota' // Spawn an entity with initial trait values const player = world.spawn( IsPlayer(), Transform(), Health({ amount: 100 }), ) // Read trait data const hp = player.get(Health) console.log(hp?.amount) // 100 // Update trait (triggers change detection) player.set(Health, (prev) => ({ ...prev, amount: prev.amount - 25 })) // Add / remove traits dynamically player.add(Velocity({ x: 1, y: 0, z: 0 })) player.remove(Velocity) // Check trait presence if (player.has(Health)) { /* ... */ } // Destroy entity player.destroy() // --- Relationships --- const ChildOf = relation({ autoRemoveTarget: true }) // cascade destroy const Targeting = relation({ exclusive: true }) // only one target const parent = world.spawn() const child = world.spawn(ChildOf(parent)) // Query all children of parent const children = world.query(ChildOf(parent)) // Relationship with data const Contains = relation({ store: { amount: 0 } }) const inventory = world.spawn() const gold = world.spawn() inventory.add(Contains(gold)) inventory.set(Contains(gold), { amount: 10 }) ``` -------------------------------- ### Clone Viber3D Repository Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md Clone the Viber3D repository locally and navigate into the project directory. ```bash git clone https://github.com/instructa/viber3d.git cd viber3d ``` -------------------------------- ### Clone viber3d Repository Source: https://github.com/instructa/viber3d/blob/main/CONTRIBUTE.md Clone the viber3d repository to your local machine and navigate into the project directory. ```bash git clone git@github.com:instructa/viber3d.git cd viber3d ``` -------------------------------- ### Step Jolt Physics Simulation Source: https://context7.com/instructa/viber3d/llms.txt System to advance the Jolt physics simulation by a given delta time. This should be called every frame. ```typescript export function UpdateJolt({ world, delta }: { world: World; delta: number }) { if (!world.has(JoltWorld)) return world.get(JoltWorld)!.stepPhysics(delta) } ``` -------------------------------- ### Implement ECS Systems (Logic) Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md Create systems that process entities based on their traits, updating game state each frame. Systems receive the world and delta time as arguments. ```typescript import { World } from 'koota' import { Position, Rotation } from './traits' import { Vector3 } from 'three' export function movementSystem({ world, delta }: { world: World; delta: number }) { // For each entity with Position, move upward world.query(Position).updateEach(([pos]) => { pos.y += 1 * delta }) } export function collisionSystem({ world }: { world: World }) { // Example collision logic ... } export function aiSystem({ world }: { world: World }) { // Example AI logic ... } ``` -------------------------------- ### Build Jolt Bodies System Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/5.addons/1.physics.md This system creates Jolt physics bodies for entities that require them and have mesh data. It infers initial transforms from the mesh and creates appropriate Jolt shapes. Ensure JoltWorld is present in the world. ```typescript import { World } from 'koota' import { NeedsJoltBody } from '../traits/needs-jolt-body' import { JoltBody } from '../traits/jolt-body' import { JoltWorld, JoltWorldImpl } from '../traits/jolt-world' import { MeshRef } from '../traits/mesh-ref' import { inferInitTransformsFromMesh, createShapeFromGeometry } from '../misc/jolt-helper' export function BuildJoltBodies({ world }: { world: World }) { if (!world.has(JoltWorld)) return const joltWorld = world.get(JoltWorld) const J = JoltWorldImpl.JOLT_NATIVE world.query(NeedsJoltBody, MeshRef).updateEach(([needs, meshRef], entity) => { const { pos, rot } = inferInitTransformsFromMesh(meshRef.ref) const shape = needs.buildConvexShape ? createShapeFromGeometry(meshRef.ref.geometry) : /* other shape logic, e.g. BoxShape */ new J.BoxShape(1,1,1) // create BodyCreationSettings const layer = needs.layer === 'moving' ? 1 : 0 const motionType = { dynamic: J.EMotionType_Dynamic, static: J.EMotionType_Static, kinematic: J.EMotionType_Kinematic }[needs.motionType] const creation = new J.BodyCreationSettings(shape, pos, rot, motionType, layer) const body = joltWorld.bodyInterface.CreateBody(creation) J.destroy(creation) // add the body to jolt joltWorld.bodyInterface.AddBody(body.GetID(), J.EActivation_Activate) // handle continuous collision if (needs.continuousCollisionMode) { joltWorld.bodyInterface.SetMotionQuality(body.GetID(), J.EMotionQuality_LinearCast) } // remove the NeedsJoltBody trait (we built the body) entity.remove(NeedsJoltBody) // add the JoltBody trait referencing the new body entity.add(JoltBody(body)) }) } ```