Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into merge-upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
jackTabsCode committed Jul 2, 2024
2 parents 15c7f27 + c304a63 commit d780d59
Show file tree
Hide file tree
Showing 36 changed files with 155 additions and 80 deletions.
169 changes: 116 additions & 53 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,57 @@ The format is based on [Keep a Changelog][kac], and this project adheres to

## [Unreleased]

## [0.8.2] - 2024-06-25
## [0.8.3] - 2024-07-02

### Fixed
- Calling `:view()` on an empty query will no longer error.
- Fixed `:snapshot()` on an empty query returning nil instead of an empty array.
- Fixed an error that would happen when calling an empty Query.

- Converted the remaining lua files in the example project to luau files.
- Iterating empty views properly iterates over nothing rather than the data structure members.

## [0.8.2] - 2024-06-25

### Changed

- Optimized `Views` performance.
- No longer allocates a table for each entity in the view, making it much cheaper for queries that match against many entities.
- No longer allocates a table for each entity in the view, making it much
cheaper for queries that match against many entities.
- Converted the lua files to luau files.

### Fixed

- Calling `:view()` on an empty query will no longer error.
- Fixed `:snapshot()` on an empty query returning nil instead of an empty array.
- Fixed an error that would happen when calling an empty Query.
- Reverted the changes to the format of the debugger table.

## [0.8.1] - 2024-04-23

### Fixed
- `QueryResult:without` now correctly matches against entity archetype after cache has been invalidated from transitioning archetype.

- `QueryResult:without` now correctly matches against entity archetype after
cache has been invalidated from transitioning archetype.

## [0.8.0] - 2024-04-22

### Changed
- Added `Views` for random-accessing entities within queries.
- Views are optimized for terse indexing, making them useful for traversing graphs of entities.
- Added `Debugger.loopParameterNames` which allows for labelling things passed to Loop.

- Added `Views` for random-accessing entities within queries.
- Views are optimized for terse indexing, making them useful for traversing
graphs of entities.
- Added `Debugger.loopParameterNames` which allows for labelling things passed
to Loop.
- Disabled `AutoLocalize` on many Plasma Widgets.
- This removes unnecessary computations for `LocalizationService::attemptLocalization`.
- This removes unnecessary computations for
`LocalizationService::attemptLocalization`.
- Improved `QueryResult:without` to narrow archetype invariants.
- The filter now works on the archetype-level rather than filtering entities
ad-hoc which will immensely improve query performance.

### Fixed

- Fixed the Scheduler not respecting priorties of systems.
- Fixed the Scheduler not respecting priorities of systems.
- Fixed padding of items in the Debugger's state view.

## [0.7.1] - 2024-01-31

### Changed
Expand All @@ -70,29 +87,37 @@ The format is based on [Keep a Changelog][kac], and this project adheres to

### Added

- Created a debugger configuration `Debugger.componentRefreshFrequency` to change the unique component list's refresh frequency.
- Created a debugger configuration `Debugger.componentRefreshFrequency` to
change the unique component list's refresh frequency.

### Changed

- Change `Matter.log` to return _nothing_ as expected.
- Exported Matter object is now read only, which prevents invalid mutations to it.
- Exported Matter object is now read only, which prevents invalid mutations to
it.
- Improve documentation for `Matter.useEvent`.
- Systems with both after and priority defined will error.
- Error message for cycles should be more descriptive.
- Systems with dependencies should be scheduled after the system with the highest priority in it's "after" list.
- Improve error message for when a component instance is passed where a component is expected, e.g `world:remove(id, componentInstance())`.
- Improve implementation of the debugger's mouse hover feature, which now supports debugging the player's character model.
- Systems with dependencies should be scheduled after the system with the
highest priority in it's "after" list.
- Improve error message for when a component instance is passed where a
component is expected, e.g `world:remove(id, componentInstance())`.
- Improve implementation of the debugger's mouse hover feature, which now
supports debugging the player's character model.

### Fixed

- Fix the debugger not showing a system's widgets properly when switching from one to another.
- Fix the debugger not showing a system's widgets properly when switching from
one to another.
- Fix slider debugger widget returning 0 when not being rendered.

