Skip to content

Adding components to an instance of a prefab with slots crashes world (de)serialization #1907

@WouterHunter

Description

@WouterHunter

Describe the bug
Adding a component to an instance of a prefab with slots causes ecs_world_to_json to serialize in the wrong order, Calling ecs_world_from_json with the resulting JSON file causes a crash in flecs_name_index_ensure after attempting to register a conflicting entity.

To Reproduce
The following example demonstrates the issue. Removing the line that adds the Rotation component prevents the crash from happening.

namespace Example
{
	struct Position { float x; };
	struct Rotation { float a; };
	struct Turret {
		struct Base {};
		struct Head {};
	};

	struct Module {
		Module(flecs::world& world) {
			// Register example components
			world.component<Position>().member("x", &Position::x);
			world.component<Rotation>().member("a", &Rotation::a);

			// Register prefab and slots
			world.prefab<Turret>().set<Position>({ 1.0f });
			world.prefab<Turret::Base>().slot_of<Turret>();
			world.prefab<Turret::Head>().slot_of<Turret>();
		}
	};
}

int main() {
	flecs::world world_a;
	world_a.import<Example::Module>();

	// Create prefab instance
	flecs::entity inst_a = world_a.entity("my_turret").is_a<Example::Turret>();
	std::cout << inst_a.target<Example::Turret::Base>().path() << std::endl;

	inst_a.add<Example::Rotation>(); // <-- Adding another component is the issue

	// Serialize world to JSON
	auto json = world_a.to_json();
	std::cout << json << std::endl;

	// Create second world, import same module and deserialize
	flecs::world world_b;
	world_b.import<Example::Module>();
	world_b.from_json(json); // <-- crash
	
	// Error message:
	//	fatal: flecs.c: 31912: abort(): conflicting entity registered with 
	//	name 'Base' (existing = 584, new = 586) (ALREADY_DEFINED)

	flecs::entity inst_b = world_b.lookup("my_turret");
	std::cout << inst_b.target<Example::Turret::Base>().path() << std::endl;
}

Expected behavior
I'd expect that adding components to prefab instances wouldn't be an issue, whether that prefab uses slots or not. I can work around this problem, but I'd like to use prefab slots and this issue currently prevents me from doing so.

Additional context
I tested this on the latest version of the master branch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions