question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[FEATURE] Archetypes with pre-defined properties

See original GitHub issue

I’d like to propose a new feature: archetypes with pre-defined properties for the components.

The use case would be to have multiple “archetypes” with the same components, but different values for the properties. This would help with a data-driven approach where you chain entity creation (eg. create entity A from data, and when it is deleted, another entity B is created). At the moment, this can be done by using archetypes, but changing properties on the components gets more tricky.

The real-life example is my current project, where I have a custom reflection-based data-driven setup for creating entities. My map loader loads objects which refer to the name of the object definition. The object definition is a JSON which has the component classes with all the properties, like so:

{
    "class": "me.manabreak.managame.common.Health",
    "properties": {
        "health": 10,
        "healthMax": 10
    }
}

Now, this works fine when loading the levels, taking about a millisecond per entity to construct. However, the issue arises when I’d like to construct a new entity when another one dies. The current approach would be to have a custom component (eg. AfterDeath) which refers to the definition of the object to create. However, it’s a bit too slow to do the same logic as I do loading the levels; a millisecond per entity is quite a bit if there’s dozens of entities to create per frame.

In the proposed feature, there would be an archetype along with the properties. This way, when defining the archetype, we could store the properties using whatever data source we have, and when the entity is created using that archetype, the properties are filled there.

At the moment, archetypes provide a facade of sorts for the entity mutators. Under the hood, creating an entity from an archetype basically translates to creating a new entity and transmuting it with a previously defined mutator. However, this doesn’t operate at all on the properties.

I’m not quite sure how this feature would be tackled in a performant manner. Deserialization during loading is allowed to have a tiny performance hit, but when a fast-pacing game is running where new entities should be created based on the game events, it gets more critical.

A train-of-thought proposal would be to have a bit of a similar functionality that we have for the pooled weaver, but instead of resetting the properties, we would copy them from the archetypal component.

Would there be any interest for such feature?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:9 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
junkdogcommented, Jan 14, 2019

Any particular reason why you aren’t using artemis’ serialization? It works with entity references, one transmuter per unique compositionId, and guarantees that all entity id:s are assigned in the same order as they appear in the json (normally, entity id:s are recycled in FIFO order).

The Prefab use-case is repeated construction of entities-with-component-data - where only some component data requires changing (e.g. Position) . It’s backed by artemis’ serialization. The raw json is cached/reused as a JsonValue.

Snipping from the tests, but with some comments:

// @PrefabData(value) is read by JsonValuePrefabReader; can be customized
// if, for example, the source isn't a plain file.
@PrefabData("prefab/some_prefab.json")
public class SomePrefab extends Prefab {

    // dependency injection is automatic 
    private ComponentMapper<ComponentX> componentXMapper;

    public SomePrefab(World world, FileHandleResolver resolver) {
        super(world, resolver);
    }

    public SaveFileFormat create(String text) {
        SaveFileFormat l = create(); // yeah, poorly named

        // optional serialization "key" (local tag), for convenient retrieval.
        componentXMapper.get(l.get("whatever")).text = text;

        // don't need to return anything ofc
        return l;
    }
}

Json from PrefabData: some_prefab.json.

Entity tag is read from SerializationTag, if available.

1reaction
junkdogcommented, May 12, 2019

I am working on making an editor with Artemis and ImGui.

I ❤️ imgui! Such a pleasure to work with.

There’s a lot of poor naming and lacking documentation - most of the serialization implementation unfortunately suffers from it.

prefab is really just a saved world state and is merged through into the world through the loading process.

Or just document that the prefab is really just a saved world state and is merged through into the world through the loading process.

I’m not quite sure what you mean by world state (if I don’t make any sense, you know why); SaveFileFormat is primarily a description of an entity set with component data. The loading mechanism creates entities and their components using the world instance, so there are no temporary worlds or merges. Loading is additive; Prefabs rely on this behavior for multiple instantiations.

Prefabs are a specialization on top of the serialization api. While prefabs are intended as blueprints for entity “types” (BasicEnemyShip.class, RedDragonBoss.class), WorldSerializationManager is more generic, and used for saving/loading arbitrary sets of entities + potentially other state (see SaveFileFormat.java) - use-cases in the vein of full-or-partial level data or player save.

What I was looking for before I realized it did not exist was a way to serialize out instances of entities to be able to be imported into the world later or another for later use.

It’s described here: https://github.com/junkdog/artemis-odb/wiki/libgdx-json#using-the-serializer

private String subscriptionToJson(EntitySubscription subscription) {
	final StringWriter writer = new StringWriter();
	final SaveFileFormat save = new SaveFileFormat(subscription.getEntities());
	world.getSystem(WorldSerializationManager.class).save(writer, save);
	return writer.toString();
}

You still have to write some glue yourself though, like where to save to/load from.

  • World Aspect Serialize instead for more compact serializations and of specific entities only.

With regards to the above snippet, you can obtain an EntitySubscription from world.getAspectSubscriptionManager().get(aspect). Alternatively, if you know the entities by id, pass them directly to SaveFileFormat(IntBag).

Imo, the only convenient way to work with Prefabs is to have some sort of (in-)game editor; then it’s pretty easy to serialize whatever entities you want saved, and instantiate prefabs as needed (I personally like binding ctrl-c, ctrl-v to save-to-clipboard/load-from-clipboard - and manually pasting prefabs i’m working on into their respective json files).

I am willing to contribute to this library.

Help is always welcome 😃

Hope I made some things a bit clearer?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Introduction to Archetypes - Apache Maven
In short, Archetype is a Maven project templating toolkit. An archetype is defined as an original pattern or model from which all other...
Read more >
Maven create archetype: Is there a way to declare properties ...
I am working on creating a maven archetype. It is working fine. I have one more enhancement to do which is explained below....
Read more >
Archetypes | Stride
An archetype is a master asset that controls the properties of assets you derive from it. Derived assets are useful when you want...
Read more >
Archetype Configuration - Evolveum Docs
Archetypes work like abstract roles, therefore all objects that need to be "archetyped" can be simply assigned to an archetype.
Read more >
Knappsack Archetypes Part 1 - Andy Gibson
The archetypes come in four flavors, basic,minimal, sandbox and sandbox demo with each one being based on the previous one. In part 1,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found