• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / ark / 13636797181

03 Mar 2025 05:30PM CUT coverage: 97.422% (-0.3%) from 97.712%
13636797181

Pull #114

github

web-flow
Merge 74bc98fa8 into 0dcd540e6
Pull Request #114: Filter caching

426 of 470 new or added lines in 9 files covered. (90.64%)

41 existing lines in 4 files now uncovered.

5592 of 5740 relevant lines covered (97.42%)

35229.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.88
/ecs/maps_gen.go
1
package ecs
2

3
// Code generated by go generate; DO NOT EDIT.
4

5
import "unsafe"
6

7
// Map1 is a mapper to access 1 components of an entity.
8
type Map1[A any] struct {
9
        world     *World
10
        ids       []ID
11
        storageA  *componentStorage
12
        relations []RelationID
13
}
14

15
// NewMap1 creates a new [Map1].
16
func NewMap1[A any](world *World) Map1[A] {
64✔
17
        ids := []ID{
64✔
18
                ComponentID[A](world),
64✔
19
        }
64✔
20
        return Map1[A]{
64✔
21
                world:    world,
64✔
22
                ids:      ids,
64✔
23
                storageA: &world.storage.components[ids[0].id],
64✔
24
        }
64✔
25
}
64✔
26

27
// NewEntity creates a new entity with the mapped components.
28
func (m *Map1[A]) NewEntity(a *A, rel ...RelationIndex) Entity {
127✔
29
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
30
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
31
                unsafe.Pointer(a),
127✔
32
        }, m.relations)
127✔
33
}
127✔
34

35
// NewBatch creates a batch of new entities with the mapped components.
36
func (m *Map1[A]) NewBatch(count int, a *A, rel ...RelationIndex) {
3✔
37
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
38
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
39
                unsafe.Pointer(a),
3✔
40
        }, m.relations)
3✔
41
}
3✔
42

43
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
44
// The initializer function can be nil.
45
func (m *Map1[A]) NewBatchFn(count int, fn func(entity Entity, a *A), rel ...RelationIndex) {
51✔
46
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
51✔
47
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
51✔
48
        if fn == nil {
51✔
49
                return
×
50
        }
×
51

52
        table := &m.world.storage.tables[tableID]
51✔
53
        columnA := m.storageA.columns[tableID]
51✔
54

51✔
55
        lock := m.world.lock()
51✔
56
        for i := range count {
675✔
57
                index := uintptr(start + i)
624✔
58
                fn(
624✔
59
                        table.GetEntity(index),
624✔
60
                        (*A)(columnA.Get(index)),
624✔
61
                )
624✔
62
        }
624✔
63
        m.world.unlock(lock)
51✔
64
}
65

66
// Get returns the mapped components for the given entity.
67
func (m *Map1[A]) Get(entity Entity) *A {
793✔
68
        if !m.world.Alive(entity) {
794✔
69
                panic("can't get components of a dead entity")
1✔
70
        }
71
        return m.GetUnchecked(entity)
792✔
72
}
73

74
// GetUnchecked returns the mapped components for the given entity.
75
// In contrast to [Map1.Get], it does not check whether the entity is alive.
76
// Can be used as an optimization when it is certain that the entity is alive.
77
func (m *Map1[A]) GetUnchecked(entity Entity) *A {
792✔
78
        m.world.storage.checkHasComponent(entity, m.ids[0])
792✔
79

792✔
80
        index := m.world.storage.entities[entity.id]
792✔
81
        row := uintptr(index.row)
792✔
82

792✔
83
        return (*A)(m.storageA.columns[index.table].Get(row))
792✔
84
}
792✔
85

86
// HasAll return whether the given entity has all mapped components.
87
func (m *Map1[A]) HasAll(entity Entity) bool {
438✔
88
        if !m.world.Alive(entity) {
439✔
89
                panic("can't check components of a dead entity")
1✔
90
        }
91
        index := m.world.storage.entities[entity.id]
437✔
92
        return m.storageA.columns[index.table] != nil
437✔
93
}
94

95
// Add the mapped components to the given entity.
96
func (m *Map1[A]) Add(entity Entity, a *A, rel ...RelationIndex) {
14✔
97
        if !m.world.Alive(entity) {
15✔
98
                panic("can't add components to a dead entity")
1✔
99
        }
100
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
13✔
101
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
13✔
102
                unsafe.Pointer(a),
13✔
103
        }, m.relations)
13✔
104
}
105

106
// AddBatch adds the mapped components to all entities matching the given batch filter.
107
func (m *Map1[A]) AddBatch(batch *Batch, a *A, rel ...RelationIndex) {
1✔
108
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
109
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
110
                unsafe.Pointer(a),
1✔
111
        }, m.relations, nil)
1✔
112
}
1✔
113

114
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
115
// running the given function on each. The function can be nil.
116
func (m *Map1[A]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A), rel ...RelationIndex) {
1✔
117
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
118

1✔
119
        var process func(tableID tableID, start, len int)
1✔
120
        if fn != nil {
2✔
121
                process = func(tableID tableID, start, len int) {
3✔
122
                        table := &m.world.storage.tables[tableID]
2✔
123
                        columnA := m.storageA.columns[tableID]
2✔
124

2✔
125
                        lock := m.world.lock()
2✔
126
                        for i := range len {
26✔
127
                                index := uintptr(start + i)
24✔
128
                                fn(
24✔
129
                                        table.GetEntity(index),
24✔
130
                                        (*A)(columnA.Get(index)),
24✔
131
                                )
24✔
132
                        }
24✔
133
                        m.world.unlock(lock)
2✔
134
                }
135
        }
136
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
137
}
138

139
// Remove the mapped components from the given entity.
140
func (m *Map1[A]) Remove(entity Entity) {
25✔
141
        if !m.world.Alive(entity) {
26✔
142
                panic("can't remove components from a dead entity")
1✔
143
        }
144
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
145
}
146

147
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
148
// running the given function on each. The function can be nil.
149
func (m *Map1[A]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
150
        var process func(tableID tableID, start, len int)
2✔
151
        if fn != nil {
3✔
152
                process = func(tableID tableID, start, len int) {
3✔
153
                        table := &m.world.storage.tables[tableID]
2✔
154

2✔
155
                        lock := m.world.lock()
2✔
156
                        for i := range len {
26✔
157
                                index := uintptr(start + i)
24✔
158
                                fn(table.GetEntity(index))
24✔
159
                        }
24✔
160
                        m.world.unlock(lock)
2✔
161
                }
162
        }
163
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
164
}
165

166
// GetRelation returns the relation target of an entity for the component at the given index.
167
func (m *Map1[A]) GetRelation(entity Entity, index int) Entity {
3✔
168
        if !m.world.Alive(entity) {
4✔
169
                panic("can't get entity relation target for a dead entity")
1✔
170
        }
171
        return m.GetRelationUnchecked(entity, index)
2✔
172
}
173

174
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
175
// In contrast to [Map1.GetRelation], it does not check whether the entity is alive.
176
// Can be used as an optimization when it is certain that the entity is alive.
177
func (m *Map1[A]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
178
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
179
}
3✔
180

181
// SetRelations sets relation targets for the given entity.
182
func (m *Map1[A]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
183
        if !m.world.Alive(entity) {
3✔
184
                panic("can't set entity relation targets for a dead entity")
1✔
185
        }
186
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
187
        m.world.setRelations(entity, m.relations)
1✔
188
}
189

190
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
191
func (m *Map1[A]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
192
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
193

1✔
194
        var process func(tableID tableID, start, len int)
1✔
195
        if fn != nil {
2✔
196
                process = func(tableID tableID, start, len int) {
2✔
197
                        table := &m.world.storage.tables[tableID]
1✔
198

1✔
199
                        lock := m.world.lock()
1✔
200
                        for i := range len {
25✔
201
                                index := uintptr(start + i)
24✔
202
                                fn(table.GetEntity(index))
24✔
203
                        }
24✔
204
                        m.world.unlock(lock)
1✔
205
                }
206
        }
207
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
208
}
209

210
// Map2 is a mapper to access 2 components of an entity.
211
type Map2[A any, B any] struct {
212
        world     *World
213
        ids       []ID
214
        storageA  *componentStorage
215
        storageB  *componentStorage
216
        relations []RelationID
217
}
218

219
// NewMap2 creates a new [Map2].
220
func NewMap2[A any, B any](world *World) Map2[A, B] {
89✔
221
        ids := []ID{
89✔
222
                ComponentID[A](world),
89✔
223
                ComponentID[B](world),
89✔
224
        }
89✔
225
        return Map2[A, B]{
89✔
226
                world:    world,
89✔
227
                ids:      ids,
89✔
228
                storageA: &world.storage.components[ids[0].id],
89✔
229
                storageB: &world.storage.components[ids[1].id],
89✔
230
        }
89✔
231
}
89✔
232

233
// NewEntity creates a new entity with the mapped components.
234
func (m *Map2[A, B]) NewEntity(a *A, b *B, rel ...RelationIndex) Entity {
285✔
235
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
285✔
236
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
285✔
237
                unsafe.Pointer(a),
285✔
238
                unsafe.Pointer(b),
285✔
239
        }, m.relations)
285✔
240
}
285✔
241

242
// NewBatch creates a batch of new entities with the mapped components.
243
func (m *Map2[A, B]) NewBatch(count int, a *A, b *B, rel ...RelationIndex) {
3✔
244
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
245
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
246
                unsafe.Pointer(a),
3✔
247
                unsafe.Pointer(b),
3✔
248
        }, m.relations)
3✔
249
}
3✔
250

251
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
252
// The initializer function can be nil.
253
func (m *Map2[A, B]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B), rel ...RelationIndex) {
50✔
254
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
50✔
255
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
50✔
256
        if fn == nil {
50✔
UNCOV
257
                return
×
UNCOV
258
        }
×
259

260
        table := &m.world.storage.tables[tableID]
50✔
261
        columnA := m.storageA.columns[tableID]
50✔
262
        columnB := m.storageB.columns[tableID]
50✔
263

50✔
264
        lock := m.world.lock()
50✔
265
        for i := range count {
662✔
266
                index := uintptr(start + i)
612✔
267
                fn(
612✔
268
                        table.GetEntity(index),
612✔
269
                        (*A)(columnA.Get(index)),
612✔
270
                        (*B)(columnB.Get(index)),
612✔
271
                )
612✔
272
        }
612✔
273
        m.world.unlock(lock)
50✔
274
}
275

276
// Get returns the mapped components for the given entity.
277
func (m *Map2[A, B]) Get(entity Entity) (*A, *B) {
25✔
278
        if !m.world.Alive(entity) {
26✔
279
                panic("can't get components of a dead entity")
1✔
280
        }
281
        return m.GetUnchecked(entity)
24✔
282
}
283

284
// GetUnchecked returns the mapped components for the given entity.
285
// In contrast to [Map2.Get], it does not check whether the entity is alive.
286
// Can be used as an optimization when it is certain that the entity is alive.
287
func (m *Map2[A, B]) GetUnchecked(entity Entity) (*A, *B) {
24✔
288
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
289
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
290

24✔
291
        index := m.world.storage.entities[entity.id]
24✔
292
        row := uintptr(index.row)
24✔
293

24✔
294
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
295
                (*B)(m.storageB.columns[index.table].Get(row))
24✔
296
}
24✔
297

298
// HasAll return whether the given entity has all mapped components.
299
func (m *Map2[A, B]) HasAll(entity Entity) bool {
78✔
300
        if !m.world.Alive(entity) {
79✔
301
                panic("can't check components of a dead entity")
1✔
302
        }
303
        index := m.world.storage.entities[entity.id]
77✔
304
        return m.storageA.columns[index.table] != nil &&
77✔
305
                m.storageB.columns[index.table] != nil
77✔
306
}
307

308
// Add the mapped components to the given entity.
309
func (m *Map2[A, B]) Add(entity Entity, a *A, b *B, rel ...RelationIndex) {
13✔
310
        if !m.world.Alive(entity) {
14✔
311
                panic("can't add components to a dead entity")
1✔
312
        }
313
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
314
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
315
                unsafe.Pointer(a),
12✔
316
                unsafe.Pointer(b),
12✔
317
        }, m.relations)
12✔
318
}
319

320
// AddBatch adds the mapped components to all entities matching the given batch filter.
321
func (m *Map2[A, B]) AddBatch(batch *Batch, a *A, b *B, rel ...RelationIndex) {
1✔
322
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
323
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
324
                unsafe.Pointer(a),
1✔
325
                unsafe.Pointer(b),
1✔
326
        }, m.relations, nil)
1✔
327
}
1✔
328

329
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
330
// running the given function on each. The function can be nil.
331
func (m *Map2[A, B]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B), rel ...RelationIndex) {
1✔
332
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
333

1✔
334
        var process func(tableID tableID, start, len int)
1✔
335
        if fn != nil {
2✔
336
                process = func(tableID tableID, start, len int) {
3✔
337
                        table := &m.world.storage.tables[tableID]
2✔
338
                        columnA := m.storageA.columns[tableID]
2✔
339
                        columnB := m.storageB.columns[tableID]
2✔
340

2✔
341
                        lock := m.world.lock()
2✔
342
                        for i := range len {
26✔
343
                                index := uintptr(start + i)
24✔
344
                                fn(
24✔
345
                                        table.GetEntity(index),
24✔
346
                                        (*A)(columnA.Get(index)),
24✔
347
                                        (*B)(columnB.Get(index)),
24✔
348
                                )
24✔
349
                        }
24✔
350
                        m.world.unlock(lock)
2✔
351
                }
352
        }
353
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
354
}
355

356
// Remove the mapped components from the given entity.
357
func (m *Map2[A, B]) Remove(entity Entity) {
25✔
358
        if !m.world.Alive(entity) {
26✔
359
                panic("can't remove components from a dead entity")
1✔
360
        }
361
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
362
}
363

364
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
365
// running the given function on each. The function can be nil.
366
func (m *Map2[A, B]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
367
        var process func(tableID tableID, start, len int)
2✔
368
        if fn != nil {
3✔
369
                process = func(tableID tableID, start, len int) {
3✔
370
                        table := &m.world.storage.tables[tableID]
2✔
371

2✔
372
                        lock := m.world.lock()
2✔
373
                        for i := range len {
26✔
374
                                index := uintptr(start + i)
24✔
375
                                fn(table.GetEntity(index))
24✔
376
                        }
24✔
377
                        m.world.unlock(lock)
2✔
378
                }
379
        }
380
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
381
}
382

383
// GetRelation returns the relation target of an entity for the component at the given index.
384
func (m *Map2[A, B]) GetRelation(entity Entity, index int) Entity {
3✔
385
        if !m.world.Alive(entity) {
4✔
386
                panic("can't get entity relation target for a dead entity")
1✔
387
        }
388
        return m.GetRelationUnchecked(entity, index)
2✔
389
}
390

391
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
392
// In contrast to [Map2.GetRelation], it does not check whether the entity is alive.
393
// Can be used as an optimization when it is certain that the entity is alive.
394
func (m *Map2[A, B]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
395
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
396
}
3✔
397

398
// SetRelations sets relation targets for the given entity.
399
func (m *Map2[A, B]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
400
        if !m.world.Alive(entity) {
3✔
401
                panic("can't set entity relation targets for a dead entity")
1✔
402
        }
403
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
404
        m.world.setRelations(entity, m.relations)
1✔
405
}
406

407
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
408
func (m *Map2[A, B]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
409
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
410

1✔
411
        var process func(tableID tableID, start, len int)
1✔
412
        if fn != nil {
2✔
413
                process = func(tableID tableID, start, len int) {
2✔
414
                        table := &m.world.storage.tables[tableID]
1✔
415

1✔
416
                        lock := m.world.lock()
1✔
417
                        for i := range len {
25✔
418
                                index := uintptr(start + i)
24✔
419
                                fn(table.GetEntity(index))
24✔
420
                        }
24✔
421
                        m.world.unlock(lock)
1✔
422
                }
423
        }
424
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
425
}
426

427
// Map3 is a mapper to access 3 components of an entity.
428
type Map3[A any, B any, C any] struct {
429
        world     *World
430
        ids       []ID
431
        storageA  *componentStorage
432
        storageB  *componentStorage
433
        storageC  *componentStorage
434
        relations []RelationID
435
}
436

437
// NewMap3 creates a new [Map3].
438
func NewMap3[A any, B any, C any](world *World) Map3[A, B, C] {
15✔
439
        ids := []ID{
15✔
440
                ComponentID[A](world),
15✔
441
                ComponentID[B](world),
15✔
442
                ComponentID[C](world),
15✔
443
        }
15✔
444
        return Map3[A, B, C]{
15✔
445
                world:    world,
15✔
446
                ids:      ids,
15✔
447
                storageA: &world.storage.components[ids[0].id],
15✔
448
                storageB: &world.storage.components[ids[1].id],
15✔
449
                storageC: &world.storage.components[ids[2].id],
15✔
450
        }
15✔
451
}
15✔
452

453
// NewEntity creates a new entity with the mapped components.
454
func (m *Map3[A, B, C]) NewEntity(a *A, b *B, c *C, rel ...RelationIndex) Entity {
167✔
455
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
167✔
456
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
167✔
457
                unsafe.Pointer(a),
167✔
458
                unsafe.Pointer(b),
167✔
459
                unsafe.Pointer(c),
167✔
460
        }, m.relations)
167✔
461
}
167✔
462

463
// NewBatch creates a batch of new entities with the mapped components.
464
func (m *Map3[A, B, C]) NewBatch(count int, a *A, b *B, c *C, rel ...RelationIndex) {
5✔
465
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
5✔
466
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
5✔
467
                unsafe.Pointer(a),
5✔
468
                unsafe.Pointer(b),
5✔
469
                unsafe.Pointer(c),
5✔
470
        }, m.relations)
5✔
471
}
5✔
472

473
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
474
// The initializer function can be nil.
475
func (m *Map3[A, B, C]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B, c *C), rel ...RelationIndex) {
1✔
476
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
477
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
478
        if fn == nil {
1✔
UNCOV
479
                return
×
UNCOV
480
        }
×
481

482
        table := &m.world.storage.tables[tableID]
1✔
483
        columnA := m.storageA.columns[tableID]
1✔
484
        columnB := m.storageB.columns[tableID]
1✔
485
        columnC := m.storageC.columns[tableID]
1✔
486

1✔
487
        lock := m.world.lock()
1✔
488
        for i := range count {
25✔
489
                index := uintptr(start + i)
24✔
490
                fn(
24✔
491
                        table.GetEntity(index),
24✔
492
                        (*A)(columnA.Get(index)),
24✔
493
                        (*B)(columnB.Get(index)),
24✔
494
                        (*C)(columnC.Get(index)),
24✔
495
                )
24✔
496
        }
24✔
497
        m.world.unlock(lock)
1✔
498
}
499

500
// Get returns the mapped components for the given entity.
501
func (m *Map3[A, B, C]) Get(entity Entity) (*A, *B, *C) {
25✔
502
        if !m.world.Alive(entity) {
26✔
503
                panic("can't get components of a dead entity")
1✔
504
        }
505
        return m.GetUnchecked(entity)
24✔
506
}
507

508
// GetUnchecked returns the mapped components for the given entity.
509
// In contrast to [Map3.Get], it does not check whether the entity is alive.
510
// Can be used as an optimization when it is certain that the entity is alive.
511
func (m *Map3[A, B, C]) GetUnchecked(entity Entity) (*A, *B, *C) {
24✔
512
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
513
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
514
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
515

24✔
516
        index := m.world.storage.entities[entity.id]
24✔
517
        row := uintptr(index.row)
24✔
518

24✔
519
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
520
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
521
                (*C)(m.storageC.columns[index.table].Get(row))
24✔
522
}
24✔
523

524
// HasAll return whether the given entity has all mapped components.
525
func (m *Map3[A, B, C]) HasAll(entity Entity) bool {
54✔
526
        if !m.world.Alive(entity) {
55✔
527
                panic("can't check components of a dead entity")
1✔
528
        }
529
        index := m.world.storage.entities[entity.id]
53✔
530
        return m.storageA.columns[index.table] != nil &&
53✔
531
                m.storageB.columns[index.table] != nil &&
53✔
532
                m.storageC.columns[index.table] != nil
53✔
533
}
534

535
// Add the mapped components to the given entity.
536
func (m *Map3[A, B, C]) Add(entity Entity, a *A, b *B, c *C, rel ...RelationIndex) {
13✔
537
        if !m.world.Alive(entity) {
14✔
538
                panic("can't add components to a dead entity")
1✔
539
        }
540
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
541
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
542
                unsafe.Pointer(a),
12✔
543
                unsafe.Pointer(b),
12✔
544
                unsafe.Pointer(c),
12✔
545
        }, m.relations)
12✔
546
}
547