## [0.6.2] - 2022-07-22

### Fixed

- Debugger no longer interferes with `queryChanged` in order to display it in the debugger view. Previously, this caused the storage to get reset. This feature may return in the future.
- Debugger no longer interferes with `queryChanged` in order to display it in
the debugger view. Previously, this caused the storage to get reset. This
feature may return in the future.

## [0.6.1] - 2022-07-10

Expand All @@ -104,31 +129,37 @@ The format is based on [Keep a Changelog][kac], and this project adheres to

### Fixed

- Fixed bug with server-side debugger when game was in deferred events mode
- Fixed bug with server-side debugger when game was in deferred events mode.

## [0.6.0] - 2022-07-08

### Changed

- The first time you call `queryChanged`, all existing entities in the world that match the component are now returned as "new" change records. Previously, nothing was returned.
- The first time you call `queryChanged`, all existing entities in the world
that match the component are now returned as "new" change records. Previously,
nothing was returned.
- Improved Debugger with highlight selections and tooltips.
- `Matter.useEvent` now supports events that have a `Connect`, `connect`, or an `on` method. Additionally, it also supports custom connection objects (returned by custom events), which have a `Destroy` or a `Disconnect` method, or are just a cleanup function.
- `Matter.useEvent` now supports events that have a `Connect`, `connect`, or an
`on` method. Additionally, it also supports custom connection objects
(returned by custom events), which have a `Destroy` or a `Disconnect` method,
or are just a cleanup function.

### Fixed

- Debugger: Fixed bug with profiling when disabling a system and then closing the debugger
- Debugger: Fixed bug with system list automatic sizing
- Debugger: Fixed bug with profiling when disabling a system and then closing
the debugger.
- Debugger: Fixed bug with system list automatic sizing.

## [0.5.3] - 2022-07-05

### Added

- Added performance information to debugger
- Add World inspector to debugger
- Added performance information to debugger.
- Add World inspector to debugger.

### Fixed

- Fix confusing error when a system yields inside a plasma context
- Fix confusing error when a system yields inside a plasma context.

## [0.5.2] - 2022-07-01

Expand All @@ -151,86 +182,118 @@ The format is based on [Keep a Changelog][kac], and this project adheres to

### Changed

- Middleware now receive event name as a second parameter
- Middleware now receive event name as a second parameter.

## [0.4.0] - 2022-06-25

### Changed

- Modifying the World while inside `World:query` can no longer cause iterator invalidation. All operations to World while inside a query are now safe. 🎉
- If you aren't using `Loop`, you must call `World:optimizeQueries` periodically (e.g., every frame)
- If a system stops calling `queryChanged`, its internal storage will now be cleaned up. It is no longer a requirement that a system calls `queryChanged` forever.
- Modifying the World while inside `World:query` can no longer cause iterator
invalidation. All operations to World while inside a query are now safe. 🎉
- If you aren't using `Loop`, you must call `World:optimizeQueries`
periodically (e.g., every frame).
- If a system stops calling `queryChanged`, its internal storage will now be
cleaned up. It is no longer a requirement that a system calls `queryChanged`
forever.
- `Matter.merge` (an undocumented function) now only accepts two parameters.

### Fixed

- `replaceSystem` now correctly works when other systems reference a system being reloaded in their `after` table
- If `spawnAt` is called with an entity ID that already exists, it now errors as expected.
- `replaceSystem` now correctly works when other systems reference a system
being reloaded in their `after` table.
- If `spawnAt` is called with an entity ID that already exists, it now errors as
expected.

## [0.3.0] - 2022-06-22

### Added

- Added `World:spawnAt` to spawn a new entity with a specified ID.
- Added `World:__iter` to allow iteration over all entities in the world the world from a for loop.
- Added `Loop:evictSystem(system)`, which removes a previously-scheduled system from the Loop. Evicting a system also cleans up any storage from hooks. This is intended to be used for hot reloading. Dynamically loading and unloading systems for gameplay logic is not recommended.
- Added `Loop:replaceSystem(before, after)`, which replaces an older version of a system with a newer version of the system. Internal system storage (which is used by hooks) will be moved to be associated with the new system. This is intended to be used for hot reloading.
- The Matter example game has been updated and adds support for both replication and hot reloading.
- Added `World:__iter` to allow iteration over all entities in the world the
world from a for loop.
- Added `Loop:evictSystem(system)`, which removes a previously-scheduled system
from the Loop. Evicting a system also cleans up any storage from hooks. This
is intended to be used for hot reloading. Dynamically loading and unloading
systems for gameplay logic is not recommended.
- Added `Loop:replaceSystem(before, after)`, which replaces an older version of
a system with a newer version of the system. Internal system storage (which is
used by hooks) will be moved to be associated with the new system. This is
intended to be used for hot reloading.
- The Matter example game has been updated and adds support for both replication
and hot reloading.

### Changed

- The first entity ID is now `1` instead of `0`
- Events that have no systems scheduled to run on them are no longer skipped upon calling `Loop:begin`.
- The first entity ID is now `1` instead of `0`.
- Events that have no systems scheduled to run on them are no longer skipped
upon calling `Loop:begin`.

### Fixed

- Old event listeners created by `useEvent` were not properly disconnected when the passed event changed after having been already created. The event parameter passed to useEvent is not intended to be dynamically changed, so an warning has been added when this happens.
- Old event listeners created by `useEvent` were not properly disconnected when
the passed event changed after having been already created. The event
parameter passed to useEvent is not intended to be dynamically changed, so an
warning has been added when this happens.

## [0.2.0] - 2022-06-04

### Added

- Added a second parameter to `Matter.component`, which allows specifying default component data.
- Add `QueryResult:snapshot` to convert a `QueryResult` into an immutable list
- Added a second parameter to `Matter.component`, which allows specifying
default component data.
- Add `QueryResult:snapshot` to convert a `QueryResult` into an immutable list.

### Changed

- `queryChanged` behavior has changed slightly: If an entity's storage was changed multiple times since your system last observed it, the `old` field in the `ChangeRecord` will be the last value your system observed the entity as having for that component, rather than what it was most recently changed from.
- World and Loop types are now exported (#9)
- `queryChanged` behavior has changed slightly: If an entity's storage was
changed multiple times since your system last observed it, the `old` field in
the `ChangeRecord` will be the last value your system observed the entity as
having for that component, rather than what it was most recently changed from.
- World and Loop types are now exported.
- Matter now uses both `__iter` and `__call` for iteration over `QueryResult`.
- Improved many error messages from World methods, including passing nil values or passing a Component instead of a Component instance.
- Removed dependency on Llama
- Improved many error messages from World methods, including passing nil values
or passing a Component instead of a Component instance.
- Removed dependency on Llama.

### Fixed

- System error stack traces are now displayed properly (#12)
- `World:clear()` now correctly resets internal changed storage used by `queryChanged` (#13)
- System error stack traces are now displayed properly.
- `World:clear()` now correctly resets internal changed storage used by
`queryChanged`.

### Removed

- Additional query parameters to `queryChanged` have been removed. `queryChanged` now only takes one argument. If your code used these additional parameters, you can use `World:get(entityId, ComponentName)` to get a component, and use `continue` to skip iteration if it is not present.
- Additional query parameters to `queryChanged` have been removed.
`queryChanged` now only takes one argument. If your code used these additional
parameters, you can use `World:get(entityId, ComponentName)` to get a
component, and use `continue` to skip iteration if it is not present.

## [0.1.2]- 2022-01-06

### Fixed

- Fix Loop sort by priority to sort properly
- Fix Loop sort by priority to sort properly.

## [0.1.1] - 2022-01-05

### Fixed

- Fix accidental system yield error message in Loop
- Fix accidental system yield error message in Loop.

### Changed

- Accidentally yielding or erroring in a system does not prevent other systems from running.
- Accidentally yielding or erroring in a system does not prevent other systems
from running.

## [0.1.0] - 2022-01-02

- Initial release

[unreleased]: https://github.com/matter-ecs/matter/compare/v0.7.1...HEAD
[unreleased]: https://github.com/matter-ecs/matter/compare/v0.8.3...HEAD
[0.8.3]: https://github.com/matter-ecs/matter/releases/tag/v0.8.3
[0.8.2]: https://github.com/matter-ecs/matter/releases/tag/v0.8.2
[0.8.1]: https://github.com/matter-ecs/matter/releases/tag/v0.8.1
[0.8.0]: https://github.com/matter-ecs/matter/releases/tag/v0.8.0
[0.7.1]: https://github.com/matter-ecs/matter/releases/tag/v0.7.1
[0.7.0]: https://github.com/matter-ecs/matter/releases/tag/v0.7.0
[0.6.2]: https://github.com/matter-ecs/matter/releases/tag/v0.6.2
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Matter can be installed with [Wally] by including it as a dependency in your
`wally.toml` file.

```toml
Matter = "matter-ecs/[email protected].2"
Matter = "matter-ecs/[email protected].3"
```

## Migration
Expand Down
12 changes: 6 additions & 6 deletions docs/BestPractices/Reconciliation.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ We can create another component (in the [Matter example game](https://github.com

We can loop over all Ships that don't also have a Model, and create one for it.

```lua title="ships.lua"
```lua title="ships.luau"
for id, ship in world:query(Ship):without(Model) do
local model = prefabs.Ship:Clone() -- assuming prefabs is a place where you store pre-made models
model.Parent = workspace
Expand All @@ -43,7 +43,7 @@ end

Now, whenever there's an entity with Ship without Model, we create the model and insert the Model component. We can then loop over all Ships that have Models, and update the position of the Model.

```lua title="ships.lua"
```lua title="ships.luau"
for id, ship, model in world:query(Ship, Model) do
model.instance.BodyPosition.Position = ship.goalPosition
end
Expand All @@ -53,7 +53,7 @@ Keep in mind, both of these loops are performed every frame - that's what a syst

We have a problem now, though: whenever an entity with both Ship and Model is despawned, the physical ship Instance in the Data Model will stick around. Since the Model component is generic and could be reused with any other component (it's not specific to just Ship), we can create another system that handles this case for anything that uses Model.

```lua title="removeModels.lua"
```lua title="removeModels.luau"
for _id, modelRecord in world:queryChanged(Model) do
if modelRecord.new == nil then
if modelRecord.old and modelRecord.old.instance then
Expand All @@ -75,7 +75,7 @@ While we generally want our state to flow in one direction (Lua into the DataMod

As an example, let's say we wanted the Ship to despawn if it was touched by anything. We can use Matter's [`useEvent`](/api/Matter#useEvent) utility to collect events that fire in a frame and loop over them.

```lua title="ships.lua"
```lua title="ships.luau"
for id, model in world:query(Model, Ship) do
for _ in Matter.useEvent(model.Instance, "Touched") do
world:despawn(id)
Expand All @@ -89,7 +89,7 @@ Sometimes, instances can be removed from the Data Model or destroyed without us

To account for this, we can simply loop over every Model and check if it's still in the world. If not, we can either remove the Model component or despawn the entire entity (whichever makes more sense for your game).

```lua title="removeModels.lua"
```lua title="removeModels.luau"
for id, model in world:query(Model) do
if model.instance:IsDescendantOf(game) == false then
world:remove(id, Model)
Expand All @@ -111,7 +111,7 @@ There are two potential ways we could want to use this component:

We can make a system that handles both of these cases for us.

```lua title="updateTransforms.lua"
```lua title="updateTransforms.luau"
-- Handle Transform added/changed to existing entity with Model
for id, transformRecord in world:queryChanged(Transform) do

Expand Down
2 changes: 1 addition & 1 deletion docs/Concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ We can reuse our `Health` component from earlier. Let's say that in our game, we

A good way to name systems is by declaring something about the world that they do. In this case: "Health Regenerates."

```lua title="healthRegenerates.lua"
```lua title="healthRegenerates.luau"
for id, health in world:query(Health) do
if health.current < health.max then
world:insert(id, health:patch({
Expand Down
Loading

0 comments on commit d780d59

Please sign in to comment.