Skip to content

Commit

Permalink
fix: when adding components with world.update add components before e…
Browse files Browse the repository at this point in the history
…mitting events
  • Loading branch information
isaac-mason committed Feb 13, 2024
1 parent 092e98e commit 56437fc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 21 deletions.
6 changes: 6 additions & 0 deletions .changeset/metal-spoons-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@arancini/core": patch
"arancini": patch
---

fix: when adding components with world.update add components before emitting events
13 changes: 13 additions & 0 deletions packages/arancini-core/src/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,21 @@ export class World<E extends AnyEntity = any> extends EntityContainer<E> {
Object.assign(future, updateFnOrPartial)
}

const added = Object.keys(future).filter((key) => entity[key] === undefined)
const removed = Object.keys(entity).filter((key) => future[key] === undefined)

// add components before indexing
for (const component of added) {
entity[component as keyof E] = future[component]
}

this.index(entity, future)

// remove components after indexing
for (const component of removed) {
delete entity[component]
}

Object.assign(entity, future)
}

Expand Down
50 changes: 29 additions & 21 deletions packages/arancini-core/tst/queries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,62 +43,70 @@ describe('Queries', () => {
expect(removed).toBe(2)
})

it('emits events when an entity is added to a query', () => {
it('emits events when entities are added or removed from a query', () => {
const world = new World<Entity>()

const query = world.query((q) => q.has('foo'))

let added = 0
const addEvents: Entity[] = []
const removeEvents: Entity[] = []

query.onEntityAdded.add(() => {
added++
query.onEntityAdded.add((entity) => {
addEvents.push({ ...entity })
})

const entity = { foo: 'test' }

world.create(entity)

expect(added).toBe(1)
})

it('emits events when an entity is removed from a query', () => {
const world = new World<Entity>()

const query = world.query((q) => q.has('foo'))

const events: Entity[] = []

query.onEntityRemoved.add((entity) => {
events.push({ ...entity })
removeEvents.push({ ...entity })
})

const entity = {}
world.create(entity)

expect(query.entities).toHaveLength(0)

// add to query
world.add(entity, 'foo', '')

expect(query.first).toEqual({ foo: '' })
expect(query.entities).toHaveLength(1)

// remove from query
world.remove(entity, 'foo')

expect(query.entities).toHaveLength(0)


// add to query
world.update(entity, { foo: '' })

expect(query.first).toEqual({ foo: '' })
expect(query.entities).toHaveLength(1)

// remove from query
world.update(entity, { foo: undefined })

expect(query.entities).toHaveLength(0)

// add to query
world.update(entity, (e) => {
e.foo = ''
})

expect(query.first).toEqual({ foo: '' })
expect(query.entities).toHaveLength(1)

// remove from query
world.update(entity, {
foo: undefined,
})

expect(events.length).toBe(3)
expect(events.every((e) => e.foo !== undefined)).toBe(true)
expect(query.entities).toHaveLength(0)

expect(addEvents.length).toBe(3)
expect(addEvents.every((e) => e.foo === '')).toBe(true)

expect(removeEvents.length).toBe(3)
expect(removeEvents.every((e) => e.foo !== undefined)).toBe(true)
})

it('should update an entity in bulk when calling update', () => {
Expand Down

0 comments on commit 56437fc

Please sign in to comment.