548
// AddBatch adds the mapped components to all entities matching the given batch filter.
549
func (m *Map3[A, B, C]) AddBatch(batch *Batch, a *A, b *B, c *C, rel ...RelationIndex) {
1✔
550
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
551
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
552
                unsafe.Pointer(a),
1✔
553
                unsafe.Pointer(b),
1✔
554
                unsafe.Pointer(c),
1✔
555
        }, m.relations, nil)
1✔
556
}
1✔
557

558
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
559
// running the given function on each. The function can be nil.
560
func (m *Map3[A, B, C]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B, c *C), rel ...RelationIndex) {
1✔
561
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
562

1✔
563
        var process func(tableID tableID, start, len int)
1✔
564
        if fn != nil {
2✔
565
                process = func(tableID tableID, start, len int) {
3✔
566
                        table := &m.world.storage.tables[tableID]
2✔
567
                        columnA := m.storageA.columns[tableID]
2✔
568
                        columnB := m.storageB.columns[tableID]
2✔
569
                        columnC := m.storageC.columns[tableID]
2✔
570

2✔
571
                        lock := m.world.lock()
2✔
572
                        for i := range len {
26✔
573
                                index := uintptr(start + i)
24✔
574
                                fn(
24✔
575
                                        table.GetEntity(index),
24✔
576
                                        (*A)(columnA.Get(index)),
24✔
577
                                        (*B)(columnB.Get(index)),
24✔
578
                                        (*C)(columnC.Get(index)),
24✔
579
                                )
24✔
580
                        }
24✔
581
                        m.world.unlock(lock)
2✔
582
                }
583
        }
584
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
585
}
586

587
// Remove the mapped components from the given entity.
588
func (m *Map3[A, B, C]) Remove(entity Entity) {
25✔
589
        if !m.world.Alive(entity) {
26✔
590
                panic("can't remove components from a dead entity")
1✔
591
        }
592
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
593
}
594

595
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
596
// running the given function on each. The function can be nil.
597
func (m *Map3[A, B, C]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
598
        var process func(tableID tableID, start, len int)
2✔
599
        if fn != nil {
3✔
600
                process = func(tableID tableID, start, len int) {
3✔
601
                        table := &m.world.storage.tables[tableID]
2✔
602

2✔
603
                        lock := m.world.lock()
2✔
604
                        for i := range len {
26✔
605
                                index := uintptr(start + i)
24✔
606
                                fn(table.GetEntity(index))
24✔
607
                        }
24✔
608
                        m.world.unlock(lock)
2✔
609
                }
610
        }
611
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
612
}
613

614
// GetRelation returns the relation target of an entity for the component at the given index.
615
func (m *Map3[A, B, C]) GetRelation(entity Entity, index int) Entity {
3✔
616
        if !m.world.Alive(entity) {
4✔
617
                panic("can't get entity relation target for a dead entity")
1✔
618
        }
619
        return m.GetRelationUnchecked(entity, index)
2✔
620
}
621

622
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
623
// In contrast to [Map3.GetRelation], it does not check whether the entity is alive.
624
// Can be used as an optimization when it is certain that the entity is alive.
625
func (m *Map3[A, B, C]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
626
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
627
}
3✔
628

629
// SetRelations sets relation targets for the given entity.
630
func (m *Map3[A, B, C]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
631
        if !m.world.Alive(entity) {
3✔
632
                panic("can't set entity relation targets for a dead entity")
1✔
633
        }
634
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
635
        m.world.setRelations(entity, m.relations)
1✔
636
}
637

638
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
639
func (m *Map3[A, B, C]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
640
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
641

1✔
642
        var process func(tableID tableID, start, len int)
1✔
643
        if fn != nil {
2✔
644
                process = func(tableID tableID, start, len int) {
2✔
645
                        table := &m.world.storage.tables[tableID]
1✔
646

1✔
647
                        lock := m.world.lock()
1✔
648
                        for i := range len {
25✔
649
                                index := uintptr(start + i)
24✔
650
                                fn(table.GetEntity(index))
24✔
651
                        }
24✔
652
                        m.world.unlock(lock)
1✔
653
                }
654
        }
655
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
656
}
657

658
// Map4 is a mapper to access 4 components of an entity.
659
type Map4[A any, B any, C any, D any] struct {
660
        world     *World
661
        ids       []ID
662
        storageA  *componentStorage
663
        storageB  *componentStorage
664
        storageC  *componentStorage
665
        storageD  *componentStorage
666
        relations []RelationID
667
}
668

669
// NewMap4 creates a new [Map4].
670
func NewMap4[A any, B any, C any, D any](world *World) Map4[A, B, C, D] {
13✔
671
        ids := []ID{
13✔
672
                ComponentID[A](world),
13✔
673
                ComponentID[B](world),
13✔
674
                ComponentID[C](world),
13✔
675
                ComponentID[D](world),
13✔
676
        }
13✔
677
        return Map4[A, B, C, D]{
13✔
678
                world:    world,
13✔
679
                ids:      ids,
13✔
680
                storageA: &world.storage.components[ids[0].id],
13✔
681
                storageB: &world.storage.components[ids[1].id],
13✔
682
                storageC: &world.storage.components[ids[2].id],
13✔
683
                storageD: &world.storage.components[ids[3].id],
13✔
684
        }
13✔
685
}
13✔
686

687
// NewEntity creates a new entity with the mapped components.
688
func (m *Map4[A, B, C, D]) NewEntity(a *A, b *B, c *C, d *D, rel ...RelationIndex) Entity {
127✔
689
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
690
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
691
                unsafe.Pointer(a),
127✔
692
                unsafe.Pointer(b),
127✔
693
                unsafe.Pointer(c),
127✔
694
                unsafe.Pointer(d),
127✔
695
        }, m.relations)
127✔
696
}
127✔
697

698
// NewBatch creates a batch of new entities with the mapped components.
699
func (m *Map4[A, B, C, D]) NewBatch(count int, a *A, b *B, c *C, d *D, rel ...RelationIndex) {
3✔
700
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
701
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
702
                unsafe.Pointer(a),
3✔
703
                unsafe.Pointer(b),
3✔
704
                unsafe.Pointer(c),
3✔
705
                unsafe.Pointer(d),
3✔
706
        }, m.relations)
3✔
707
}
3✔
708

709
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
710
// The initializer function can be nil.
711
func (m *Map4[A, B, C, D]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B, c *C, d *D), rel ...RelationIndex) {
1✔
712
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
713
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
714
        if fn == nil {
1✔
UNCOV
715
                return
×
UNCOV
716
        }
×
717

718
        table := &m.world.storage.tables[tableID]
1✔
719
        columnA := m.storageA.columns[tableID]
1✔
720
        columnB := m.storageB.columns[tableID]
1✔
721
        columnC := m.storageC.columns[tableID]
1✔
722
        columnD := m.storageD.columns[tableID]
1✔
723

1✔
724
        lock := m.world.lock()
1✔
725
        for i := range count {
25✔
726
                index := uintptr(start + i)
24✔
727
                fn(
24✔
728
                        table.GetEntity(index),
24✔
729
                        (*A)(columnA.Get(index)),
24✔
730
                        (*B)(columnB.Get(index)),
24✔
731
                        (*C)(columnC.Get(index)),
24✔
732
                        (*D)(columnD.Get(index)),
24✔
733
                )
24✔
734
        }
24✔
735
        m.world.unlock(lock)
1✔
736
}
737

738
// Get returns the mapped components for the given entity.
739
func (m *Map4[A, B, C, D]) Get(entity Entity) (*A, *B, *C, *D) {
25✔
740
        if !m.world.Alive(entity) {
26✔
741
                panic("can't get components of a dead entity")
1✔
742
        }
743
        return m.GetUnchecked(entity)
24✔
744
}
745

746
// GetUnchecked returns the mapped components for the given entity.
747
// In contrast to [Map4.Get], it does not check whether the entity is alive.
748
// Can be used as an optimization when it is certain that the entity is alive.
749
func (m *Map4[A, B, C, D]) GetUnchecked(entity Entity) (*A, *B, *C, *D) {
24✔
750
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
751
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
752
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
753
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
754

24✔
755
        index := m.world.storage.entities[entity.id]
24✔
756
        row := uintptr(index.row)
24✔
757

24✔
758
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
759
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
760
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
761
                (*D)(m.storageD.columns[index.table].Get(row))
24✔
762
}
24✔
763

764
// HasAll return whether the given entity has all mapped components.
765
func (m *Map4[A, B, C, D]) HasAll(entity Entity) bool {
54✔
766
        if !m.world.Alive(entity) {
55✔
767
                panic("can't check components of a dead entity")
1✔
768
        }
769
        index := m.world.storage.entities[entity.id]
53✔
770
        return m.storageA.columns[index.table] != nil &&
53✔
771
                m.storageB.columns[index.table] != nil &&
53✔
772
                m.storageC.columns[index.table] != nil &&
53✔
773
                m.storageD.columns[index.table] != nil
53✔
774
}
775

776
// Add the mapped components to the given entity.
777
func (m *Map4[A, B, C, D]) Add(entity Entity, a *A, b *B, c *C, d *D, rel ...RelationIndex) {
13✔
778
        if !m.world.Alive(entity) {
14✔
779
                panic("can't add components to a dead entity")
1✔
780
        }
781
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
782
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
783
                unsafe.Pointer(a),
12✔
784
                unsafe.Pointer(b),
12✔
785
                unsafe.Pointer(c),
12✔
786
                unsafe.Pointer(d),
12✔
787
        }, m.relations)
12✔
788
}
789

790
// AddBatch adds the mapped components to all entities matching the given batch filter.
791
func (m *Map4[A, B, C, D]) AddBatch(batch *Batch, a *A, b *B, c *C, d *D, rel ...RelationIndex) {
1✔
792
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
793
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
794
                unsafe.Pointer(a),
1✔
795
                unsafe.Pointer(b),
1✔
796
                unsafe.Pointer(c),
1✔
797
                unsafe.Pointer(d),
1✔
798
        }, m.relations, nil)
1✔
799
}
1✔
800

801
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
802
// running the given function on each. The function can be nil.
803
func (m *Map4[A, B, C, D]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B, c *C, d *D), rel ...RelationIndex) {
1✔
804
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
805

1✔
806
        var process func(tableID tableID, start, len int)
1✔
807
        if fn != nil {
2✔
808
                process = func(tableID tableID, start, len int) {
3✔
809
                        table := &m.world.storage.tables[tableID]
2✔
810
                        columnA := m.storageA.columns[tableID]
2✔
811
                        columnB := m.storageB.columns[tableID]
2✔
812
                        columnC := m.storageC.columns[tableID]
2✔
813
                        columnD := m.storageD.columns[tableID]
2✔
814

2✔
815
                        lock := m.world.lock()
2✔
816
                        for i := range len {
26✔
817
                                index := uintptr(start + i)
24✔
818
                                fn(
24✔
819
                                        table.GetEntity(index),
24✔
820
                                        (*A)(columnA.Get(index)),
24✔
821
                                        (*B)(columnB.Get(index)),
24✔
822
                                        (*C)(columnC.Get(index)),
24✔
823
                                        (*D)(columnD.Get(index)),
24✔
824
                                )
24✔
825
                        }
24✔
826
                        m.world.unlock(lock)
2✔
827
                }
828
        }
829
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
830
}
831

