Relationships are a special kind of component created by pairing a relation component with an entity id.

A relation component is created using the relation function.

let GravitatingTo = j.relation()

The value returned by relation is a function that builds relationships on a per-entity basis. Relationships can be added to entities like any other component.

let planet = world.create(Planet)
let spaceship = world.create(j.type(Spaceship, GravitatingTo(planet)))

Relationships can be used as query terms to resolve related entities.

world.query(Planet).each(planet => {
  world.query(GravitatingTo(planet), Velocity).each((entity, velocity) => {
    // (apply gravity)

Behind the scenes, relation creates a hidden tag component that is also attached to any entities with a GravitatingTo(entity) relationship component. The relation builder will be subsituted with this hidden tag component when included in a list of query terms.

The following example query finds all entities with relationships of the GravitatingTo variety.

world.query(GravitatingTo).each(entity => {
  // `entity` is affected by gravity

Entity Heirarchies

Javelin comes with a special relation component called ChildOf that provides the means to create tree-like entity hierarchies.

let bag = world.create(Bag)
let sword = world.create(j.type(Sword, j.ChildOf(bag)))

ChildOf can be used with queries to find all children of an entity.

world.query(j.ChildOf(bag)).each(item => {
  // `item` is a child of `bag`

Deleting a parent entity will also delete its children.

world.delete(bag) // also deletes `sword`

An entity may have only one parent.

world.create(type(j.ChildOf(spaceship), j.ChildOf(planet)))
// Error: a type may have only one ChildOf relationship

The parent of an entity can be resolved using world.parentOf:

world.parentOf(sword) // `bag`