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

mlange-42 / ark / 13639891374

03 Mar 2025 08:33PM CUT coverage: 98.504%. Remained the same
13639891374

Pull #117

github

web-flow
Merge f2543287f into 14baa6b40
Pull Request #117: Extend filter documentation

5730 of 5817 relevant lines covered (98.5%)

34452.31 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] {
67✔
17
        ids := []ID{
67✔
18
                ComponentID[A](world),
67✔
19
        }
67✔
20
        return Map1[A]{
67✔
21
                world:    world,
67✔
22
                ids:      ids,
67✔
23
                storageA: &world.storage.components[ids[0].id],
67✔
24
        }
67✔
25
}
67✔
26

27
// NewEntity creates a new entity with the mapped components.
28
func (m *Map1[A]) NewEntity(a *A, rel ...RelationIndex) Entity {
131✔
29
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
131✔
30
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
131✔
31
                unsafe.Pointer(a),
131✔
32
        }, m.relations)
131✔
33
}
131✔
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) {
4✔
37
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
4✔
38
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
4✔
39
                unsafe.Pointer(a),
4✔
40
        }, m.relations)
4✔
41
}
4✔
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) {
3✔
183
        // alive check is done in World.setRelations
3✔
184
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
185
        m.world.setRelations(entity, m.relations)
3✔
186
}
3✔
187

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

396
// SetRelations sets relation targets for the given entity.
397
func (m *Map2[A, B]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
398
        // alive check is done in World.setRelations
3✔
399
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
400
        m.world.setRelations(entity, m.relations)
3✔
401
}
3✔
402

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

2✔
407
        var process func(tableID tableID, start, len int)
2✔
408
        if fn != nil {
4✔
409
                process = func(tableID tableID, start, len int) {
3✔
410
                        table := &m.world.storage.tables[tableID]
1✔
411

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

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

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

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

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

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

478
        table := &m.world.storage.tables[tableID]
1✔
479
        columnA := m.storageA.columns[tableID]
1✔
480
        columnB := m.storageB.columns[tableID]
1✔
481
        columnC := m.storageC.columns[tableID]
1✔
482

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

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

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

24✔
512
        index := m.world.storage.entities[entity.id]
24✔
513
        row := uintptr(index.row)
24✔
514

24✔
515
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
516
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
517
                (*C)(m.storageC.columns[index.table].Get(row))
24✔
518
}
24✔
519

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

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

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

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

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

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

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

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

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

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

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

625
// SetRelations sets relation targets for the given entity.
626
func (m *Map3[A, B, C]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
627
        // alive check is done in World.setRelations
3✔
628
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
629
        m.world.setRelations(entity, m.relations)
3✔
630
}
3✔
631

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

2✔
636
        var process func(tableID tableID, start, len int)
2✔
637
        if fn != nil {
4✔
638
                process = func(tableID tableID, start, len int) {
3✔
639
                        table := &m.world.storage.tables[tableID]
1✔
640

1✔
641
                        lock := m.world.lock()
1✔
642
                        for i := range len {
25✔
643
                                index := uintptr(start + i)
24✔
644
                                fn(table.GetEntity(index))
24✔
645
                        }
24✔
646
                        m.world.unlock(lock)
1✔
647
                }
648
        }
649
        m.world.setRelationsBatch(batch, m.relations, process)
2✔
650
}
651

652
// Map4 is a mapper to access 4 components of an entity.
653
type Map4[A any, B any, C any, D any] struct {
654
        world     *World
655
        ids       []ID
656
        storageA  *componentStorage
657
        storageB  *componentStorage
658
        storageC  *componentStorage
659
        storageD  *componentStorage
660
        relations []RelationID
661
}
662

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

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

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

703
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
704
// The initializer function can be nil.
705
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✔
706
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
707
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
708
        if fn == nil {
1✔
709
                return
×
710
        }
×
711

712
        table := &m.world.storage.tables[tableID]
1✔
713
        columnA := m.storageA.columns[tableID]
1✔
714
        columnB := m.storageB.columns[tableID]
1✔
715
        columnC := m.storageC.columns[tableID]
1✔
716
        columnD := m.storageD.columns[tableID]
1✔
717

1✔
718
        lock := m.world.lock()
1✔
719
        for i := range count {
25✔
720
                index := uintptr(start + i)
24✔
721
                fn(
24✔
722
                        table.GetEntity(index),
24✔
723
                        (*A)(columnA.Get(index)),
24✔
724
                        (*B)(columnB.Get(index)),
24✔
725
                        (*C)(columnC.Get(index)),
24✔
726
                        (*D)(columnD.Get(index)),
24✔
727
                )
24✔
728
        }
24✔
729
        m.world.unlock(lock)
1✔
730
}
731

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

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

24✔
749
        index := m.world.storage.entities[entity.id]
24✔
750
        row := uintptr(index.row)
24✔
751

24✔
752
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
753
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
754
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
755
                (*D)(m.storageD.columns[index.table].Get(row))
24✔
756
}
24✔
757

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

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

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

795
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
796
// running the given function on each. The function can be nil.
797
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✔
798
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
799

1✔
800
        var process func(tableID tableID, start, len int)
1✔
801
        if fn != nil {
2✔
802
                process = func(tableID tableID, start, len int) {
3✔
803
                        table := &m.world.storage.tables[tableID]
2✔
804
                        columnA := m.storageA.columns[tableID]
2✔
805
                        columnB := m.storageB.columns[tableID]
2✔
806
                        columnC := m.storageC.columns[tableID]
2✔
807
                        columnD := m.storageD.columns[tableID]
2✔
808

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

826
// Remove the mapped components from the given entity.
827
func (m *Map4[A, B, C, D]) Remove(entity Entity) {
25✔
828
        if !m.world.Alive(entity) {
26✔
829
                panic("can't remove components from a dead entity")
1✔
830
        }
831
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
832
}
833

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

2✔
842
                        lock := m.world.lock()
2✔
843
                        for i := range len {
26✔
844
                                index := uintptr(start + i)
24✔
845
                                fn(table.GetEntity(index))
24✔
846
                        }
24✔
847
                        m.world.unlock(lock)
2✔
848
                }
849
        }
850
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
851
}
852

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

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

868
// SetRelations sets relation targets for the given entity.
869
func (m *Map4[A, B, C, D]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
870
        // alive check is done in World.setRelations
3✔
871
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
872
        m.world.setRelations(entity, m.relations)
3✔
873
}
3✔
874

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

2✔
879
        var process func(tableID tableID, start, len int)
2✔
880
        if fn != nil {
4✔
881
                process = func(tableID tableID, start, len int) {
3✔
882
                        table := &m.world.storage.tables[tableID]
1✔
883

1✔
884
                        lock := m.world.lock()
1✔
885
                        for i := range len {
25✔
886
                                index := uintptr(start + i)
24✔
887
                                fn(table.GetEntity(index))
24✔
888
                        }
24✔
889
                        m.world.unlock(lock)
1✔
890
                }
891
        }
892
        m.world.setRelationsBatch(batch, m.relations, process)
2✔
893
}
894

895
// Map5 is a mapper to access 5 components of an entity.
896
type Map5[A any, B any, C any, D any, E any] struct {
897
        world     *World
898
        ids       []ID
899
        storageA  *componentStorage
900
        storageB  *componentStorage
901
        storageC  *componentStorage
902
        storageD  *componentStorage
903
        storageE  *componentStorage
904
        relations []RelationID
905
}
906

907
// NewMap5 creates a new [Map5].
908
func NewMap5[A any, B any, C any, D any, E any](world *World) Map5[A, B, C, D, E] {
13✔
909
        ids := []ID{
13✔
910
                ComponentID[A](world),
13✔
911
                ComponentID[B](world),
13✔
912
                ComponentID[C](world),
13✔
913
                ComponentID[D](world),
13✔
914
                ComponentID[E](world),
13✔
915
        }
13✔
916
        return Map5[A, B, C, D, E]{
13✔
917
                world:    world,
13✔
918
                ids:      ids,
13✔
919
                storageA: &world.storage.components[ids[0].id],
13✔
920
                storageB: &world.storage.components[ids[1].id],
13✔
921
                storageC: &world.storage.components[ids[2].id],
13✔
922
                storageD: &world.storage.components[ids[3].id],
13✔
923
                storageE: &world.storage.components[ids[4].id],
13✔
924
        }
13✔
925
}
13✔
926

927
// NewEntity creates a new entity with the mapped components.
928
func (m *Map5[A, B, C, D, E]) NewEntity(a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) Entity {
127✔
929
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
930
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
931
                unsafe.Pointer(a),
127✔
932
                unsafe.Pointer(b),
127✔
933
                unsafe.Pointer(c),
127✔
934
                unsafe.Pointer(d),
127✔
935
                unsafe.Pointer(e),
127✔
936
        }, m.relations)
127✔
937
}
127✔
938

939
// NewBatch creates a batch of new entities with the mapped components.
940
func (m *Map5[A, B, C, D, E]) NewBatch(count int, a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) {
3✔
941
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
942
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
943
                unsafe.Pointer(a),
3✔
944
                unsafe.Pointer(b),
3✔
945
                unsafe.Pointer(c),
3✔
946
                unsafe.Pointer(d),
3✔
947
                unsafe.Pointer(e),
3✔
948
        }, m.relations)
3✔
949
}
3✔
950

951
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
952
// The initializer function can be nil.
953
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✔
954
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
955
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
956
        if fn == nil {
1✔
957
                return
×
958
        }
×
959

960
        table := &m.world.storage.tables[tableID]
1✔
961
        columnA := m.storageA.columns[tableID]
1✔
962
        columnB := m.storageB.columns[tableID]
1✔
963
        columnC := m.storageC.columns[tableID]
1✔
964
        columnD := m.storageD.columns[tableID]
1✔
965
        columnE := m.storageE.columns[tableID]
1✔
966

1✔
967
        lock := m.world.lock()
1✔
968
        for i := range count {
25✔
969
                index := uintptr(start + i)
24✔
970
                fn(
24✔
971
                        table.GetEntity(index),
24✔
972
                        (*A)(columnA.Get(index)),
24✔
973
                        (*B)(columnB.Get(index)),
24✔
974
                        (*C)(columnC.Get(index)),
24✔
975
                        (*D)(columnD.Get(index)),
24✔
976
                        (*E)(columnE.Get(index)),
24✔
977
                )
24✔
978
        }
24✔
979
        m.world.unlock(lock)
1✔
980
}
981

982
// Get returns the mapped components for the given entity.
983
func (m *Map5[A, B, C, D, E]) Get(entity Entity) (*A, *B, *C, *D, *E) {
25✔
984
        if !m.world.Alive(entity) {
26✔
985
                panic("can't get components of a dead entity")
1✔
986
        }
987
        return m.GetUnchecked(entity)
24✔
988
}
989

990
// GetUnchecked returns the mapped components for the given entity.
991
// In contrast to [Map5.Get], it does not check whether the entity is alive.
992
// Can be used as an optimization when it is certain that the entity is alive.
993
func (m *Map5[A, B, C, D, E]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E) {
24✔
994
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
995
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
996
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
997
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
998
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
999

24✔
1000
        index := m.world.storage.entities[entity.id]
24✔
1001
        row := uintptr(index.row)
24✔
1002

24✔
1003
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1004
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1005
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1006
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1007
                (*E)(m.storageE.columns[index.table].Get(row))
24✔
1008
}
24✔
1009

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

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

1038
// AddBatch adds the mapped components to all entities matching the given batch filter.
1039
func (m *Map5[A, B, C, D, E]) AddBatch(batch *Batch, a *A, b *B, c *C, d *D, e *E, rel ...RelationIndex) {
1✔
1040
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1041
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1042
                unsafe.Pointer(a),
1✔
1043
                unsafe.Pointer(b),
1✔
1044
                unsafe.Pointer(c),
1✔
1045
                unsafe.Pointer(d),
1✔
1046
                unsafe.Pointer(e),
1✔
1047
        }, m.relations, nil)
1✔
1048
}
1✔
1049

1050
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1051
// running the given function on each. The function can be nil.
1052
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✔
1053
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1054

1✔
1055
        var process func(tableID tableID, start, len int)
1✔
1056
        if fn != nil {
2✔
1057
                process = func(tableID tableID, start, len int) {
3✔
1058
                        table := &m.world.storage.tables[tableID]
2✔
1059
                        columnA := m.storageA.columns[tableID]
2✔
1060
                        columnB := m.storageB.columns[tableID]
2✔
1061
                        columnC := m.storageC.columns[tableID]
2✔
1062
                        columnD := m.storageD.columns[tableID]
2✔
1063
                        columnE := m.storageE.columns[tableID]
2✔
1064

2✔
1065
                        lock := m.world.lock()
2✔
1066
                        for i := range len {
26✔
1067
                                index := uintptr(start + i)
24✔
1068
                                fn(
24✔
1069
                                        table.GetEntity(index),
24✔
1070
                                        (*A)(columnA.Get(index)),
24✔
1071
                                        (*B)(columnB.Get(index)),
24✔
1072
                                        (*C)(columnC.Get(index)),
24✔
1073
                                        (*D)(columnD.Get(index)),
24✔
1074
                                        (*E)(columnE.Get(index)),
24✔
1075
                                )
24✔
1076
                        }
24✔
1077
                        m.world.unlock(lock)
2✔
1078
                }
1079
        }
1080
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1081
}
1082

1083
// Remove the mapped components from the given entity.
1084
func (m *Map5[A, B, C, D, E]) Remove(entity Entity) {
25✔
1085
        if !m.world.Alive(entity) {
26✔
1086
                panic("can't remove components from a dead entity")
1✔
1087
        }
1088
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1089
}
1090

1091
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1092
// running the given function on each. The function can be nil.
1093
func (m *Map5[A, B, C, D, E]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1094
        var process func(tableID tableID, start, len int)
2✔
1095
        if fn != nil {
3✔
1096
                process = func(tableID tableID, start, len int) {
3✔
1097
                        table := &m.world.storage.tables[tableID]
2✔
1098

2✔
1099
                        lock := m.world.lock()
2✔
1100
                        for i := range len {
26✔
1101
                                index := uintptr(start + i)
24✔
1102
                                fn(table.GetEntity(index))
24✔
1103
                        }
24✔
1104
                        m.world.unlock(lock)
2✔
1105
                }
1106
        }
1107
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1108
}
1109

1110
// GetRelation returns the relation target of an entity for the component at the given index.
1111
func (m *Map5[A, B, C, D, E]) GetRelation(entity Entity, index int) Entity {
3✔
1112
        if !m.world.Alive(entity) {
4✔
1113
                panic("can't get entity relation target for a dead entity")
1✔
1114
        }
1115
        return m.GetRelationUnchecked(entity, index)
2✔
1116
}
1117

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

1125
// SetRelations sets relation targets for the given entity.
1126
func (m *Map5[A, B, C, D, E]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
1127
        // alive check is done in World.setRelations
3✔
1128
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1129
        m.world.setRelations(entity, m.relations)
3✔
1130
}
3✔
1131

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

2✔
1136
        var process func(tableID tableID, start, len int)
2✔
1137
        if fn != nil {
4✔
1138
                process = func(tableID tableID, start, len int) {
3✔
1139
                        table := &m.world.storage.tables[tableID]
1✔
1140

1✔
1141
                        lock := m.world.lock()
1✔
1142
                        for i := range len {
25✔
1143
                                index := uintptr(start + i)
24✔
1144
                                fn(table.GetEntity(index))
24✔
1145
                        }
24✔
1146
                        m.world.unlock(lock)
1✔
1147
                }
1148
        }
1149
        m.world.setRelationsBatch(batch, m.relations, process)
2✔
1150
}
1151

1152
// Map6 is a mapper to access 6 components of an entity.
1153
type Map6[A any, B any, C any, D any, E any, F any] struct {
1154
        world     *World
1155
        ids       []ID
1156
        storageA  *componentStorage
1157
        storageB  *componentStorage
1158
        storageC  *componentStorage
1159
        storageD  *componentStorage
1160
        storageE  *componentStorage
1161
        storageF  *componentStorage
1162
        relations []RelationID
1163
}
1164

1165
// NewMap6 creates a new [Map6].
1166
func NewMap6[A any, B any, C any, D any, E any, F any](world *World) Map6[A, B, C, D, E, F] {
13✔
1167
        ids := []ID{
13✔
1168
                ComponentID[A](world),
13✔
1169
                ComponentID[B](world),
13✔
1170
                ComponentID[C](world),
13✔
1171
                ComponentID[D](world),
13✔
1172
                ComponentID[E](world),
13✔
1173
                ComponentID[F](world),
13✔
1174
        }
13✔
1175
        return Map6[A, B, C, D, E, F]{
13✔
1176
                world:    world,
13✔
1177
                ids:      ids,
13✔
1178
                storageA: &world.storage.components[ids[0].id],
13✔
1179
                storageB: &world.storage.components[ids[1].id],
13✔
1180
                storageC: &world.storage.components[ids[2].id],
13✔
1181
                storageD: &world.storage.components[ids[3].id],
13✔
1182
                storageE: &world.storage.components[ids[4].id],
13✔
1183
                storageF: &world.storage.components[ids[5].id],
13✔
1184
        }
13✔
1185
}
13✔
1186

1187
// NewEntity creates a new entity with the mapped components.
1188
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✔
1189
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
1190
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
1191
                unsafe.Pointer(a),
127✔
1192
                unsafe.Pointer(b),
127✔
1193
                unsafe.Pointer(c),
127✔
1194
                unsafe.Pointer(d),
127✔
1195
                unsafe.Pointer(e),
127✔
1196
                unsafe.Pointer(f),
127✔
1197
        }, m.relations)
127✔
1198
}
127✔
1199

1200
// NewBatch creates a batch of new entities with the mapped components.
1201
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✔
1202
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1203
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
1204
                unsafe.Pointer(a),
3✔
1205
                unsafe.Pointer(b),
3✔
1206
                unsafe.Pointer(c),
3✔
1207
                unsafe.Pointer(d),
3✔
1208
                unsafe.Pointer(e),
3✔
1209
                unsafe.Pointer(f),
3✔
1210
        }, m.relations)
3✔
1211
}
3✔
1212

1213
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
1214
// The initializer function can be nil.
1215
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✔
1216
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1217
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
1218
        if fn == nil {
1✔
1219
                return
×
1220
        }
×
1221

1222
        table := &m.world.storage.tables[tableID]
1✔
1223
        columnA := m.storageA.columns[tableID]
1✔
1224
        columnB := m.storageB.columns[tableID]
1✔
1225
        columnC := m.storageC.columns[tableID]
1✔
1226
        columnD := m.storageD.columns[tableID]
1✔
1227
        columnE := m.storageE.columns[tableID]
1✔
1228
        columnF := m.storageF.columns[tableID]
1✔
1229

1✔
1230
        lock := m.world.lock()
1✔
1231
        for i := range count {
25✔
1232
                index := uintptr(start + i)
24✔
1233
                fn(
24✔
1234
                        table.GetEntity(index),
24✔
1235
                        (*A)(columnA.Get(index)),
24✔
1236
                        (*B)(columnB.Get(index)),
24✔
1237
                        (*C)(columnC.Get(index)),
24✔
1238
                        (*D)(columnD.Get(index)),
24✔
1239
                        (*E)(columnE.Get(index)),
24✔
1240
                        (*F)(columnF.Get(index)),
24✔
1241
                )
24✔
1242
        }
24✔
1243
        m.world.unlock(lock)
1✔
1244
}
1245

1246
// Get returns the mapped components for the given entity.
1247
func (m *Map6[A, B, C, D, E, F]) Get(entity Entity) (*A, *B, *C, *D, *E, *F) {
25✔
1248
        if !m.world.Alive(entity) {
26✔
1249
                panic("can't get components of a dead entity")
1✔
1250
        }
1251
        return m.GetUnchecked(entity)
24✔
1252
}
1253

1254
// GetUnchecked returns the mapped components for the given entity.
1255
// In contrast to [Map6.Get], it does not check whether the entity is alive.
1256
// Can be used as an optimization when it is certain that the entity is alive.
1257
func (m *Map6[A, B, C, D, E, F]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E, *F) {
24✔
1258
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1259
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1260
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1261
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1262
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1263
        m.world.storage.checkHasComponent(entity, m.ids[5])
24✔
1264

24✔
1265
        index := m.world.storage.entities[entity.id]
24✔
1266
        row := uintptr(index.row)
24✔
1267

24✔
1268
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1269
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1270
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1271
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1272
                (*E)(m.storageE.columns[index.table].Get(row)),
24✔
1273
                (*F)(m.storageF.columns[index.table].Get(row))
24✔
1274
}
24✔
1275

1276
// HasAll return whether the given entity has all mapped components.
1277
func (m *Map6[A, B, C, D, E, F]) HasAll(entity Entity) bool {
54✔
1278
        if !m.world.Alive(entity) {
55✔
1279
                panic("can't check components of a dead entity")
1✔
1280
        }
1281
        index := m.world.storage.entities[entity.id]
53✔
1282
        return m.storageA.columns[index.table] != nil &&
53✔
1283
                m.storageB.columns[index.table] != nil &&
53✔
1284
                m.storageC.columns[index.table] != nil &&
53✔
1285
                m.storageD.columns[index.table] != nil &&
53✔
1286
                m.storageE.columns[index.table] != nil &&
53✔
1287
                m.storageF.columns[index.table] != nil
53✔
1288
}
1289

1290
// Add the mapped components to the given entity.
1291
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✔
1292
        if !m.world.Alive(entity) {
14✔
1293
                panic("can't add components to a dead entity")
1✔
1294
        }
1295
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1296
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1297
                unsafe.Pointer(a),
12✔
1298
                unsafe.Pointer(b),
12✔
1299
                unsafe.Pointer(c),
12✔
1300
                unsafe.Pointer(d),
12✔
1301
                unsafe.Pointer(e),
12✔
1302
                unsafe.Pointer(f),
12✔
1303
        }, m.relations)
12✔
1304
}
1305

1306
// AddBatch adds the mapped components to all entities matching the given batch filter.
1307
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✔
1308
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1309
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1310
                unsafe.Pointer(a),
1✔
1311
                unsafe.Pointer(b),
1✔
1312
                unsafe.Pointer(c),
1✔
1313
                unsafe.Pointer(d),
1✔
1314
                unsafe.Pointer(e),
1✔
1315
                unsafe.Pointer(f),
1✔
1316
        }, m.relations, nil)
1✔
1317
}
1✔
1318

1319
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1320
// running the given function on each. The function can be nil.
1321
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✔
1322
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1323

1✔
1324
        var process func(tableID tableID, start, len int)
1✔
1325
        if fn != nil {
2✔
1326
                process = func(tableID tableID, start, len int) {
3✔
1327
                        table := &m.world.storage.tables[tableID]
2✔
1328
                        columnA := m.storageA.columns[tableID]
2✔
1329
                        columnB := m.storageB.columns[tableID]
2✔
1330
                        columnC := m.storageC.columns[tableID]
2✔
1331
                        columnD := m.storageD.columns[tableID]
2✔
1332
                        columnE := m.storageE.columns[tableID]
2✔
1333
                        columnF := m.storageF.columns[tableID]
2✔
1334

2✔
1335
                        lock := m.world.lock()
2✔
1336
                        for i := range len {
26✔
1337
                                index := uintptr(start + i)
24✔
1338
                                fn(
24✔
1339
                                        table.GetEntity(index),
24✔
1340
                                        (*A)(columnA.Get(index)),
24✔
1341
                                        (*B)(columnB.Get(index)),
24✔
1342
                                        (*C)(columnC.Get(index)),
24✔
1343
                                        (*D)(columnD.Get(index)),
24✔
1344
                                        (*E)(columnE.Get(index)),
24✔
1345
                                        (*F)(columnF.Get(index)),
24✔
1346
                                )
24✔
1347
                        }
24✔
1348
                        m.world.unlock(lock)
2✔
1349
                }
1350
        }
1351
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1352
}
1353

1354
// Remove the mapped components from the given entity.
1355
func (m *Map6[A, B, C, D, E, F]) Remove(entity Entity) {
25✔
1356
        if !m.world.Alive(entity) {
26✔
1357
                panic("can't remove components from a dead entity")
1✔
1358
        }
1359
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1360
}
1361

1362
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1363
// running the given function on each. The function can be nil.
1364
func (m *Map6[A, B, C, D, E, F]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1365
        var process func(tableID tableID, start, len int)
2✔
1366
        if fn != nil {
3✔
1367
                process = func(tableID tableID, start, len int) {
3✔
1368
                        table := &m.world.storage.tables[tableID]
2✔
1369

2✔
1370
                        lock := m.world.lock()
2✔
1371
                        for i := range len {
26✔
1372
                                index := uintptr(start + i)
24✔
1373
                                fn(table.GetEntity(index))
24✔
1374
                        }
24✔
1375
                        m.world.unlock(lock)
2✔
1376
                }
1377
        }
1378
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1379
}
1380

1381
// GetRelation returns the relation target of an entity for the component at the given index.
1382
func (m *Map6[A, B, C, D, E, F]) GetRelation(entity Entity, index int) Entity {
3✔
1383
        if !m.world.Alive(entity) {
4✔
1384
                panic("can't get entity relation target for a dead entity")
1✔
1385
        }
1386
        return m.GetRelationUnchecked(entity, index)
2✔
1387
}
1388

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

1396
// SetRelations sets relation targets for the given entity.
1397
func (m *Map6[A, B, C, D, E, F]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
1398
        // alive check is done in World.setRelations
3✔
1399
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1400
        m.world.setRelations(entity, m.relations)
3✔
1401
}
3✔
1402

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

2✔
1407
        var process func(tableID tableID, start, len int)
2✔
1408
        if fn != nil {
4✔
1409
                process = func(tableID tableID, start, len int) {
3✔
1410
                        table := &m.world.storage.tables[tableID]
1✔
1411

1✔
1412
                        lock := m.world.lock()
1✔
1413
                        for i := range len {
25✔
1414
                                index := uintptr(start + i)
24✔
1415
                                fn(table.GetEntity(index))
24✔
1416
                        }
24✔
1417
                        m.world.unlock(lock)
1✔
1418
                }
1419
        }
1420
        m.world.setRelationsBatch(batch, m.relations, process)
2✔
1421
}
1422

1423
// Map7 is a mapper to access 7 components of an entity.
1424
type Map7[A any, B any, C any, D any, E any, F any, G any] struct {
1425
        world     *World
1426
        ids       []ID
1427
        storageA  *componentStorage
1428
        storageB  *componentStorage
1429
        storageC  *componentStorage
1430
        storageD  *componentStorage
1431
        storageE  *componentStorage
1432
        storageF  *componentStorage
1433
        storageG  *componentStorage
1434
        relations []RelationID
1435
}
1436

1437
// NewMap7 creates a new [Map7].
1438
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✔
1439
        ids := []ID{
13✔
1440
                ComponentID[A](world),
13✔
1441
                ComponentID[B](world),
13✔
1442
                ComponentID[C](world),
13✔
1443
                ComponentID[D](world),
13✔
1444
                ComponentID[E](world),
13✔
1445
                ComponentID[F](world),
13✔
1446
                ComponentID[G](world),
13✔
1447
        }
13✔
1448
        return Map7[A, B, C, D, E, F, G]{
13✔
1449
                world:    world,
13✔
1450
                ids:      ids,
13✔
1451
                storageA: &world.storage.components[ids[0].id],
13✔
1452
                storageB: &world.storage.components[ids[1].id],
13✔
1453
                storageC: &world.storage.components[ids[2].id],
13✔
1454
                storageD: &world.storage.components[ids[3].id],
13✔
1455
                storageE: &world.storage.components[ids[4].id],
13✔
1456
                storageF: &world.storage.components[ids[5].id],
13✔
1457
                storageG: &world.storage.components[ids[6].id],
13✔
1458
        }
13✔
1459
}
13✔
1460

1461
// NewEntity creates a new entity with the mapped components.
1462
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✔
1463
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
1464
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
1465
                unsafe.Pointer(a),
127✔
1466
                unsafe.Pointer(b),
127✔
1467
                unsafe.Pointer(c),
127✔
1468
                unsafe.Pointer(d),
127✔
1469
                unsafe.Pointer(e),
127✔
1470
                unsafe.Pointer(f),
127✔
1471
                unsafe.Pointer(g),
127✔
1472
        }, m.relations)
127✔
1473
}
127✔
1474

1475
// NewBatch creates a batch of new entities with the mapped components.
1476
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✔
1477
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1478
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
1479
                unsafe.Pointer(a),
3✔
1480
                unsafe.Pointer(b),
3✔
1481
                unsafe.Pointer(c),
3✔
1482
                unsafe.Pointer(d),
3✔
1483
                unsafe.Pointer(e),
3✔
1484
                unsafe.Pointer(f),
3✔
1485
                unsafe.Pointer(g),
3✔
1486
        }, m.relations)
3✔
1487
}
3✔
1488

1489
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
1490
// The initializer function can be nil.
1491
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✔
1492
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1493
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
1494
        if fn == nil {
1✔
1495
                return
×
1496
        }
×
1497

1498
        table := &m.world.storage.tables[tableID]
1✔
1499
        columnA := m.storageA.columns[tableID]
1✔
1500
        columnB := m.storageB.columns[tableID]
1✔
1501
        columnC := m.storageC.columns[tableID]
1✔
1502
        columnD := m.storageD.columns[tableID]
1✔
1503
        columnE := m.storageE.columns[tableID]
1✔
1504
        columnF := m.storageF.columns[tableID]
1✔
1505
        columnG := m.storageG.columns[tableID]
1✔
1506

1✔
1507
        lock := m.world.lock()
1✔
1508
        for i := range count {
25✔
1509
                index := uintptr(start + i)
24✔
1510
                fn(
24✔
1511
                        table.GetEntity(index),
24✔
1512
                        (*A)(columnA.Get(index)),
24✔
1513
                        (*B)(columnB.Get(index)),
24✔
1514
                        (*C)(columnC.Get(index)),
24✔
1515
                        (*D)(columnD.Get(index)),
24✔
1516
                        (*E)(columnE.Get(index)),
24✔
1517
                        (*F)(columnF.Get(index)),
24✔
1518
                        (*G)(columnG.Get(index)),
24✔
1519
                )
24✔
1520
        }
24✔
1521
        m.world.unlock(lock)
1✔
1522
}
1523

1524
// Get returns the mapped components for the given entity.
1525
func (m *Map7[A, B, C, D, E, F, G]) Get(entity Entity) (*A, *B, *C, *D, *E, *F, *G) {
25✔
1526
        if !m.world.Alive(entity) {
26✔
1527
                panic("can't get components of a dead entity")
1✔
1528
        }
1529
        return m.GetUnchecked(entity)
24✔
1530
}
1531

1532
// GetUnchecked returns the mapped components for the given entity.
1533
// In contrast to [Map7.Get], it does not check whether the entity is alive.
1534
// Can be used as an optimization when it is certain that the entity is alive.
1535
func (m *Map7[A, B, C, D, E, F, G]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E, *F, *G) {
24✔
1536
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1537
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1538
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1539
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1540
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1541
        m.world.storage.checkHasComponent(entity, m.ids[5])
24✔
1542
        m.world.storage.checkHasComponent(entity, m.ids[6])
24✔
1543

24✔
1544
        index := m.world.storage.entities[entity.id]
24✔
1545
        row := uintptr(index.row)
24✔
1546

24✔
1547
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1548
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1549
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1550
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1551
                (*E)(m.storageE.columns[index.table].Get(row)),
24✔
1552
                (*F)(m.storageF.columns[index.table].Get(row)),
24✔
1553
                (*G)(m.storageG.columns[index.table].Get(row))
24✔
1554
}
24✔
1555

1556
// HasAll return whether the given entity has all mapped components.
1557
func (m *Map7[A, B, C, D, E, F, G]) HasAll(entity Entity) bool {
54✔
1558
        if !m.world.Alive(entity) {
55✔
1559
                panic("can't check components of a dead entity")
1✔
1560
        }
1561
        index := m.world.storage.entities[entity.id]
53✔
1562
        return m.storageA.columns[index.table] != nil &&
53✔
1563
                m.storageB.columns[index.table] != nil &&
53✔
1564
                m.storageC.columns[index.table] != nil &&
53✔
1565
                m.storageD.columns[index.table] != nil &&
53✔
1566
                m.storageE.columns[index.table] != nil &&
53✔
1567
                m.storageF.columns[index.table] != nil &&
53✔
1568
                m.storageG.columns[index.table] != nil
53✔
1569
}
1570

1571
// Add the mapped components to the given entity.
1572
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✔
1573
        if !m.world.Alive(entity) {
14✔
1574
                panic("can't add components to a dead entity")
1✔
1575
        }
1576
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1577
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1578
                unsafe.Pointer(a),
12✔
1579
                unsafe.Pointer(b),
12✔
1580
                unsafe.Pointer(c),
12✔
1581
                unsafe.Pointer(d),
12✔
1582
                unsafe.Pointer(e),
12✔
1583
                unsafe.Pointer(f),
12✔
1584
                unsafe.Pointer(g),
12✔
1585
        }, m.relations)
12✔
1586
}
1587

1588
// AddBatch adds the mapped components to all entities matching the given batch filter.
1589
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✔
1590
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1591
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1592
                unsafe.Pointer(a),
1✔
1593
                unsafe.Pointer(b),
1✔
1594
                unsafe.Pointer(c),
1✔
1595
                unsafe.Pointer(d),
1✔
1596
                unsafe.Pointer(e),
1✔
1597
                unsafe.Pointer(f),
1✔
1598
                unsafe.Pointer(g),
1✔
1599
        }, m.relations, nil)
1✔
1600
}
1✔
1601

1602
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1603
// running the given function on each. The function can be nil.
1604
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✔
1605
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1606

1✔
1607
        var process func(tableID tableID, start, len int)
1✔
1608
        if fn != nil {
2✔
1609
                process = func(tableID tableID, start, len int) {
3✔
1610
                        table := &m.world.storage.tables[tableID]
2✔
1611
                        columnA := m.storageA.columns[tableID]
2✔
1612
                        columnB := m.storageB.columns[tableID]
2✔
1613
                        columnC := m.storageC.columns[tableID]
2✔
1614
                        columnD := m.storageD.columns[tableID]
2✔
1615
                        columnE := m.storageE.columns[tableID]
2✔
1616
                        columnF := m.storageF.columns[tableID]
2✔
1617
                        columnG := m.storageG.columns[tableID]
2✔
1618

2✔
1619
                        lock := m.world.lock()
2✔
1620
                        for i := range len {
26✔
1621
                                index := uintptr(start + i)
24✔
1622
                                fn(
24✔
1623
                                        table.GetEntity(index),
24✔
1624
                                        (*A)(columnA.Get(index)),
24✔
1625
                                        (*B)(columnB.Get(index)),
24✔
1626
                                        (*C)(columnC.Get(index)),
24✔
1627
                                        (*D)(columnD.Get(index)),
24✔
1628
                                        (*E)(columnE.Get(index)),
24✔
1629
                                        (*F)(columnF.Get(index)),
24✔
1630
                                        (*G)(columnG.Get(index)),
24✔
1631
                                )
24✔
1632
                        }
24✔
1633
                        m.world.unlock(lock)
2✔
1634
                }
1635
        }
1636
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1637
}
1638

1639
// Remove the mapped components from the given entity.
1640
func (m *Map7[A, B, C, D, E, F, G]) Remove(entity Entity) {
25✔
1641
        if !m.world.Alive(entity) {
26✔
1642
                panic("can't remove components from a dead entity")
1✔
1643
        }
1644
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1645
}
1646

1647
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1648
// running the given function on each. The function can be nil.
1649
func (m *Map7[A, B, C, D, E, F, G]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1650
        var process func(tableID tableID, start, len int)
2✔
1651
        if fn != nil {
3✔
1652
                process = func(tableID tableID, start, len int) {
3✔
1653
                        table := &m.world.storage.tables[tableID]
2✔
1654

2✔
1655
                        lock := m.world.lock()
2✔
1656
                        for i := range len {
26✔
1657
                                index := uintptr(start + i)
24✔
1658
                                fn(table.GetEntity(index))
24✔
1659
                        }
24✔
1660
                        m.world.unlock(lock)
2✔
1661
                }
1662
        }
1663
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1664
}
1665

1666
// GetRelation returns the relation target of an entity for the component at the given index.
1667
func (m *Map7[A, B, C, D, E, F, G]) GetRelation(entity Entity, index int) Entity {
3✔
1668
        if !m.world.Alive(entity) {
4✔
1669
                panic("can't get entity relation target for a dead entity")
1✔
1670
        }
1671
        return m.GetRelationUnchecked(entity, index)
2✔
1672
}
1673

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

1681
// SetRelations sets relation targets for the given entity.
1682
func (m *Map7[A, B, C, D, E, F, G]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
1683
        // alive check is done in World.setRelations
3✔
1684
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1685
        m.world.setRelations(entity, m.relations)
3✔
1686
}
3✔
1687

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

2✔
1692
        var process func(tableID tableID, start, len int)
2✔
1693
        if fn != nil {
4✔
1694
                process = func(tableID tableID, start, len int) {
3✔
1695
                        table := &m.world.storage.tables[tableID]
1✔
1696

1✔
1697
                        lock := m.world.lock()
1✔
1698
                        for i := range len {
25✔
1699
                                index := uintptr(start + i)
24✔
1700
                                fn(table.GetEntity(index))
24✔
1701
                        }
24✔
1702
                        m.world.unlock(lock)
1✔
1703
                }
1704
        }
1705
        m.world.setRelationsBatch(batch, m.relations, process)
2✔
1706
}
1707

1708
// Map8 is a mapper to access 8 components of an entity.
1709
type Map8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1710
        world     *World
1711
        ids       []ID
1712
        storageA  *componentStorage
1713
        storageB  *componentStorage
1714
        storageC  *componentStorage
1715
        storageD  *componentStorage
1716
        storageE  *componentStorage
1717
        storageF  *componentStorage
1718
        storageG  *componentStorage
1719
        storageH  *componentStorage
1720
        relations []RelationID
1721
}
1722

1723
// NewMap8 creates a new [Map8].
1724
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✔
1725
        ids := []ID{
13✔
1726
                ComponentID[A](world),
13✔
1727
                ComponentID[B](world),
13✔
1728
                ComponentID[C](world),
13✔
1729
                ComponentID[D](world),
13✔
1730
                ComponentID[E](world),
13✔
1731
                ComponentID[F](world),
13✔
1732
                ComponentID[G](world),
13✔
1733
                ComponentID[H](world),
13✔
1734
        }
