• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 14804036802

02 May 2025 09:58PM UTC coverage: 5.927% (-83.4%) from 89.28%
14804036802

Pull #3404

github

web-flow
Merge 5c103d7f8 into 0f2ccaeb2
Pull Request #3404: feat: added Graph module to Math

234 of 8383 branches covered (2.79%)

229 of 246 new or added lines in 1 file covered. (93.09%)

13145 existing lines in 208 files now uncovered.

934 of 15759 relevant lines covered (5.93%)

4.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/engine/EntityComponentSystem/Query.ts
1
import { Entity } from './Entity';
2
import { Observable } from '../Util/Observable';
3
import { Component, ComponentCtor } from '../EntityComponentSystem/Component';
4

5
export type ComponentInstance<T> = T extends ComponentCtor<infer R> ? R : never;
6

7
/**
8
 * Represents query for entities that match a list of types that is cached and observable
9
 *
10
 * Queries can be strongly typed by supplying a type union in the optional type parameter
11
 * ```typescript
12
 * const queryAB = new ex.Query<ComponentTypeA | ComponentTypeB>(['A', 'B']);
13
 * ```
14
 */
15
export class Query<TKnownComponentCtors extends ComponentCtor<Component> = never> {
16
  public readonly id: string;
UNCOV
17
  public components = new Set<TKnownComponentCtors>();
×
UNCOV
18
  public entities: Entity<ComponentInstance<TKnownComponentCtors>>[] = [];
×
19
  /**
20
   * This fires right after the component is added
21
   */
UNCOV
22
  public entityAdded$ = new Observable<Entity<ComponentInstance<TKnownComponentCtors>>>();
×
23
  /**
24
   * This fires right before the component is actually removed from the entity, it will still be available for cleanup purposes
25
   */
UNCOV
26
  public entityRemoved$ = new Observable<Entity<ComponentInstance<TKnownComponentCtors>>>();
×
27

UNCOV
28
  constructor(public readonly requiredComponents: TKnownComponentCtors[]) {
×
UNCOV
29
    if (requiredComponents.length === 0) {
×
UNCOV
30
      throw new Error('Cannot create query without components');
×
31
    }
UNCOV
32
    for (const type of requiredComponents) {
×
UNCOV
33
      this.components.add(type);
×
34
    }
35

UNCOV
36
    this.id = Query.createId(requiredComponents);
×
37
  }
38

39
  static createId(requiredComponents: Function[]) {
40
    // TODO what happens if a user defines the same type name as a built in type
41
    // ! TODO this could be dangerous depending on the bundler's settings for names
42
    // Maybe some kind of hash function is better here?
UNCOV
43
    return requiredComponents
×
44
      .slice()
UNCOV
45
      .map((c) => c.name)
×
46
      .sort()
47
      .join('-');
48
  }
49

50
  /**
51
   * Potentially adds an entity to a query index, returns true if added, false if not
52
   * @param entity
53
   */
54
  checkAndAdd(entity: Entity) {
UNCOV
55
    if (!this.entities.includes(entity) && entity.hasAll(Array.from(this.components))) {
×
UNCOV
56
      this.entities.push(entity);
×
UNCOV
57
      this.entityAdded$.notifyAll(entity);
×
UNCOV
58
      return true;
×
59
    }
UNCOV
60
    return false;
×
61
  }
62

63
  removeEntity(entity: Entity) {
UNCOV
64
    const index = this.entities.indexOf(entity);
×
UNCOV
65
    if (index > -1) {
×
UNCOV
66
      this.entities.splice(index, 1);
×
UNCOV
67
      this.entityRemoved$.notifyAll(entity);
×
68
    }
69
  }
70

71
  /**
72
   * Returns a list of entities that match the query
73
   * @param sort Optional sorting function to sort entities returned from the query
74
   */
75
  public getEntities(sort?: (a: Entity, b: Entity) => number): Entity<ComponentInstance<TKnownComponentCtors>>[] {
UNCOV
76
    if (sort) {
×
77
      this.entities.sort(sort);
×
78
    }
UNCOV
79
    return this.entities;
×
80
  }
81
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc