Terasology
Terasology copied to clipboard
Entity creation within the context of `initialise()` is silently ignored without access to the entity
General Info
Terasology Launcher Version: n/a Terasology Version: 71a98a1bc771aa0c0b2969db6878134e5022fb28 (v5.2.0+) Operating System: Linux Mint 20.2 x86_64 Onboard / Dedicated Graphics: NVIDIA GeForce GTX 1070 Java Version: openjdk version "11.0.11" 2021-04-20
What you were trying to do
In the context of https://github.com/Terasology/LightAndShadow/pull/256 we were trying to get the Light and Shadow game entity during the initialisation of an entity system to add mandatory components to it before starting the game.
https://github.com/Terasology/LightAndShadow/blob/6b7eab6e0170e165a65f9b388b55c17f73e7e43a/src/main/java/org/terasology/module/lightandshadow/phases/authority/PhaseSystem.java#L39-L43
The respective call to GameEntitySystem#getGameEntity()
is supposed to fetch the respective entity if it exists, or create it otherwise.
https://github.com/Terasology/LightAndShadow/blob/ad522934014b3296b725a4b97442fdd793aa3f83/src/main/java/org/terasology/module/lightandshadow/systems/GameEntitySystem.java#L33-L45
What actually happened
Later during testing we figured out that the entity is actually not created.
We verified this by looking at entity dumps created with dumpEntities
from the in-game console.
The entity creation within the context of initialise()
is silently ignored.
For debugging purposes we then tried to print out the entity.toFullDescription()
, which suddenly caused an an error.
The entity creation itself within the context of initialise()
should already throw an exception, not only if the entity is also accessed. Actions like entity creation should not silently be ignored.
How to reproduce
Entity creation is silently ignored:
- Create or entity within the context of
initialise()
in an entity system - Create an entity dump in-game and check whether that entity exists (it should not)
- :question: entity creation is silently ignored
Access to entity throws exception:
- Create or entity within the context of
initialise()
in an entity system - Access the entity within the context of
initialise()
, e.g., by getting and printingentity.getId()
- :x: game crashes with
IllegalStateException
Log details
12:46:22.476 [main] ERROR o.t.e.c.m.loadProcesses.LoadEntities - Entity created before load: {
"id": 1,
"parentPrefab": "LightAndShadow:gameEntity",
"LightAndShadow:Phase": {
"currentPhase": "IDLE"
}
}
12:46:22.478 [main] ERROR o.t.engine.core.modes.StateLoading - Error while loading org.terasology.engine.core.modes.loadProcesses.LoadEntities@66e17bf2
java.lang.IllegalStateException: Entity creation detected during component system initialisation, game load aborting
at org.terasology.engine.core.modes.loadProcesses.LoadEntities.step(LoadEntities.java:40)
at org.terasology.engine.core.modes.StateLoading.update(StateLoading.java:257)
at org.terasology.engine.core.TerasologyEngine.tick(TerasologyEngine.java:499)
at org.terasology.engine.core.TerasologyEngine.mainLoop(TerasologyEngine.java:459)
at org.terasology.engine.core.TerasologyEngine.runMain(TerasologyEngine.java:435)
at org.terasology.engine.core.TerasologyEngine.run(TerasologyEngine.java:401)
at org.terasology.engine.Terasology.call(Terasology.java:206)
at org.terasology.engine.Terasology.call(Terasology.java:69)
at picocli.CommandLine.executeUserObject(CommandLine.java:1933)
at picocli.CommandLine.access$1200(CommandLine.java:145)
at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2332)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2326)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2291)
at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2159)
at picocli.CommandLine.execute(CommandLine.java:2058)
at org.terasology.engine.Terasology.main(Terasology.java:138)
Workaround
I think using the postBegin
hook is the correct place to do these kind of initialization.
https://github.com/Terasology/LightAndShadow/blob/13cc215483d2b0bac25217c38ae201c28fd26720/src/main/java/org/terasology/module/lightandshadow/phases/authority/PhaseSystem.java#L39-L45
Additional Infos / Context
Creating entities in initialise()
is forbidden.
The game will crash if a system tries to access an entity within the context of initialise()
, e.g., entity.getId()
.
However, the entity creation is silently ignored if it happened within the context of initialise()
and there is no immediate access to it.
This leads to hard-to-debug situations where entities are seemingy missing for no reason, i.e., creation did not throw errors but they are nowhere to be found in an entity dump.