Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions component.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
GetComponentId() ComponentId
}

type ComponentIdConf struct {
ComponentId
conf any
}

func (world *World) getComponentsIds(components ...ComponentInterface) []ComponentId {
componentsIds := make([]ComponentId, len(components))

Expand Down Expand Up @@ -367,6 +372,40 @@
return nil
}

// AddComponents adds variadic components to the EntityId.
//
// This non-generic version is adapted for when generics are not available, though might be slower.
// It returns an error if:
// - the entity already has the components Ids
// - the componentsIds are not registered in the World
// - an internal error occurs
func (world *World) AddComponents(entityId EntityId, componentsIdsConfs ...ComponentIdConf) error {
var componentsIds []ComponentId
for _, componentIdConf := range componentsIdsConfs {
componentsIds = append(componentsIds, componentIdConf.ComponentId)
}

if world.HasComponents(entityId, componentsIds...) {
return fmt.Errorf("the entity %d already owns the components %v", entityId, componentsIds)
}

Check warning on line 390 in component.go

View check run for this annotation

Codecov / codecov/patch

component.go#L389-L390

Added lines #L389 - L390 were not covered by tests

for _, componentIdConf := range componentsIdsConfs {
componentRegistry, err := world.getConfigByComponentId(componentIdConf.ComponentId)
if err != nil {
return err
}

Check warning on line 396 in component.go

View check run for this annotation

Codecov / codecov/patch

component.go#L395-L396

Added lines #L395 - L396 were not covered by tests

err = componentRegistry.addComponent(world, entityId, componentIdConf.conf)
if err != nil {
return err
}

Check warning on line 401 in component.go

View check run for this annotation

Codecov / codecov/patch

component.go#L400-L401

Added lines #L400 - L401 were not covered by tests

world.componentAddedFn(entityId, componentIdConf.ComponentId)
}

return nil
}

// RemoveComponent removes the component to EntityId.
//
// It returns an error if the EntityId does not have the component.
Expand Down Expand Up @@ -498,16 +537,14 @@
// If the entity has no component, simply add it the archetype
if entityRecord.archetypeId == 0 {
world.setArchetype(entityRecord, archetype)
storageA.add(archetype.Id, component)
} else {
oldArchetype := world.getArchetype(entityRecord)
if archetype.Id != oldArchetype.Id {
moveComponentsToArchetype(world, entityRecord, oldArchetype, archetype)
world.setArchetype(entityRecord, archetype)
}

storageA.add(archetype.Id, component)
}
storageA.add(archetype.Id, component)

return nil
}
Expand Down
26 changes: 26 additions & 0 deletions component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,32 @@ func TestAddComponent(t *testing.T) {
}
}

func TestAddComponents(t *testing.T) {
entities := make([]EntityId, TEST_ENTITY_NUMBER)
world := CreateWorld(1024)

RegisterComponent[testComponent1](world, &ComponentConfig[testComponent1]{BuilderFn: func(component any, configuration any) {}})
RegisterComponent[testComponent2](world, &ComponentConfig[testComponent2]{BuilderFn: func(component any, configuration any) {}})
RegisterComponent[testComponent3](world, &ComponentConfig[testComponent3]{BuilderFn: func(component any, configuration any) {}})
RegisterComponent[testComponent4](world, &ComponentConfig[testComponent4]{BuilderFn: func(component any, configuration any) {}})
RegisterComponent[testComponent5](world, &ComponentConfig[testComponent5]{BuilderFn: func(component any, configuration any) {}})

for i := 0; i < TEST_ENTITY_NUMBER; i++ {
entities[i] = world.CreateEntity(fmt.Sprint(i))

err := world.AddComponents(entities[i], ComponentIdConf{ComponentId: testComponent1Id}, ComponentIdConf{ComponentId: testComponent2Id}, ComponentIdConf{ComponentId: testComponent3Id}, ComponentIdConf{ComponentId: testComponent4Id}, ComponentIdConf{ComponentId: testComponent5Id})
if err != nil {
t.Errorf("could not add components to entity %d: %s", entities[i], err)
}
}

for _, entityId := range entities {
if !world.HasComponents(entityId, testComponent1Id, testComponent2Id, testComponent3Id, testComponent4Id, testComponent5Id) {
t.Errorf("Expected 5 components for entity %d", entityId)
}
}
}

func TestConfigureComponent(t *testing.T) {
world := CreateWorld(1024)
RegisterComponent[testComponent1](world, &ComponentConfig[testComponent1]{BuilderFn: func(component any, configuration any) {
Expand Down
Loading