mirror of
https://github.com/Ukendio/jecs.git
synced 2025-08-04 03:09:18 +00:00
Address docs issues
This commit is contained in:
parent
f792c98585
commit
3777585677
4 changed files with 186 additions and 31 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
Jecs. Just an Entity Component System.
|
||||
|
||||
# Properties
|
||||
# Members
|
||||
|
||||
## World
|
||||
```luau
|
||||
|
@ -12,27 +12,93 @@ A world is a container of all ECS data. Games can have multiple worlds but compo
|
|||
|
||||
## Wildcard
|
||||
```luau
|
||||
jecs.Wildcard: Entity
|
||||
jecs.Wildcard: Id
|
||||
```
|
||||
Builtin component type. This ID is used for wildcard queries.
|
||||
|
||||
## Component
|
||||
```luau
|
||||
jecs.Component: Entity
|
||||
jecs.Component: Id
|
||||
```
|
||||
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
|
||||
jecs.ChildOf: Id
|
||||
```
|
||||
Builtin component type. This ID is for creating parent-child hierarchies.
|
||||
|
||||
## OnAdd
|
||||
|
||||
```luau
|
||||
jecs.OnAdd: Id
|
||||
```
|
||||
Builtin component type. This ID is for setting up a callback that is invoked when an instance of a component is added.
|
||||
|
||||
## OnRemove
|
||||
|
||||
```luau
|
||||
jecs.OnRemove: Id
|
||||
```
|
||||
|
||||
Builtin component type. This ID is for setting up a callback that is invoked when an instance of a component is removed.
|
||||
|
||||
## OnChange
|
||||
|
||||
```luau
|
||||
jecs.OnChange: Id
|
||||
```
|
||||
|
||||
Builtin component type. This ID is for setting up a callback that is invoked when an instance of a component is changed.
|
||||
|
||||
## Exclusive
|
||||
|
||||
```lua
|
||||
jecs.Exclusive: Id
|
||||
```
|
||||
|
||||
Builtin component type. This ID is for encoding that an ID is Exclusive meaning that an entity can never have more than one target for that exclusive relation.
|
||||
|
||||
:::code-group
|
||||
```luau [luau]
|
||||
local ChildOf = world:entity()
|
||||
world:add(ChildOf, jecs.Exclusive)
|
||||
|
||||
local pop = world:entity()
|
||||
local dad = world:entity()
|
||||
local kid = world:entity()
|
||||
|
||||
world:add(kid, pair(ChildOf, dad))
|
||||
print(world:target(kid, ChildOf, 0) == dad)
|
||||
world:add(kid, pair(ChildOf, pop))
|
||||
print(world:target(kid, ChildOf, 1) == dad) -- If ChildOf was not exclusive this would have been true
|
||||
print(world:target(kid, ChildOf, 0) == pop)
|
||||
|
||||
-- Output:
|
||||
-- true
|
||||
-- false
|
||||
-- true
|
||||
```
|
||||
|
||||
:::info
|
||||
By default, jecs.ChildOf is already an exclusive relationship and this is just a demonstration of how to use it.
|
||||
In some cases you can use Exclusive relationships as a performance optimization as you can guarantee there will only be one target, therefore
|
||||
retrieving the data from a wildcard pair with that exclusive relationship can be deterministic.
|
||||
:::
|
||||
|
||||
## Name
|
||||
```luau
|
||||
jecs.Name: Id
|
||||
```
|
||||
Builtin component type. This ID is for naming components, but realistically you could use any component to do that.
|
||||
|
||||
## Rest
|
||||
```luau
|
||||
jecs.Rest: Entity
|
||||
jecs.Rest: Id
|
||||
```
|
||||
|
||||
Builtin component type. This ID is for setting up a callback that is invoked when an instance of a component is changed.
|
||||
|
||||
# Functions
|
||||
|
||||
## pair()
|
||||
|
@ -48,3 +114,19 @@ function jecs.pair(
|
|||
While relationship pairs can be used as components and have data associated with an ID, they cannot be used as entities. Meaning you cannot add components to a pair as the source of a binding.
|
||||
|
||||
:::
|
||||
|
||||
## pair_first()
|
||||
```luau
|
||||
function jecs.pair_first(
|
||||
pair: Id, -- A full pair ID encoded using a relation-target pair.
|
||||
): Entity -- The ID of the first element. Returns 0 if the ID is not alive.
|
||||
```
|
||||
Returns the first element (the relation part) of a pair ID.
|
||||
|
||||
## pair_second()
|
||||
```luau
|
||||
function jecs.pair_second(
|
||||
pair: Id, -- A full pair ID encoded using a relation-target pair.
|
||||
): Entity -- The ID of the second element. Returns 0 if the ID is not alive.
|
||||
```
|
||||
Returns the second element (the target part) of a pair ID.
|
||||
|
|
|
@ -4,13 +4,33 @@ A World contains entities which have components. The World is queryable and can
|
|||
|
||||
# Methods
|
||||
|
||||
## iter
|
||||
## cached
|
||||
|
||||
Returns an iterator that can be used to iterate over the query.
|
||||
Returns a cached version of the query. This is useful if you want to create a query that you can iterate multiple times.
|
||||
|
||||
```luau
|
||||
function Query:iter(): () -> (Entity, ...)
|
||||
function Query:cached(): Query -- Returns the cached Query
|
||||
```
|
||||
Example:
|
||||
|
||||
```luau [luau]
|
||||
local lerps = world:query(Lerp):cached() -- Ensure that you cache this outside a system so you do not create a new cache for a query every frame
|
||||
|
||||
local function system(dt)
|
||||
for entity, lerp in lerps do
|
||||
-- Do something
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
```ts [typescript]
|
||||
const lerps = world.query(Lerp).cached()
|
||||
|
||||
function system(dt) {
|
||||
for (const [entity, lerp] of lerps) {
|
||||
// Do something
|
||||
}
|
||||
}
|
||||
|
||||
## with
|
||||
|
||||
|
@ -83,15 +103,13 @@ Example:
|
|||
|
||||
```luau [luau]
|
||||
for i, archetype in world:query(Position, Velocity):archetypes() do
|
||||
local columns = archetype.columns
|
||||
local field = archetype.records
|
||||
|
||||
local P = field[Position]
|
||||
local V = field[Velocity]
|
||||
local field = archetype.columns_map
|
||||
local positions = field[Position]
|
||||
local velocities = field[Velocity]
|
||||
|
||||
for row, entity in archetype.entities do
|
||||
local position = columns[P][row]
|
||||
local velocity = columns[V][row]
|
||||
local position = positions[row]
|
||||
local velocity = velocities[row]
|
||||
-- Do something
|
||||
end
|
||||
end
|
||||
|
@ -101,10 +119,10 @@ end
|
|||
This function is meant for people who want to really customize their query behaviour at the archetype-level
|
||||
:::
|
||||
|
||||
## cached
|
||||
## iter
|
||||
|
||||
Returns a cached version of the query. This is useful if you want to iterate over the same query multiple times.
|
||||
If you are on the old solver, to get types for the returned values, requires usage of `:iter` to get an explicit returntype of an iterator function.
|
||||
|
||||
```luau
|
||||
function Query:cached(): Query -- Returns the cached Query
|
||||
function Query:iter(): () -> (Entity, ...)
|
||||
```
|
||||
|
|
|
@ -241,7 +241,10 @@ print(world.get(Entity, Health));
|
|||
// 100
|
||||
// 50
|
||||
```
|
||||
:::
|
||||
|
||||
:::info
|
||||
`world:set(entity, component, value)` propagates that a change has happened for thes component on this entity, while mutating a value directly would not.
|
||||
:::
|
||||
|
||||
## query
|
||||
|
@ -289,10 +292,52 @@ If the index is larger than the total number of instances the entity has for the
|
|||
```luau
|
||||
function World:target(
|
||||
entity: Entity, -- The entity
|
||||
relation: Entity, -- The relationship between the entity and the target
|
||||
relation: Id, -- The relationship between the entity and the target
|
||||
nth: number, -- The index
|
||||
): Entity? -- The target for the relationship at the specified index.
|
||||
): Id? -- The target for the relationship at the specified index.
|
||||
```
|
||||
Example:
|
||||
|
||||
::: code-group
|
||||
|
||||
```luau [luau]
|
||||
local function timers_count(world: types.World)
|
||||
local timers = world
|
||||
:query(jecs.pair(ct.Timer, jecs.w))
|
||||
:without(ct.Destroy)
|
||||
:cached()
|
||||
|
||||
return function(_, dt: number)
|
||||
for entity in timers do
|
||||
local index = 0
|
||||
local nth = world:target(entity, ct.Timer, index)
|
||||
while nth do
|
||||
local timer = world:get(entity, jecs.pair(ct.Timer, nth))
|
||||
local elapsed = timer.elapsed + dt
|
||||
if elapsed >= timer.duration then
|
||||
world:add(entity, ct.Destroy)
|
||||
end
|
||||
timer.elapsed = elapsed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
```ts [typescript]
|
||||
const entity = world.entity();
|
||||
print(world.contains(entity));
|
||||
print(world.contains(1));
|
||||
print(world.contains(2));
|
||||
|
||||
// Outputs:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
## parent
|
||||
|
||||
|
@ -355,9 +400,9 @@ print(world.contains(2));
|
|||
Removes a component (ID) from an entity
|
||||
|
||||
```luau
|
||||
function World:remove(
|
||||
function World:remove<T>(
|
||||
entity: Entity,
|
||||
component: Entity<T>
|
||||
component: Id<T>
|
||||
): void
|
||||
```
|
||||
|
||||
|
@ -458,20 +503,20 @@ Useful when you only need the entity for a specific ID and you want to avoid cre
|
|||
|
||||
```luau
|
||||
function World:each(
|
||||
id: Entity -- The component ID
|
||||
component: Id -- The component ID
|
||||
): () -> Entity
|
||||
```
|
||||
|
||||
Example:
|
||||
::: code-group
|
||||
```luau [luau]
|
||||
local id = world:entity()
|
||||
local id = world:component()
|
||||
for entity in world:each(id) do
|
||||
-- Do something
|
||||
end
|
||||
```
|
||||
```ts [typescript]
|
||||
const id = world.entity();
|
||||
const id = world.component();
|
||||
for (const entity of world.each(id)) {
|
||||
// Do something
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ local jecs = require(path/to/jecs)
|
|||
local world = jecs.world()
|
||||
```
|
||||
```typescript [typescript]
|
||||
import { World } from "@rbxts/jecs"
|
||||
const world = new World()
|
||||
import * as jecs from "@rbxts/jecs"
|
||||
const world = jecs.world()
|
||||
// creates a new entity with no components and returns its identifier
|
||||
const entity = world.entity()
|
||||
|
||||
|
@ -156,6 +156,13 @@ world.set(Transform, OnChange, (entity, id, data) => {
|
|||
```
|
||||
:::
|
||||
|
||||
:::info
|
||||
Children are cleaned up before parents
|
||||
When a parent and its children are deleted, OnRemove hooks will be invoked for children first, under the condition that there are no cycles in the relationship graph of the deleted entities. This order is maintained for any relationship that has the (OnDeleteTarget, Delete) trait (see Component Traits for more details).
|
||||
|
||||
When an entity graph contains cycles, order is undefined. This includes cycles that can be formed using different relationships.
|
||||
:::
|
||||
|
||||
### Cleanup Traits
|
||||
|
||||
When entities that are used as tags, components, relationships or relationship targets are deleted, cleanup traits ensure that the store does not contain any dangling references. Any cleanup policy provides this guarantee, so while they are configurable, games cannot configure traits that allows for dangling references.
|
||||
|
@ -285,9 +292,10 @@ jecs.world() -- Position gets registered here
|
|||
```
|
||||
|
||||
```typescript [typescript]
|
||||
import { world } from "@rbxts/jecs"
|
||||
const Position = jecs.component<Vector3>();
|
||||
|
||||
new World() // Position gets registered here
|
||||
world() // Position gets registered here
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -301,9 +309,11 @@ jecs.world() -- Position gets registered here with its name "Position"
|
|||
```
|
||||
|
||||
```typescript [typescript]
|
||||
import { world } from "@rbxts/jecs"
|
||||
|
||||
jecs.meta(Position, jecs.Name, "Position")
|
||||
|
||||
new World() // Position gets registered here with its name "Position"
|
||||
world() // Position gets registered here with its name "Position"
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -632,7 +642,7 @@ world:set(e, pair(Eats, Apples), { amount = 1 })
|
|||
world:set(e, pair(Begin, Position), Vector3.new(0, 0, 0))
|
||||
world:set(e, pair(End, Position), Vector3.new(10, 20, 30))
|
||||
|
||||
world:add(e, jecs.ChildOf, Position)
|
||||
world:add(e, pair(jecs.ChildOf, Position))
|
||||
|
||||
```
|
||||
```typescript [typescript]
|
||||
|
@ -648,7 +658,7 @@ world.set(e, pair(Eats, Apples), { amount: 1 })
|
|||
world.set(e, pair(Begin, Position), new Vector3(0, 0, 0))
|
||||
world.set(e, pair(End, Position), new Vector3(10, 20, 30))
|
||||
|
||||
world.add(e, jecs.ChildOf, Position)
|
||||
world.add(e, pair(jecs.ChildOf, Position))
|
||||
```
|
||||
:::
|
||||
|
||||
|
|
Loading…
Reference in a new issue