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

mlange-42 / ark / 13723344389

07 Mar 2025 03:01PM CUT coverage: 99.423%. Remained the same
13723344389

Pull #151

github

web-flow
Merge e9fce0bab into ca9dc1892
Pull Request #151: Explain FilterX.Register

6378 of 6415 relevant lines covered (99.42%)

27908.64 hits per line

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

99.05
/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
        filter     *filter
17
        relations  []RelationID
18
        lock       uint8
19
        cursor     cursor
20
        tables     []tableID
21
        table      *table
22
        cache      *cacheEntry
23
        components []*componentStorage
24
}
25

26
func newQuery0(world *World, filter *filter, relations []RelationID,
27
        cacheID cacheID, components []*componentStorage) Query0 {
10✔
28
        var cache *cacheEntry
10✔
29
        if cacheID != maxCacheID {
11✔
30
                cache = world.storage.getRegisteredFilter(cacheID)
1✔
31
        }
1✔
32

33
        return Query0{
10✔
34
                world:      world,
10✔
35
                filter:     filter,
10✔
36
                relations:  relations,
10✔
37
                cache:      cache,
10✔
38
                lock:       world.lock(),
10✔
39
                components: components,
10✔
40
                cursor: cursor{
10✔
41
                        archetype: -1,
10✔
42
                        table:     -1,
10✔
43
                        index:     0,
10✔
44
                        maxIndex:  -1,
10✔
45
                },
10✔
46
        }
10✔
47
}
48

49
// Next advances the query's cursor to the next entity.
50
func (q *Query0) Next() bool {
239✔
51
        q.world.checkQueryNext(&q.cursor)
239✔
52
        if int64(q.cursor.index) < q.cursor.maxIndex {
452✔
53
                q.cursor.index++
213✔
54
                return true
213✔
55
        }
213✔
56
        return q.nextTableOrArchetype()
26✔
57
}
58

59
// Entity returns the current entity.
60
func (q *Query0) Entity() Entity {
218✔
61
        q.world.checkQueryGet(&q.cursor)
218✔
62
        return q.table.GetEntity(q.cursor.index)
218✔
63
}
218✔
64

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

78
func (q *Query0) nextTableOrArchetype() bool {
26✔
79
        if q.cache != nil {
31✔
80
                return q.nextTable(q.cache.tables)
5✔
81
        }
5✔
82
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
83
                return true
2✔
84
        }
2✔
85
        return q.nextArchetype()
19✔
86
}
87

88
func (q *Query0) nextArchetype() bool {
19✔
89
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
90
        for q.cursor.archetype < maxArchIndex {
40✔
91
                q.cursor.archetype++
21✔
92
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
21✔
93
                if !q.filter.matches(&archetype.mask) {
25✔
94
                        continue
4✔
95
                }
96

97
                if !archetype.HasRelations() {
31✔
98
                        table := &q.world.storage.tables[archetype.tables[0]]
15✔
99
                        if table.Len() > 0 {
23✔
100
                                q.setTable(0, table)
8✔
101
                                return true
8✔
102
                        }
8✔
103
                        continue
7✔
104
                }
105

106
                q.tables = archetype.GetTables(q.relations)
1✔
107
                q.cursor.table = -1
1✔
108
                if q.nextTable(q.tables) {
2✔
109
                        return true
1✔
110
                }
1✔
111
        }
112
        q.Close()
9✔
113
        return false
9✔
114
}
115

116
func (q *Query0) nextTable(tables []tableID) bool {
17✔
117
        maxTableIndex := len(tables) - 1
17✔
118
        for q.cursor.table < maxTableIndex {
24✔
119
                q.cursor.table++
7✔
120
                table := &q.world.storage.tables[tables[q.cursor.table]]
7✔
121
                if table.Len() == 0 {
7✔
122
                        continue
×
123
                }
124
                if !table.Matches(q.relations) {
7✔
125
                        continue
×
126
                }
127
                q.setTable(q.cursor.table, table)
7✔
128
                return true
7✔
129
        }
130
        if q.cache != nil {
11✔
131
                q.Close()
1✔
132
        }
1✔
133
        return false
10✔
134
}
135

136
func (q *Query0) setTable(index int, table *table) {
15✔
137
        q.cursor.table = index
15✔
138
        q.table = table
15✔
139
        q.cursor.index = 0
15✔
140
        q.cursor.maxIndex = int64(q.table.Len() - 1)
15✔
141
}
15✔
142

143
// Query1 is a query for 1 components.
144
// Use a [NewFilter1] to create one.
145
type Query1[A any] struct {
146
        world      *World
147
        filter     *filter
148
        relations  []RelationID
149
        lock       uint8
150
        cursor     cursor
151
        tables     []tableID
152
        table      *table
153
        cache      *cacheEntry
154
        components []*componentStorage
155
        columnA    *column
156
}
157

158
func newQuery1[A any](world *World, filter *filter, ids []ID, relations []RelationID,
159
        cacheID cacheID, components []*componentStorage) Query1[A] {
1,112✔
160
        var cache *cacheEntry
1,112✔
161
        if cacheID != maxCacheID {
1,115✔
162
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
163
        }
3✔
164

165
        return Query1[A]{
1,112✔
166
                world:      world,
1,112✔
167
                filter:     filter,
1,112✔
168
                relations:  relations,
1,112✔
169
                cache:      cache,
1,112✔
170
                lock:       world.lock(),
1,112✔
171
                components: components,
1,112✔
172
                cursor: cursor{
1,112✔
173
                        archetype: -1,
1,112✔
174
                        table:     -1,
1,112✔
175
                        index:     0,
1,112✔
176
                        maxIndex:  -1,
1,112✔
177
                },
1,112✔
178
        }
1,112✔
179
}
180

181
// Next advances the query's cursor to the next entity.
182
func (q *Query1[A]) Next() bool {
979,572✔
183
        q.world.checkQueryNext(&q.cursor)
979,572✔
184
        if int64(q.cursor.index) < q.cursor.maxIndex {
1,956,910✔
185
                q.cursor.index++
977,338✔
186
                return true
977,338✔
187
        }
977,338✔
188
        return q.nextTableOrArchetype()
2,234✔
189
}
190

191
// Entity returns the current entity.
192
func (q *Query1[A]) Entity() Entity {
1,955,132✔
193
        q.world.checkQueryGet(&q.cursor)
1,955,132✔
194
        return q.table.GetEntity(q.cursor.index)
1,955,132✔
195
}
1,955,132✔
196

197
// Get returns the queried components of the current entity.
198
func (q *Query1[A]) Get() *A {
977,667✔
199
        q.world.checkQueryGet(&q.cursor)
977,667✔
200
        return (*A)(q.columnA.Get(q.cursor.index))
977,667✔
201
}
977,667✔
202

203
// GetRelation returns the entity relation target of the component at the given index.
204
func (q *Query1[A]) GetRelation(index int) Entity {
42✔
205
        return q.components[index].columns[q.table.id].target
42✔
206
}
42✔
207

208
// Close closes the Query and unlocks the world.
209
//
210
// Automatically called when iteration finishes.
211
// Needs to be called only if breaking out of the query iteration or not iterating at all.
212
func (q *Query1[A]) Close() {
1,112✔
213
        q.cursor.archetype = -2
1,112✔
214
        q.cursor.table = -2
1,112✔
215
        q.tables = nil
1,112✔
216
        q.table = nil
1,112✔
217
        q.cache = nil
1,112✔
218
        q.columnA = nil
1,112✔
219
        q.world.unlock(q.lock)
1,112✔
220
}
1,112✔
221

222
func (q *Query1[A]) nextTableOrArchetype() bool {
2,234✔
223
        if q.cache != nil {
2,241✔
224
                return q.nextTable(q.cache.tables)
7✔
225
        }
7✔
226
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
2,228✔
227
                return true
1✔
228
        }
1✔
229
        return q.nextArchetype()
2,226✔
230
}
231

232
func (q *Query1[A]) nextArchetype() bool {
2,226✔
233
        maxArchIndex := len(q.world.storage.archetypes) - 1
2,226✔
234
        for q.cursor.archetype < maxArchIndex {
4,717✔
235
                q.cursor.archetype++
2,491✔
236
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
2,491✔
237
                if !q.filter.matches(&archetype.mask) {
3,792✔
238
                        continue
1,301✔
239
                }
240

241
                if !archetype.HasRelations() {
2,356✔
242
                        table := &q.world.storage.tables[archetype.tables[0]]
1,167✔
243
                        if table.Len() > 0 {
2,270✔
244
                                q.setTable(0, table)
1,103✔
245
                                return true
1,103✔
246
                        }
1,103✔
247
                        continue
64✔
248
                }
249

250
                q.tables = archetype.GetTables(q.relations)
22✔
251
                q.cursor.table = -1
22✔
252
                if q.nextTable(q.tables) {
35✔
253
                        return true
13✔
254
                }
13✔
255
        }
256
        q.Close()
1,109✔
257
        return false
1,109✔
258
}
259

260
func (q *Query1[A]) nextTable(tables []tableID) bool {
1,146✔
261
        maxTableIndex := len(tables) - 1
1,146✔
262
        for q.cursor.table < maxTableIndex {
1,177✔
263
                q.cursor.table++
31✔
264
                table := &q.world.storage.tables[tables[q.cursor.table]]
31✔
265
                if table.Len() == 0 {
43✔
266
                        continue
12✔
267
                }
268
                if !table.Matches(q.relations) {
20✔
269
                        continue
1✔
270
                }
271
                q.setTable(q.cursor.table, table)
18✔
272
                return true
18✔
273
        }
274
        if q.cache != nil {
1,131✔
275
                q.Close()
3✔
276
        }
3✔
277
        return false
1,128✔
278
}
279

280
func (q *Query1[A]) setTable(index int, table *table) {
1,121✔
281
        q.cursor.table = index
1,121✔
282
        q.table = table
1,121✔
283
        q.columnA = q.components[0].columns[q.table.id]
1,121✔
284
        q.cursor.index = 0
1,121✔
285
        q.cursor.maxIndex = int64(q.table.Len() - 1)
1,121✔
286
}
1,121✔
287

288
// Query2 is a query for 2 components.
289
// Use a [NewFilter2] to create one.
290
type Query2[A any, B any] struct {
291
        world      *World
292
        filter     *filter
293
        relations  []RelationID
294
        lock       uint8
295
        cursor     cursor
296
        tables     []tableID
297
        table      *table
298
        cache      *cacheEntry
299
        components []*componentStorage
300
        columnA    *column
301
        columnB    *column
302
}
303

304
func newQuery2[A any, B any](world *World, filter *filter, ids []ID, relations []RelationID,
305
        cacheID cacheID, components []*componentStorage) Query2[A, B] {
14✔
306
        var cache *cacheEntry
14✔
307
        if cacheID != maxCacheID {
17✔
308
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
309
        }
3✔
310

311
        return Query2[A, B]{
14✔
312
                world:      world,
14✔
313
                filter:     filter,
14✔
314
                relations:  relations,
14✔
315
                cache:      cache,
14✔
316
                lock:       world.lock(),
14✔
317
                components: components,
14✔
318
                cursor: cursor{
14✔
319
                        archetype: -1,
14✔
320
                        table:     -1,
14✔
321
                        index:     0,
14✔
322
                        maxIndex:  -1,
14✔
323
                },
14✔
324
        }
14✔
325
}
326

327
// Next advances the query's cursor to the next entity.
328
func (q *Query2[A, B]) Next() bool {
249✔
329
        q.world.checkQueryNext(&q.cursor)
249✔
330
        if int64(q.cursor.index) < q.cursor.maxIndex {
467✔
331
                q.cursor.index++
218✔
332
                return true
218✔
333
        }
218✔
334
        return q.nextTableOrArchetype()
31✔
335
}
336

337
// Entity returns the current entity.
338
func (q *Query2[A, B]) Entity() Entity {
204✔
339
        q.world.checkQueryGet(&q.cursor)
204✔
340
        return q.table.GetEntity(q.cursor.index)
204✔
341
}
204✔
342

343
// Get returns the queried components of the current entity.
344
func (q *Query2[A, B]) Get() (*A, *B) {
236✔
345
        q.world.checkQueryGet(&q.cursor)
236✔
346
        return (*A)(q.columnA.Get(q.cursor.index)),
236✔
347
                (*B)(q.columnB.Get(q.cursor.index))
236✔
348
}
236✔
349

350
// GetRelation returns the entity relation target of the component at the given index.
351
func (q *Query2[A, B]) GetRelation(index int) Entity {
40✔
352
        return q.components[index].columns[q.table.id].target
40✔
353
}
40✔
354

355
// Close closes the Query and unlocks the world.
356
//
357
// Automatically called when iteration finishes.
358
// Needs to be called only if breaking out of the query iteration or not iterating at all.
359
func (q *Query2[A, B]) Close() {
14✔
360
        q.cursor.archetype = -2
14✔
361
        q.cursor.table = -2
14✔
362
        q.tables = nil
14✔
363
        q.table = nil
14✔
364
        q.cache = nil
14✔
365
        q.columnA = nil
14✔
366
        q.columnB = nil
14✔
367
        q.world.unlock(q.lock)
14✔
368
}
14✔
369

370
func (q *Query2[A, B]) nextTableOrArchetype() bool {
31✔
371
        if q.cache != nil {
38✔
372
                return q.nextTable(q.cache.tables)
7✔
373
        }
7✔
374
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
25✔
375
                return true
1✔
376
        }
1✔
377
        return q.nextArchetype()
23✔
378
}
379

380
func (q *Query2[A, B]) nextArchetype() bool {
23✔
381
        maxArchIndex := len(q.world.storage.archetypes) - 1
23✔
382
        for q.cursor.archetype < maxArchIndex {
54✔
383
                q.cursor.archetype++
31✔
384
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
31✔
385
                if !q.filter.matches(&archetype.mask) {
50✔
386
                        continue
19✔
387
                }
388

389
                if !archetype.HasRelations() {
18✔
390
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
391
                        if table.Len() > 0 {
14✔
392
                                q.setTable(0, table)
7✔
393
                                return true
7✔
394
                        }
7✔
395
                        continue
×
396
                }
397

398
                q.tables = archetype.GetTables(q.relations)
4✔
399
                q.cursor.table = -1
4✔
400
                if q.nextTable(q.tables) {
8✔
401
                        return true
4✔
402
                }
4✔
403
        }
404
        q.Close()
11✔
405
        return false
11✔
406
}
407

408
func (q *Query2[A, B]) nextTable(tables []tableID) bool {
23✔
409
        maxTableIndex := len(tables) - 1
23✔
410
        for q.cursor.table < maxTableIndex {
36✔
411
                q.cursor.table++
13✔
412
                table := &q.world.storage.tables[tables[q.cursor.table]]
13✔
413
                if table.Len() == 0 {
16✔
414
                        continue
3✔
415
                }
416
                if !table.Matches(q.relations) {
11✔
417
                        continue
1✔
418
                }
419
                q.setTable(q.cursor.table, table)
9✔
420
                return true
9✔
421
        }
422
        if q.cache != nil {
17✔
423
                q.Close()
3✔
424
        }
3✔
425
        return false
14✔
426
}
427

428
func (q *Query2[A, B]) setTable(index int, table *table) {
16✔
429
        q.cursor.table = index
16✔
430
        q.table = table
16✔
431
        q.columnA = q.components[0].columns[q.table.id]
16✔
432
        q.columnB = q.components[1].columns[q.table.id]
16✔
433
        q.cursor.index = 0
16✔
434
        q.cursor.maxIndex = int64(q.table.Len() - 1)
16✔
435
}
16✔
436

437
// Query3 is a query for 3 components.
438
// Use a [NewFilter3] to create one.
439
type Query3[A any, B any, C any] struct {
440
        world      *World
441
        filter     *filter
442
        relations  []RelationID
443
        lock       uint8
444
        cursor     cursor
445
        tables     []tableID
446
        table      *table
447
        cache      *cacheEntry
448
        components []*componentStorage
449
        columnA    *column
450
        columnB    *column
451
        columnC    *column
452
}
453

454
func newQuery3[A any, B any, C any](world *World, filter *filter, ids []ID, relations []RelationID,
455
        cacheID cacheID, components []*componentStorage) Query3[A, B, C] {
16✔
456
        var cache *cacheEntry
16✔
457
        if cacheID != maxCacheID {
19✔
458
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
459
        }
3✔
460

461
        return Query3[A, B, C]{
16✔
462
                world:      world,
16✔
463
                filter:     filter,
16✔
464
                relations:  relations,
16✔
465
                cache:      cache,
16✔
466
                lock:       world.lock(),
16✔
467
                components: components,
16✔
468
                cursor: cursor{
16✔
469
                        archetype: -1,
16✔
470
                        table:     -1,
16✔
471
                        index:     0,
16✔
472
                        maxIndex:  -1,
16✔
473
                },
16✔
474
        }
16✔
475
}
476

477
// Next advances the query's cursor to the next entity.
478
func (q *Query3[A, B, C]) Next() bool {
289✔
479
        q.world.checkQueryNext(&q.cursor)
289✔
480
        if int64(q.cursor.index) < q.cursor.maxIndex {
539✔
481
                q.cursor.index++
250✔
482
                return true
250✔
483
        }
250✔
484
        return q.nextTableOrArchetype()
39✔
485
}
486

487
// Entity returns the current entity.
488
func (q *Query3[A, B, C]) Entity() Entity {
204✔
489
        q.world.checkQueryGet(&q.cursor)
204✔
490
        return q.table.GetEntity(q.cursor.index)
204✔
491
}
204✔
492

493
// Get returns the queried components of the current entity.
494
func (q *Query3[A, B, C]) Get() (*A, *B, *C) {
204✔
495
        q.world.checkQueryGet(&q.cursor)
204✔
496
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
497
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
498
                (*C)(q.columnC.Get(q.cursor.index))
204✔
499
}
204✔
500

501
// GetRelation returns the entity relation target of the component at the given index.
502
func (q *Query3[A, B, C]) GetRelation(index int) Entity {
40✔
503
        return q.components[index].columns[q.table.id].target
40✔
504
}
40✔
505

506
// Close closes the Query and unlocks the world.
507
//
508
// Automatically called when iteration finishes.
509
// Needs to be called only if breaking out of the query iteration or not iterating at all.
510
func (q *Query3[A, B, C]) Close() {
16✔
511
        q.cursor.archetype = -2
16✔
512
        q.cursor.table = -2
16✔
513
        q.tables = nil
16✔
514
        q.table = nil
16✔
515
        q.cache = nil
16✔
516
        q.columnA = nil
16✔
517
        q.columnB = nil
16✔
518
        q.columnC = nil
16✔
519
        q.world.unlock(q.lock)
16✔
520
}
16✔
521

522
func (q *Query3[A, B, C]) nextTableOrArchetype() bool {
39✔
523
        if q.cache != nil {
46✔
524
                return q.nextTable(q.cache.tables)
7✔
525
        }
7✔
526
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
37✔
527
                return true
5✔
528
        }
5✔
529
        return q.nextArchetype()
27✔
530
}
531

532
func (q *Query3[A, B, C]) nextArchetype() bool {
27✔
533
        maxArchIndex := len(q.world.storage.archetypes) - 1
27✔
534
        for q.cursor.archetype < maxArchIndex {
62✔
535
                q.cursor.archetype++
35✔
536
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
35✔
537
                if !q.filter.matches(&archetype.mask) {
56✔
538
                        continue
21✔
539
                }
540

541
                if !archetype.HasRelations() {
20✔
542
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
543
                        if table.Len() > 0 {
14✔
544
                                q.setTable(0, table)
7✔
545
                                return true
7✔
546
                        }
7✔
547
                        continue
×
548
                }
549

550
                q.tables = archetype.GetTables(q.relations)
6✔
551
                q.cursor.table = -1
6✔
552
                if q.nextTable(q.tables) {
12✔
553
                        return true
6✔
554
                }
6✔
555
        }
556
        q.Close()
13✔
557
        return false
13✔
558
}
559

560
func (q *Query3[A, B, C]) nextTable(tables []tableID) bool {
31✔
561
        maxTableIndex := len(tables) - 1
31✔
562
        for q.cursor.table < maxTableIndex {
51✔
563
                q.cursor.table++
20✔
564
                table := &q.world.storage.tables[tables[q.cursor.table]]
20✔
565
                if table.Len() == 0 {
23✔
566
                        continue
3✔
567
                }
568
                if !table.Matches(q.relations) {
19✔
569
                        continue
2✔
570
                }
571
                q.setTable(q.cursor.table, table)
15✔
572
                return true
15✔
573
        }
574
        if q.cache != nil {
19✔
575
                q.Close()
3✔
576
        }
3✔
577
        return false
16✔
578
}
579

580
func (q *Query3[A, B, C]) setTable(index int, table *table) {
22✔
581
        q.cursor.table = index
22✔
582
        q.table = table
22✔
583
        q.columnA = q.components[0].columns[q.table.id]
22✔
584
        q.columnB = q.components[1].columns[q.table.id]
22✔
585
        q.columnC = q.components[2].columns[q.table.id]
22✔
586
        q.cursor.index = 0
22✔
587
        q.cursor.maxIndex = int64(q.table.Len() - 1)
22✔
588
}
22✔
589

590
// Query4 is a query for 4 components.
591
// Use a [NewFilter4] to create one.
592
type Query4[A any, B any, C any, D any] struct {
593
        world      *World
594
        filter     *filter
595
        relations  []RelationID
596
        lock       uint8
597
        cursor     cursor
598
        tables     []tableID
599
        table      *table
600
        cache      *cacheEntry
601
        components []*componentStorage
602
        columnA    *column
603
        columnB    *column
604
        columnC    *column
605
        columnD    *column
606
}
607

608
func newQuery4[A any, B any, C any, D any](world *World, filter *filter, ids []ID, relations []RelationID,
609
        cacheID cacheID, components []*componentStorage) Query4[A, B, C, D] {
13✔
610
        var cache *cacheEntry
13✔
611
        if cacheID != maxCacheID {
16✔
612
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
613
        }
3✔
614

615
        return Query4[A, B, C, D]{
13✔
616
                world:      world,
13✔
617
                filter:     filter,
13✔
618
                relations:  relations,
13✔
619
                cache:      cache,
13✔
620
                lock:       world.lock(),
13✔
621
                components: components,
13✔
622
                cursor: cursor{
13✔
623
                        archetype: -1,
13✔
624
                        table:     -1,
13✔
625
                        index:     0,
13✔
626
                        maxIndex:  -1,
13✔
627
                },
13✔
628
        }
13✔
629
}
630

631
// Next advances the query's cursor to the next entity.
632
func (q *Query4[A, B, C, D]) Next() bool {
216✔
633
        q.world.checkQueryNext(&q.cursor)
216✔
634
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
635
                q.cursor.index++
187✔
636
                return true
187✔
637
        }
187✔
638
        return q.nextTableOrArchetype()
29✔
639
}
640

641
// Entity returns the current entity.
642
func (q *Query4[A, B, C, D]) Entity() Entity {
204✔
643
        q.world.checkQueryGet(&q.cursor)
204✔
644
        return q.table.GetEntity(q.cursor.index)
204✔
645
}
204✔
646

647
// Get returns the queried components of the current entity.
648
func (q *Query4[A, B, C, D]) Get() (*A, *B, *C, *D) {
204✔
649
        q.world.checkQueryGet(&q.cursor)
204✔
650
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
651
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
652
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
653
                (*D)(q.columnD.Get(q.cursor.index))
204✔
654
}
204✔
655

656
// GetRelation returns the entity relation target of the component at the given index.
657
func (q *Query4[A, B, C, D]) GetRelation(index int) Entity {
40✔
658
        return q.components[index].columns[q.table.id].target
40✔
659
}
40✔
660

661
// Close closes the Query and unlocks the world.
662
//
663
// Automatically called when iteration finishes.
664
// Needs to be called only if breaking out of the query iteration or not iterating at all.
665
func (q *Query4[A, B, C, D]) Close() {
13✔
666
        q.cursor.archetype = -2
13✔
667
        q.cursor.table = -2
13✔
668
        q.tables = nil
13✔
669
        q.table = nil
13✔
670
        q.cache = nil
13✔
671
        q.columnA = nil
13✔
672
        q.columnB = nil
13✔
673
        q.columnC = nil
13✔
674
        q.columnD = nil
13✔
675
        q.world.unlock(q.lock)
13✔
676
}
13✔
677

678
func (q *Query4[A, B, C, D]) nextTableOrArchetype() bool {
29✔
679
        if q.cache != nil {
36✔
680
                return q.nextTable(q.cache.tables)
7✔
681
        }
7✔
682
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
683
                return true
1✔
684
        }
1✔
685
        return q.nextArchetype()
21✔
686
}
687

688
func (q *Query4[A, B, C, D]) nextArchetype() bool {
21✔
689
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
690
        for q.cursor.archetype < maxArchIndex {
50✔
691
                q.cursor.archetype++
29✔
692
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
693
                if !q.filter.matches(&archetype.mask) {
47✔
694
                        continue
18✔
695
                }
696

697
                if !archetype.HasRelations() {
17✔
698
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
699
                        if table.Len() > 0 {
14✔
700
                                q.setTable(0, table)
7✔
701
                                return true
7✔
702
                        }
7✔
703
                        continue
×
704
                }
705

706
                q.tables = archetype.GetTables(q.relations)
3✔
707
                q.cursor.table = -1
3✔
708
                if q.nextTable(q.tables) {
6✔
709
                        return true
3✔
710
                }
3✔
711
        }
712
        q.Close()
10✔
713
        return false
10✔
714
}
715

716
func (q *Query4[A, B, C, D]) nextTable(tables []tableID) bool {
21✔
717
        maxTableIndex := len(tables) - 1
21✔
718
        for q.cursor.table < maxTableIndex {
33✔
719
                q.cursor.table++
12✔
720
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
721
                if table.Len() == 0 {
15✔
722
                        continue
3✔
723
                }
724
                if !table.Matches(q.relations) {
10✔
725
                        continue
1✔
726
                }
727
                q.setTable(q.cursor.table, table)
8✔
728
                return true
8✔
729
        }
730
        if q.cache != nil {
16✔
731
                q.Close()
3✔
732
        }
3✔
733
        return false
13✔
734
}
735

736
func (q *Query4[A, B, C, D]) setTable(index int, table *table) {
15✔
737
        q.cursor.table = index
15✔
738
        q.table = table
15✔
739
        q.columnA = q.components[0].columns[q.table.id]
15✔
740
        q.columnB = q.components[1].columns[q.table.id]
15✔
741
        q.columnC = q.components[2].columns[q.table.id]
15✔
742
        q.columnD = q.components[3].columns[q.table.id]
15✔
743
        q.cursor.index = 0
15✔
744
        q.cursor.maxIndex = int64(q.table.Len() - 1)
15✔
745
}
15✔
746

747
// Query5 is a query for 5 components.
748
// Use a [NewFilter5] to create one.
749
type Query5[A any, B any, C any, D any, E any] struct {
750
        world      *World
751
        filter     *filter
752
        relations  []RelationID
753
        lock       uint8
754
        cursor     cursor
755
        tables     []tableID
756
        table      *table
757
        cache      *cacheEntry
758
        components []*componentStorage
759
        columnA    *column
760
        columnB    *column
761
        columnC    *column
762
        columnD    *column
763
        columnE    *column
764
}
765

766
func newQuery5[A any, B any, C any, D any, E any](world *World, filter *filter, ids []ID, relations []RelationID,
767
        cacheID cacheID, components []*componentStorage) Query5[A, B, C, D, E] {
13✔
768
        var cache *cacheEntry
13✔
769
        if cacheID != maxCacheID {
16✔
770
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
771
        }
3✔
772

773
        return Query5[A, B, C, D, E]{
13✔
774
                world:      world,
13✔
775
                filter:     filter,
13✔
776
                relations:  relations,
13✔
777
                cache:      cache,
13✔
778
                lock:       world.lock(),
13✔
779
                components: components,
13✔
780
                cursor: cursor{
13✔
781
                        archetype: -1,
13✔
782
                        table:     -1,
13✔
783
                        index:     0,
13✔
784
                        maxIndex:  -1,
13✔
785
                },
13✔
786
        }
13✔
787
}
788

789
// Next advances the query's cursor to the next entity.
790
func (q *Query5[A, B, C, D, E]) Next() bool {
216✔
791
        q.world.checkQueryNext(&q.cursor)
216✔
792
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
793
                q.cursor.index++
187✔
794
                return true
187✔
795
        }
187✔
796
        return q.nextTableOrArchetype()
29✔
797
}
798

799
// Entity returns the current entity.
800
func (q *Query5[A, B, C, D, E]) Entity() Entity {
204✔
801
        q.world.checkQueryGet(&q.cursor)
204✔
802
        return q.table.GetEntity(q.cursor.index)
204✔
803
}
204✔
804

805
// Get returns the queried components of the current entity.
806
func (q *Query5[A, B, C, D, E]) Get() (*A, *B, *C, *D, *E) {
204✔
807
        q.world.checkQueryGet(&q.cursor)
204✔
808
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
809
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
810
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
811
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
812
                (*E)(q.columnE.Get(q.cursor.index))
204✔
813
}
204✔
814

815
// GetRelation returns the entity relation target of the component at the given index.
816
func (q *Query5[A, B, C, D, E]) GetRelation(index int) Entity {
40✔
817
        return q.components[index].columns[q.table.id].target
40✔
818
}
40✔
819

820
// Close closes the Query and unlocks the world.
821
//
822
// Automatically called when iteration finishes.
823
// Needs to be called only if breaking out of the query iteration or not iterating at all.
824
func (q *Query5[A, B, C, D, E]) Close() {
13✔
825
        q.cursor.archetype = -2
13✔
826
        q.cursor.table = -2
13✔
827
        q.tables = nil
13✔
828
        q.table = nil
13✔
829
        q.cache = nil
13✔
830
        q.columnA = nil
13✔
831
        q.columnB = nil
13✔
832
        q.columnC = nil
13✔
833
        q.columnD = nil
13✔
834
        q.columnE = nil
13✔
835
        q.world.unlock(q.lock)
13✔
836
}
13✔
837

838
func (q *Query5[A, B, C, D, E]) nextTableOrArchetype() bool {
29✔
839
        if q.cache != nil {
36✔
840
                return q.nextTable(q.cache.tables)
7✔
841
        }
7✔
842
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
843
                return true
1✔
844
        }
1✔
845
        return q.nextArchetype()
21✔
846
}
847

848
func (q *Query5[A, B, C, D, E]) nextArchetype() bool {
21✔
849
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
850
        for q.cursor.archetype < maxArchIndex {
50✔
851
                q.cursor.archetype++
29✔
852
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
853
                if !q.filter.matches(&archetype.mask) {
47✔
854
                        continue
18✔
855
                }
856

857
                if !archetype.HasRelations() {
17✔
858
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
859
                        if table.Len() > 0 {
14✔
860
                                q.setTable(0, table)
7✔
861
                                return true
7✔
862
                        }
7✔
863
                        continue
×
864
                }
865

866
                q.tables = archetype.GetTables(q.relations)
3✔
867
                q.cursor.table = -1
3✔
868
                if q.nextTable(q.tables) {
6✔
869
                        return true
3✔
870
                }
3✔
871
        }
872
        q.Close()
10✔
873
        return false
10✔
874
}
875

876
func (q *Query5[A, B, C, D, E]) nextTable(tables []tableID) bool {
21✔
877
        maxTableIndex := len(tables) - 1
21✔
878
        for q.cursor.table < maxTableIndex {
33✔
879
                q.cursor.table++
12✔
880
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
881
                if table.Len() == 0 {
15✔
882
                        continue
3✔
883
                }
884
                if !table.Matches(q.relations) {
10✔
885
                        continue
1✔
886
                }
887
                q.setTable(q.cursor.table, table)
8✔
888
                return true
8✔
889
        }
890
        if q.cache != nil {
16✔
891
                q.Close()
3✔
892
        }
3✔
893
        return false
13✔
894
}
895

896
func (q *Query5[A, B, C, D, E]) setTable(index int, table *table) {
15✔
897
        q.cursor.table = index
15✔
898
        q.table = table
15✔
899
        q.columnA = q.components[0].columns[q.table.id]
15✔
900
        q.columnB = q.components[1].columns[q.table.id]
15✔
901
        q.columnC = q.components[2].columns[q.table.id]
15✔
902
        q.columnD = q.components[3].columns[q.table.id]
15✔
903
        q.columnE = q.components[4].columns[q.table.id]
15✔
904
        q.cursor.index = 0
15✔
905
        q.cursor.maxIndex = int64(q.table.Len() - 1)
15✔
906
}
15✔
907

908
// Query6 is a query for 6 components.
909
// Use a [NewFilter6] to create one.
910
type Query6[A any, B any, C any, D any, E any, F any] struct {
911
        world      *World
912
        filter     *filter
913
        relations  []RelationID
914
        lock       uint8
915
        cursor     cursor
916
        tables     []tableID
917
        table      *table
918
        cache      *cacheEntry
919
        components []*componentStorage
920
        columnA    *column
921
        columnB    *column
922
        columnC    *column
923
        columnD    *column
924
        columnE    *column
925
        columnF    *column
926
}
927

928
func newQuery6[A any, B any, C any, D any, E any, F any](world *World, filter *filter, ids []ID, relations []RelationID,
929
        cacheID cacheID, components []*componentStorage) Query6[A, B, C, D, E, F] {
13✔
930
        var cache *cacheEntry
13✔
931
        if cacheID != maxCacheID {
16✔
932
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
933
        }
3✔
934

935
        return Query6[A, B, C, D, E, F]{
13✔
936
                world:      world,
13✔
937
                filter:     filter,
13✔
938
                relations:  relations,
13✔
939
                cache:      cache,
13✔
940
                lock:       world.lock(),
13✔
941
                components: components,
13✔
942
                cursor: cursor{
13✔
943
                        archetype: -1,
13✔
944
                        table:     -1,
13✔
945
                        index:     0,
13✔
946
                        maxIndex:  -1,
13✔
947
                },
13✔
948
        }
13✔
949
}
950

951
// Next advances the query's cursor to the next entity.
952
func (q *Query6[A, B, C, D, E, F]) Next() bool {
216✔
953
        q.world.checkQueryNext(&q.cursor)
216✔
954
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
955
                q.cursor.index++
187✔
956
                return true
187✔
957
        }
187✔
958
        return q.nextTableOrArchetype()
29✔
959
}
960

961
// Entity returns the current entity.
962
func (q *Query6[A, B, C, D, E, F]) Entity() Entity {
204✔
963
        q.world.checkQueryGet(&q.cursor)
204✔
964
        return q.table.GetEntity(q.cursor.index)
204✔
965
}
204✔
966

967
// Get returns the queried components of the current entity.
968
func (q *Query6[A, B, C, D, E, F]) Get() (*A, *B, *C, *D, *E, *F) {
204✔
969
        q.world.checkQueryGet(&q.cursor)
204✔
970
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
971
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
972
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
973
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
974
                (*E)(q.columnE.Get(q.cursor.index)),
204✔
975
                (*F)(q.columnF.Get(q.cursor.index))
204✔
976
}
204✔
977

978
// GetRelation returns the entity relation target of the component at the given index.
979
func (q *Query6[A, B, C, D, E, F]) GetRelation(index int) Entity {
40✔
980
        return q.components[index].columns[q.table.id].target
40✔
981
}
40✔
982

983
// Close closes the Query and unlocks the world.
984
//
985
// Automatically called when iteration finishes.
986
// Needs to be called only if breaking out of the query iteration or not iterating at all.
987
func (q *Query6[A, B, C, D, E, F]) Close() {
13✔
988
        q.cursor.archetype = -2
13✔
989
        q.cursor.table = -2
13✔
990
        q.tables = nil
13✔
991
        q.table = nil
13✔
992
        q.cache = nil
13✔
993
        q.columnA = nil
13✔
994
        q.columnB = nil
13✔
995
        q.columnC = nil
13✔
996
        q.columnD = nil
13✔
997
        q.columnE = nil
13✔
998
        q.columnF = nil
13✔
999
        q.world.unlock(q.lock)
13✔
1000
}
13✔
1001

1002
func (q *Query6[A, B, C, D, E, F]) nextTableOrArchetype() bool {
29✔
1003
        if q.cache != nil {
36✔
1004
                return q.nextTable(q.cache.tables)
7✔
1005
        }
7✔
1006
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1007
                return true
1✔
1008
        }
1✔
1009
        return q.nextArchetype()
21✔
1010
}
1011

1012
func (q *Query6[A, B, C, D, E, F]) nextArchetype() bool {
21✔
1013
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1014
        for q.cursor.archetype < maxArchIndex {
50✔
1015
                q.cursor.archetype++
29✔
1016
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1017
                if !q.filter.matches(&archetype.mask) {
47✔
1018
                        continue
18✔
1019
                }
1020

1021
                if !archetype.HasRelations() {
17✔
1022
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1023
                        if table.Len() > 0 {
14✔
1024
                                q.setTable(0, table)
7✔
1025
                                return true
7✔
1026
                        }
7✔
1027
                        continue
×
1028
                }
1029

1030
                q.tables = archetype.GetTables(q.relations)
3✔
1031
                q.cursor.table = -1
3✔
1032
                if q.nextTable(q.tables) {
6✔
1033
                        return true
3✔
1034
                }
3✔
1035
        }
1036
        q.Close()
10✔
1037
        return false
10✔
1038
}
1039

1040
func (q *Query6[A, B, C, D, E, F]) nextTable(tables []tableID) bool {
21✔
1041
        maxTableIndex := len(tables) - 1
21✔
1042
        for q.cursor.table < maxTableIndex {
33✔
1043
                q.cursor.table++
12✔
1044
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
1045
                if table.Len() == 0 {
15✔
1046
                        continue
3✔
1047
                }
1048
                if !table.Matches(q.relations) {
10✔
1049
                        continue
1✔
1050
                }
1051
                q.setTable(q.cursor.table, table)
8✔
1052
                return true
8✔
1053
        }
1054
        if q.cache != nil {
16✔
1055
                q.Close()
3✔
1056
        }
3✔
1057
        return false
13✔
1058
}
1059

1060
func (q *Query6[A, B, C, D, E, F]) setTable(index int, table *table) {
15✔
1061
        q.cursor.table = index
15✔
1062
        q.table = table
15✔
1063
        q.columnA = q.components[0].columns[q.table.id]
15✔
1064
        q.columnB = q.components[1].columns[q.table.id]
15✔
1065
        q.columnC = q.components[2].columns[q.table.id]
15✔
1066
        q.columnD = q.components[3].columns[q.table.id]
15✔
1067
        q.columnE = q.components[4].columns[q.table.id]
15✔
1068
        q.columnF = q.components[5].columns[q.table.id]
15✔
1069
        q.cursor.index = 0
15✔
1070
        q.cursor.maxIndex = int64(q.table.Len() - 1)
15✔
1071
}
15✔
1072

1073
// Query7 is a query for 7 components.
1074
// Use a [NewFilter7] to create one.
1075
type Query7[A any, B any, C any, D any, E any, F any, G any] struct {
1076
        world      *World
1077
        filter     *filter
1078
        relations  []RelationID
1079
        lock       uint8
1080
        cursor     cursor
1081
        tables     []tableID
1082
        table      *table
1083
        cache      *cacheEntry
1084
        components []*componentStorage
1085
        columnA    *column
1086
        columnB    *column
1087
        columnC    *column
1088
        columnD    *column
1089
        columnE    *column
1090
        columnF    *column
1091
        columnG    *column
1092
}
1093