832
// Remove the mapped components from the given entity.
833
func (m *Map4[A, B, C, D]) Remove(entity Entity) {
25✔
834
        if !m.world.Alive(entity) {
26✔
835
                panic("can't remove components from a dead entity")
1✔
836
        }
837
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
838
}
839

840
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
841
// running the given function on each. The function can be nil.
842
func (m *Map4[A, B, C, D]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
843
        var process func(tableID tableID, start, len int)
2✔
844
        if fn != nil {
3✔
845
                process = func(tableID tableID, start, len int) {
3✔
846
                        table := &m.world.storage.tables[tableID]
2✔
847

2✔
848
                        lock := m.world.lock()
2✔
849
                        for i := range len {
26✔
850
                                index := uintptr(start + i)
24✔
851
                                fn(table.GetEntity(index))
24✔
852
                        }
24✔
853
                        m.world.unlock(lock)
2✔
854
                }
855
        }
856
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
857
}
858

859
// GetRelation returns the relation target of an entity for the component at the given index.
860
func (m *Map4[A, B, C, D]) GetRelation(entity Entity, index int) Entity {
3✔
861
        if !m.world.Alive(entity) {
4✔
862
                panic("can't get entity relation target for a dead entity")
1✔
863
        }
864
        return m.GetRelationUnchecked(entity, index)
2✔
865
}
866

867
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
868
// In contrast to [Map4.GetRelation], it does not check whether the entity is alive.
869
// Can be used as an optimization when it is certain that the entity is alive.
870
func (m *Map4[A, B, C, D]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
871
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
872
}
3✔
873

874
// SetRelations sets relation targets for the given entity.
875
func (m *Map4[A, B, C, D]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
876
        if !m.world.Alive(entity) {
3✔
877
                panic("can't set entity relation targets for a dead entity")
1✔
878
        }
879
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
880
        m.world.setRelations(entity, m.relations)
1✔
881
}
882

883
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
884
func (m *Map4[A, B, C, D]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
885
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
886

1✔
887
        var process func(tableID tableID, start, len int)
1✔
888
        if fn != nil {
2✔
889
                process = func(tableID tableID, start, len int) {
2✔
890
                        table := &m.world.storage.tables[tableID]
1✔
891

1✔
892
                        lock := m.world.lock()
1✔
893
                        for i := range len {
25✔
894
                                index := uintptr(start + i)
24✔
895
                                fn(table.GetEntity(index))
24✔
896
                        }
24✔
897
                        m.world.unlock(lock)
1✔
898
                }
899
        }
900
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
901
}
902

903
// Map5 is a mapper to access 5 components of an entity.
904
type Map5[A any, B any, C any, D any, E any] struct {
905
        world     *World
906
        ids       []ID
907
        storageA  *componentStorage
908
        storageB  *componentStorage
909
        storageC  *componentStorage
910
        storageD  *componentStorage
911
        storageE  *componentStorage
912
        relations []RelationID
913
}
914

915
// NewMap5 creates a new [Map5].
916
func NewMap5[A any, B any, C any, D any, E any](world *World) Map5[A, B, C, D, E] {
13✔
917
        ids := []ID{
13✔
918
                ComponentID[A](world),
13✔
919
                ComponentID[B](world),
13✔
920
                ComponentID[C](world),
13✔
921
                ComponentID[D](world),
13✔
922
                ComponentID[E](world),
13✔
923
        }
13✔
924
        return Map5[A, B, C, D, E]{
13✔
925
                world:    world,
13✔
926
                ids:      ids,
13✔
927
                storageA: &world.storage.components[ids[0].id],
13✔
928
                storageB: &world.storage.components[ids[1].id],
13✔
929
                storageC: &world.storage.components[ids[2].id],
13✔
930
                storageD: &world.storage.components[ids[3].id],
13✔
931
                storageE: &world.storage.components[ids[4].id],
13✔
932
        }
13✔
933
}
13✔
934

935
// NewEntity creates a new entity with the mapped components.
936
func (m *Map5[A, B, C, D, E]) NewEntity(a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) Entity {
127✔
937
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
938
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
939
                unsafe.Pointer(a),
127✔
940
                unsafe.Pointer(b),
127✔
941
                unsafe.Pointer(c),
127✔
942
                unsafe.Pointer(d),
127✔
943
                unsafe.Pointer(e),
127✔
944
        }, m.relations)
127✔
945
}
127✔
946

947
// NewBatch creates a batch of new entities with the mapped components.
948
func (m *Map5[A, B, C, D, E]) NewBatch(count int, a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) {
3✔
949
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
950
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
951
                unsafe.Pointer(a),
3✔
952
                unsafe.Pointer(b),
3✔
953
                unsafe.Pointer(c),
3✔
954
                unsafe.Pointer(d),
3✔
955
                unsafe.Pointer(e),
3✔
956
        }, m.relations)
3✔
957
}
3✔
958

959
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
960
// The initializer function can be nil.
961
func (m *Map5[A, B, C, D, E]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E), rel ...RelationIndex) {
1✔
962
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
963
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
964
        if fn == nil {
1✔
UNCOV
965
                return
×
UNCOV
966
        }
×
967

968
        table := &m.world.storage.tables[tableID]
1✔
969
        columnA := m.storageA.columns[tableID]
1✔
970
        columnB := m.storageB.columns[tableID]
1✔
971
        columnC := m.storageC.columns[tableID]
1✔
972
        columnD := m.storageD.columns[tableID]
1✔
973
        columnE := m.storageE.columns[tableID]
1✔
974

1✔
975
        lock := m.world.lock()
1✔
976
        for i := range count {
25✔
977
                index := uintptr(start + i)
24✔
978
                fn(
24✔
979
                        table.GetEntity(index),
24✔
980
                        (*A)(columnA.Get(index)),
24✔
981
                        (*B)(columnB.Get(index)),
24✔
982
                        (*C)(columnC.Get(index)),
24✔
983
                        (*D)(columnD.Get(index)),
24✔
984
                        (*E)(columnE.Get(index)),
24✔
985
                )
24✔
986
        }
24✔
987
        m.world.unlock(lock)
1✔
988
}
989

990
// Get returns the mapped components for the given entity.
991
func (m *Map5[A, B, C, D, E]) Get(entity Entity) (*A, *B, *C, *D, *E) {
25✔
992
        if !m.world.Alive(entity) {
26✔
993
                panic("can't get components of a dead entity")
1✔
994
        }
995
        return m.GetUnchecked(entity)
24✔
996
}
997

998
// GetUnchecked returns the mapped components for the given entity.
999
// In contrast to [Map5.Get], it does not check whether the entity is alive.
1000
// Can be used as an optimization when it is certain that the entity is alive.
1001
func (m *Map5[A, B, C, D, E]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E) {
24✔
1002
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1003
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1004
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1005
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1006
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1007

24✔
1008
        index := m.world.storage.entities[entity.id]
24✔
1009
        row := uintptr(index.row)
24✔
1010

24✔
1011
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1012
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1013
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1014
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1015
                (*E)(m.storageE.columns[index.table].Get(row))
24✔
1016
}
24✔
1017

1018
// HasAll return whether the given entity has all mapped components.
1019
func (m *Map5[A, B, C, D, E]) HasAll(entity Entity) bool {
54✔
1020
        if !m.world.Alive(entity) {
55✔
1021
                panic("can't check components of a dead entity")
1✔
1022
        }
1023
        index := m.world.storage.entities[entity.id]
53✔
1024
        return m.storageA.columns[index.table] != nil &&
53✔
1025
                m.storageB.columns[index.table] != nil &&
53✔
1026
                m.storageC.columns[index.table] != nil &&
53✔
1027
                m.storageD.columns[index.table] != nil &&
53✔
1028
                m.storageE.columns[index.table] != nil
53✔
1029
}
1030

1031
// Add the mapped components to the given entity.
1032
func (m *Map5[A, B, C, D, E]) Add(entity Entity, a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) {
13✔
1033
        if !m.world.Alive(entity) {
14✔
1034
                panic("can't add components to a dead entity")
1✔
1035
        }
1036
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1037
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1038
                unsafe.Pointer(a),
12✔
1039
                unsafe.Pointer(b),
12✔
1040
                unsafe.Pointer(c),
12✔
1041
                unsafe.Pointer(d),
12✔
1042
                unsafe.Pointer(e),
12✔
1043
        }, m.relations)
12✔
1044
}
1045

1046
// AddBatch adds the mapped components to all entities matching the given batch filter.
1047
func (m *Map5[A, B, C, D, E]) AddBatch(batch *Batch, a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) {
1✔
1048
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1049
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1050
                unsafe.Pointer(a),
1✔
1051
                unsafe.Pointer(b),
1✔
1052
                unsafe.Pointer(c),
1✔
1053
                unsafe.Pointer(d),
1✔
1054
                unsafe.Pointer(e),
1✔
1055
        }, m.relations, nil)
1✔
1056
}
1✔
1057

1058
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1059
// running the given function on each. The function can be nil.
1060
func (m *Map5[A, B, C, D, E]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E), rel ...RelationIndex) {
1✔
1061
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1062

1✔
1063
        var process func(tableID tableID, start, len int)
1✔
1064
        if fn != nil {
2✔
1065
                process = func(tableID tableID, start, len int) {
3✔
1066
                        table := &m.world.storage.tables[tableID]
2✔
1067
                        columnA := m.storageA.columns[tableID]
2✔
1068
                        columnB := m.storageB.columns[tableID]
2✔
1069
                        columnC := m.storageC.columns[tableID]
2✔
1070
                        columnD := m.storageD.columns[tableID]
2✔
1071
                        columnE := m.storageE.columns[tableID]
2✔
1072

2✔
1073
                        lock := m.world.lock()
2✔
1074
                        for i := range len {
26✔
1075
                                index := uintptr(start + i)
24✔
1076
                                fn(
24✔
1077
                                        table.GetEntity(index),
24✔
1078
                                        (*A)(columnA.Get(index)),
24✔
1079
                                        (*B)(columnB.Get(index)),
24✔
1080
                                        (*C)(columnC.Get(index)),
24✔
1081
                                        (*D)(columnD.Get(index)),
24✔
1082
                                        (*E)(columnE.Get(index)),
24✔
1083
                                )
24✔
1084
                        }
24✔
1085
                        m.world.unlock(lock)
2✔
1086
                }
1087
        }
1088
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1089
}
1090

1091
// Remove the mapped components from the given entity.
1092
func (m *Map5[A, B, C, D, E]) Remove(entity Entity) {
25✔
1093
        if !m.world.Alive(entity) {
26✔
1094
                panic("can't remove components from a dead entity")
1✔
1095
        }
1096
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1097
}
1098

1099
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1100
// running the given function on each. The function can be nil.
1101
func (m *Map5[A, B, C, D, E]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1102
        var process func(tableID tableID, start, len int)
2✔
1103
        if fn != nil {
3✔
1104
                process = func(tableID tableID, start, len int) {
3✔
1105
                        table := &m.world.storage.tables[tableID]
2✔
1106

2✔
1107
                        lock := m.world.lock()
2✔
1108
                        for i := range len {
26✔
1109
                                index := uintptr(start + i)
24✔
1110
                                fn(table.GetEntity(index))
24✔
1111
                        }
24✔
1112
                        m.world.unlock(lock)
2✔
1113
                }
1114
        }
1115
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1116
}
1117

1118
// GetRelation returns the relation target of an entity for the component at the given index.
1119
func (m *Map5[A, B, C, D, E]) GetRelation(entity Entity, index int) Entity {
3✔
1120
        if !m.world.Alive(entity) {
4✔
1121
                panic("can't get entity relation target for a dead entity")
1✔
1122
        }
1123
        return m.GetRelationUnchecked(entity, index)
2✔
1124
}
1125

1126
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
1127
// In contrast to [Map5.GetRelation], it does not check whether the entity is alive.
1128
// Can be used as an optimization when it is certain that the entity is alive.
1129
func (m *Map5[A, B, C, D, E]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
1130
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
1131
}
3✔
1132

1133
// SetRelations sets relation targets for the given entity.
1134
func (m *Map5[A, B, C, D, E]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
1135
        if !m.world.Alive(entity) {
3✔
1136
                panic("can't set entity relation targets for a dead entity")
1✔
1137
        }
1138
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1139
        m.world.setRelations(entity, m.relations)
1✔
1140
}
1141

1142
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
1143
func (m *Map5[A, B, C, D, E]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
1144
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1145

1✔
1146
        var process func(tableID tableID, start, len int)
1✔
1147
        if fn != nil {
2✔
1148
                process = func(tableID tableID, start, len int) {
2✔
1149
                        table := &m.world.storage.tables[tableID]
1✔
1150

1✔
1151
                        lock := m.world.lock()
1✔
1152
                        for i := range len {
25✔
1153
                                index := uintptr(start + i)
24✔
1154
                                fn(table.GetEntity(index))
24✔
1155
                        }
24✔
1156
                        m.world.unlock(lock)
1✔
1157
                }
1158
        }
1159
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
1160
}
1161

1162
// Map6 is a mapper to access 6 components of an entity.
1163
type Map6[A any, B any, C any, D any, E any, F any] struct {
1164
        world     *World
1165
        ids       []ID
1166
        storageA  *componentStorage
1167
        storageB  *componentStorage
1168
        storageC  *componentStorage
1169
        storageD  *componentStorage
1170
        storageE  *componentStorage
1171
        storageF  *componentStorage
1172
        relations []RelationID
1173
}
1174

1175
// NewMap6 creates a new [Map6].
1176
func NewMap6[A any, B any, C any, D any, E any, F any](world *World) Map6[A, B, C, D, E, F] {
13✔
1177
        ids := []ID{
13✔
1178
                ComponentID[A](world),
13✔
1179
                ComponentID[B](world),
13✔
1180
                ComponentID[C](world),
13✔
1181
                ComponentID[D](world),
13✔
1182
                ComponentID[E](world),
13✔
1183
                ComponentID[F](world),
13✔
1184
        }
13✔
1185
        return Map6[A, B, C, D, E, F]{
13✔
1186
                world:    world,
13✔
1187
                ids:      ids,
13✔
1188
                storageA: &world.storage.components[ids[0].id],
13✔
1189
                storageB: &world.storage.components[ids[1].id],
13✔
1190
                storageC: &world.storage.components[ids[2].id],
13✔
1191
                storageD: &world.storage.components[ids[3].id],
13✔
1192
                storageE: &world.storage.components[ids[4].id],
13✔
1193
                storageF: &world.storage.components[ids[5].id],
13✔
1194
        }
13✔
1195
}
13✔
1196

1197
// NewEntity creates a new entity with the mapped components.
1198
func (m *Map6[A, B, C, D, E, F]) NewEntity(a *A, b *B, c *C, d *D, e *E, f *F, rel ...RelationIndex) Entity {
127✔
1199
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
1200
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
1201
                unsafe.Pointer(a),
127✔
1202
                unsafe.Pointer(b),
127✔
1203
                unsafe.Pointer(c),
127✔
1204
                unsafe.Pointer(d),
127✔
1205
                unsafe.Pointer(e),
127✔
1206
                unsafe.Pointer(f),
127✔
1207
        }, m.relations)
127✔
1208
}
127✔
1209

1210
// NewBatch creates a batch of new entities with the mapped components.
1211
func (m *Map6[A, B, C, D, E, F]) NewBatch(count int, a *A, b *B, c *C, d *D, e *E, f *F, rel ...RelationIndex) {
3✔
1212
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1213
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
1214
                unsafe.Pointer(a),
3✔
1215
                unsafe.Pointer(b),
3✔
1216
                unsafe.Pointer(c),
3✔
1217
                unsafe.Pointer(d),
3✔
1218
                unsafe.Pointer(e),
3✔
1219
                unsafe.Pointer(f),
3✔
1220
        }, m.relations)
3✔
1221
}
3✔
1222

1223
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
1224
// The initializer function can be nil.
1225
func (m *Map6[A, B, C, D, E, F]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F), rel ...RelationIndex) {
1✔
1226
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1227
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
1228
        if fn == nil {
1✔
UNCOV
1229
                return
×
UNCOV
1230
        }
×
1231

1232
        table := &m.world.storage.tables[tableID]
1✔
1233
        columnA := m.storageA.columns[tableID]
1✔
1234
        columnB := m.storageB.columns[tableID]
1✔
1235
        columnC := m.storageC.columns[tableID]
1✔
1236
        columnD := m.storageD.columns[tableID]
1✔
1237
        columnE := m.storageE.columns[tableID]
1✔
1238
        columnF := m.storageF.columns[tableID]
1✔
1239

1✔
1240
        lock := m.world.lock()
1✔
1241
        for i := range count {
25✔
1242
                index := uintptr(start + i)
24✔
1243
                fn(
24✔
1244
                        table.GetEntity(index),
24✔
1245
                        (*A)(columnA.Get(index)),
24✔
1246
                        (*B)(columnB.Get(index)),
24✔
1247
                        (*C)(columnC.Get(index)),
24✔
1248
                        (*D)(columnD.Get(index)),
24✔
1249
                        (*E)(columnE.Get(index)),
24✔
1250
                        (*F)(columnF.Get(index)),
24✔
1251
                )
24✔
1252
        }
24✔
1253
        m.world.unlock(lock)
1✔
1254
}
1255

1256
// Get returns the mapped components for the given entity.
1257
func (m *Map6[A, B, C, D, E, F]) Get(entity Entity) (*A, *B, *C, *D, *E, *F) {
25✔
1258
        if !m.world.Alive(entity) {
26✔
1259
                panic("can't get components of a dead entity")
1✔
1260
        }
1261
        return m.GetUnchecked(entity)
24✔
1262
}
1263

1264
// GetUnchecked returns the mapped components for the given entity.
1265
// In contrast to [Map6.Get], it does not check whether the entity is alive.
1266
// Can be used as an optimization when it is certain that the entity is alive.
1267
func (m *Map6[A, B, C, D, E, F]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E, *F) {
24✔
1268
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1269
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1270
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1271
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1272
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1273
        m.world.storage.checkHasComponent(entity, m.ids[5])
24✔
1274

24✔
1275
        index := m.world.storage.entities[entity.id]
24✔
1276
        row := uintptr(index.row)
24✔
1277

24✔
1278
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1279
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1280
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1281
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1282
                (*E)(m.storageE.columns[index.table].Get(row)),
24✔
1283
                (*F)(m.storageF.columns[index.table].Get(row))
24✔
1284
}
24✔
1285

1286
// HasAll return whether the given entity has all mapped components.
1287
func (m *Map6[A, B, C, D, E, F]) HasAll(entity Entity) bool {
54✔
1288
        if !m.world.Alive(entity) {
55✔
1289
                panic("can't check components of a dead entity")
1✔
1290
        }
1291
        index := m.world.storage.entities[entity.id]
53✔
1292
        return m.storageA.columns[index.table] != nil &&
53✔
1293
                m.storageB.columns[index.table] != nil &&
53✔
1294
                m.storageC.columns[index.table] != nil &&
53✔
1295
                m.storageD.columns[index.table] != nil &&
53✔
1296
                m.storageE.columns[index.table] != nil &&
53✔
1297
                m.storageF.columns[index.table] != nil
53✔
1298
}
1299

1300
// Add the mapped components to the given entity.
1301
func (m *Map6[A, B, C, D, E, F]) Add(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, rel ...RelationIndex) {
13✔
1302
        if !m.world.Alive(entity) {
14✔
1303
                panic("can't add components to a dead entity")
1✔
1304
        }
1305
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1306
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1307
                unsafe.Pointer(a),
12✔
1308
                unsafe.Pointer(b),
12✔
1309
                unsafe.Pointer(c),
12✔
1310
                unsafe.Pointer(d),
12✔
1311
                unsafe.Pointer(e),
12✔
1312
                unsafe.Pointer(f),
12✔
1313
        }, m.relations)
12✔
1314
}
1315

1316
// AddBatch adds the mapped components to all entities matching the given batch filter.
1317
func (m *Map6[A, B, C, D, E, F]) AddBatch(batch *Batch, a *A, b *B, c *C, d *D, e *E, f *F, rel ...RelationIndex) {
1✔
1318
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1319
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1320
                unsafe.Pointer(a),
1✔
1321
                unsafe.Pointer(b),
1✔
1322
                unsafe.Pointer(c),
1✔
1323
                unsafe.Pointer(d),
1✔
1324
                unsafe.Pointer(e),
1✔
1325
                unsafe.Pointer(f),
1✔
1326
        }, m.relations, nil)