13✔
1735
        return Map8[A, B, C, D, E, F, G, H]{
13✔
1736
                world:    world,
13✔
1737
                ids:      ids,
13✔
1738
                storageA: &world.storage.components[ids[0].id],
13✔
1739
                storageB: &world.storage.components[ids[1].id],
13✔
1740
                storageC: &world.storage.components[ids[2].id],
13✔
1741
                storageD: &world.storage.components[ids[3].id],
13✔
1742
                storageE: &world.storage.components[ids[4].id],
13✔
1743
                storageF: &world.storage.components[ids[5].id],
13✔
1744
                storageG: &world.storage.components[ids[6].id],
13✔
1745
                storageH: &world.storage.components[ids[7].id],
13✔
1746
        }
13✔
1747
}
13✔
1748

1749
// NewEntity creates a new entity with the mapped components.
1750
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✔
1751
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
127✔
1752
        return m.world.newEntityWith(m.ids, []unsafe.Pointer{
127✔
1753
                unsafe.Pointer(a),
127✔
1754
                unsafe.Pointer(b),
127✔
1755
                unsafe.Pointer(c),
127✔
1756
                unsafe.Pointer(d),
127✔
1757
                unsafe.Pointer(e),
127✔
1758
                unsafe.Pointer(f),
127✔
1759
                unsafe.Pointer(g),
127✔
1760
                unsafe.Pointer(h),
127✔
1761
        }, m.relations)
127✔
1762
}
127✔
1763

1764
// NewBatch creates a batch of new entities with the mapped components.
1765
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✔
1766
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1767
        m.world.newEntitiesWith(count, m.ids, []unsafe.Pointer{
3✔
1768
                unsafe.Pointer(a),
3✔
1769
                unsafe.Pointer(b),
3✔
1770
                unsafe.Pointer(c),
3✔
1771
                unsafe.Pointer(d),
3✔
1772
                unsafe.Pointer(e),
3✔
1773
                unsafe.Pointer(f),
3✔
1774
                unsafe.Pointer(g),
3✔
1775
                unsafe.Pointer(h),
3✔
1776
        }, m.relations)
3✔
1777
}
3✔
1778

1779
// NewBatchFn creates a batch of new entities with the mapped components, running the given initializer function on each.
1780
// The initializer function can be nil.
1781
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✔
1782
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1783
        tableID, start := m.world.newEntities(count, m.ids, m.relations)
1✔
1784
        if fn == nil {
1✔
1785
                return
×
1786
        }
×
1787

1788
        table := &m.world.storage.tables[tableID]
1✔
1789
        columnA := m.storageA.columns[tableID]
1✔
1790
        columnB := m.storageB.columns[tableID]
1✔
1791
        columnC := m.storageC.columns[tableID]
1✔
1792
        columnD := m.storageD.columns[tableID]
1✔
1793
        columnE := m.storageE.columns[tableID]
1✔
1794
        columnF := m.storageF.columns[tableID]
1✔
1795
        columnG := m.storageG.columns[tableID]
1✔
1796
        columnH := m.storageH.columns[tableID]
1✔
1797

1✔
1798
        lock := m.world.lock()
1✔
1799
        for i := range count {
25✔
1800
                index := uintptr(start + i)
24✔
1801
                fn(
24✔
1802
                        table.GetEntity(index),
24✔
1803
                        (*A)(columnA.Get(index)),
24✔
1804
                        (*B)(columnB.Get(index)),
24✔
1805
                        (*C)(columnC.Get(index)),
24✔
1806
                        (*D)(columnD.Get(index)),
24✔
1807
                        (*E)(columnE.Get(index)),
24✔
1808
                        (*F)(columnF.Get(index)),
24✔
1809
                        (*G)(columnG.Get(index)),
24✔
1810
                        (*H)(columnH.Get(index)),
24✔
1811
                )
24✔
1812
        }
24✔
1813
        m.world.unlock(lock)
1✔
1814
}
1815

1816
// Get returns the mapped components for the given entity.
1817
func (m *Map8[A, B, C, D, E, F, G, H]) Get(entity Entity) (*A, *B, *C, *D, *E, *F, *G, *H) {
25✔
1818
        if !m.world.Alive(entity) {
26✔
1819
                panic("can't get components of a dead entity")
1✔
1820
        }
1821
        return m.GetUnchecked(entity)
24✔
1822
}
1823

1824
// GetUnchecked returns the mapped components for the given entity.
1825
// In contrast to [Map8.Get], it does not check whether the entity is alive.
1826
// Can be used as an optimization when it is certain that the entity is alive.
1827
func (m *Map8[A, B, C, D, E, F, G, H]) GetUnchecked(entity Entity) (*A, *B, *C, *D, *E, *F, *G, *H) {
24✔
1828
        m.world.storage.checkHasComponent(entity, m.ids[0])
24✔
1829
        m.world.storage.checkHasComponent(entity, m.ids[1])
24✔
1830
        m.world.storage.checkHasComponent(entity, m.ids[2])
24✔
1831
        m.world.storage.checkHasComponent(entity, m.ids[3])
24✔
1832
        m.world.storage.checkHasComponent(entity, m.ids[4])
24✔
1833
        m.world.storage.checkHasComponent(entity, m.ids[5])
24✔
1834
        m.world.storage.checkHasComponent(entity, m.ids[6])
24✔
1835
        m.world.storage.checkHasComponent(entity, m.ids[7])
24✔
1836

24✔
1837
        index := m.world.storage.entities[entity.id]
24✔
1838
        row := uintptr(index.row)
24✔
1839

24✔
1840
        return (*A)(m.storageA.columns[index.table].Get(row)),
24✔
1841
                (*B)(m.storageB.columns[index.table].Get(row)),
24✔
1842
                (*C)(m.storageC.columns[index.table].Get(row)),
24✔
1843
                (*D)(m.storageD.columns[index.table].Get(row)),
24✔
1844
                (*E)(m.storageE.columns[index.table].Get(row)),
24✔
1845
                (*F)(m.storageF.columns[index.table].Get(row)),
24✔
1846
                (*G)(m.storageG.columns[index.table].Get(row)),
24✔
1847
                (*H)(m.storageH.columns[index.table].Get(row))
24✔
1848
}
24✔
1849

1850
// HasAll return whether the given entity has all mapped components.
1851
func (m *Map8[A, B, C, D, E, F, G, H]) HasAll(entity Entity) bool {
54✔
1852
        if !m.world.Alive(entity) {
55✔
1853
                panic("can't check components of a dead entity")
1✔
1854
        }
1855
        index := m.world.storage.entities[entity.id]
53✔
1856
        return m.storageA.columns[index.table] != nil &&
53✔
1857
                m.storageB.columns[index.table] != nil &&
53✔
1858
                m.storageC.columns[index.table] != nil &&
53✔
1859
                m.storageD.columns[index.table] != nil &&
53✔
1860
                m.storageE.columns[index.table] != nil &&
53✔
1861
                m.storageF.columns[index.table] != nil &&
53✔
1862
                m.storageG.columns[index.table] != nil &&
53✔
1863
                m.storageH.columns[index.table] != nil
53✔
1864
}
1865

