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

mlange-42 / ark / 13593874277

28 Feb 2025 06:06PM CUT coverage: 96.872% (+2.1%) from 94.795%
13593874277

Pull #79

github

web-flow
Merge 94da96c6d into 10315654e
Pull Request #79: Relation getters for queries and maps

118 of 118 new or added lines in 6 files covered. (100.0%)

8 existing lines in 1 file now uncovered.

3562 of 3677 relevant lines covered (96.87%)

50530.93 hits per line

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

98.12
/ecs/query_gen.go
1
package ecs
2

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

5
type cursor struct {
6
        archetype int
7
        table     int
8
        index     uintptr
9
        maxIndex  int64
10
}
11

12
// Query0 is a query for 0 components.
13
// Use a [NewFilter0] to create one.
14
type Query0 struct {
15
        world      *World
16
        mask       Mask
17
        without    Mask
18
        relations  []relationID
19
        lock       uint8
20
        cursor     cursor
21
        tables     []tableID
22
        table      *table
23
        components []*componentStorage
24
        hasWithout bool
25
}
26

27
func newQuery0(world *World, mask Mask, without Mask, relations []relationID) Query0 {
8✔
28
        components := make([]*componentStorage, 0)
8✔
29

8✔
30
        return Query0{
8✔
31
                world:      world,
8✔
32
                mask:       mask,
8✔
33
                without:    without,
8✔
34
                relations:  relations,
8✔
35
                hasWithout: !without.IsZero(),
8✔
36
                lock:       world.lock(),
8✔
37
                components: components,
8✔
38
                cursor: cursor{
8✔
39
                        archetype: -1,
8✔
40
                        table:     -1,
8✔
41
                        index:     0,
8✔
42
                        maxIndex:  -1,
8✔
43
                },
8✔
44
        }
8✔
45
}
8✔
46

47
// Next advances the query's cursor to the next entity.
48
func (q *Query0) Next() bool {
192✔
49
        checkQueryNext(&q.cursor)
192✔
50
        if int64(q.cursor.index) < q.cursor.maxIndex {
365✔
51
                q.cursor.index++
173✔
52
                return true
173✔
53
        }
173✔
54
        return q.nextTableOrArchetype()
19✔
55
}
56

57
// Entity returns the current entity.
58
func (q *Query0) Entity() Entity {
185✔
59
        checkQueryGet(&q.cursor)
185✔
60
        return q.table.GetEntity(q.cursor.index)
185✔
61
}
185✔
62

63
// Close closes the Query and unlocks the world.
64
//
65
// Automatically called when iteration finishes.
66
// Needs to be called only if breaking out of the query iteration or not iterating at all.
67
func (q *Query0) Close() {
8✔
68
        q.cursor.archetype = -2
8✔
69
        q.cursor.table = -2
8✔
70
        q.tables = nil
8✔
71
        q.table = nil
8✔
72
        q.world.unlock(q.lock)
8✔
73
}
8✔
74

75
func (q *Query0) nextTableOrArchetype() bool {
19✔
76
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
77
                return true
2✔
78
        }
2✔
79
        return q.nextArchetype()
17✔
80
}
81

82
func (q *Query0) nextArchetype() bool {
17✔
83
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
84
        for q.cursor.archetype < maxArchIndex {
34✔
85
                q.cursor.archetype++
17✔
86
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
17✔
87
                if !archetype.mask.Contains(&q.mask) ||
17✔
88
                        archetype.mask.ContainsAny(&q.without) {
21✔
89
                        continue
4✔
90
                }
91

92
                if !archetype.HasRelations() {
23✔
93
                        table := &q.world.storage.tables[archetype.tables[0]]
11✔
94
                        if table.Len() > 0 {
18✔
95
                                q.setTable(0, table)
7✔
96
                                return true
7✔
97
                        }
7✔
98
                        continue
4✔
99
                }
100

101
                q.tables = archetype.GetTables(q.relations)
1✔
102
                q.cursor.table = -1
1✔
103
                if q.nextTable() {
2✔
104
                        return true
1✔
105
                }
1✔
106
        }
107
        q.Close()
8✔
108
        return false
8✔
109
}
110

111
func (q *Query0) nextTable() bool {
11✔
112
        maxTableIndex := len(q.tables) - 1
11✔
113
        for q.cursor.table < maxTableIndex {
14✔
114
                q.cursor.table++
3✔
115
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
116
                if table.Len() == 0 {
3✔
117
                        continue
×
118
                }
119
                if !table.Matches(q.relations) {
3✔
120
                        continue
×
121
                }
122
                q.setTable(q.cursor.table, table)
3✔
123
                return true
3✔
124
        }
125
        return false
8✔
126
}
127

128
func (q *Query0) setTable(index int, table *table) {
10✔
129
        q.cursor.table = index
10✔
130
        q.table = table
10✔
131
        q.cursor.index = 0
10✔
132
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
133
}
10✔
134

135
// Query1 is a query for 1 components.
136
// Use a [NewFilter1] to create one.
137
type Query1[A any] struct {
138
        world      *World
139
        mask       Mask
140
        without    Mask
141
        relations  []relationID
142
        lock       uint8
143
        cursor     cursor
144
        tables     []tableID
145
        table      *table
146
        components []*componentStorage
147
        columnA    *column
148
        hasWithout bool
149
}
150

151
func newQuery1[A any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query1[A] {
1,009✔
152
        components := make([]*componentStorage, 1)
1,009✔
153
        for i := range 1 {
2,018✔
154
                components[i] = &world.storage.components[ids[i].id]
1,009✔
155
        }
1,009✔
156

157
        return Query1[A]{
1,009✔
158
                world:      world,
1,009✔
159
                mask:       mask,
1,009✔
160
                without:    without,
1,009✔
161
                relations:  relations,
1,009✔
162
                hasWithout: !without.IsZero(),
1,009✔
163
                lock:       world.lock(),
1,009✔
164
                components: components,
1,009✔
165
                cursor: cursor{
1,009✔
166
                        archetype: -1,
1,009✔
167
                        table:     -1,
1,009✔
168
                        index:     0,
1,009✔
169
                        maxIndex:  -1,
1,009✔
170
                },
1,009✔
171
        }
1,009✔
172
}
173

174
// Next advances the query's cursor to the next entity.
175
func (q *Query1[A]) Next() bool {
1,002,857✔
176
        checkQueryNext(&q.cursor)
1,002,857✔
177
        if int64(q.cursor.index) < q.cursor.maxIndex {
2,003,694✔
178
                q.cursor.index++
1,000,837✔
179
                return true
1,000,837✔
180
        }
1,000,837✔
181
        return q.nextTableOrArchetype()
2,020✔
182
}
183

184
// Entity returns the current entity.
185
func (q *Query1[A]) Entity() Entity {
2,003,544✔
186
        checkQueryGet(&q.cursor)
2,003,544✔
187
        return q.table.GetEntity(q.cursor.index)
2,003,544✔
188
}
2,003,544✔
189

190
// Get returns the queried components of the current entity.
191
func (q *Query1[A]) Get() *A {
1,001,849✔
192
        checkQueryGet(&q.cursor)
1,001,849✔
193
        return (*A)(q.columnA.Get(q.cursor.index))
1,001,849✔
194
}
1,001,849✔
195

196
// GetRelation returns the entity relation target of the component at the given index.
197
func (q *Query1[A]) GetRelation(index int) Entity {
10✔
198
        return q.components[index].columns[q.table.id].target
10✔
199
}
10✔
200

201
// Close closes the Query and unlocks the world.
202
//
203
// Automatically called when iteration finishes.
204
// Needs to be called only if breaking out of the query iteration or not iterating at all.
205
func (q *Query1[A]) Close() {
1,009✔
206
        q.cursor.archetype = -2
1,009✔
207
        q.cursor.table = -2
1,009✔
208
        q.tables = nil
1,009✔
209
        q.table = nil
1,009✔
210
        q.columnA = nil
1,009✔
211
        q.world.unlock(q.lock)
1,009✔
212
}
1,009✔
213

214
func (q *Query1[A]) nextTableOrArchetype() bool {
2,020✔
215
        if q.cursor.archetype >= 0 && q.nextTable() {
2,021✔
216
                return true
1✔
217
        }
1✔
218
        return q.nextArchetype()
2,019✔
219
}
220

221
func (q *Query1[A]) nextArchetype() bool {
2,019✔
222
        maxArchIndex := len(q.world.storage.archetypes) - 1
2,019✔
223
        for q.cursor.archetype < maxArchIndex {
4,042✔
224
                q.cursor.archetype++
2,023✔
225
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
2,023✔
226
                if !archetype.mask.Contains(&q.mask) ||
2,023✔
227
                        archetype.mask.ContainsAny(&q.without) {
3,036✔
228
                        continue
1,013✔
229
                }
230

231
                if !archetype.HasRelations() {
2,016✔
232
                        table := &q.world.storage.tables[archetype.tables[0]]
1,007✔
233
                        if table.Len() > 0 {
2,014✔
234
                                q.setTable(0, table)
1,007✔
235
                                return true
1,007✔
236
                        }
1,007✔
UNCOV
237
                        continue
×
238
                }
239

240
                q.tables = archetype.GetTables(q.relations)
2✔
241
                q.cursor.table = -1
2✔
242
                if q.nextTable() {
4✔
243
                        return true
2✔
244
                }
2✔
245
        }
246
        q.Close()
1,009✔
247
        return false
1,009✔
248
}
249

250
func (q *Query1[A]) nextTable() bool {
1,012✔
251
        maxTableIndex := len(q.tables) - 1
1,012✔
252
        for q.cursor.table < maxTableIndex {
1,016✔
253
                q.cursor.table++
4✔
254
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
255
                if table.Len() == 0 {
5✔
256
                        continue
1✔
257
                }
258
                if !table.Matches(q.relations) {
3✔
259
                        continue
×
260
                }
261
                q.setTable(q.cursor.table, table)
3✔
262
                return true
3✔
263
        }
264
        return false
1,009✔
265
}
266

267
func (q *Query1[A]) setTable(index int, table *table) {
1,010✔
268
        q.cursor.table = index
1,010✔
269
        q.table = table
1,010✔
270
        q.columnA = q.components[0].columns[q.table.id]
1,010✔
271
        q.cursor.index = 0
1,010✔
272
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
1,010✔
273
}
1,010✔
274

275
// Query2 is a query for 2 components.
276
// Use a [NewFilter2] to create one.
277
type Query2[A any, B any] struct {
278
        world      *World
279
        mask       Mask
280
        without    Mask
281
        relations  []relationID
282
        lock       uint8
283
        cursor     cursor
284
        tables     []tableID
285
        table      *table
286
        components []*componentStorage
287
        columnA    *column
288
        columnB    *column
289
        hasWithout bool
290
}
291

292
func newQuery2[A any, B any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query2[A, B] {
10✔
293
        components := make([]*componentStorage, 2)
10✔
294
        for i := range 2 {
30✔
295
                components[i] = &world.storage.components[ids[i].id]
20✔
296
        }
20✔
297

298
        return Query2[A, B]{
10✔
299
                world:      world,
10✔
300
                mask:       mask,
10✔
301
                without:    without,
10✔
302
                relations:  relations,
10✔
303
                hasWithout: !without.IsZero(),
10✔
304
                lock:       world.lock(),
10✔
305
                components: components,
10✔
306
                cursor: cursor{
10✔
307
                        archetype: -1,
10✔
308
                        table:     -1,
10✔
309
                        index:     0,
10✔
310
                        maxIndex:  -1,
10✔
311
                },
10✔
312
        }
10✔
313
}
314

315
// Next advances the query's cursor to the next entity.
316
func (q *Query2[A, B]) Next() bool {
195✔
317
        checkQueryNext(&q.cursor)
195✔
318
        if int64(q.cursor.index) < q.cursor.maxIndex {
368✔
319
                q.cursor.index++
173✔
320
                return true
173✔
321
        }
173✔
322
        return q.nextTableOrArchetype()
22✔
323
}
324

325
// Entity returns the current entity.
326
func (q *Query2[A, B]) Entity() Entity {
154✔
327
        checkQueryGet(&q.cursor)
154✔
328
        return q.table.GetEntity(q.cursor.index)
154✔
329
}
154✔
330

331
// Get returns the queried components of the current entity.
332
func (q *Query2[A, B]) Get() (*A, *B) {
186✔
333
        checkQueryGet(&q.cursor)
186✔
334
        return (*A)(q.columnA.Get(q.cursor.index)),
186✔
335
                (*B)(q.columnB.Get(q.cursor.index))
186✔
336
}
186✔
337

338
// GetRelation returns the entity relation target of the component at the given index.
339
func (q *Query2[A, B]) GetRelation(index int) Entity {
10✔
340
        return q.components[index].columns[q.table.id].target
10✔
341
}
10✔
342

343
// Close closes the Query and unlocks the world.
344
//
345
// Automatically called when iteration finishes.
346
// Needs to be called only if breaking out of the query iteration or not iterating at all.
347
func (q *Query2[A, B]) Close() {
10✔
348
        q.cursor.archetype = -2
10✔
349
        q.cursor.table = -2
10✔
350
        q.tables = nil
10✔
351
        q.table = nil
10✔
352
        q.columnA = nil
10✔
353
        q.columnB = nil
10✔
354
        q.world.unlock(q.lock)
10✔
355
}
10✔
356

357
func (q *Query2[A, B]) nextTableOrArchetype() bool {
22✔
358
        if q.cursor.archetype >= 0 && q.nextTable() {
23✔
359
                return true
1✔
360
        }
1✔
361
        return q.nextArchetype()
21✔
362
}
363

364
func (q *Query2[A, B]) nextArchetype() bool {
21✔
365
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
366
        for q.cursor.archetype < maxArchIndex {
50✔
367
                q.cursor.archetype++
29✔
368
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
369
                if !archetype.mask.Contains(&q.mask) ||
29✔
370
                        archetype.mask.ContainsAny(&q.without) {
47✔
371
                        continue
18✔
372
                }
373

374
                if !archetype.HasRelations() {
17✔
375
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
376
                        if table.Len() > 0 {
14✔
377
                                q.setTable(0, table)
7✔
378
                                return true
7✔
379
                        }
7✔
UNCOV
380
                        continue
×
381
                }
382

383
                q.tables = archetype.GetTables(q.relations)
3✔
384
                q.cursor.table = -1
3✔
385
                if q.nextTable() {
6✔
386
                        return true
3✔
387
                }
3✔
388
        }
389
        q.Close()
10✔
390
        return false
10✔
391
}
392

393
func (q *Query2[A, B]) nextTable() bool {
14✔
394
        maxTableIndex := len(q.tables) - 1
14✔
395
        for q.cursor.table < maxTableIndex {
19✔
396
                q.cursor.table++
5✔
397
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
5✔
398
                if table.Len() == 0 {
6✔
399
                        continue
1✔
400
                }
401
                if !table.Matches(q.relations) {
4✔
402
                        continue
×
403
                }
404
                q.setTable(q.cursor.table, table)
4✔
405
                return true
4✔
406
        }
407
        return false
10✔
408
}
409

410
func (q *Query2[A, B]) setTable(index int, table *table) {
11✔
411
        q.cursor.table = index
11✔
412
        q.table = table
11✔
413
        q.columnA = q.components[0].columns[q.table.id]
11✔
414
        q.columnB = q.components[1].columns[q.table.id]
11✔
415
        q.cursor.index = 0
11✔
416
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
11✔
417
}
11✔
418

419
// Query3 is a query for 3 components.
420
// Use a [NewFilter3] to create one.
421
type Query3[A any, B any, C any] struct {
422
        world      *World
423
        mask       Mask
424
        without    Mask
425
        relations  []relationID
426
        lock       uint8
427
        cursor     cursor
428
        tables     []tableID
429
        table      *table
430
        components []*componentStorage
431
        columnA    *column
432
        columnB    *column
433
        columnC    *column
434
        hasWithout bool
435
}
436

437
func newQuery3[A any, B any, C any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query3[A, B, C] {
12✔
438
        components := make([]*componentStorage, 3)
12✔
439
        for i := range 3 {
48✔
440
                components[i] = &world.storage.components[ids[i].id]
36✔
441
        }
36✔
442

443
        return Query3[A, B, C]{
12✔
444
                world:      world,
12✔
445
                mask:       mask,
12✔
446
                without:    without,
12✔
447
                relations:  relations,
12✔
448
                hasWithout: !without.IsZero(),
12✔
449
                lock:       world.lock(),
12✔
450
                components: components,
12✔
451
                cursor: cursor{
12✔
452
                        archetype: -1,
12✔
453
                        table:     -1,
12✔
454
                        index:     0,
12✔
455
                        maxIndex:  -1,
12✔
456
                },
12✔
457
        }
12✔
458
}
459

460
// Next advances the query's cursor to the next entity.
461
func (q *Query3[A, B, C]) Next() bool {
235✔
462
        checkQueryNext(&q.cursor)
235✔
463
        if int64(q.cursor.index) < q.cursor.maxIndex {
440✔
464
                q.cursor.index++
205✔
465
                return true
205✔
466
        }
205✔
467
        return q.nextTableOrArchetype()
30✔
468
}
469

470
// Entity returns the current entity.
471
func (q *Query3[A, B, C]) Entity() Entity {
154✔
472
        checkQueryGet(&q.cursor)
154✔
473
        return q.table.GetEntity(q.cursor.index)
154✔
474
}
154✔
475

476
// Get returns the queried components of the current entity.
477
func (q *Query3[A, B, C]) Get() (*A, *B, *C) {
154✔
478
        checkQueryGet(&q.cursor)
154✔
479
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
480
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
481
                (*C)(q.columnC.Get(q.cursor.index))
154✔
482
}
154✔
483

484
// GetRelation returns the entity relation target of the component at the given index.
485
func (q *Query3[A, B, C]) GetRelation(index int) Entity {
10✔
486
        return q.components[index].columns[q.table.id].target
10✔
487
}
10✔
488

489
// Close closes the Query and unlocks the world.
490
//
491
// Automatically called when iteration finishes.
492
// Needs to be called only if breaking out of the query iteration or not iterating at all.
493
func (q *Query3[A, B, C]) Close() {
12✔
494
        q.cursor.archetype = -2
12✔
495
        q.cursor.table = -2
12✔
496
        q.tables = nil
12✔
497
        q.table = nil
12✔
498
        q.columnA = nil
12✔
499
        q.columnB = nil
12✔
500
        q.columnC = nil
12✔
501
        q.world.unlock(q.lock)
12✔
502
}
12✔
503

504
func (q *Query3[A, B, C]) nextTableOrArchetype() bool {
30✔
505
        if q.cursor.archetype >= 0 && q.nextTable() {
35✔
506
                return true
5✔
507
        }
5✔
508
        return q.nextArchetype()
25✔
509
}
510

511
func (q *Query3[A, B, C]) nextArchetype() bool {
25✔
512
        maxArchIndex := len(q.world.storage.archetypes) - 1
25✔
513
        for q.cursor.archetype < maxArchIndex {
58✔
514
                q.cursor.archetype++
33✔
515
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
33✔
516
                if !archetype.mask.Contains(&q.mask) ||
33✔
517
                        archetype.mask.ContainsAny(&q.without) {
53✔
518
                        continue
20✔
519
                }
520

521
                if !archetype.HasRelations() {
19✔
522
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
523
                        if table.Len() > 0 {
14✔
524
                                q.setTable(0, table)
7✔
525
                                return true
7✔
526
                        }
7✔
UNCOV
527
                        continue
×
528
                }
529

530
                q.tables = archetype.GetTables(q.relations)
5✔
531
                q.cursor.table = -1
5✔
532
                if q.nextTable() {
10✔
533
                        return true
5✔
534
                }
5✔
535
        }
536
        q.Close()
12✔
537
        return false
12✔
538
}
539

540
func (q *Query3[A, B, C]) nextTable() bool {
22✔
541
        maxTableIndex := len(q.tables) - 1
22✔
542
        for q.cursor.table < maxTableIndex {
34✔
543
                q.cursor.table++
12✔
544
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
12✔
545
                if table.Len() == 0 {
13✔
546
                        continue
1✔
547
                }
548
                if !table.Matches(q.relations) {
12✔
549
                        continue
1✔
550
                }
551
                q.setTable(q.cursor.table, table)
10✔
552
                return true
10✔
553
        }
554
        return false
12✔
555
}
556

557
func (q *Query3[A, B, C]) setTable(index int, table *table) {
17✔
558
        q.cursor.table = index
17✔
559
        q.table = table
17✔
560
        q.columnA = q.components[0].columns[q.table.id]
17✔
561
        q.columnB = q.components[1].columns[q.table.id]
17✔
562
        q.columnC = q.components[2].columns[q.table.id]
17✔
563
        q.cursor.index = 0
17✔
564
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
17✔
565
}
17✔
566

567
// Query4 is a query for 4 components.
568
// Use a [NewFilter4] to create one.
569
type Query4[A any, B any, C any, D any] struct {
570
        world      *World
571
        mask       Mask
572
        without    Mask
573
        relations  []relationID
574
        lock       uint8
575
        cursor     cursor
576
        tables     []tableID
577
        table      *table
578
        components []*componentStorage
579
        columnA    *column
580
        columnB    *column
581
        columnC    *column
582
        columnD    *column
583
        hasWithout bool
584
}
585

586
func newQuery4[A any, B any, C any, D any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query4[A, B, C, D] {
9✔
587
        components := make([]*componentStorage, 4)
9✔
588
        for i := range 4 {
45✔
589
                components[i] = &world.storage.components[ids[i].id]
36✔
590
        }
36✔
591

592
        return Query4[A, B, C, D]{
9✔
593
                world:      world,
9✔
594
                mask:       mask,
9✔
595
                without:    without,
9✔
596
                relations:  relations,
9✔
597
                hasWithout: !without.IsZero(),
9✔
598
                lock:       world.lock(),
9✔
599
                components: components,
9✔
600
                cursor: cursor{
9✔
601
                        archetype: -1,
9✔
602
                        table:     -1,
9✔
603
                        index:     0,
9✔
604
                        maxIndex:  -1,
9✔
605
                },
9✔
606
        }
9✔
607
}
608

609
// Next advances the query's cursor to the next entity.
610
func (q *Query4[A, B, C, D]) Next() bool {
162✔
611
        checkQueryNext(&q.cursor)
162✔
612
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
613
                q.cursor.index++
142✔
614
                return true
142✔
615
        }
142✔
616
        return q.nextTableOrArchetype()
20✔
617
}
618

619
// Entity returns the current entity.
620
func (q *Query4[A, B, C, D]) Entity() Entity {
154✔
621
        checkQueryGet(&q.cursor)
154✔
622
        return q.table.GetEntity(q.cursor.index)
154✔
623
}
154✔
624

625
// Get returns the queried components of the current entity.
626
func (q *Query4[A, B, C, D]) Get() (*A, *B, *C, *D) {
154✔
627
        checkQueryGet(&q.cursor)
154✔
628
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
629
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
630
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
631
                (*D)(q.columnD.Get(q.cursor.index))
154✔
632
}
154✔
633

634
// GetRelation returns the entity relation target of the component at the given index.
635
func (q *Query4[A, B, C, D]) GetRelation(index int) Entity {
10✔
636
        return q.components[index].columns[q.table.id].target
10✔
637
}
10✔
638

639
// Close closes the Query and unlocks the world.
640
//
641
// Automatically called when iteration finishes.
642
// Needs to be called only if breaking out of the query iteration or not iterating at all.
643
func (q *Query4[A, B, C, D]) Close() {
9✔
644
        q.cursor.archetype = -2
9✔
645
        q.cursor.table = -2
9✔
646
        q.tables = nil
9✔
647
        q.table = nil
9✔
648
        q.columnA = nil
9✔
649
        q.columnB = nil
9✔
650
        q.columnC = nil
9✔
651
        q.columnD = nil
9✔
652
        q.world.unlock(q.lock)
9✔
653
}
9✔
654

655
func (q *Query4[A, B, C, D]) nextTableOrArchetype() bool {
20✔
656
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
657
                return true
1✔
658
        }
1✔
659
        return q.nextArchetype()
19✔
660
}
661

662
func (q *Query4[A, B, C, D]) nextArchetype() bool {
19✔
663
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
664
        for q.cursor.archetype < maxArchIndex {
46✔
665
                q.cursor.archetype++
27✔
666
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
667
                if !archetype.mask.Contains(&q.mask) ||
27✔
668
                        archetype.mask.ContainsAny(&q.without) {
44✔
669
                        continue
17✔
670
                }
671

672
                if !archetype.HasRelations() {
16✔
673
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
674
                        if table.Len() > 0 {
14✔
675
                                q.setTable(0, table)
7✔
676
                                return true
7✔
677
                        }
7✔
UNCOV
678
                        continue
×
679
                }
680

681
                q.tables = archetype.GetTables(q.relations)
2✔
682
                q.cursor.table = -1
2✔
683
                if q.nextTable() {
4✔
684
                        return true
2✔
685
                }
2✔
686
        }
687
        q.Close()
9✔
688
        return false
9✔
689
}
690

691
func (q *Query4[A, B, C, D]) nextTable() bool {
12✔
692
        maxTableIndex := len(q.tables) - 1
12✔
693
        for q.cursor.table < maxTableIndex {
16✔
694
                q.cursor.table++
4✔
695
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
696
                if table.Len() == 0 {
5✔
697
                        continue
1✔
698
                }
699
                if !table.Matches(q.relations) {
3✔
700
                        continue
×
701
                }
702
                q.setTable(q.cursor.table, table)
3✔
703
                return true
3✔
704
        }
705
        return false
9✔
706
}
707

708
func (q *Query4[A, B, C, D]) setTable(index int, table *table) {
10✔
709
        q.cursor.table = index
10✔
710
        q.table = table
10✔
711
        q.columnA = q.components[0].columns[q.table.id]
10✔
712
        q.columnB = q.components[1].columns[q.table.id]
10✔
713
        q.columnC = q.components[2].columns[q.table.id]
10✔
714
        q.columnD = q.components[3].columns[q.table.id]
10✔
715
        q.cursor.index = 0
10✔
716
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
717
}
10✔
718

719
// Query5 is a query for 5 components.
720
// Use a [NewFilter5] to create one.
721
type Query5[A any, B any, C any, D any, E any] struct {
722
        world      *World
723
        mask       Mask
724
        without    Mask
725
        relations  []relationID
726
        lock       uint8
727
        cursor     cursor
728
        tables     []tableID
729
        table      *table
730
        components []*componentStorage
731
        columnA    *column
732
        columnB    *column
733
        columnC    *column
734
        columnD    *column
735
        columnE    *column
736
        hasWithout bool
737
}
738

739
func newQuery5[A any, B any, C any, D any, E any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query5[A, B, C, D, E] {
9✔
740
        components := make([]*componentStorage, 5)
9✔
741
        for i := range 5 {
54✔
742
                components[i] = &world.storage.components[ids[i].id]
45✔
743
        }
45✔
744

745
        return Query5[A, B, C, D, E]{
9✔
746
                world:      world,
9✔
747
                mask:       mask,
9✔
748
                without:    without,
9✔
749
                relations:  relations,
9✔
750
                hasWithout: !without.IsZero(),
9✔
751
                lock:       world.lock(),
9✔
752
                components: components,
9✔
753
                cursor: cursor{
9✔
754
                        archetype: -1,
9✔
755
                        table:     -1,
9✔
756
                        index:     0,
9✔
757
                        maxIndex:  -1,
9✔
758
                },
9✔
759
        }
9✔
760
}
761

762
// Next advances the query's cursor to the next entity.
763
func (q *Query5[A, B, C, D, E]) Next() bool {
162✔
764
        checkQueryNext(&q.cursor)
162✔
765
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
766
                q.cursor.index++
142✔
767
                return true
142✔
768
        }
142✔
769
        return q.nextTableOrArchetype()
20✔
770
}
771

772
// Entity returns the current entity.
773
func (q *Query5[A, B, C, D, E]) Entity() Entity {
154✔
774
        checkQueryGet(&q.cursor)
154✔
775
        return q.table.GetEntity(q.cursor.index)
154✔
776
}
154✔
777

778
// Get returns the queried components of the current entity.
779
func (q *Query5[A, B, C, D, E]) Get() (*A, *B, *C, *D, *E) {
154✔
780
        checkQueryGet(&q.cursor)
154✔
781
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
782
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
783
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
784
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
785
                (*E)(q.columnE.Get(q.cursor.index))
154✔
786
}
154✔
787

788
// GetRelation returns the entity relation target of the component at the given index.
789
func (q *Query5[A, B, C, D, E]) GetRelation(index int) Entity {
10✔
790
        return q.components[index].columns[q.table.id].target
10✔
791
}
10✔
792

793
// Close closes the Query and unlocks the world.
794
//
795
// Automatically called when iteration finishes.
796
// Needs to be called only if breaking out of the query iteration or not iterating at all.
797
func (q *Query5[A, B, C, D, E]) Close() {
9✔
798
        q.cursor.archetype = -2
9✔
799
        q.cursor.table = -2
9✔
800
        q.tables = nil
9✔
801
        q.table = nil
9✔
802
        q.columnA = nil
9✔
803
        q.columnB = nil
9✔
804
        q.columnC = nil
9✔
805
        q.columnD = nil
9✔
806
        q.columnE = nil
9✔
807
        q.world.unlock(q.lock)
9✔
808
}
9✔
809

810
func (q *Query5[A, B, C, D, E]) nextTableOrArchetype() bool {
20✔
811
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
812
                return true
1✔
813
        }
1✔
814
        return q.nextArchetype()
19✔
815
}
816

817
func (q *Query5[A, B, C, D, E]) nextArchetype() bool {
19✔
818
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
819
        for q.cursor.archetype < maxArchIndex {
46✔
820
                q.cursor.archetype++
27✔
821
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
822
                if !archetype.mask.Contains(&q.mask) ||
27✔
823
                        archetype.mask.ContainsAny(&q.without) {
44✔
824
                        continue
17✔
825
                }
826

827
                if !archetype.HasRelations() {
16✔
828
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
829
                        if table.Len() > 0 {
14✔
830
                                q.setTable(0, table)
7✔
831
                                return true
7✔
832
                        }
7✔
UNCOV
833
                        continue
×
834
                }
835

836
                q.tables = archetype.GetTables(q.relations)
2✔
837
                q.cursor.table = -1
2✔
838
                if q.nextTable() {
4✔
839
                        return true
2✔
840
                }
2✔
841
        }
842
        q.Close()
9✔
843
        return false
9✔
844
}
845

846
func (q *Query5[A, B, C, D, E]) nextTable() bool {
12✔
847
        maxTableIndex := len(q.tables) - 1
12✔
848
        for q.cursor.table < maxTableIndex {
16✔
849
                q.cursor.table++
4✔
850
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
851
                if table.Len() == 0 {
5✔
852
                        continue
1✔
853
                }
854
                if !table.Matches(q.relations) {
3✔
855
                        continue
×
856
                }
857
                q.setTable(q.cursor.table, table)
3✔
858
                return true
3✔
859
        }
860
        return false
9✔
861
}
862

863
func (q *Query5[A, B, C, D, E]) setTable(index int, table *table) {
10✔
864
        q.cursor.table = index
10✔
865
        q.table = table
10✔
866
        q.columnA = q.components[0].columns[q.table.id]
10✔
867
        q.columnB = q.components[1].columns[q.table.id]
10✔
868
        q.columnC = q.components[2].columns[q.table.id]
10✔
869
        q.columnD = q.components[3].columns[q.table.id]
10✔
870
        q.columnE = q.components[4].columns[q.table.id]
10✔
871
        q.cursor.index = 0
10✔
872
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
873
}
10✔
874

875
// Query6 is a query for 6 components.
876
// Use a [NewFilter6] to create one.
877
type Query6[A any, B any, C any, D any, E any, F any] struct {
878
        world      *World
879
        mask       Mask
880
        without    Mask
881
        relations  []relationID
882
        lock       uint8
883
        cursor     cursor
884
        tables     []tableID
885
        table      *table
886
        components []*componentStorage
887
        columnA    *column
888
        columnB    *column
889
        columnC    *column
890
        columnD    *column
891
        columnE    *column
892
        columnF    *column
893
        hasWithout bool
894
}
895

896
func newQuery6[A any, B any, C any, D any, E any, F any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query6[A, B, C, D, E, F] {
9✔
897
        components := make([]*componentStorage, 6)
9✔
898
        for i := range 6 {
63✔
899
                components[i] = &world.storage.components[ids[i].id]
54✔
900
        }
54✔
901

902
        return Query6[A, B, C, D, E, F]{
9✔
903
                world:      world,
9✔
904
                mask:       mask,
9✔
905
                without:    without,
9✔
906
                relations:  relations,
9✔
907
                hasWithout: !without.IsZero(),
9✔
908
                lock:       world.lock(),
9✔
909
                components: components,
9✔
910
                cursor: cursor{
9✔
911
                        archetype: -1,
9✔
912
                        table:     -1,
9✔
913
                        index:     0,
9✔
914
                        maxIndex:  -1,
9✔
915
                },
9✔
916
        }
9✔
917
}
918

919
// Next advances the query's cursor to the next entity.
920
func (q *Query6[A, B, C, D, E, F]) Next() bool {
162✔
921
        checkQueryNext(&q.cursor)
162✔
922
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
923
                q.cursor.index++
142✔
924
                return true
142✔
925
        }
142✔
926
        return q.nextTableOrArchetype()
20✔
927
}
928

929
// Entity returns the current entity.
930
func (q *Query6[A, B, C, D, E, F]) Entity() Entity {
154✔
931
        checkQueryGet(&q.cursor)
154✔
932
        return q.table.GetEntity(q.cursor.index)
154✔
933
}
154✔
934

935
// Get returns the queried components of the current entity.
936
func (q *Query6[A, B, C, D, E, F]) Get() (*A, *B, *C, *D, *E, *F) {
154✔
937
        checkQueryGet(&q.cursor)
154✔
938
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
939
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
940
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
941
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
942
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
943
                (*F)(q.columnF.Get(q.cursor.index))
154✔
944
}
154✔
945

946
// GetRelation returns the entity relation target of the component at the given index.
947
func (q *Query6[A, B, C, D, E, F]) GetRelation(index int) Entity {
10✔
948
        return q.components[index].columns[q.table.id].target
10✔
949
}
10✔
950

951
// Close closes the Query and unlocks the world.
952
//
953
// Automatically called when iteration finishes.
954
// Needs to be called only if breaking out of the query iteration or not iterating at all.
955
func (q *Query6[A, B, C, D, E, F]) Close() {
9✔
956
        q.cursor.archetype = -2
9✔
957
        q.cursor.table = -2
9✔
958
        q.tables = nil
9✔
959
        q.table = nil
9✔
960
        q.columnA = nil
9✔
961
        q.columnB = nil
9✔
962
        q.columnC = nil
9✔
963
        q.columnD = nil
9✔
964
        q.columnE = nil
9✔
965
        q.columnF = nil
9✔
966
        q.world.unlock(q.lock)
9✔
967
}
9✔
968

969
func (q *Query6[A, B, C, D, E, F]) nextTableOrArchetype() bool {
20✔
970
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
971
                return true
1✔
972
        }
1✔
973
        return q.nextArchetype()
19✔
974
}
975

976
func (q *Query6[A, B, C, D, E, F]) nextArchetype() bool {
19✔
977
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
978
        for q.cursor.archetype < maxArchIndex {
46✔
979
                q.cursor.archetype++
27✔
980
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
981
                if !archetype.mask.Contains(&q.mask) ||
27✔
982
                        archetype.mask.ContainsAny(&q.without) {
44✔
983
                        continue
17✔
984
                }
985

986
                if !archetype.HasRelations() {
16✔
987
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
988
                        if table.Len() > 0 {
14✔
989
                                q.setTable(0, table)
7✔
990
                                return true
7✔
991
                        }
7✔
UNCOV
992
                        continue
×
993
                }
994

995
                q.tables = archetype.GetTables(q.relations)
2✔
996
                q.cursor.table = -1
2✔
997
                if q.nextTable() {
4✔
998
                        return true
2✔
999
                }
2✔
1000
        }
1001
        q.Close()
9✔
1002
        return false
9✔
1003
}
1004

1005
func (q *Query6[A, B, C, D, E, F]) nextTable() bool {
12✔
1006
        maxTableIndex := len(q.tables) - 1
12✔
1007
        for q.cursor.table < maxTableIndex {
16✔
1008
                q.cursor.table++
4✔
1009
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
1010
                if table.Len() == 0 {
5✔
1011
                        continue
1✔
1012
                }
1013
                if !table.Matches(q.relations) {
3✔
1014
                        continue
×
1015
                }
1016
                q.setTable(q.cursor.table, table)
3✔
1017
                return true
3✔
1018
        }
1019
        return false
9✔
1020
}
1021

1022
func (q *Query6[A, B, C, D, E, F]) setTable(index int, table *table) {
10✔
1023
        q.cursor.table = index
10✔
1024
        q.table = table
10✔
1025
        q.columnA = q.components[0].columns[q.table.id]
10✔
1026
        q.columnB = q.components[1].columns[q.table.id]
10✔
1027
        q.columnC = q.components[2].columns[q.table.id]
10✔
1028
        q.columnD = q.components[3].columns[q.table.id]
10✔
1029
        q.columnE = q.components[4].columns[q.table.id]
10✔
1030
        q.columnF = q.components[5].columns[q.table.id]
10✔
1031
        q.cursor.index = 0
10✔
1032
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1033
}
10✔
1034

1035
// Query7 is a query for 7 components.
1036
// Use a [NewFilter7] to create one.
1037
type Query7[A any, B any, C any, D any, E any, F any, G any] struct {
1038
        world      *World
1039
        mask       Mask
1040
        without    Mask
1041
        relations  []relationID
1042
        lock       uint8
1043
        cursor     cursor
1044
        tables     []tableID
1045
        table      *table
1046
        components []*componentStorage
1047
        columnA    *column
1048
        columnB    *column
1049
        columnC    *column
1050
        columnD    *column
1051
        columnE    *column
1052
        columnF    *column
1053
        columnG    *column
1054
        hasWithout bool
1055
}
1056