1✔
1327
}
1✔
1328

1329
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1330
// running the given function on each. The function can be nil.
1331
func (m *Map6[A, B, C, D, E, F]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F), rel ...RelationIndex) {
1✔
1332
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1333

1✔
1334
        var process func(tableID tableID, start, len int)
1✔
1335
        if fn != nil {
2✔
1336
                process = func(tableID tableID, start, len int) {
3✔
1337
                        table := &m.world.storage.tables[tableID]
2✔
1338
                        columnA := m.storageA.columns[tableID]
2✔
1339
                        columnB := m.storageB.columns[tableID]
2✔
1340
                        columnC := m.storageC.columns[tableID]
2✔
1341
                        columnD := m.storageD.columns[tableID]
2✔
1342
                        columnE := m.storageE.columns[tableID]
2✔
1343
                        columnF := m.storageF.columns[tableID]
2✔
1344

2✔
1345
                        lock := m.world.lock()
2✔
1346
                        for i := range len {
26✔
1347
                                index := uintptr(start + i)
24✔
1348
                                fn(
24✔
1349
                                        table.GetEntity(index),
24✔
1350
                                        (*A)(columnA.Get(index)),
24✔
1351
                                        (*B)(columnB.Get(index)),
24✔
1352
                                        (*C)(columnC.Get(index)),
24✔
1353
                                        (*D)(columnD.Get(index)),
24✔
1354
                                        (*E)(columnE.Get(index)),
24✔
1355
                                        (*F)(columnF.Get(index)),
24✔
1356
                                )
24✔
1357
                        }
24✔
1358
                        m.world.unlock(lock)
2✔
1359
                }
1360
        }
1361
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1362
}
1363

1364
// Remove the mapped components from the given entity.
1365
func (m *Map6[A, B, C, D, E, F]) Remove(entity Entity) {
25✔
1366
        if !m.world.Alive(entity) {
26✔
1367
                panic("can't remove components from a dead entity")
1✔
1368
        }
1369
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1370
}
1371

1372
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1373
// running the given function on each. The function can be nil.
1374
func (m *Map6[A, B, C, D, E, F]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1375
        var process func(tableID tableID, start, len int)
2✔
1376
        if fn != nil {
3✔
1377
                process = func(tableID tableID, start, len int) {
3✔
1378
                        table := &m.world.storage.tables[tableID]
2✔
1379

2✔
1380
                        lock := m.world.lock()
2✔
1381
                        for i := range len {
26✔
1382
                                index := uintptr(start + i)
24✔
1383
                                fn(table.GetEntity(index))
24✔
1384
                        }
24✔
1385
                        m.world.unlock(lock)
2✔
1386
                }
1387
        }
1388
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1389
}
1390

1391
// GetRelation returns the relation target of an entity for the component at the given index.
1392
func (m *Map6[A, B, C, D, E, F]) GetRelation(entity Entity, index int) Entity {
3✔
1393
        if !m.world.Alive(entity) {
4✔
1394
                panic("can't get entity relation target for a dead entity")
1✔
1395
        }
1396
        return m.GetRelationUnchecked(entity, index)
2✔
1397
}
1398

1399
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
1400
// In contrast to [Map6.GetRelation], it does not check whether the entity is alive.
1401
// Can be used as an optimization when it is certain that the entity is alive.
1402
func (m *Map6[A, B, C, D, E, F]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
1403
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
1404
}
3✔
1405

1406
// SetRelations sets relation targets for the given entity.
1407
func (m *Map6[A, B, C, D, E, F]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
1408
        if !m.world.Alive(entity) {
3✔
1409
                panic("can't set entity relation targets for a dead entity")
1✔
1410
        }
1411
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1412
        m.world.setRelations(entity, m.relations)
1✔
1413
}
1414

1415
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
1416
func (m *Map6[A, B, C, D, E, F]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
1417
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1418

1✔
1419
        var process func(tableID tableID, start, len int)
1✔
1420
        if fn != nil {
2✔
1421
                process = func(tableID tableID, start, len int) {
2✔
1422
                        table := &m.world.storage.tables[tableID]
1✔
1423

1✔
1424
                        lock := m.world.lock()
1✔
1425
                        for i := range len {
25✔
1426
                                index := uintptr(start + i)
24✔
1427
                                fn(table.GetEntity(index))
24✔
1428
                        }
24✔
1429
                        m.world.unlock(lock)
1✔
1430
                }
1431
        }
1432
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
1433
}
1434

1435
// Map7 is a mapper to access 7 components of an entity.
1436
type Map7[A any, B any, C any, D any, E any, F any, G any] struct {
1437
        world     *World
1438
        ids       []ID
1439
        storageA  *componentStorage
1440
        storageB  *componentStorage
1441
        storageC  *componentStorage
1442
        storageD  *componentStorage
1443
        storageE  *componentStorage
1444
        storageF  *componentStorage
1445
        storageG  *componentStorage
1446
        relations []RelationID
1447
}
1448

1449
// NewMap7 creates a new [Map7].
1450
func NewMap7[A any, B any, C any, D any, E any, F any, G any](world *World) Map7[A, B, C, D, E, F, G] {
13✔
1451
        ids := []ID{
13✔
1452
                ComponentID[A](world),
13✔
1453
                ComponentID[B](world),
13✔
1454
                ComponentID[C](world),
13✔
1455
                ComponentID[D](world),
13✔
1456
                ComponentID[E](world),
13✔
1457
                ComponentID[F](world),
13✔
1458
                ComponentID[G](world),
13✔
1459
        }
13✔
1460
        return Map7[A, B, C, D, E, F, G]{
13✔
1461
                world:    world,
13✔
1462
                ids:      ids,
13✔
1463
                storageA: &world.storage.components[ids[0].id],
13✔
1464
                storageB: &world.storage.components[ids[1].id],
13✔
1465
                storageC: &world.storage.components[ids[2].id],
13✔
1466
                storageD: &world.storage.components[ids[3].id],
13✔
1467
                storageE: &world.storage.components[ids[4].id],
13✔
1468
                storageF: &world.storage.components[ids[5].id],
13✔
1469
                storageG: &world.storage.components[ids[6].id],
13✔
1470
        }
13✔
1471
}
13✔
1472

1473
// NewEntity creates a new entity with the mapped components.
1474
func (m *Map7[A, B, C, D, E, F, G]) NewEntity(a *A, b *B, c *C, d *D, e *E, f *F, g *G, rel ...RelationIndex) Entity {
127✔
1475
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
1476
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
1477
                unsafe.Pointer(a),
127✔
1478
                unsafe.Pointer(b),
127✔
1479
                unsafe.Pointer(c),
127✔
1480
                unsafe.Pointer(d),
127✔
1481
                unsafe.Pointer(e),
127✔
1482
                unsafe.Pointer(f),
127✔
1483
                unsafe.Pointer(g),
127✔
1484
        }, m.relations)
127✔
1485
}
127✔
1486

1487
// NewBatch creates a batch of new entities with the mapped components.
1488
func (m *Map7[A, B, C, D, E, F, G]) NewBatch(count int, a *A, b *B, c *C, d *D, e *E, f *F, g *G, rel ...RelationIndex) {
3✔
1489
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1490
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
1491
                unsafe.Pointer(a),
3✔
1492
                unsafe.Pointer(b),
3✔
1493
                unsafe.Pointer(c),
3✔
1494
                unsafe.Pointer(d),
3✔
1495
                unsafe.Pointer(e),
3✔
1496
                unsafe.Pointer(f),
3✔
1497
                unsafe.Pointer(g),
3✔
1498
        }, m.relations)
3✔
1499
}
3✔
1500

1501
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
1502
// The initializer function can be nil.
1503
func (m *Map7[A, B, C, D, E, F, G]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, g *G), rel ...RelationIndex) {
1✔
1504
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1505
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
1506
        if fn == nil {
1✔
UNCOV
1507
                return
×
UNCOV
1508
        }
×
1509

1510
        table := &m.world.storage.tables[tableID]
1✔
1511
        columnA := m.storageA.columns[tableID]
1✔
1512
        columnB := m.storageB.columns[tableID]
1✔
1513
        columnC := m.storageC.columns[tableID]
1✔
1514
        columnD := m.storageD.columns[tableID]
1✔
1515
        columnE := m.storageE.columns[tableID]
1✔
1516
        columnF := m.storageF.columns[tableID]
1✔
1517
        columnG := m.storageG.columns[tableID]
1✔
1518

1✔
1519
        lock := m.world.lock()
1✔
1520
        for i := range count {
25✔
1521
                index := uintptr(start + i)
24✔
1522
                fn(
24✔
1523
                        table.GetEntity(index),
24✔
1524
                        (*A)(columnA.Get(index)),
24✔
1525
                        (*B)(columnB.Get(index)),
24✔
1526
                        (*C)(columnC.Get(index)),
24✔
1527
                        (*D)(columnD.Get(index)),
24✔
1528
                        (*E)(columnE.Get(index)),
24✔
1529
                        (*F)(columnF.Get(index)),
24✔
1530
                        (*G)(columnG.Get(index)),
24✔
1531
                )
24✔
1532
        }
24✔
1533
        m.world.unlock(lock)
1✔
1534
}
1535

1536
// Get returns the mapped components for the given entity.
1537
func (m *Map7[A, B, C, D, E, F, G]) Get(entity Entity) (*A, *B, *C, *D, *E, *F, *G) {
25✔
1538
        if !m.world.Alive(entity) {
26✔
1539
                panic("can't get components of a dead entity")
1✔
1540
        }
1541
        return m.GetUnchecked(entity)
24✔
1542
}
1543

1544
// GetUnchecked returns the mapped components for the given entity.
1545
// In contrast to [Map7.Get], it does not check whether the entity is alive.
1546
// Can be used as an optimization when it is certain that the entity is alive.
1547
func (m *Map7[A, B, C, D, E, F, G]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E, *F, *G) {
24✔
1548
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1549
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1550
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1551
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1552
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1553
        m.world.storage.checkHasComponent(entity, m.ids[5])
24✔
1554
        m.world.storage.checkHasComponent(entity, m.ids[6])
24✔
1555

24✔
1556
        index := m.world.storage.entities[entity.id]
24✔
1557
        row := uintptr(index.row)
24✔
1558

24✔
1559
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1560
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1561
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1562
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1563
                (*E)(m.storageE.columns[index.table].Get(row)),
24✔
1564
                (*F)(m.storageF.columns[index.table].Get(row)),
24✔
1565
                (*G)(m.storageG.columns[index.table].Get(row))
24✔
1566
}
24✔
1567