1094
func newQuery7[A any, B any, C any, D any, E any, F any, G any](world *World, filter *filter, ids []ID, relations []RelationID,
1095
        cacheID cacheID, components []*componentStorage) Query7[A, B, C, D, E, F, G] {
13✔
1096
        var cache *cacheEntry
13✔
1097
        if cacheID != maxCacheID {
16✔
1098
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
1099
        }
3✔
1100

1101
        return Query7[A, B, C, D, E, F, G]{
13✔
1102
                world:      world,
13✔
1103
                filter:     filter,
13✔
1104
                relations:  relations,
13✔
1105
                cache:      cache,
13✔
1106
                lock:       world.lock(),
13✔
1107
                components: components,
13✔
1108
                cursor: cursor{
13✔
1109
                        archetype: -1,
13✔
1110
                        table:     -1,
13✔
1111
                        index:     0,
13✔
1112
                        maxIndex:  -1,
13✔
1113
                },
13✔
1114
        }
13✔
1115
}
1116

1117
// Next advances the query's cursor to the next entity.
1118
func (q *Query7[A, B, C, D, E, F, G]) Next() bool {
216✔
1119
        q.world.checkQueryNext(&q.cursor)
216✔
1120
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
1121
                q.cursor.index++
187✔
1122
                return true
187✔
1123
        }
187✔
1124
        return q.nextTableOrArchetype()
29✔
1125
}
1126

1127
// Entity returns the current entity.
1128
func (q *Query7[A, B, C, D, E, F, G]) Entity() Entity {
204✔
1129
        q.world.checkQueryGet(&q.cursor)
204✔
1130
        return q.table.GetEntity(q.cursor.index)
204✔
1131
}
204✔
1132

1133
// Get returns the queried components of the current entity.
1134
func (q *Query7[A, B, C, D, E, F, G]) Get() (*A, *B, *C, *D, *E, *F, *G) {
204✔
1135
        q.world.checkQueryGet(&q.cursor)
204✔
1136
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
1137
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
1138
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
1139
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
1140
                (*E)(q.columnE.Get(q.cursor.index)),
204✔
1141
                (*F)(q.columnF.Get(q.cursor.index)),
204✔
1142
                (*G)(q.columnG.Get(q.cursor.index))
204✔
1143
}
204✔
1144

1145
// GetRelation returns the entity relation target of the component at the given index.
1146
func (q *Query7[A, B, C, D, E, F, G]) GetRelation(index int) Entity {
40✔
1147
        return q.components[index].columns[q.table.id].target
40✔
1148
}
40✔
1149

1150
// Close closes the Query and unlocks the world.
1151
//
1152
// Automatically called when iteration finishes.
1153
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1154
func (q *Query7[A, B, C, D, E, F, G]) Close() {
13✔
1155
        q.cursor.archetype = -2
13✔
1156
        q.cursor.table = -2
13✔
1157
        q.tables = nil
13✔
1158
        q.table = nil
13✔
1159
        q.cache = nil
13✔
1160
        q.columnA = nil
13✔
1161
        q.columnB = nil
13✔
1162
        q.columnC = nil
13✔
1163
        q.columnD = nil
13✔
1164
        q.columnE = nil
13✔
1165
        q.columnF = nil
13✔
1166
        q.columnG = nil
13✔
1167
        q.world.unlock(q.lock)
13✔
1168
}
13✔
1169

1170
func (q *Query7[A, B, C, D, E, F, G]) nextTableOrArchetype() bool {
29✔
1171
        if q.cache != nil {
36✔
1172
                return q.nextTable(q.cache.tables)
7✔
1173
        }
7✔
1174
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1175
                return true
1✔
1176
        }
1✔
1177
        return q.nextArchetype()
21✔
1178
}
1179

1180
func (q *Query7[A, B, C, D, E, F, G]) nextArchetype() bool {
21✔
1181
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1182
        for q.cursor.archetype < maxArchIndex {
50✔
1183
                q.cursor.archetype++
29✔
1184
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1185
                if !q.filter.matches(&archetype.mask) {
47✔
1186
                        continue
18✔
1187
                }
1188

1189
                if !archetype.HasRelations() {
17✔
1190
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1191
                        if table.Len() > 0 {
14✔
1192
                                q.setTable(0, table)
7✔
1193
                                return true
7✔
1194
                        }
7✔
1195
                        continue
×
1196
                }
1197

1198
                q.tables = archetype.GetTables(q.relations)
3✔
1199
                q.cursor.table = -1
3✔
1200
                if q.nextTable(q.tables) {
6✔
1201
                        return true
3✔
1202
                }
3✔
1203
        }
1204
        q.Close()
10✔
1205
        return false
10✔
1206
}
1207

1208
func (q *Query7[A, B, C, D, E, F, G]) nextTable(tables []tableID) bool {
21✔
1209
        maxTableIndex := len(tables) - 1
21✔
1210
        for q.cursor.table < maxTableIndex {
33✔
1211
                q.cursor.table++
12✔
1212
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
1213
                if table.Len() == 0 {
15✔
1214
                        continue
3✔
1215
                }
1216
                if !table.Matches(q.relations) {
10✔
1217
                        continue
1✔
1218
                }
1219
                q.setTable(q.cursor.table, table)
8✔
1220
                return true
8✔
1221
        }
1222
        if q.cache != nil {
16✔
1223
                q.Close()
3✔
1224
        }
3✔
1225
        return false
13✔
1226
}
1227

1228
func (q *Query7[A, B, C, D, E, F, G]) setTable(index int, table *table) {
15✔
1229
        q.cursor.table = index
15✔
1230
        q.table = table
15✔
1231
        q.columnA = q.components[0].columns[q.table.id]
15✔
1232
        q.columnB = q.components[1].columns[q.table.id]
15✔
1233
        q.columnC = q.components[2].columns[q.table.id]
15✔
1234
        q.columnD = q.components[3].columns[q.table.id]
15✔
1235
        q.columnE = q.components[4].columns[q.table.id]
15✔
1236
        q.columnF = q.components[5].columns[q.table.id]
15✔
1237
        q.columnG = q.components[6].columns[q.table.id]
15✔
1238
        q.cursor.index = 0
15✔
1239
        q.cursor.maxIndex = int64(q.table.Len() - 1)
15✔
1240
}
15✔
1241

1242
// Query8 is a query for 8 components.
1243
// Use a [NewFilter8] to create one.
1244
type Query8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1245
        world      *World
1246
        filter     *filter
1247
        relations  []RelationID
1248
        lock       uint8
1249
        cursor     cursor
1250
        tables     []tableID
1251
        table      *table
1252
        cache      *cacheEntry
1253
        components []*componentStorage
1254
        columnA    *column
