Instead of directly setting position and orientation we've now
added a "transforms" property. This property contains zero or many
transformations. The result of these is what drives changes to an
entity's position and orientation.
By cleanly separate disrete transformations we can more easily undo
or alter them. This allows us to do things where the position or
orientation of an entity is affected by other properties, or other
entities.
The client protocol is intact. Changes to position and orientation is
still sent the same way, by specifying "pos" and "orientation". However,
these values will now not be written directly to corresponding values on
the entity. Instead they will first be written to the "transforms" property,
with the final values being a result of combining all data in the property.
Instead of the root entity always being the default one (for new
entities being created etc.) we now can specify another entity which is
the default one.
Don't keep the time in field, updated only at poll requests. Instead
calculate it when it's needed.
This fixes an old bug where all client movements were slightly
incorrect. The time was only recalculated at WorldRouter::poll calls. However,
when polling for IO the process waited up to 100 milliseconds. That
meant that any client received operation would get an on average 50
milliseconds offset in it's registered time. The result of this was that
most Move operations would be slightly incorrect, resulting in jerky
movement.
Since the queues weren't queues until after the destructor had run,
there was a risk of a spawn entity being deleted later on, leading to it
referencing invalid spawns since m_spawns weren't cleared.
There's no reason to use the hacked in "contains" feature for creating
inventory. Instead we can rely on the Archtype features. Any entity
declaration for which we also want inventory created should use an
archetype.
The change is that the "contains" and "character_types" attributes are
removed. Instead there's a "entities" attribute, which is a map. The
keys are the names of the entities as seen to the client, and the values
are the entity specifications.
The "respawning" property makes an entity respawn instead of being
deleted. It intercepts the Delete op and instead of deleting the entity
it moves it to the specified spawn point.
A typical use case of this is to place the property on any user
controlled entity, thus making sure that it's never deleted and istead
respawned when killed or defeated.
An archetype is used for creating new entities. It contains one or many
definitions for entities, along with relationship between them. It also
contains any extra data needed for a world simultion, such as thoughts
and knowledge.
Archetypes should be seen as blueprints for entity types, as they
describe how new one should be composed. They are created just as
regular entities, using the existing Create op functionality.
As an example, there should be one "human" entity type, with archetypes
such as "settler", "merchant", "soldier" etc. This differs from the
current setup where each of these are separate entity types.
While in suspended state all "Tick" ops will be placed in a special queue
and not delivered until the world is resumed.
This is of most use for world authors who want to edit the world and
not worry about entities being altered.
All IG code should use the interface of LocatedEntity when dealing
with any entity, rather than sometimes requiring Entity. Add virtual
functions to the interface where required, and modify all other interfaces
to stop them using Entity. This makes the code way cleaner, and much better
de-coupled.