1057
func newQuery7[A any, B any, C any, D any, E any, F any, G any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query7[A, B, C, D, E, F, G] {
9✔
1058
        components := make([]*componentStorage, 7)
9✔
1059
        for i := range 7 {
72✔
1060
                components[i] = &world.storage.components[ids[i].id]
63✔
1061
        }
63✔
1062

1063
        return Query7[A, B, C, D, E, F, G]{
9✔
1064
                world:      world,
9✔
1065
                mask:       mask,
9✔
1066
                without:    without,
9✔
1067
                relations:  relations,
9✔
1068
                hasWithout: !without.IsZero(),
9✔
1069
                lock:       world.lock(),
9✔
1070
                components: components,
9✔
1071
                cursor: cursor{
9✔
1072
                        archetype: -1,
9✔
1073
                        table:     -1,
9✔
1074
                        index:     0,
9✔
1075
                        maxIndex:  -1,
9✔
1076
                },
9✔
1077
        }
9✔
1078
}
1079

1080
// Next advances the query's cursor to the next entity.
1081
func (q *Query7[A, B, C, D, E, F, G]) Next() bool {
162✔
1082
        checkQueryNext(&q.cursor)
162✔
1083
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
1084
                q.cursor.index++
142✔
1085
                return true
142✔
1086
        }
142✔
1087
        return q.nextTableOrArchetype()
20✔
1088
}
1089

1090
// Entity returns the current entity.
1091
func (q *Query7[A, B, C, D, E, F, G]) Entity() Entity {
154✔
1092
        checkQueryGet(&q.cursor)
154✔
1093
        return q.table.GetEntity(q.cursor.index)
154✔
1094
}
154✔
1095

1096
// Get returns the queried components of the current entity.
1097
func (q *Query7[A, B, C, D, E, F, G]) Get() (*A, *B, *C, *D, *E, *F, *G) {
154✔
1098
        checkQueryGet(&q.cursor)
154✔
1099
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
1100
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
1101
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
1102
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
1103
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
1104
                (*F)(q.columnF.Get(q.cursor.index)),
154✔
1105
                (*G)(q.columnG.Get(q.cursor.index))
154✔
1106
}
154✔
1107

1108
// GetRelation returns the entity relation target of the component at the given index.
1109
func (q *Query7[A, B, C, D, E, F, G]) GetRelation(index int) Entity {
10✔
1110
        return q.components[index].columns[q.table.id].target
10✔
1111
}
10✔
1112

1113
// Close closes the Query and unlocks the world.
1114
//
1115
// Automatically called when iteration finishes.
1116
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1117
func (q *Query7[A, B, C, D, E, F, G]) Close() {
9✔
1118
        q.cursor.archetype = -2
9✔
1119
        q.cursor.table = -2
9✔
1120
        q.tables = nil
9✔
1121
        q.table = nil
9✔
1122
        q.columnA = nil
9✔
1123
        q.columnB = nil
9✔
1124
        q.columnC = nil
9✔
1125
        q.columnD = nil
9✔
1126
        q.columnE = nil
9✔
1127
        q.columnF = nil
9✔
1128
        q.columnG = nil
9✔
1129
        q.world.unlock(q.lock)
9✔
1130
}
9✔
1131

1132
func (q *Query7[A, B, C, D, E, F, G]) nextTableOrArchetype() bool {
20✔
1133
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
1134
                return true
1✔
1135
        }
1✔
1136
        return q.nextArchetype()
19✔
1137
}
1138

1139
func (q *Query7[A, B, C, D, E, F, G]) nextArchetype() bool {
19✔
1140
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
1141
        for q.cursor.archetype < maxArchIndex {
46✔
1142
                q.cursor.archetype++
27✔
1143
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
1144
                if !archetype.mask.Contains(&q.mask) ||
27✔
1145
                        archetype.mask.ContainsAny(&q.without) {
44✔
1146
                        continue
17✔
1147
                }
1148

1149
                if !archetype.HasRelations() {
16✔
1150
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1151
                        if table.Len() > 0 {
14✔
1152
                                q.setTable(0, table)
7✔
1153
                                return true
7✔
1154
                        }
7✔
UNCOV
1155
                        continue
×
1156
                }
1157

1158
                q.tables = archetype.GetTables(q.relations)
2✔
1159
                q.cursor.table = -1
2✔
1160
                if q.nextTable() {
4✔
1161
                        return true
2✔
1162
                }
2✔
1163
        }
1164
        q.Close()
9✔
1165
        return false
9✔
1166
}
1167

1168
func (q *Query7[A, B, C, D, E, F, G]) nextTable() bool {
12✔
1169
        maxTableIndex := len(q.tables) - 1
12✔
1170
        for q.cursor.table < maxTableIndex {
16✔
1171
                q.cursor.table++
4✔
1172
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
1173
                if table.Len() == 0 {
5✔
1174
                        continue
1✔
1175
                }
1176
                if !table.Matches(q.relations) {
3✔
1177
                        continue
×
1178
                }
1179
                q.setTable(q.cursor.table, table)
3✔
1180
                return true
3✔
1181
        }
1182
        return false
9✔
1183
}
1184

1185
func (q *Query7[A, B, C, D, E, F, G]) setTable(index int, table *table) {
10✔
1186
        q.cursor.table = index
10✔
1187
        q.table = table
10✔
1188
        q.columnA = q.components[0].columns[q.table.id]
10✔
1189
        q.columnB = q.components[1].columns[q.table.id]
10✔
1190
        q.columnC = q.components[2].columns[q.table.id]
10✔
1191
        q.columnD = q.components[3].columns[q.table.id]
10✔
1192
        q.columnE = q.components[4].columns[q.table.id]
10✔
1193
        q.columnF = q.components[5].columns[q.table.id]
10✔
1194
        q.columnG = q.components[6].columns[q.table.id]
10✔
1195
        q.cursor.index = 0
10✔
1196
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1197
}
10✔
1198

1199
// Query8 is a query for 8 components.
1200
// Use a [NewFilter8] to create one.
1201
type Query8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1202
        world      *World
1203
        mask       Mask
1204
        without    Mask
1205
        relations  []relationID
1206
        lock       uint8
1207
        cursor     cursor
1208
        tables     []tableID