1866
// Add the mapped components to the given entity.
1867
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✔
1868
        if !m.world.Alive(entity) {
14✔
1869
                panic("can't add components to a dead entity")
1✔
1870
        }
1871
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
12✔
1872
        m.world.exchange(entity, m.ids, nil, []unsafe.Pointer{
12✔
1873
                unsafe.Pointer(a),
12✔
1874
                unsafe.Pointer(b),
12✔
1875
                unsafe.Pointer(c),
12✔
1876
                unsafe.Pointer(d),
12✔
1877
                unsafe.Pointer(e),
12✔
1878
                unsafe.Pointer(f),
12✔
1879
                unsafe.Pointer(g),
12✔
1880
                unsafe.Pointer(h),
12✔
1881
        }, m.relations)
12✔
1882
}
1883

1884
// AddBatch adds the mapped components to all entities matching the given batch filter.
1885
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✔
1886
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1887
        m.world.exchangeBatch(batch, m.ids, nil, []unsafe.Pointer{
1✔
1888
                unsafe.Pointer(a),
1✔
1889
                unsafe.Pointer(b),
1✔
1890
                unsafe.Pointer(c),
1✔
1891
                unsafe.Pointer(d),
1✔
1892
                unsafe.Pointer(e),
1✔
1893
                unsafe.Pointer(f),
1✔
1894
                unsafe.Pointer(g),
1✔
1895
                unsafe.Pointer(h),
1✔
1896
        }, m.relations, nil)
1✔
1897
}
1✔
1898

1899
// AddBatchFn adds the mapped components to all entities matching the given batch filter,
1900
// running the given function on each. The function can be nil.
1901
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✔
1902
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
1✔
1903

1✔
1904
        var process func(tableID tableID, start, len int)
1✔
1905
        if fn != nil {
2✔
1906
                process = func(tableID tableID, start, len int) {
3✔
1907
                        table := &m.world.storage.tables[tableID]
2✔
1908
                        columnA := m.storageA.columns[tableID]
2✔
1909
                        columnB := m.storageB.columns[tableID]
2✔
1910
                        columnC := m.storageC.columns[tableID]
2✔
1911
                        columnD := m.storageD.columns[tableID]
2✔
1912
                        columnE := m.storageE.columns[tableID]
2✔
1913
                        columnF := m.storageF.columns[tableID]
2✔
1914
                        columnG := m.storageG.columns[tableID]
2✔
1915
                        columnH := m.storageH.columns[tableID]
2✔
1916

2✔
1917
                        lock := m.world.lock()
2✔
1918
                        for i := range len {
26✔
1919
                                index := uintptr(start + i)
24✔
1920
                                fn(
24✔
1921
                                        table.GetEntity(index),
24✔
1922
                                        (*A)(columnA.Get(index)),
24✔
1923
                                        (*B)(columnB.Get(index)),
24✔
1924
                                        (*C)(columnC.Get(index)),
24✔
1925
                                        (*D)(columnD.Get(index)),
24✔
1926
                                        (*E)(columnE.Get(index)),
24✔
1927
                                        (*F)(columnF.Get(index)),
24✔
1928
                                        (*G)(columnG.Get(index)),
24✔
1929
                                        (*H)(columnH.Get(index)),
24✔
1930
                                )
24✔
1931
                        }
24✔
1932
                        m.world.unlock(lock)
2✔
1933
                }
1934
        }
1935
        m.world.exchangeBatch(batch, m.ids, nil, nil, m.relations, process)
1✔
1936
}
1937

1938
// Remove the mapped components from the given entity.
1939
func (m *Map8[A, B, C, D, E, F, G, H]) Remove(entity Entity) {
25✔
1940
        if !m.world.Alive(entity) {
26✔
1941
                panic("can't remove components from a dead entity")
1✔
1942
        }
1943
        m.world.exchange(entity, nil, m.ids, nil, nil)
24✔
1944
}
1945

1946
// RemoveBatch removes the mapped components from all entities matching the given batch filter,
1947
// running the given function on each. The function can be nil.
1948
func (m *Map8[A, B, C, D, E, F, G, H]) RemoveBatch(batch *Batch, fn func(entity Entity)) {
2✔
1949
        var process func(tableID tableID, start, len int)
2✔
1950
        if fn != nil {
3✔
1951
                process = func(tableID tableID, start, len int) {
3✔
1952
                        table := &m.world.storage.tables[tableID]
2✔
1953

2✔
1954
                        lock := m.world.lock()
2✔
1955
                        for i := range len {
26✔
1956
                                index := uintptr(start + i)
24✔
1957
                                fn(table.GetEntity(index))
24✔
1958
                        }
24✔
1959
                        m.world.unlock(lock)
2✔
1960
                }
1961
        }
1962
        m.world.exchangeBatch(batch, nil, m.ids, nil, nil, process)
2✔
1963
}
1964

1965
// GetRelation returns the relation target of an entity for the component at the given index.
1966
func (m *Map8[A, B, C, D, E, F, G, H]) GetRelation(entity Entity, index int) Entity {
3✔
1967
        if !m.world.Alive(entity) {
4✔
1968
                panic("can't get entity relation target for a dead entity")
1✔
1969
        }
1970
        return m.GetRelationUnchecked(entity, index)
2✔
1971
}
1972

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

1980
// SetRelations sets relation targets for the given entity.
1981
func (m *Map8[A, B, C, D, E, F, G, H]) SetRelations(entity Entity, rel ...RelationIndex) {
3✔
1982
        // alive check is done in World.setRelations
3✔
1983
        m.relations = relations(rel).toRelations(&m.world.storage.registry, m.ids, nil, m.relations)
3✔
1984
        m.world.setRelations(entity, m.relations)
3✔
1985
}
3✔
1986

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

2✔
1991
        var process func(tableID tableID, start, len int)
2✔
1992
        if fn != nil {
4✔
1993
                process = func(tableID tableID, start, len int) {
3✔
1994
                        table := &m.world.storage.tables[tableID]
1✔
1995

1✔
1996
                        lock := m.world.lock()
1✔
1997
                        for i := range len {
25✔
1998
                                index := uintptr(start + i)
24✔
1999
                                fn(table.GetEntity(index))
24✔
2000
                        }
24✔
2001
                        m.world.unlock(lock)
1✔
2002
                }
2003
        }
2004
        m.world.setRelationsBatch(batch, m.relations, process)
2✔
2005
}
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