1255
        columnB    *column
1256
        columnC    *column
1257
        columnD    *column
1258
        columnE    *column
1259
        columnF    *column
1260
        columnG    *column
1261
        columnH    *column
1262
}
1263

1264
func newQuery8[A any, B any, C any, D any, E any, F any, G any, H any](world *World, filter *filter, ids []ID, relations []RelationID,
1265
        cacheID cacheID, components []*componentStorage) Query8[A, B, C, D, E, F, G, H] {
13✔
1266
        var cache *cacheEntry
13✔
1267
        if cacheID != maxCacheID {
16✔
1268
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
1269
        }
3✔
1270

1271
        return Query8[A, B, C, D, E, F, G, H]{
13✔
1272
                world:      world,
13✔
1273
                filter:     filter,
13✔
1274
                relations:  relations,
13✔
1275
                cache:      cache,
13✔
1276
                lock:       world.lock(),
13✔
1277
                components: components,
13✔
1278
                cursor: cursor{
13✔
1279
                        archetype: -1,
13✔
1280
                        table:     -1,
13✔
1281
                        index:     0,
13✔
1282
                        maxIndex:  -1,
13✔
1283
                },
13✔
1284
        }
13✔
1285
}
1286

1287
// Next advances the query's cursor to the next entity.
1288
func (q *Query8[A, B, C, D, E, F, G, H]) Next() bool {
216✔
1289
        q.world.checkQueryNext(&q.cursor)
216✔
1290
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
1291
                q.cursor.index++
187✔
1292
                return true
187✔
1293
        }
187✔
1294
        return q.nextTableOrArchetype()
29✔
1295
}
1296

1297
// Entity returns the current entity.
1298
func (q *Query8[A, B, C, D, E, F, G, H]) Entity() Entity {
204✔
1299
        q.world.checkQueryGet(&q.cursor)
204✔
1300
        return q.table.GetEntity(q.cursor.index)
204✔
1301
}
204✔
1302

1303
// Get returns the queried components of the current entity.
1304
func (q *Query8[A, B, C, D, E, F, G, H]) Get() (*A, *B, *C, *D, *E, *F, *G, *H) {
204✔
1305
        q.world.checkQueryGet(&q.cursor)
204✔
1306
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
1307
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
1308
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
1309
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
1310
                (*E)(q.columnE.Get(q.cursor.index)),
204✔
1311
                (*F)(q.columnF.Get(q.cursor.index)),
204✔
1312
                (*G)(q.columnG.Get(q.cursor.index)),
204✔
1313
                (*H)(q.columnH.Get(q.cursor.index))
204✔
1314
}
204✔
1315

1316
// GetRelation returns the entity relation target of the component at the given index.
1317
func (q *Query8[A, B, C, D, E, F, G, H]) GetRelation(index int) Entity {
40✔
1318
        return q.components[index].columns[q.table.id].target
40✔
1319
}
40✔
1320

1321
// Close closes the Query and unlocks the world.
1322
//
1323
// Automatically called when iteration finishes.
1324
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1325
func (q *Query8[A, B, C, D, E, F, G, H]) Close() {
13✔
1326
        q.cursor.archetype = -2
13✔
1327
        q.cursor.table = -2
13✔
1328
        q.tables = nil
13✔
1329
        q.table = nil
13✔
1330
        q.cache = nil
13✔
1331
        q.columnA = nil
13✔
1332
        q.columnB = nil
13✔
1333
        q.columnC = nil
13✔
1334
        q.columnD = nil
13✔
1335
        q.columnE = nil
13✔
1336
        q.columnF = nil
13✔
1337
        q.columnG = nil
13✔
1338
        q.columnH = nil
13✔
1339
        q.world.unlock(q.lock)
13✔
1340
}
13✔
1341

1342
func (q *Query8[A, B, C, D, E, F, G, H]) nextTableOrArchetype() bool {
29✔
1343
        if q.cache != nil {
36✔
1344
                return q.nextTable(q.cache.tables)
7✔
1345
        }
7✔
1346
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1347
                return true
1✔
1348
        }
1✔
1349
        return q.nextArchetype()
21✔
1350
}
1351

1352
func (q *Query8[A, B, C, D, E, F, G, H]) nextArchetype() bool {
21✔
1353
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1354
        for q.cursor.archetype < maxArchIndex {
50✔
1355
                q.cursor.archetype++
29✔
1356
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1357
                if !q.filter.matches(&archetype.mask) {
47✔
1358
                        continue
18✔
1359
                }
1360

1361
                if !archetype.HasRelations() {
17✔
1362
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1363
                        if table.Len() > 0 {
14✔
1364
                                q.setTable(0, table)
7✔
1365
                                return true
7✔
1366
                        }
7✔
1367
                        continue
×
1368
                }
1369

1370
                q.tables = archetype.GetTables(q.relations)
3✔
1371
                q.cursor.table = -1
3✔
1372
                if q.nextTable(q.tables) {
6✔
1373
                        return true
3✔
1374
                }
3✔
1375
        }
1376
        q.Close()
10✔
1377
        return false
10✔
1378
}
1379

1380
func (q *Query8[A, B, C, D, E, F, G, H]) nextTable(tables []tableID) bool {
21✔
1381
        maxTableIndex := len(tables) - 1
21✔
1382
        for q.cursor.table < maxTableIndex {
33✔
1383
                q.cursor.table++
12✔
1384
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
1385
                if table.Len() == 0 {
15✔
1386
                        continue
3✔
1387
                }
1388
                if !table.Matches(q.relations) {
10✔
1389
                        continue
1✔
1390
                }
1391
                q.setTable(q.cursor.table, table)
8✔
1392
                return true
8✔
1393
        }
1394
        if q.cache != nil {
16✔
1395
                q.Close()
3✔
1396
        }
3✔
1397
        return false
13✔
1398
}
1399

1400
func (q *Query8[A, B, C, D, E, F, G, H]) setTable(index int, table *table) {
15✔
1401
        q.cursor.table = index
15✔
1402
        q.table = table
15✔
1403
        q.columnA = q.components[0].columns[q.table.id]
15✔
1404
        q.columnB = q.components[1].columns[q.table.id]
15✔
1405
        q.columnC = q.components[2].columns[q.table.id]
15✔
1406
        q.columnD = q.components[3].columns[q.table.id]
15✔
1407
        q.columnE = q.components[4].columns[q.table.id]
15✔
1408
        q.columnF = q.components[5].columns[q.table.id]
15✔
1409
        q.columnG = q.components[6].columns[q.table.id]
15✔
1410
        q.columnH = q.components[7].columns[q.table.id]
15✔
1411
        q.cursor.index = 0
15✔
1412
        q.cursor.maxIndex = int64(q.table.Len() - 1)
15✔
1413
}
15✔
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