1568
// HasAll return whether the given entity has all mapped components.
1569
func (m *Map7[A, B, C, D, E, F, G]) HasAll(entity Entity) bool {
54✔
1570
        if !m.world.Alive(entity) {
55✔
1571
                panic("can't check components of a dead entity")
1✔
1572
        }
1573
        index := m.world.storage.entities[entity.id]
53✔
1574
        return m.storageA.columns[index.table] != nil &&
53✔
1575
                m.storageB.columns[index.table] != nil &&
53✔
1576
                m.storageC.columns[index.table] != nil &&
53✔
1577
                m.storageD.columns[index.table] != nil &&
53✔
1578
                m.storageE.columns[index.table] != nil &&
53✔
1579
                m.storageF.columns[index.table] != nil &&
53✔
1580
                m.storageG.columns[index.table] != nil
53✔
1581
}
1582

1583
// Add the mapped components to the given entity.
1584
func (m *Map7[A, B, C, D, E, F, G]) Add(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, g *G, rel ...RelationIndex) {
13✔
1585
        if !m.world.Alive(entity) {
14✔
1586
                panic("can't add components to a dead entity")
1✔
1587
        }
1588
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1589
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1590
                unsafe.Pointer(a),
12✔
1591
                unsafe.Pointer(b),
12✔
1592
                unsafe.Pointer(c),
12✔
1593
                unsafe.Pointer(d),
12✔
1594
                unsafe.Pointer(e),
12✔
1595
                unsafe.Pointer(f),
12✔
1596
                unsafe.Pointer(g),
12✔
1597
        }, m.relations)
12✔
1598
}
1599

1600
// AddBatch adds the mapped components to all entities matching the given batch filter.
1601
func (m *Map7[A, B, C, D, E, F, G]) AddBatch(batch *Batch, a *A, b *B, c *C, d *D, e *E, f *F, g *G, rel ...RelationIndex) {
1✔
1602
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1603
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1604
                unsafe.Pointer(a),
1✔
1605
                unsafe.Pointer(b),
1✔
1606
                unsafe.Pointer(c),
1✔
1607
                unsafe.Pointer(d),
1✔
1608
                unsafe.Pointer(e),
1✔
1609
                unsafe.Pointer(f),
1✔
1610
                unsafe.Pointer(g),
1✔
1611
        }, m.relations, nil)
1✔
1612
}
1✔
1613

1614
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1615
// running the given function on each. The function can be nil.
1616
func (m *Map7[A, B, C, D, E, F, G]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, g *G), rel ...RelationIndex) {
1✔
1617
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1618

1✔
1619
        var process func(tableID tableID, start, len int)
1✔
1620
        if fn != nil {
2✔
1621
                process = func(tableID tableID, start, len int) {
3✔
1622
                        table := &m.world.storage.tables[tableID]
2✔
1623
                        columnA := m.storageA.columns[tableID]
2✔
1624
                        columnB := m.storageB.columns[tableID]
2✔
1625
                        columnC := m.storageC.columns[tableID]
2✔
1626
                        columnD := m.storageD.columns[tableID]
2✔
1627
                        columnE := m.storageE.columns[tableID]
2✔
1628
                        columnF := m.storageF.columns[tableID]
2✔
1629
                        columnG := m.storageG.columns[tableID]
2✔
1630

2✔
1631
                        lock := m.world.lock()
2✔
1632
                        for i := range len {
26✔
1633
                                index := uintptr(start + i)
24✔
1634
                                fn(
24✔
1635
                                        table.GetEntity(index),
24✔
1636
                                        (*A)(columnA.Get(index)),
24✔
1637
                                        (*B)(columnB.Get(index)),
24✔
1638
                                        (*C)(columnC.Get(index)),
24✔
1639
                                        (*D)(columnD.Get(index)),
24✔
1640
                                        (*E)(columnE.Get(index)),
24✔
1641
                                        (*F)(columnF.Get(index)),
24✔
1642
                                        (*G)(columnG.Get(index)),
24✔
1643
                                )
24✔
1644
                        }
24✔
1645
                        m.world.unlock(lock)
2✔
1646
                }
1647
        }
1648
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1649
}
1650

1651
// Remove the mapped components from the given entity.
1652
func (m *Map7[A, B, C, D, E, F, G]) Remove(entity Entity) {
25✔
1653
        if !m.world.Alive(entity) {
26✔
1654
                panic("can't remove components from a dead entity")
1✔
1655
        }
1656
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1657
}
1658

1659
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1660
// running the given function on each. The function can be nil.
1661
func (m *Map7[A, B, C, D, E, F, G]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1662
        var process func(tableID tableID, start, len int)
2✔
1663
        if fn != nil {
3✔
1664
                process = func(tableID tableID, start, len int) {
3✔
1665
                        table := &m.world.storage.tables[tableID]
2✔
1666

2✔
1667
                        lock := m.world.lock()
2✔
1668
                        for i := range len {
26✔
1669
                                index := uintptr(start + i)
24✔
1670
                                fn(table.GetEntity(index))
24✔
1671
                        }
24✔
1672
                        m.world.unlock(lock)
2✔
1673
                }
1674
        }
1675
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1676
}
1677

1678
// GetRelation returns the relation target of an entity for the component at the given index.
1679
func (m *Map7[A, B, C, D, E, F, G]) GetRelation(entity Entity, index int) Entity {
3✔
1680
        if !m.world.Alive(entity) {
4✔
1681
                panic("can't get entity relation target for a dead entity")
1✔
1682
        }
1683
        return m.GetRelationUnchecked(entity, index)
2✔
1684
}
1685

1686
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
1687
// In contrast to [Map7.GetRelation], it does not check whether the entity is alive.
1688
// Can be used as an optimization when it is certain that the entity is alive.
1689
func (m *Map7[A, B, C, D, E, F, G]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
1690
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
1691
}
3✔
1692

1693
// SetRelations sets relation targets for the given entity.
1694
func (m *Map7[A, B, C, D, E, F, G]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
1695
        if !m.world.Alive(entity) {
3✔
1696
                panic("can't set entity relation targets for a dead entity")
1✔
1697
        }
1698
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1699
        m.world.setRelations(entity, m.relations)
1✔
1700
}
1701

1702
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
1703
func (m *Map7[A, B, C, D, E, F, G]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
1704
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1705

1✔
1706
        var process func(tableID tableID, start, len int)
1✔
1707
        if fn != nil {
2✔
1708
                process = func(tableID tableID, start, len int) {
2✔
1709
                        table := &m.world.storage.tables[tableID]
1✔
1710

1✔
1711
                        lock := m.world.lock()
1✔
1712
                        for i := range len {
25✔
1713
                                index := uintptr(start + i)
24✔
1714
                                fn(table.GetEntity(index))
24✔
1715
                        }
24✔
1716
                        m.world.unlock(lock)
1✔
1717
                }
1718
        }
1719
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
1720
}
1721

1722
// Map8 is a mapper to access 8 components of an entity.
1723
type Map8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1724
        world     *World
1725
        ids       []ID
1726
        storageA  *componentStorage
1727
        storageB  *componentStorage
1728
        storageC  *componentStorage
1729
        storageD  *componentStorage
1730
        storageE  *componentStorage
1731
        storageF  *componentStorage
1732
        storageG  *componentStorage
1733
        storageH  *componentStorage
1734
        relations []RelationID
1735
}
1736

1737
// NewMap8 creates a new [Map8].
1738
func NewMap8[A any, B any, C any, D any, E any, F any, G any, H any](world *World) Map8[A, B, C, D, E, F, G, H] {
13✔
1739
        ids := []ID{
13✔
1740
                ComponentID[A](world),
13✔
1741
                ComponentID[B](world),
13✔
1742
                ComponentID[C](world),
13✔
1743
                ComponentID[D](world),
13✔
1744
                ComponentID[E](world),
13✔
1745
                ComponentID[F](world),
13✔
1746
                ComponentID[G](world),
13✔
1747
                ComponentID[H](world),
13✔
1748
        }
13✔
1749
        return Map8[A, B, C, D, E, F, G, H]{
13✔
1750
                world:    world,
13✔
1751
                ids:      ids,
13✔
1752
                storageA: &world.storage.components[ids[0].id],
13✔
1753
                storageB: &world.storage.components[ids[1].id],
13✔
1754
                storageC: &world.storage.components[ids[2].id],
13✔
1755
                storageD: &world.storage.components[ids[3].id],
13✔
1756
                storageE: &world.storage.components[ids[4].id],
13✔
1757
                storageF: &world.storage.components[ids[5].id],
13✔
1758
                storageG: &world.storage.components[ids[6].id],
13✔
1759
                storageH: &world.storage.components[ids[7].id],
13✔
1760
        }
13✔
1761
}
13✔
1762

1763
// NewEntity creates a new entity with the mapped components.
1764
func (m *Map8[A, B, C, D, E, F, G, H]) NewEntity(a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H, rel ...RelationIndex) Entity {
127✔
1765
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
1766
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
1767
                unsafe.Pointer(a),
127✔
1768
                unsafe.Pointer(b),
127✔
1769
                unsafe.Pointer(c),
127✔
1770
                unsafe.Pointer(d),
127✔
1771
                unsafe.Pointer(e),
127✔
1772
                unsafe.Pointer(f),
127✔
1773
                unsafe.Pointer(g),
127✔
1774
                unsafe.Pointer(h),
127✔
1775
        }, m.relations)
127✔
1776
}
127✔
1777

1778
// NewBatch creates a batch of new entities with the mapped components.
1779
func (m *Map8[A, B, C, D, E, F, G, H]) NewBatch(count int, a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H, rel ...RelationIndex) {
3✔
1780
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1781
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
1782
                unsafe.Pointer(a),
3✔
1783
                unsafe.Pointer(b),
3✔
1784
                unsafe.Pointer(c),
3✔
1785
                unsafe.Pointer(d),
3✔
1786
                unsafe.Pointer(e),
3✔
1787
                unsafe.Pointer(f),
3✔
1788
                unsafe.Pointer(g),
3✔
1789
                unsafe.Pointer(h),
3✔
1790
        }, m.relations)
3✔
1791
}
3✔
1792

