Change Log (we do our best to adhere to semantic versioning)
-
BREAKING CHANGES
- Web backend upgraded to GWT
2.8.2
. - Serialization modules that depend on libGDX now require
1.9.10
. - Make sure you clean your build when using Fluid entities.
- Web backend upgraded to GWT
-
Fluid entities quality of life changes.
- New
EntitySubscription
facadeESubscription
, for convenientE
iteration. - Annotation driven aspects allow DI of
ESubscription
(requires registeredFluidEntityPlugin
) - Ability to exclude specific component methods from the fluid API.
@FluidMethod(exclude=true)
E
toString now reports entity id for easier debugging. ie:E{id=10}
.
- New
-
Gradle plugin now supports
classesDirs
, deprecatedclassesDir
. -
Improve flexibility of logic behind annotations dependency injection. (no user impact).
-
FIX: Avoiding an NPE in optimizer.EntitySystemType if meta.superClass is null.
-
FIX: ObjectWeb ASM updated to 7.0 to avoid choking on more modern bytecode.
-
FIX: Artemis-odb integration tests now run properly on JDK 9+.
-
FIX: Fluid gradle plugin logging (now reports what artifacts it scans).
-
BREAKING CHANGES
- Web backend upgraded to GWT
2.8.0
(LibGDX is blocking2.8.2
). - Serialization modules that depend on libGDX now require
1.9.9
.
- Web backend upgraded to GWT
-
Global option to delay component removal until all subscriptions have been notified.
new WorldConfigurationBuilder().alwaysDelayComponentRemoval(true)
-
Annotation driven aspects (
@All
,@Exclude
,@One
).- Annotate BaseEntitySystem subclass, alternative to constructor argument.
- Adds DI of
Archetype
,Aspect
,Aspect.Builder
andEntitySubscription
fields.
-
Fluid entities quality of life changes.
- To enable fluid entities in your world, best practice register
FluidEntityPlugin
instead ofSuperMapper
. FluidEntityPlugin
generated as part of the fluid generation process.- Added
FluidIteratingSystem
. - Generate class C containing all fluid component class literals. (not usable in annotations, sorry).
- Convenience methods to find entities:
- by group
for ( E e : E.withGroup("enemy") ) { .. }
- by tag
E player = E.withTag("player");
- by aspect
for ( E e : E.withAspect(Aspect.all(Pickup.class, Pos.class)) ) { .. }
- by component
for ( E e : E.withComponent(Pickup.class) ) { .. }
- by group
- Allow plugins for fluid interface generation.
- Override type handling via FieldProxyStrategy. (Want extra methods for LibGDX's
Pos2
? Now you can!)
- Override type handling via FieldProxyStrategy. (Want extra methods for LibGDX's
- To enable fluid entities in your world, best practice register
-
Support for abstract plugins with multiple possible implementations. For example, a logging plugin might have multiple implementations (TinyLog, SLF4J+??, LibGDX). As a plugin developer, we want to be able to refer to the generic facade (LoggingPlugin) and throw a warning when no specific implementation has been registered.
-
Fix: Better document side effects of ComponentMapper and EntitySubscription.
-
Fix: Unchecked warning in
SuperMapper
. -
Fix: ArtemisMultiException was missing no-args ctor (req by serializaion)
-
World
instances can now inject themselves (World::inject
)
- Opt-in Fluid Entities API, convenient way to assemble and interact with your entities, making code less verbose, improving readability.
- Entity templates using Prefabs.
- Wasteful memory allocation during deserialization under control.
- Added
EntitySubscription::removeSubscriptionListener
. - Fix: IOException when serializing to json and prettyPrint is
false
same as RC6
- Fix:
IntBag::get(index)
, ArrayIndexOutOfBoundsException reported size of backing array, not logical size. - Fix: Possible IOOB exception when registering more than 64 systems.
- Fix: EntityLinkManager/LinkListener::onLinkKilled never fired for unestablished links.
-
BREAKING CHANGES
- All usage of BitSet replaced by BitVector.
-
BitVector: custom bitset implementation, generally faster than
java.util.BitSet
.- Optimized decoding of bits to integers, making all entity mutations more efficient.
unsafeGet
,unsafeSet
,unsafeClear
require that the underlying array can contain the bit index.BitVector::ensureCapacity(int bits)
explicitly grows the bit vector. Typically used together with theunsafe-
methods.EntityManager::registerEntityStore(BitVector)
- when representing entity id:s as bits, makesunsafe-
methods safe - as theEntityManager
grows the bit vector as necessary.
-
Fix: Bag and IntBag equals method would return false for identical bags with different capacities.
-
BREAKING CHANGES
- Removed previously deprecated code, see: 5de377d.
InvocationStrategy
- affectes custom implementations:- bag-of-systems now stored as a field, instead of being passed as a parameter
to
InvocationStrategy::process
InvocationStrategy::updateEntityStates
must be called before processing the first system. Previously, the initial update was done by the world instance.
- bag-of-systems now stored as a field, instead of being passed as a parameter
to
-
ComponentManager::compositionIdentity(BitSet)
now public. -
@AspectDescriptor
now also valid on Archetypes. -
EntityLinkManager
fires events for initial entities when registering a LinkListener; toggleable in constructor.
-
BREAKING CHANGES
- World's systems array is now typed with
BaseSystem
; this should only have implication for custom implementations ofSystemInvocationStrategy
. - EntityFactory annotation processor and related classes have been removed, for more background, see #428.
- World's systems array is now typed with
-
AspectFieldResolver; additional default injection field resolver
@AspectDescriptor
on appropriate fields to inject- Valid targets:
Aspect
,Aspect.Builder
,EntityTransmuter
,EntitySubscription
-
add
EntityTransmuter(World, Aspect.Builder)
constructor -
Deserialization exception reports on missing component identifiers (usually from manually edited json).
-
Fix: WorldConfigurationBuilder.Priority didn't compare properly.
-
Fix: thread safefty; InjectionCache's fields no longer static.
-
BREAKING CHANGES
- Components require a public no-args constructor. While this was allowed in past versions, it never worked with serialization or pooled components.
-
World#compositionId(entityId)
added. Previously, one had to go viaEntity#getCompositionId()
-
EntityManager#reset
- if the world is empty, resets entity id generation to0
-
Optimized entity subscriptions: compositionId pre-calculated and bundled by
AspectSubscriptionManager
before informing listeners. -
Fix: ComponentMapper was accidentally marked as final in RC1.
-
BREAKING CHANGES
- Methods added to interface
Injector#getRegistered(Class|String)
ComponentMapper#getSafe
deprecated,#get
is sufficient for all use-cases now. due to mappers always growing their backing arrays to accomodate the highest entity id.- Calling
BaseSystem#process
will now run the system, even ifsetEnabled(false)
has been called.SystemInvocationStrategy
now tracks which systems are enabled/disabled. (you may want to update your customSystemInvocationStrategy
implementations). - Bag#getData throws ClassCastException when container wasn't created with any of the typed constructors.
- Methods added to interface
-
Optional manager: EntityLinkManager, discovery and maintenance of relationships between entities.
- Automatically tracks component fields:
@EntityId int
,Entity
,@EntityId IntBag
,Bag<Entity>
(shares behavior with serialization). LinkListener
for listening in on when links between entities are established, changed or disconnected.- Tune behavior with
@LinkPolicy
, applied on component fields referencing entities. - Optimized link accessors via maven/gradle plugin - reflection-based fallback during development.
- Automatically tracks component fields:
-
@DelayedComponentRemoval
guarantees that component is available inSubscriptionListener#removed(IntBag)
. -
World#getRegistered
, retrieves injectable objects programmatically. -
Re-worked
EntityEdit
logic, less code and more performance. -
ComponentType validates component when first encountered.
-
Removed
PackedComponent
and@PackedWeaver
. -
added
AspectSubscriptionManager#getSubscriptions
-
added
Bag(Class<T>)
andBag(Class<T>, int capacity)
-
IntBag#get
throwsArrayIndexOutOfBoundsException
wheneverindex
is greater than the reported size, regardless of the size of the underlying array. -
All systems are first injected, after which all systems are initialized. Previously, each system was injected/initialized at the same time.
-
Serialization
- new
artemis-odb-serializer
artifact, used by all serialization backends, - Kryo serialization backend: binary with kryo (thanks to @piotr-j).
- new
-
BREAKING CHANGES
- If you have overridden default injection functionality and instance FieldHandler yourself, be aware the FieldHandler constructor behaviour has changed. See below.
-
Fix:
IntervalEntitySystem#getIntervalDelta
sometimes returned wrong value when interval <world.delta
. -
Fix: Transmuting deleted entities throws an exception, mirroring `EntityEdit`` on deleted.
-
Fix: Simultaneous transmute + delete caused dead entities in
SubscriptionListener#inserted
. -
Fix: Using custom FieldHandler or FieldResolver disabled @Wire on fields.
- Warn if attempting to inject custom objects without prerequisite resolver (PojoFieldResolver).
- Fix: During deserialization, indirectly referenced entities were not included in the archetypes section
- Serialization
- Archetypes recorded in output; somewhat smaller output and faster load.
- If
JsonArtemisSerializer#setUsePrototypes
is true (default), omit components made up of default values. - Json DOM was parsed multiple times, fixed.
- Overloaded JsonArtemisSerializer#load - deserialize directly from JsonValue.
- When loading entities, each deserialized child is assigned an entity id greater than its parent.
- added
WorldSerializationManager#getSerializer
(if you need to load JsonValue directly, for instance)
- Fix: Work-around for a NPE during weaving; occurred when trying to inspect fields belonging to any parent class
- Fix:
@PooledWeaver
properly resets primitives and strings back to initial values. - Fix: Entity edit right after delete could cause entities to show up in subscription insertions.
- ComponentMappers are reused when injected or when retrieved via
World#getMapper
. - Deprecated
EntityEdit#deleteEntity
, useWorld#delete
orEntity#deleteFromWorld
instead. - Fix:
@Wire
registered classes would silently fail when not registered. - Fix: Woven pooled components didn't null strings on reset.
- Fix: EntityTransmuter cause entities to lose any pending deletes.
- Fix: entities having more than one tag.
- Fix: New entity subscriptions could end up with an initial batch of dead entities.
@PooledWeaver
clears Bag, IntBag, all Lists, Sets, Maps in java.util, all Arrays and Maps in libgdx.- Serialization: named entities; like tags, but local to the SaveFileFormat instance.
- Register entities using
com.artemis.components.SerializationTag
.
- Register entities using
- Serialization: new setUsePrototypes method, writes default values.
- Fix: Deleted entities could still linger in the TagManager.
- Fix: Serializing an entity field having a value of
null
or-1
no longer throws an exception.
- Fix: Optimized IteratingSystems were only partially rewritten. Crash on ART.
- Serialization: Removed component key integer prefix in json.
- In case of collisions, adds an integer suffix to the key name.
- New
ArtemisPlugin
API - New
WorldConfigurationBuilder
convenience class. - Added
World.edit(int entityId)
- Added
World.create()
, returns int entityId - Managers' inserted/removed passes Entity, again.
- EntitySystem extends BaseEntitySystem, new BaseEntitySystems work directly on entityId:
IteratingSystem
:EntityProcessingSystem
.IntervalSystem
andIntervalIteratingSystem
:IntervalEntity*System
DelayedIteratingSystem
:DelayedEntityProcessingSystem
IteratingSystem
eligible for compile-time optimizations, like EntityProcessingSystem.- By convention,
@Wire
is now implied on all systems and managers. Use@SkipWire
to suppress. - new
IntBag
methods: addAll, removeValue. - Dropped EntityObserver methods taking single entityId.
- Removed flyweight entities
- No more bugs due to escaping flyweights.
- Removed artemis-odb-debug, as it's no longer needed.
Manager
now treated as a system.Manager
is now part of theBaseSystem
hierarchy.- EntityObserver removed, covered by EntitySubscriptions.
- Removed deprecated methods and classes
- Removed
@Mapper
- Removed UUID related accessors on Entity and World.
- Removed
@PackedWeaver
marked as deprecated until performance issues have been resolved.EntityManager#isNew
removed.- Passive flag on systems removed.
- SystemInvocationStrategy#initialize added.
- Fix: No longer possible to accidentally add multiple systems of the same type.
- Fix: Deleted entities no longer mess up subscriptions when edited in
SubscriptionListener#removed
. - Fix: Deleted entities retain components.
-
BREAKING CHANGES
World#getEntity(int)
can return inactive Entities, check state usingEntity#isActive
orEntitityManager.isActive(int)
.Entity.isActive
no longer works for checking whether an entity was just created, instead useEntityManager#isNew(int)
.
-
New additional serialization backend: json via libgdx.
- GWT support, works with libgdx's HTML5 backend.
- Supports more libgdx classes out of the box.
-
New
artemis-odb-debug
artifact- Replaces normal artemis-odb with this (remove artemis-odb from pom/gradle/IDE)
- Performs extra runtime checks; tries to catch run-away flyweights.
- Incurs a rather hefty performance penalty.
-
Fix: SubscriptionListeners#removed ids resolved to a lot of nulls.
- Fix: IntDeque resets beginIndex when growing.
- InvocationStrategy configurable via WorldConfiguration.
- Add @SkipWire annotation to exclude injection targets.
- Entities recycled in FIFO order.
- Change EntitySubscription order to deleted/added/changed.
- Change AspectSubscription order to removed/inserted.
- FIX: Resolved potential "markSupported() is undefined for the type InputStream" message when compiling for GWT.
- Fix: Excessive object creation when serializing entities.
- Fix: Components referencing other entities are implicitly included when serializing.
- Fix: SaveFileFormat should only enumerate required components.
- Fix: entity reference operations could fail when loading into a fresh World instance.
- Added boolean
WorldSerializationManager#alwaysLoadStreamMemory
, forces fully loading the stream into memory during loading, even if stream reports thatmark
is supported. Necessary when working with libgdx's FileHandles.- Enabled by default.
- Fix: Duplicate ComponentNameComparator in json module, causing failing android builds.
- Fix: Entities not registered as added to world during batch entity synchronization.
-
BREAKING CHANGES
- EntitySubscription's inserted/removed method pass an IntBag of entity ids, instead of a Bag of entities.
- EntityObserver's methods pass entity id.
-
Optionally customized injection strategies.
- Injector caches class members per default.
-
Serialize to json.
- New WorldSerializationManager.
- Customize output by extending SaveFileFormat.
- Uses JsonBeans behind the scenes.
-
ComponentMappers now also sport get(int)/has(int) methods.
-
Entity get/setUuid deprecated.
-
Add getTag method to TagManager
-
Bag does equality comparisons, always.
-
EntityManager counters stubbed and deprecated.
-
Fix: UuidEntityManager deleted reused UUID's entity reference if it was created/deleted during the same tick.
-
Fix:
@SafeVarargs
on Aspect - no more warnings. -
Fix: Replaced pooled components were not returned to pool.
- Fix: Transmuters didn't resolve flyweight instances.
- Fix: Reduced visibility of AspectionSubscriptionManager constructor.
- Fix: NPE related to
EntitySubscription#createSubscription
.
-
MINOR BREAKING CHANGES
- BaseSystem is now the most basic system type.
- World#getSystems returns Bag.
- EntitySystem constructor expects Aspect.Builder:
- Implies existing classes have to be recompiled against this release.
- Existing custom entity systems need to pass Aspect.Builder to EntitySystem.
- EntitySystem no longer implements EntityObserver.
- ArtemisProfiler#initialize now requires BaseSystem instead of EntitySystem.
- VoidEntitySystem no longer subclass of EntitySystem.
setSystem
andsetManager
now underWorldConfiguration
. This effectively removesWorld#initialize
, as initializations happens inside World's constructor.
- BaseSystem is now the most basic system type.
-
New internal EntitySubscription and accompanying AspectSubscriptionManager resulting in cleaner and more flexible EntitySystems.
-
SystemInvocationStrategy opening up for more granular control over system processing.
- Default strategy behaves as before.
-
Aspect split into Aspect and Aspect.Builder.
- Simplified static method names, mirroring Aspect's old instance methods.
-
EntityFactories support for enum values.
-
Children of EntitySystems can create flyweight entities.
-
Fix: Uninitialized worlds threw cryptic NPE when invoking #process.
-
Fix:
World#createFactory(Class<EntityFactory>)
was package local. -
Fix:
Entity#edit
used together with EntityTransmuters or Archetypes caused the wrong compositionId to be reported, if all changes took place during the same processing round..
-
MINOR BREAKING CHANGES
- Entity instances should never be compared by reference equality; always do
entity1.equals(entity2)
. - It is no longer valid to add additional managers or systems to initialized worlds.
- Entity instances should never be compared by reference equality; always do
-
MundaneWireException thrown by World#inject if class lacks @Wire. Previously, it silently failed to inject.
-
Systems' entity iteration speed slightly faster.
-
New EntityTransmuter class, an alternative but more efficient way of adding/removing components.
-
Optimized entity removal speed.
-
Adding and removing existing entities from systems is now considerably faster.
-
Add enablePackedWeaving to maven, gradle and CLI tool.
-
Reduced EntitySystem memory footprint by 2/3.
-
Fix: Entity systems can now subscribe to all entities when aspect is empty.
-
Fix: EntityFactory annotation processor sometimes failed generating the factory implementation when running from within Eclipse.
- CLI command for configuring eclipse projects with annotation processor (entity factories)
- Fix: Adding a component to an archetyped entity prior to it being added to the world
resulted in the component never being registered.
- Note that editing an entity created by an archetype voids the performance benefit of archetypes..
-
MINOR BREAKING CHANGES
- Archetype moved to
com.artemis
package.
- Archetype moved to
-
Auto-generate EntityFactories.
-
ArchetypeBuilder constructor accepts null passed as parent.
- Fix: Chaining Entity#edit caused the internal bitset to reset between component removals.
- Gradle plugin for bytecode weaving. See Weave Automation
- Faster removal of components.
-
MINOR BREAKING CHANGES
- Entity state changes aren't reflected until the next system starts processing
or a new
World#process
round begins, whichever comes first. - Removed initial parameter (type) from Aspect methods; this changes the method descriptor, requiring any project to be recompiled.
- Entity state changes aren't reflected until the next system starts processing
or a new
-
The GWT backend can now read values off annotations.
-
Bytecode optimizations: (invoked via maven plugin or the CLI tool)
- Automatically optimize entity processing systems.
@PackedWeaver
components no longer overwrite data in multi-World scenarios.
-
Removed
artemis-benchmark
, refer to entity-system-benchmarks instead. -
It's no longer necessary to call
Entity#changedInWorld
andEntity#addToWorld
- Use
Entity#edit
when adding or removing components.
- Use
-
Adding and removing entities to systems is now approximately 150% faster.
- Entity compositions are no longer primarily identified by BitSets, but instead have a compositionId - EntitySystems track which composition ids are of interest.
ArchetypeBuilder
andArchetype
precalculates compositionId, allowing for greatly increased insertion performance.- Optimized
EntitySystem#check
, entities are processed in bulk, less checks when removing entities, removed systemIndex.
-
@Profile entity systems with custom classes.
-
New WorldConfiguration class
- Set expected entity count
- Limit number of rebuilt active entities per system/tick. Rebuilt indices ensure entities are processed in sequential order.
-
New interface
PackedComponent.DisposedWithWorld
for freeing packed components' resources when disposing the world.- Automatically added to all
@PackedWeaver
components.
- Automatically added to all
-
World#inject(Object)
can inject normal java classes with artemis types.- Requires that the injected object is annotated with
@Wire
- Requires that the injected object is annotated with
-
Less bounds checking for PackedComponents.
-
Added
World#getManagers
method. -
Lots of methods now deprecated
- These will be removed when 1.0.0 is released.
- See the
@deprecated
notice for how things work in the new world.
-
maven plugin registered as "artemis-odb", ie
mvn artemis-odb:matrix
, ormvn artemis-odb:artemis
-
Fix:
@PooledWeaver
wasn't resetting components.- Additionaly, only primitive fields are reset - objects are left intact.
-
Fix:
EntityManager#getActiveEntityCount
could report the wrong number if entities were deleted before having been added to the world. -
Fix: Disabled entities are no longer added to systems.
-
Fix:
EntityManager#isActive
could throw an OOB exception.. -
FIX: Possible IOOB in
@PackedWeaver
components when accessing component data.
- Better support for multiple concurrent worlds in regards to memory usage.
- Smaller entity instances.
- Fix: Actually fixed GWT support, bumped gwt to 2.6.0.
- Fix: Potential IOOB exceptions in UuidEntityManager.
- UUID is now optional for entities.
- Add UuidEntityManager to automatically map UUID:s to entities.
- UUID:s are lazily instantiated.
- Fix: GWT build was broken in 0.6.1.
- New standalone
artemis-odb-cli
artifact:- Handles weaving (new in 0.6.1) and matrix generation.
- Replaces
artemis-odb-matrix-X.Y.Z-cli.jar
.
- Fix: OOB Exception in ComponentManager with componentsByType when component types > 64.
- Fix: Calling
Entity#changedInWorld
before an entity is added to the world yields null.
- GWT support (demo) sporting
libgdx's reflection wrapper code.
- This means that
@Mapper
and@Wire
works for GWT builds too. - Note:
@PooledWeaver
and@PackedWeaver
don't work under GWT, though the presence of the annotations doesn't break anything.
- This means that
- Automatically generate a bird's eye view of artemis: Component Dependency Matrix.
- Faux structs with @PackedWeaver`.
- Looks and behaves just like normal java classes.
- Direct field access works - no need to generate getters and setters - i.e.
position.x += 0.24f
is valid. - Contiguously stored in memory, internally backed by a shared
ByteBuffer.allocateDirect()
. - Works for all components composed of primitive types.
- Entity systems and managers can
@Wire
(inject) anything from the world: will eventually replace@Mapper
. No need to annotate each field - just annotate the class and artemis will take care of injecting applicable fields.@Wire
can inject parent classes too.@Wire
can resolve non-final references. Eg, AbstractEntityFactory is resolved as EntityFactory etc. See test/example.
- EntitySystems process entities in ascending id order.
- Considerably faster processing when memory access is aligned (potential biggest gains from PackedComponents).
- Slightly slower insert/remove (3-4% with 4096 entities)
- New optional
UuidEntityManager
, tracks entities by UUID. - Optional
expectedEntityCount
parameters inWorld
constructor. -DideFriendlyPacking
: If true, will leave field stubs to keep IDE:s happy after transformations. Defaults to false.-DenablePooledWeaving
: Enables weaving of pooled components (more viable on Android than JVM). Defaults to true.-DenableArtemisPlugin
: If set to false, no weaving will take place (useful for debugging).- Fix: Possible NPE when removing recently created entities.
- Fix:
Entity#getComponent
would sometimes throw anArrayIndexOutOfBoundsException
.
- Changed artemis to a multi-module project (the
artemis
folder is the old root). - Entity instances are recycled.
- New component types,
PooledComponent
andPackedComponent
.- Optionally transform components with
@PackedWeaver
and@PooledWeaver
by configuring theartemis-odb-maven-plugin
.
- Optionally transform components with
- New method
Entity#createComponent(Class<Component>)
. - Annotation processor validates pooled and packed component types.
- Managers support
@Mapper
annotation. - No longer necessary to stub
Manager#initialize()
. GroupManager#getGroups
returns an empty bag if entity isn't in any group.World#dispose
for disposing managers and systems with managed resources.- Fix: DelayedEntityProcessingSystem prematurely expired entities.
- Fix: Recycled entities would sometimes have their components cleared when recycled during the same round as the original entity was deleted.
- Fix: GroupManager avoids duplicate entities and removes them upon deletion.