v0.8.0
This update prioritizes some necessary cleanup and stability improvements, and so is a bit light on features and heavier on breaking changes. As part of this cleanup, worlds use less memory and bundles should be smaller (especially in production builds)!
The next release will include some some important feature work, including the ability to set default values for component fields and to initialize data when inserting components on entities.
💥 Breaking Changes
- The Dependency API has changed:
defineSystem
returns an instance of the newSystemDefinition
class.addSystem
only accepts one argument - aSystemDefinition
.SystemDefinition
instances havebefore(...others: SystemDefinition[]): this
,after(...others: SystemDefinition[]): this
,beforeAll(): this
, andafterAll(): this
methods. These are now how you declare dependencies.- Dependencies behave the same as before (see v0.2.0 changelog for a refresher).
- When a system is added to the world, its dependencies are cleared. This allows systems to have different dependencies across worlds.
- For this reason, it is recommended that you either declare dependencies when you add systems to a world, or in the same module you build a world.
- As before, dependencies remain unused for startup systems, though this will likely change in the future.
WorldBuilder
'sregisterThreadChannel
method andThreadGroup
'ssend
have been modified.- A
createThreadChannel
function is now exported. This function accepts a channel name (string) and a message handler creator - just like the previousregisterThreadChannel
function signature. registerTheadChannel
now accepts a singleThreadMessageChannel
argument, which is the value returned bycreateThreadChannel
.- The
send
method onThreadGroup
now accepts a singleThreadMessage
argument, which is created by calling your thread message channel with the data you want to send. - This new API has much more robust type safety - the types of the data sent to threads and the data returned are intrinsically linked.
- A
- All validation now only occurs in development builds.
- This currently includes:
- Validation of world config.
- Validation preventing direct access of ZSTs.
- Validation that queries have some possible match criteria.
- Validation that system dependencies are not circular.
- Most validation prevents more cryptic errors from being thrown later, but some (e.g. queries that do not match) are silent.
- This change only impacts you if you have significant differences between your world in prod vs. development, which should not be the case!
- This currently includes:
- Partial rewrites of
Entities
,Table
.- This only impacts you if you directly access properties/methods!
world.archetypes
is now aTable[]
(previouslyMap<Bigint, Table>
).world.systems
is now a((...args: any[]) => any)[]
- Worlds now also have
arguments: any[][]
, so each system has a corresponding member in the arguments array (includes some empty arrays).
- Worlds now also have
✨ Features
- Added
esm-env
as a dependency.- This allows Thyseus to check whether you're building for development or production. We'll use more of these checks in the future to provide better correctness guarantees in dev and better performance in prod!
- Added
isAlive(entityId: bigint)
toEntities
(world.entities
), if you need to check if an entity is still alive. - Added
clone(): SystemDefinition
method toSystemDefinition
.- Useful if you need to add multiple instances of the same system (e.g., if you'd like to add an additional
applyCommands
system in the middle of your update loop). clone
does not clone dependencies or dependents. It's a completely new system with the same functionality!
- Useful if you need to add multiple instances of the same system (e.g., if you'd like to add an additional
- Dependencies are now recursively validated.
- Previously, errors were only thrown if dependencies were directly circular (e.g.,
A before B before A
orA before A
). - We now detect chains of dependencies and throw for those (e.g.
A before B before C before A
will throw).
- Previously, errors were only thrown if dependencies were directly circular (e.g.,
- Added
setExecutor(executor: ExecutorType)
method toWorldBuilder
, so you may pass a custom executor implementation.- Custom executors are an especially advanced pattern - some documentation around API requirements has been added.
- Added
SimpleExecutor
, which is automatically used in single-threaded worlds.SimpleExecutor
currently performs much better thanParallelExecutor
.
🐛 Bug Fixes
- Fixed bug where Executors could get into a bad state that prevented system execution.
- Fixed types for
Query
iterators. - Fixed issue where commands could be added for despawned entities, causing entities with recycled ids to incorrectly add/remove components.
- Fixed entities not being correctly despawned.
- Fixed Commands not properly creating
Entity
stores, preventing access to entityindex
andgeneration
for (spawned) entity handles. - The promise returned by
world.update()
now (correctly) only resolves when all systems have finished executing. - Fixed a rare bug where
beforeAll
/afterAll
could introduce undetected circular dependencies. - Fixed bug where using more than 2 threads would cause unresolveable promises and prevent worlds from being built.
🔧 Maintenance
- Bump dev dependency versions.