1793
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
1794
// The initializer function can be nil.
1795
func (m *Map8[A, B, C, D, E, F, G, H]) NewBatchFn(count int, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H), rel ...RelationIndex) {
1✔
1796
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1797
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
1798
        if fn == nil {
1✔
UNCOV
1799
                return
×
UNCOV
1800
        }
×
1801

1802
        table := &m.world.storage.tables[tableID]
1✔
1803
        columnA := m.storageA.columns[tableID]
1✔
1804
        columnB := m.storageB.columns[tableID]
1✔
1805
        columnC := m.storageC.columns[tableID]
1✔
1806
        columnD := m.storageD.columns[tableID]
1✔
1807
        columnE := m.storageE.columns[tableID]
1✔
1808
        columnF := m.storageF.columns[tableID]
1✔
1809
        columnG := m.storageG.columns[tableID]
1✔
1810
        columnH := m.storageH.columns[tableID]
1✔
1811

1✔
1812
        lock := m.world.lock()
1✔
1813
        for i := range count {
25✔
1814
                index := uintptr(start + i)
24✔
1815
                fn(
24✔
1816
                        table.GetEntity(index),
24✔
1817
                        (*A)(columnA.Get(index)),
24✔
1818
                        (*B)(columnB.Get(index)),
24✔
1819
                        (*C)(columnC.Get(index)),
24✔
1820
                        (*D)(columnD.Get(index)),
24✔
1821
                        (*E)(columnE.Get(index)),
24✔
1822
                        (*F)(columnF.Get(index)),
24✔
1823
                        (*G)(columnG.Get(index)),
24✔
1824
                        (*H)(columnH.Get(index)),
24✔
1825
                )
24✔
1826
        }
24✔
1827
        m.world.unlock(lock)
1✔
1828
}
1829

1830
// Get returns the mapped components for the given entity.
1831
func (m *Map8[A, B, C, D, E, F, G, H]) Get(entity Entity) (*A, *B, *C, *D, *E, *F, *G, *H) {
25✔
1832
        if !m.world.Alive(entity) {
26✔
1833
                panic("can't get components of a dead entity")
1✔
1834
        }
1835
        return m.GetUnchecked(entity)
24✔
1836
}
1837

1838
// GetUnchecked returns the mapped components for the given entity.
1839
// In contrast to [Map8.Get], it does not check whether the entity is alive.
1840
// Can be used as an optimization when it is certain that the entity is alive.
1841
func (m *Map8[A, B, C, D, E, F, G, H]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E, *F, *G, *H) {
24✔
1842
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1843
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1844
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1845
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1846
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1847
        m.world.storage.checkHasComponent(entity, m.ids[5])
24✔
1848
        m.world.storage.checkHasComponent(entity, m.ids[6])
24✔
1849
        m.world.storage.checkHasComponent(entity, m.ids[7])
24✔
1850

24✔
1851
        index := m.world.storage.entities[entity.id]
24✔
1852
        row := uintptr(index.row)
24✔
1853

24✔
1854
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1855
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1856
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1857
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1858
                (*E)(m.storageE.columns[index.table].Get(row)),
24✔
1859
                (*F)(m.storageF.columns[index.table].Get(row)),
24✔
1860
                (*G)(m.storageG.columns[index.table].Get(row)),
24✔
1861
                (*H)(m.storageH.columns[index.table].Get(row))
24✔
1862
}
24✔
1863

1864
// HasAll return whether the given entity has all mapped components.
1865
func (m *Map8[A, B, C, D, E, F, G, H]) HasAll(entity Entity) bool {
54✔
1866
        if !m.world.Alive(entity) {
55✔
1867
                panic("can't check components of a dead entity")
1✔
1868
        }
1869
        index := m.world.storage.entities[entity.id]
53✔
1870
        return m.storageA.columns[index.table] != nil &&
53✔
1871
                m.storageB.columns[index.table] != nil &&
53✔
1872
                m.storageC.columns[index.table] != nil &&
53✔
1873
                m.storageD.columns[index.table] != nil &&
53✔
1874
                m.storageE.columns[index.table] != nil &&
53✔
1875
                m.storageF.columns[index.table] != nil &&
53✔
1876
                m.storageG.columns[index.table] != nil &&
53✔
1877
                m.storageH.columns[index.table] != nil
53✔
1878
}
1879

1880
// Add the mapped components to the given entity.
1881
func (m *Map8[A, B, C, D, E, F, G, H]) Add(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H, rel ...RelationIndex) {
13✔
1882
        if !m.world.Alive(entity) {
14✔
1883
                panic("can't add components to a dead entity")
1✔
1884
        }
1885
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1886
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1887
                unsafe.Pointer(a),
12✔
1888
                unsafe.Pointer(b),
12✔
1889
                unsafe.Pointer(c),
12✔
1890
                unsafe.Pointer(d),
12✔
1891
                unsafe.Pointer(e),
12✔
1892
                unsafe.Pointer(f),
12✔
1893
                unsafe.Pointer(g),
12✔
1894
                unsafe.Pointer(h),
12✔
1895
        }, m.relations)
12✔
1896
}
1897

1898
// AddBatch adds the mapped components to all entities matching the given batch filter.
1899
func (m *Map8[A, B, C, D, E, F, G, H]) AddBatch(batch *Batch, a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H, rel ...RelationIndex) {
1✔
1900
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1901
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1902
                unsafe.Pointer(a),
1✔
1903
                unsafe.Pointer(b),
1✔
1904
                unsafe.Pointer(c),
1✔
1905
                unsafe.Pointer(d),
1✔
1906
                unsafe.Pointer(e),
1✔
1907
                unsafe.Pointer(f),
1✔
1908
                unsafe.Pointer(g),
1✔
1909
                unsafe.Pointer(h),
1✔
1910
        }, m.relations, nil)
1✔
1911
}
1✔
1912

1913
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1914
// running the given function on each. The function can be nil.
1915
func (m *Map8[A, B, C, D, E, F, G, H]) AddBatchFn(batch *Batch, fn func(entity Entity, a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H), rel ...RelationIndex) {
1✔
1916
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1917

1✔
1918
        var process func(tableID tableID, start, len int)
1✔
1919
        if fn != nil {
2✔
1920
                process = func(tableID tableID, start, len int) {
3✔
1921
                        table := &m.world.storage.tables[tableID]
2✔
1922
                        columnA := m.storageA.columns[tableID]
2✔
1923
                        columnB := m.storageB.columns[tableID]
2✔
1924
                        columnC := m.storageC.columns[tableID]
2✔
1925
                        columnD := m.storageD.columns[tableID]
2✔
1926
                        columnE := m.storageE.columns[tableID]
2✔
1927
                        columnF := m.storageF.columns[tableID]
2✔
1928
                        columnG := m.storageG.columns[tableID]
2✔
1929
                        columnH := m.storageH.columns[tableID]
2✔
1930

2✔
1931
                        lock := m.world.lock()
2✔
1932
                        for i := range len {
26✔
1933
                                index := uintptr(start + i)
24✔
1934
                                fn(
24✔
1935
                                        table.GetEntity(index),
24✔
1936
                                        (*A)(columnA.Get(index)),
24✔
1937
                                        (*B)(columnB.Get(index)),
24✔
1938
                                        (*C)(columnC.Get(index)),
24✔
1939
                                        (*D)(columnD.Get(index)),
24✔
1940
                                        (*E)(columnE.Get(index)),
24✔
1941
                                        (*F)(columnF.Get(index)),
24✔
1942
                                        (*G)(columnG.Get(index)),
24✔
1943
                                        (*H)(columnH.Get(index)),
24✔
1944
                                )
24✔
1945
                        }
24✔
1946
                        m.world.unlock(lock)
2✔
1947
                }
1948
        }
1949
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1950
}
1951

1952
// Remove the mapped components from the given entity.
1953
func (m *Map8[A, B, C, D, E, F, G, H]) Remove(entity Entity) {
25✔
1954
        if !m.world.Alive(entity) {
26✔
1955
                panic("can't remove components from a dead entity")
1✔
1956
        }
1957
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1958
}
1959

1960
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1961
// running the given function on each. The function can be nil.
1962
func (m *Map8[A, B, C, D, E, F, G, H]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1963
        var process func(tableID tableID, start, len int)
2✔
1964
        if fn != nil {
3✔
1965
                process = func(tableID tableID, start, len int) {
3✔
1966
                        table := &m.world.storage.tables[tableID]
2✔
1967

2✔
1968
                        lock := m.world.lock()
2✔
1969
                        for i := range len {
26✔
1970
                                index := uintptr(start + i)
24✔
1971
                                fn(table.GetEntity(index))
24✔
1972
                        }
24✔
1973
                        m.world.unlock(lock)
2✔
1974
                }
1975
        }
1976
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1977
}
1978

1979
// GetRelation returns the relation target of an entity for the component at the given index.
1980
func (m *Map8[A, B, C, D, E, F, G, H]) GetRelation(entity Entity, index int) Entity {
3✔
1981
        if !m.world.Alive(entity) {
4✔
1982
                panic("can't get entity relation target for a dead entity")
1✔
1983
        }
1984
        return m.GetRelationUnchecked(entity, index)
2✔
1985
}
1986

1987
// GetRelationUnchecked returns the relation target of an entity for the component at the given index.
1988
// In contrast to [Map8.GetRelation], it does not check whether the entity is alive.
1989
// Can be used as an optimization when it is certain that the entity is alive.
1990
func (m *Map8[A, B, C, D, E, F, G, H]) GetRelationUnchecked(entity Entity, index int) Entity {
3✔
1991
        return m.world.storage.getRelation(entity, m.ids[index])
3✔
1992
}
3✔
1993

1994
// SetRelations sets relation targets for the given entity.
1995
func (m *Map8[A, B, C, D, E, F, G, H]) SetRelations(entity Entity, rel ...RelationIndex) {
2✔
1996
        if !m.world.Alive(entity) {
3✔
1997
                panic("can't set entity relation targets for a dead entity")
1✔
1998
        }
1999
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
2000
        m.world.setRelations(entity, m.relations)
1✔
2001
}
2002

2003
// SetRelationsBatch sets relation targets for all entities matching the given batch filter.
2004
func (m *Map8[A, B, C, D, E, F, G, H]) SetRelationsBatch(batch *Batch, fn func(entity Entity), rel ...RelationIndex) {
1✔
2005
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
2006

1✔
2007
        var process func(tableID tableID, start, len int)
1✔
2008
        if fn != nil {
2✔
2009
                process = func(tableID tableID, start, len int) {
2✔
2010
                        table := &m.world.storage.tables[tableID]
1✔
2011

1✔
2012
                        lock := m.world.lock()
1✔
2013
                        for i := range len {
25✔
2014
                                index := uintptr(start + i)
24✔
2015
                                fn(table.GetEntity(index))
24✔
2016
                        }
24✔
2017
                        m.world.unlock(lock)
1✔
2018
                }
2019
        }
2020
        m.world.setRelationsBatch(batch, m.relations, process)
1✔
2021
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc