Skip to content

Commit

Permalink
Add pages to docs (#92)
Browse files Browse the repository at this point in the history
* Explicit error for query:next

* Add drain to docs

* Fix next call

* Add relationships page
  • Loading branch information
Ukendio authored Jul 31, 2024
1 parent 24f9f58 commit 51ed9e2
Show file tree
Hide file tree
Showing 18 changed files with 806 additions and 356 deletions.
6 changes: 3 additions & 3 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ export default defineConfig({
{
text: 'Concepts',
items: [
{ text: 'Entities', link: 'learn/concepts/entities' },
{ text: 'Static Components', link: 'learn/concepts/static-components' },
{ text: 'Queries', link: 'learn/concepts/queries' },
{ text: 'Entities and Components', link: 'learn/concepts/entities-and-components' },
{ text: 'Builtin Components', link: 'learn/concepts/builtin-components' },
{ text: 'Relationships', link: 'learn/concepts/relationships' },
]
},
{
Expand Down
23 changes: 23 additions & 0 deletions docs/api/jecs.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,31 @@ Jecs. Just an Entity Component System.
```luau
jecs.World: World
```
A world is a container of all ECS data. Games can have multiple worlds but component IDs may conflict between worlds. Ensure to register the same component IDs in the same order for each world.

### Wildcard
```luau
jecs.Wildcard: Entity
```
Builtin component type. This ID is used for [wildcard queries]().

### Component
```luau
jecs.Component: Entity
```
Builtin component type. Every ID created with [world:component()](world.md#component()) has this type added to it. This is meant for querying every component ID.

### ChildOf
```luau
jecs.ChildOf: Entity
```
Builtin component type. This ID is for creating parent-child hierarchies.

:::
### Rest
```luau
jecs.Rest: Entity
```

## Functions

Expand Down
14 changes: 13 additions & 1 deletion docs/api/query.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
# Query
# Query

A World contains entities which have components. The World is queryable and can be used to get entities with a specific set of components.

## Functions

### drain()
```luau
function query:drain(): Query
```
This function will impede it from being reset when the query is being iterated.

### next()
```luau
function query:next(): Query
```
Get the next result in the query. Drain must have been called beforehand or otherwise it will error.

### with()
```luau
function query:with(
Expand Down
29 changes: 29 additions & 0 deletions docs/api/world.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,33 @@ for (const [id, position, velocity] of world.query(Position, Velocity) {
:::info
Queries are uncached by default, this is generally very cheap unless you have high fragmentation from e.g. relationships.
:::
### target()
```luau
function World:target(
entity: Entity, -- The entity
relation: Entity -- The relationship between the entity and the target
): Entity? -- Returns the parent of the child
```

Get the target of a relationship.

This will return a target (second element of a pair) of the entity for the specified relationship.

If there is no pair with specified relationship, it will return nil.

### parent()
```luau
function World:parent(
child: Entity -- The child ID to find the parent of
): Entity? -- Returns the parent of the child
```

Get parent (target of ChildOf relationship) for entity. If there is no ChildOf relationship pair, it will return nil.

This operation is the same as calling:

```luau
world:target(entity, jecs.ChildOf)
```
File renamed without changes.
109 changes: 109 additions & 0 deletions docs/learn/concepts/entities-and-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Entities and Components

## Entities
Entities represent things in a game. In a game there may be entities of characters, buildings, projectiles, particle effects etc.

By itself, an entity is just an unique identifier without any data

### Creation

## Components
A component is something that is added to an entity. Components can simply tag an entity ("this entity is an `Npc`"), attach data to an entity ("this entity is at `Position` `Vector3.new(10, 20, 30)`") and create relationships between entities ("bob `Likes` alice") that may also contain data ("bob `Eats` `10` apples").

### Operations
Operation | Description
----------|------------
`get` | Get a specific component or set of components from an entity.
`add` | Adds component to an entity. If entity already has the component, `add` does nothing.
`set` | Sets the value of a component for an entity. `set` behaves as a combination of `add` and `get`
`remove` | Removes component from entity. If entity doesn't have the component, `remove` does nothing.
`clear` | Remove all components from an entity. Clearing is more efficient than removing one by one.

### Components are entities

In an ECS, components need to be uniquely identified. In Jecs this is done by making each component is its own unique entity. If a game has a component Position and Velocity, there will be two entities, one for each component. Component entities can be distinguished from "regular" entities as they have a `Component` component. An example:

:::code-group
```luau [luau]
local Position = world:component() :: jecs.Entity<Vector3>
print(world:has(Position, Jecs.Component))
```

```typescript [typescript]
const Position = world.component<Vector3>();
print(world.has(Position, Jecs.Component))
```

All of the APIs that apply to regular entities also apply to component entities. This means it is possible to contexualize components with logic by adding traits to components

:::code-group
```luau [luau]
local Networked = world:component()
local Type = world:component()
local Name = world:component()
local Position = world:component() :: jecs.Entity<Vector3>
world:add(Position, Networked)
world:set(Posiition, Name, "Position")
world:set(Position, Type, { size = 12, type = "Vector3" } ) -- 12 bytes to represent a Vector3
for id, ty, name in world:query(Type, Name):with(Networked) do
local batch = {}
for entity, data in world:query(id) do
table.insert(batch, { entity = entity, data = data })
end
-- entities are sized f64
local packet = buffer.create(#batch * (8 + ty.size))
local offset = 0
for _, entityData in batch do
offset+=8
buffer.writef64(packet, offset, entityData.entity)
if ty.type == "Vector3" then
local vec3 = entity.data :: Vector3
offset += 4
buffer.writei32(packet, offset, vec3.X)
offset += 4
buffer.writei32(packet, offset, vec3.Y)
offset += 4
buffer.writei32(packet, offset, vec3.Z)
end
end
updatePositions:FireServer(packet)
end
```

```typescript [typescript]
const Networked = world.component()
const Type = world.component()
const Name = world.component()
const Position = world.component<Vector3>();
world.add(Position, Networked)
world.set(Posiition, Name, "Position")
world.set(Position, Type, { size: 12, type: "Vector3" } ) // 12 bytes to represent a Vector3

for (const [id, ty, name] of world.query(Type, Name).with(Networked)) {
const batch = new Array<{ entity: Entity, data: unknown}>()

for (const [entity, data] of world.query(id)) {
batch.push({ entity, data })
}
// entities are sized f64
const packet = buffer.create(batch.size() * (8 + ty.size))
const offset = 0
for (const [_, entityData] of batch) {
offset+=8
buffer.writef64(packet, offset, entityData.entity)
if (ty.type == "Vector3") {
const vec3 = entity.data as Vector3
offset += 4
buffer.writei32(packet, offsetm, vec3.X)
offset += 4
buffer.writei32(packet, offset, vec3.Y)
offset += 4
buffer.writei32(packet, offset, vec3.Z)
}
}

updatePositions.FireServer(packet)
}
```
1 change: 0 additions & 1 deletion docs/learn/concepts/entities.md

This file was deleted.

Loading

0 comments on commit 51ed9e2

Please sign in to comment.