1209
        table      *table
1210
        components []*componentStorage
1211
        columnA    *column
1212
        columnB    *column
1213
        columnC    *column
1214
        columnD    *column
1215
        columnE    *column
1216
        columnF    *column
1217
        columnG    *column
1218
        columnH    *column
1219
        hasWithout bool
1220
}
1221

1222
func newQuery8[A any, B any, C any, D any, E any, F any, G any, H any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query8[A, B, C, D, E, F, G, H] {
9✔
1223
        components := make([]*componentStorage, 8)
9✔
1224
        for i := range 8 {
81✔
1225
                components[i] = &world.storage.components[ids[i].id]
72✔
1226
        }
72✔
1227

1228
        return Query8[A, B, C, D, E, F, G, H]{
9✔
1229
                world:      world,
9✔
1230
                mask:       mask,
9✔
1231
                without:    without,
9✔
1232
                relations:  relations,
9✔
1233
                hasWithout: !without.IsZero(),
9✔
1234
                lock:       world.lock(),
9✔
1235
                components: components,
9✔
1236
                cursor: cursor{
9✔
1237
                        archetype: -1,
9✔
1238
                        table:     -1,
9✔
1239
                        index:     0,
9✔
1240
                        maxIndex:  -1,
9✔
1241
                },
9✔
1242
        }
9✔
1243
}
1244

1245
// Next advances the query's cursor to the next entity.
1246
func (q *Query8[A, B, C, D, E, F, G, H]) Next() bool {
162✔
1247
        checkQueryNext(&q.cursor)
162✔
1248
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
1249
                q.cursor.index++
142✔
1250
                return true
142✔
1251
        }
142✔
1252
        return q.nextTableOrArchetype()
20✔
1253
}
1254

1255
// Entity returns the current entity.
1256
func (q *Query8[A, B, C, D, E, F, G, H]) Entity() Entity {
154✔
1257
        checkQueryGet(&q.cursor)
154✔
1258
        return q.table.GetEntity(q.cursor.index)
154✔
1259
}
154✔
1260

1261
// Get returns the queried components of the current entity.
1262
func (q *Query8[A, B, C, D, E, F, G, H]) Get() (*A, *B, *C, *D, *E, *F, *G, *H) {
154✔
1263
        checkQueryGet(&q.cursor)
154✔
1264
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
1265
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
1266
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
1267
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
1268
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
1269
                (*F)(q.columnF.Get(q.cursor.index)),
154✔
1270
                (*G)(q.columnG.Get(q.cursor.index)),
154✔
1271
                (*H)(q.columnH.Get(q.cursor.index))
154✔
1272
}
154✔
1273

1274
// GetRelation returns the entity relation target of the component at the given index.
1275
func (q *Query8[A, B, C, D, E, F, G, H]) GetRelation(index int) Entity {
10✔
1276
        return q.components[index].columns[q.table.id].target
10✔
1277
}
10✔
1278

1279
// Close closes the Query and unlocks the world.
1280
//
1281
// Automatically called when iteration finishes.
1282
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1283
func (q *Query8[A, B, C, D, E, F, G, H]) Close() {
9✔
1284
        q.cursor.archetype = -2
9✔
1285
        q.cursor.table = -2
9✔
1286
        q.tables = nil
9✔
1287
        q.table = nil
9✔
1288
        q.columnA = nil
9✔
1289
        q.columnB = nil
9✔
1290
        q.columnC = nil
9✔
1291
        q.columnD = nil
9✔
1292
        q.columnE = nil
9✔
1293
        q.columnF = nil
9✔
1294
        q.columnG = nil
9✔
1295
        q.columnH = nil
9✔
1296
        q.world.unlock(q.lock)
9✔
1297
}
9✔
1298

1299
func (q *Query8[A, B, C, D, E, F, G, H]) nextTableOrArchetype() bool {
20✔
1300
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
1301
                return true
1✔
1302
        }
1✔
1303
        return q.nextArchetype()
19✔
1304
}
1305

1306
func (q *Query8[A, B, C, D, E, F, G, H]) nextArchetype() bool {
19✔
1307
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
1308
        for q.cursor.archetype < maxArchIndex {
46✔
1309
                q.cursor.archetype++
27✔
1310
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
1311
                if !archetype.mask.Contains(&q.mask) ||
27✔
1312
                        archetype.mask.ContainsAny(&q.without) {
44✔
1313
                        continue
17✔
1314
                }
1315

1316
                if !archetype.HasRelations() {
16✔
1317
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1318
                        if table.Len() > 0 {
14✔
1319
                                q.setTable(0, table)
7✔
1320
                                return true
7✔
1321
                        }
7✔
UNCOV
1322
                        continue
×
1323
                }
1324

1325
                q.tables = archetype.GetTables(q.relations)
2✔
1326
                q.cursor.table = -1
2✔
1327
                if q.nextTable() {
4✔
1328
                        return true
2✔
1329
                }
2✔
1330
        }
1331
        q.Close()
9✔
1332
        return false
9✔
1333
}
1334

1335
func (q *Query8[A, B, C, D, E, F, G, H]) nextTable() bool {
12✔
1336
        maxTableIndex := len(q.tables) - 1
12✔
1337
        for q.cursor.table < maxTableIndex {
16✔
1338
                q.cursor.table++
4✔
1339
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
1340
                if table.Len() == 0 {
5✔
1341
                        continue
1✔
1342
                }
1343
                if !table.Matches(q.relations) {
3✔
1344
                        continue
×
1345
                }
1346
                q.setTable(q.cursor.table, table)
3✔
1347
                return true
3✔
1348
        }
1349
        return false
9✔
1350
}
1351

1352
func (q *Query8[A, B, C, D, E, F, G, H]) setTable(index int, table *table) {
10✔
1353
        q.cursor.table = index
10✔
1354
        q.table = table
10✔
1355
        q.columnA = q.components[0].columns[q.table.id]
10✔
1356
        q.columnB = q.components[1].columns[q.table.id]
10✔
1357
        q.columnC = q.components[2].columns[q.table.id]
10✔
1358
        q.columnD = q.components[3].columns[q.table.id]
10✔
1359
        q.columnE = q.components[4].columns[q.table.id]
10✔
1360
        q.columnF = q.components[5].columns[q.table.id]
10✔
1361
        q.columnG = q.components[6].columns[q.table.id]
10✔
1362
        q.columnH = q.components[7].columns[q.table.id]
10✔
1363
        q.cursor.index = 0
10✔
1364
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1365
}
10✔
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