Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.0] Update entities, mark as dirty, reindex #220

Open
hmans opened this issue Oct 30, 2022 · 1 comment
Open

[2.0] Update entities, mark as dirty, reindex #220

hmans opened this issue Oct 30, 2022 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@hmans
Copy link
Owner

hmans commented Oct 30, 2022

Miniplex 2.0 supports predicate-based queries, which allows the user to also check for component values (instead of just presence/absence). For this to work, there also needs to be a mechanism that allows the user to mark an entity as dirty, so that it will be reindexed (because it's important that Miniplex mutates entities directly, instead of treating them like microstores.)

Suggested API (naming TBD):

/* Given a bucket containing entities with low health: */
const lowHealth = world.where((e) => e.health < 10);

/* Mutate the entity directly, as usual */
entity.health -= 10;

/* Mark the entity as dirty */
world.dirty(entity);

/* Regulary -- eg. once per tick -- reindex the world. At this point the entity might show up in the `lowHealth` bucket. */
world.flushDirty();

Changed events?

There's an opportunity here to implement an onEntityChanged event (or similar) that may help with #154. However, since entities are mutated directly (by design), it'll be difficult to impossible to provide the same sort of information (or even API fidelity) as eg. a reactive store solution (at least not without creating a potentially high number of new objects every frame.) There is a big potential for a significant divide between user expectations and what this library could realistically deliver.

@hmans hmans added this to the Miniplex 2.0.0 milestone Oct 30, 2022
@hmans hmans added the enhancement New feature or request label Oct 30, 2022
@hmans hmans self-assigned this Oct 30, 2022
@hmans hmans linked a pull request Oct 30, 2022 that will close this issue
@mikecann
Copy link

mikecann commented Nov 10, 2022

Interesting idea! I assume you have already considered Proxy's to do this... Probably too much of an overhead (might be worth a perf test or two tho)

Another potential option that I have used in the past is to have a "Mutable" type:

export class Mutable<T> {
  public onChange = new Signal1<T>();
  private _changed = true;
  private _value: T;
  private equalityChecker: EqualityChecker<T>;

  constructor(_value: T, equalityChecker: EqualityChecker<T> = shallowIsEqual) {
    this._value = _value;
    this.equalityChecker = equalityChecker;
  }

  get value() {
    return this._value;
  }

  set value(v: T) {
    if (this.equalityChecker(this._value, v)) return;
    this._value = v;
    this._changed = true;
    this.onChange.dispatch(v);
  }

  get changed() {
    return this._changed;
  }

  resetChanged() {
    this._changed = false;
  }
}

Then usage becomes:

/* Given a bucket containing entities with low health: */
const lowHealth = world.where((e) => e.health.value < 10);

/* Mutate the entity directly, as usual */
entity.health.value -= 10;

Something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants