diff --git a/pages/concepts/entities.mdx b/pages/concepts/entities.mdx index 4da93eb..b5e866a 100644 --- a/pages/concepts/entities.mdx +++ b/pages/concepts/entities.mdx @@ -1,8 +1,106 @@ +import { Callout } from 'nextra/components' + # Entities -In Dreamlab, entities are any object in the world. They can move, have physics and colliders, render sprites, and more. +In Dreamlab, an entity is a distinct object that can be created, updated, or destroyed. +They can respond to events such as physics ticks or network packets and run logic in the game world. + + + You will most likely not want to work with Entities directly. Dreamlab has an + abstraction called Spawnable Entities that you should use to represent objects + in the world. + + +## Spawnable Entities + +Spawnable Entities are an abstraction on top of Entities that have stricter requirements. +They must have a position in the world, they must be able to be created and destroyed at runtime, and they must be able to be synced over the network. + +### Defining + + + The export `z` from `@dreamlab.gg/core/sdk` is actually a re-export of + [Zod](https://zod.dev). Refer to their documentation for more info on how to + define arguments. + + +```ts filename="TypeScript" +import { createSpawnableEntity } from '@dreamlab.gg/core' +import { z } from '@dreamlab.gg/core/sdk' + +// Define the arguments for this entity +const ArgsSchema = z.object({}) + +const createExampleEntity = createSpawnableEntity(ArgsSchema, context => ({ + // ... implement all required members +})) +``` + +### Registering + +Spawnable Entities must be registered with the `game` instance in order for them to be created by name. +This is most commonly done inside of a `sharedInit()` function, which is a convention that world scripts use to run initialization code on both client and server. + + + Refer to your world scripts for how `sharedInit()` relates to the + initialization of a world. + + +Entity names registered with the game instance **must be unique**. To avoid collisions, you should namespace your entity names as shown below. +Although we recommend namespacing using the `@project/entity` format, this is just a convention and you are free to solve uniqueness issues however you like. + +```ts filename="shared.ts" +export const sharedInit = async game => { + // register your entity with the game + game.register('@example/example-entity', createExampleEntity) +} +``` + +### Spawning -The best way to learn the anatomy of an entity is an example. Below are some sample entities of varying complexity. +{/* TODO: Write better copy */} + +#### required + +- `entity` +- `args` +- `transform.position` + +#### optional + +- `transform.rotation` / `0` +- `transform.zIndex` / `0` +- `uid` / `random cuid` +- `label` +- `tags` / `[]` + +```ts filename="server.ts" +import type { InitServer } from '@dreamlab.gg/core/sdk' + +export const init: InitServer = game => { + // ... server-side initialization + + await game.spawn({ + // Reference the entity we registered by name + entity: '@example/example-entity', + + // TODO + args: {}, + + // TODO + transform: { + position: [], + rotation: 0, + zIndex: 0, + }, + + // TODO + tags: [], + }) +} +``` + +--- ## Example 1 - Bouncing Ball @@ -102,19 +200,6 @@ export const createTestBall = createSpawnableEntity( ) ``` -### Registering Entities - -All entities need to be registered with the Dreamlab engine before they can be used. This is done in the `sharedInit` function that runs on both the client and the server. - -```ts filename="TypeScript" -export const sharedInit = async game => { - // register testBall - game.register('testBall', createTestBall) - // spawn the rest of our predefined level - await game.spawnMany(...level) -} -``` - ### Spawning Entities For this example, we want our bouncy ball to be synced between the client and server and also spawn over time.