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

mlange-42 / ark / 13636797181

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

Pull #114

github

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

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

41 existing lines in 4 files now uncovered.

5592 of 5740 relevant lines covered (97.42%)

35229.13 hits per line

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

99.01
/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, cache *cacheEntry) Query0 {
10✔
27
        components := make([]*componentStorage, 0)
10✔
28

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

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

55
// Entity returns the current entity.
56
func (q *Query0) Entity() Entity {
218✔
57
        q.world.checkQueryGet(&q.cursor)
218✔
58
        return q.table.GetEntity(q.cursor.index)
218✔
59
}
218✔
60

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

73
func (q *Query0) nextTableOrArchetype() bool {
26✔
74
        if q.cache != nil {
31✔
75
                return q.nextTable(q.cache.tables)
5✔
76
        }
5✔
77
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
78
                return true
2✔
79
        }
2✔
80
        return q.nextArchetype()
19✔
81
}
82

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

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

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

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

128
func (q *Query0) setTable(index int, table *table) {
15✔
129
        q.cursor.table = index
15✔
130
        q.table = table
15✔
131
        q.cursor.index = 0
15✔
132
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
133
}
15✔
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
        filter     Filter
140
        relations  []RelationID
141
        lock       uint8
142
        cursor     cursor
143
        tables     []tableID
144
        table      *table
145
        cache      *cacheEntry
146
        components []*componentStorage
147
        columnA    *column
148
}
149

150
func newQuery1[A any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query1[A] {
1,111✔
151
        components := make([]*componentStorage, 1)
1,111✔
152
        for i := range 1 {
2,222✔
153
                components[i] = &world.storage.components[ids[i].id]
1,111✔
154
        }
1,111✔
155

156
        return Query1[A]{
1,111✔
157
                world:      world,
1,111✔
158
                filter:     filter,
1,111✔
159
                relations:  relations,
1,111✔
160
                cache:      cache,
1,111✔
161
                lock:       world.lock(),
1,111✔
162
                components: components,
1,111✔
163
                cursor: cursor{
1,111✔
164
                        archetype: -1,
1,111✔
165
                        table:     -1,
1,111✔
166
                        index:     0,
1,111✔
167
                        maxIndex:  -1,
1,111✔
168
                },
1,111✔
169
        }
1,111✔
170
}
171

172
// Next advances the query's cursor to the next entity.
173
func (q *Query1[A]) Next() bool {
1,004,561✔
174
        q.world.checkQueryNext(&q.cursor)
1,004,561✔
175
        if int64(q.cursor.index) < q.cursor.maxIndex {
2,006,890✔
176
                q.cursor.index++
1,002,329✔
177
                return true
1,002,329✔
178
        }
1,002,329✔
179
        return q.nextTableOrArchetype()
2,232✔
180
}
181

182
// Entity returns the current entity.
183
func (q *Query1[A]) Entity() Entity {
2,005,114✔
184
        q.world.checkQueryGet(&q.cursor)
2,005,114✔
185
        return q.table.GetEntity(q.cursor.index)
2,005,114✔
186
}
2,005,114✔
187

188
// Get returns the queried components of the current entity.
189
func (q *Query1[A]) Get() *A {
1,002,659✔
190
        q.world.checkQueryGet(&q.cursor)
1,002,659✔
191
        return (*A)(q.columnA.Get(q.cursor.index))
1,002,659✔
192
}
1,002,659✔
193

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

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

212
func (q *Query1[A]) nextTableOrArchetype() bool {
2,232✔
213
        if q.cache != nil {
2,239✔
214
                return q.nextTable(q.cache.tables)
7✔
215
        }
7✔
216
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
2,226✔
217
                return true
1✔
218
        }
1✔
219
        return q.nextArchetype()
2,224✔
220
}
221

222
func (q *Query1[A]) nextArchetype() bool {
2,224✔
223
        maxArchIndex := len(q.world.storage.archetypes) - 1
2,224✔
224
        for q.cursor.archetype < maxArchIndex {
4,713✔
225
                q.cursor.archetype++
2,489✔
226
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
2,489✔
227
                if !q.filter.matches(&archetype.mask) {
3,789✔
228
                        continue
1,300✔
229
                }
230

231
                if !archetype.HasRelations() {
2,355✔
232
                        table := &q.world.storage.tables[archetype.tables[0]]
1,167✔
233
                        if table.Len() > 0 {
2,270✔
234
                                q.setTable(0, table)
1,103✔
235
                                return true
1,103✔
236
                        }
1,103✔
237
                        continue
64✔
238
                }
239

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

250
func (q *Query1[A]) nextTable(tables []tableID) bool {
1,144✔
251
        maxTableIndex := len(tables) - 1
1,144✔
252
        for q.cursor.table < maxTableIndex {
1,174✔
253
                q.cursor.table++
30✔
254
                table := &q.world.storage.tables[tables[q.cursor.table]]
30✔
255
                if table.Len() == 0 {
42✔
256
                        continue
12✔
257
                }
258
                if !table.Matches(q.relations) {
19✔
259
                        continue
1✔
260
                }
261
                q.setTable(q.cursor.table, table)
17✔
262
                return true
17✔
263
        }
264
        return false
1,127✔
265
}
266

267
func (q *Query1[A]) setTable(index int, table *table) {
1,120✔
268
        q.cursor.table = index
1,120✔
269
        q.table = table
1,120✔
270
        q.columnA = q.components[0].columns[q.table.id]
1,120✔
271
        q.cursor.index = 0
1,120✔
272
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
1,120✔
273
}
1,120✔
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
        filter     Filter
280
        relations  []RelationID
281
        lock       uint8
282
        cursor     cursor
283
        tables     []tableID
284
        table      *table
285
        cache      *cacheEntry
286
        components []*componentStorage
287
        columnA    *column
288
        columnB    *column
289
}
290

291
func newQuery2[A any, B any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query2[A, B] {
14✔
292
        components := make([]*componentStorage, 2)
14✔
293
        for i := range 2 {
42✔
294
                components[i] = &world.storage.components[ids[i].id]
28✔
295
        }
28✔
296

297
        return Query2[A, B]{
14✔
298
                world:      world,
14✔
299
                filter:     filter,
14✔
300
                relations:  relations,
14✔
301
                cache:      cache,
14✔
302
                lock:       world.lock(),
14✔
303
                components: components,
14✔
304
                cursor: cursor{
14✔
305
                        archetype: -1,
14✔
306
                        table:     -1,
14✔
307
                        index:     0,
14✔
308
                        maxIndex:  -1,
14✔
309
                },
14✔
310
        }
14✔
311
}
312

313
// Next advances the query's cursor to the next entity.
314
func (q *Query2[A, B]) Next() bool {
249✔
315
        q.world.checkQueryNext(&q.cursor)
249✔
316
        if int64(q.cursor.index) < q.cursor.maxIndex {
467✔
317
                q.cursor.index++
218✔
318
                return true
218✔
319
        }
218✔
320
        return q.nextTableOrArchetype()
31✔
321
}
322

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

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

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

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

355
func (q *Query2[A, B]) nextTableOrArchetype() bool {
31✔
356
        if q.cache != nil {
38✔
357
                return q.nextTable(q.cache.tables)
7✔
358
        }
7✔
359
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
25✔
360
                return true
1✔
361
        }
1✔
362
        return q.nextArchetype()
23✔
363
}
364

365
func (q *Query2[A, B]) nextArchetype() bool {
23✔
366
        maxArchIndex := len(q.world.storage.archetypes) - 1
23✔
367
        for q.cursor.archetype < maxArchIndex {
54✔
368
                q.cursor.archetype++
31✔
369
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
31✔
370
                if !q.filter.matches(&archetype.mask) {
50✔
371
                        continue
19✔
372
                }
373

374
                if !archetype.HasRelations() {
18✔
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)
4✔
384
                q.cursor.table = -1
4✔
385
                if q.nextTable(q.tables) {
8✔
386
                        return true
4✔
387
                }
4✔
388
        }
389
        q.Close()
11✔
390
        return false
11✔
391
}
392

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

410
func (q *Query2[A, B]) setTable(index int, table *table) {
16✔
411
        q.cursor.table = index
16✔
412
        q.table = table
16✔
413
        q.columnA = q.components[0].columns[q.table.id]
16✔
414
        q.columnB = q.components[1].columns[q.table.id]
16✔
415
        q.cursor.index = 0
16✔
416
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
16✔
417
}
16✔
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
        filter     Filter
424
        relations  []RelationID
425
        lock       uint8
426
        cursor     cursor
427
        tables     []tableID
428
        table      *table
429
        cache      *cacheEntry
430
        components []*componentStorage
431
        columnA    *column
432
        columnB    *column
433
        columnC    *column
434
}
435

436
func newQuery3[A any, B any, C any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query3[A, B, C] {
16✔
437
        components := make([]*componentStorage, 3)
16✔
438
        for i := range 3 {
64✔
439
                components[i] = &world.storage.components[ids[i].id]
48✔
440
        }
48✔
441

442
        return Query3[A, B, C]{
16✔
443
                world:      world,
16✔
444
                filter:     filter,
16✔
445
                relations:  relations,
16✔
446
                cache:      cache,
16✔
447
                lock:       world.lock(),
16✔
448
                components: components,
16✔
449
                cursor: cursor{
16✔
450
                        archetype: -1,
16✔
451
                        table:     -1,
16✔
452
                        index:     0,
16✔
453
                        maxIndex:  -1,
16✔
454
                },
16✔
455
        }
16✔
456
}
457

458
// Next advances the query's cursor to the next entity.
459
func (q *Query3[A, B, C]) Next() bool {
289✔
460
        q.world.checkQueryNext(&q.cursor)
289✔
461
        if int64(q.cursor.index) < q.cursor.maxIndex {
539✔
462
                q.cursor.index++
250✔
463
                return true
250✔
464
        }
250✔
465
        return q.nextTableOrArchetype()
39✔
466
}
467

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

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

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

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

502
func (q *Query3[A, B, C]) nextTableOrArchetype() bool {
39✔
503
        if q.cache != nil {
46✔
504
                return q.nextTable(q.cache.tables)
7✔
505
        }
7✔
506
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
37✔
507
                return true
5✔
508
        }
5✔
509
        return q.nextArchetype()
27✔
510
}
511

512
func (q *Query3[A, B, C]) nextArchetype() bool {
27✔
513
        maxArchIndex := len(q.world.storage.archetypes) - 1
27✔
514
        for q.cursor.archetype < maxArchIndex {
62✔
515
                q.cursor.archetype++
35✔
516
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
35✔
517
                if !q.filter.matches(&archetype.mask) {
56✔
518
                        continue
21✔
519
                }
520

521
                if !archetype.HasRelations() {
20✔
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)
6✔
531
                q.cursor.table = -1
6✔
532
                if q.nextTable(q.tables) {
12✔
533
                        return true
6✔
534
                }
6✔
535
        }
536
        q.Close()
13✔
537
        return false
13✔
538
}
539

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

557
func (q *Query3[A, B, C]) setTable(index int, table *table) {
22✔
558
        q.cursor.table = index
22✔
559
        q.table = table
22✔
560
        q.columnA = q.components[0].columns[q.table.id]
22✔
561
        q.columnB = q.components[1].columns[q.table.id]
22✔
562
        q.columnC = q.components[2].columns[q.table.id]
22✔
563
        q.cursor.index = 0
22✔
564
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
22✔
565
}
22✔
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
        filter     Filter
572
        relations  []RelationID
573
        lock       uint8
574
        cursor     cursor
575
        tables     []tableID
576
        table      *table
577
        cache      *cacheEntry
578
        components []*componentStorage
579
        columnA    *column
580
        columnB    *column
581
        columnC    *column
582
        columnD    *column
583
}
584

585
func newQuery4[A any, B any, C any, D any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query4[A, B, C, D] {
13✔
586
        components := make([]*componentStorage, 4)
13✔
587
        for i := range 4 {
65✔
588
                components[i] = &world.storage.components[ids[i].id]
52✔
589
        }
52✔
590

591
        return Query4[A, B, C, D]{
13✔
592
                world:      world,
13✔
593
                filter:     filter,
13✔
594
                relations:  relations,
13✔
595
                cache:      cache,
13✔
596
                lock:       world.lock(),
13✔
597
                components: components,
13✔
598
                cursor: cursor{
13✔
599
                        archetype: -1,
13✔
600
                        table:     -1,
13✔
601
                        index:     0,
13✔
602
                        maxIndex:  -1,
13✔
603
                },
13✔
604
        }
13✔
605
}
606

607
// Next advances the query's cursor to the next entity.
608
func (q *Query4[A, B, C, D]) Next() bool {
216✔
609
        q.world.checkQueryNext(&q.cursor)
216✔
610
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
611
                q.cursor.index++
187✔
612
                return true
187✔
613
        }
187✔
614
        return q.nextTableOrArchetype()
29✔
615
}
616

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

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

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

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

653
func (q *Query4[A, B, C, D]) nextTableOrArchetype() bool {
29✔
654
        if q.cache != nil {
36✔
655
                return q.nextTable(q.cache.tables)
7✔
656
        }
7✔
657
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
658
                return true
1✔
659
        }
1✔
660
        return q.nextArchetype()
21✔
661
}
662

663
func (q *Query4[A, B, C, D]) nextArchetype() bool {
21✔
664
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
665
        for q.cursor.archetype < maxArchIndex {
50✔
666
                q.cursor.archetype++
29✔
667
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
668
                if !q.filter.matches(&archetype.mask) {
47✔
669
                        continue
18✔
670
                }
671

672
                if !archetype.HasRelations() {
17✔
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✔
678
                        continue
×
679
                }
680

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

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

708
func (q *Query4[A, B, C, D]) setTable(index int, table *table) {
15✔
709
        q.cursor.table = index
15✔
710
        q.table = table
15✔
711
        q.columnA = q.components[0].columns[q.table.id]
15✔
712
        q.columnB = q.components[1].columns[q.table.id]
15✔
713
        q.columnC = q.components[2].columns[q.table.id]
15✔
714
        q.columnD = q.components[3].columns[q.table.id]
15✔
715
        q.cursor.index = 0
15✔
716
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
717
}
15✔
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
        filter     Filter
724
        relations  []RelationID
725
        lock       uint8
726
        cursor     cursor
727
        tables     []tableID
728
        table      *table
729
        cache      *cacheEntry
730
        components []*componentStorage
731
        columnA    *column
732
        columnB    *column
733
        columnC    *column
734
        columnD    *column
735
        columnE    *column
736
}
737

738
func newQuery5[A any, B any, C any, D any, E any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query5[A, B, C, D, E] {
13✔
739
        components := make([]*componentStorage, 5)
13✔
740
        for i := range 5 {
78✔
741
                components[i] = &world.storage.components[ids[i].id]
65✔
742
        }
65✔
743

744
        return Query5[A, B, C, D, E]{
13✔
745
                world:      world,
13✔
746
                filter:     filter,
13✔
747
                relations:  relations,
13✔
748
                cache:      cache,
13✔
749
                lock:       world.lock(),
13✔
750
                components: components,
13✔
751
                cursor: cursor{
13✔
752
                        archetype: -1,
13✔
753
                        table:     -1,
13✔
754
                        index:     0,
13✔
755
                        maxIndex:  -1,
13✔
756
                },
13✔
757
        }
13✔
758
}
759

760
// Next advances the query's cursor to the next entity.
761
func (q *Query5[A, B, C, D, E]) Next() bool {
216✔
762
        q.world.checkQueryNext(&q.cursor)
216✔
763
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
764
                q.cursor.index++
187✔
765
                return true
187✔
766
        }
187✔
767
        return q.nextTableOrArchetype()
29✔
768
}
769

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

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

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

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

808
func (q *Query5[A, B, C, D, E]) nextTableOrArchetype() bool {
29✔
809
        if q.cache != nil {
36✔
810
                return q.nextTable(q.cache.tables)
7✔
811
        }
7✔
812
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
813
                return true
1✔
814
        }
1✔
815
        return q.nextArchetype()
21✔
816
}
817

818
func (q *Query5[A, B, C, D, E]) nextArchetype() bool {
21✔
819
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
820
        for q.cursor.archetype < maxArchIndex {
50✔
821
                q.cursor.archetype++
29✔
822
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
823
                if !q.filter.matches(&archetype.mask) {
47✔
824
                        continue
18✔
825
                }
826

827
                if !archetype.HasRelations() {
17✔
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)
3✔
837
                q.cursor.table = -1
3✔
838
                if q.nextTable(q.tables) {
6✔
839
                        return true
3✔
840
                }
3✔
841
        }
842
        q.Close()
10✔
843
        return false
10✔
844
}
845

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

863
func (q *Query5[A, B, C, D, E]) setTable(index int, table *table) {
15✔
864
        q.cursor.table = index
15✔
865
        q.table = table
15✔
866
        q.columnA = q.components[0].columns[q.table.id]
15✔
867
        q.columnB = q.components[1].columns[q.table.id]
15✔
868
        q.columnC = q.components[2].columns[q.table.id]
15✔
869
        q.columnD = q.components[3].columns[q.table.id]
15✔
870
        q.columnE = q.components[4].columns[q.table.id]
15✔
871
        q.cursor.index = 0
15✔
872
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
873
}
15✔
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
        filter     Filter
880
        relations  []RelationID
881
        lock       uint8
882
        cursor     cursor
883
        tables     []tableID
884
        table      *table
885
        cache      *cacheEntry
886
        components []*componentStorage
887
        columnA    *column
888
        columnB    *column
889
        columnC    *column
890
        columnD    *column
891
        columnE    *column
892
        columnF    *column
893
}
894

895
func newQuery6[A any, B any, C any, D any, E any, F any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query6[A, B, C, D, E, F] {
13✔
896
        components := make([]*componentStorage, 6)
13✔
897
        for i := range 6 {
91✔
898
                components[i] = &world.storage.components[ids[i].id]
78✔
899
        }
78✔
900

901
        return Query6[A, B, C, D, E, F]{
13✔
902
                world:      world,
13✔
903
                filter:     filter,
13✔
904
                relations:  relations,
13✔
905
                cache:      cache,
13✔
906
                lock:       world.lock(),
13✔
907
                components: components,
13✔
908
                cursor: cursor{
13✔
909
                        archetype: -1,
13✔
910
                        table:     -1,
13✔
911
                        index:     0,
13✔
912
                        maxIndex:  -1,
13✔
913
                },
13✔
914
        }
13✔
915
}
916

917
// Next advances the query's cursor to the next entity.
918
func (q *Query6[A, B, C, D, E, F]) Next() bool {
216✔
919
        q.world.checkQueryNext(&q.cursor)
216✔
920
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
921
                q.cursor.index++
187✔
922
                return true
187✔
923
        }
187✔
924
        return q.nextTableOrArchetype()
29✔
925
}
926

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

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

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

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

967
func (q *Query6[A, B, C, D, E, F]) nextTableOrArchetype() bool {
29✔
968
        if q.cache != nil {
36✔
969
                return q.nextTable(q.cache.tables)
7✔
970
        }
7✔
971
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
972
                return true
1✔
973
        }
1✔
974
        return q.nextArchetype()
21✔
975
}
976

977
func (q *Query6[A, B, C, D, E, F]) nextArchetype() bool {
21✔
978
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
979
        for q.cursor.archetype < maxArchIndex {
50✔
980
                q.cursor.archetype++
29✔
981
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
982
                if !q.filter.matches(&archetype.mask) {
47✔
983
                        continue
18✔
984
                }
985

986
                if !archetype.HasRelations() {
17✔
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)
3✔
996
                q.cursor.table = -1
3✔
997
                if q.nextTable(q.tables) {
6✔
998
                        return true
3✔
999
                }
3✔
1000
        }
1001
        q.Close()
10✔
1002
        return false
10✔
1003
}
1004

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

1022
func (q *Query6[A, B, C, D, E, F]) setTable(index int, table *table) {
15✔
1023
        q.cursor.table = index
15✔
1024
        q.table = table
15✔
1025
        q.columnA = q.components[0].columns[q.table.id]
15✔
1026
        q.columnB = q.components[1].columns[q.table.id]
15✔
1027
        q.columnC = q.components[2].columns[q.table.id]
15✔
1028
        q.columnD = q.components[3].columns[q.table.id]
15✔
1029
        q.columnE = q.components[4].columns[q.table.id]
15✔
1030
        q.columnF = q.components[5].columns[q.table.id]
15✔
1031
        q.cursor.index = 0
15✔
1032
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
1033
}
15✔
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
        filter     Filter
1040
        relations  []RelationID
1041
        lock       uint8
1042
        cursor     cursor
1043
        tables     []tableID
1044
        table      *table
1045
        cache      *cacheEntry
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
}
1055

1056
func newQuery7[A any, B any, C any, D any, E any, F any, G any](world *World, filter Filter, ids []ID, relations []RelationID, cache *cacheEntry) Query7[A, B, C, D, E, F, G] {
13✔
1057
        components := make([]*componentStorage, 7)
13✔
1058
        for i := range 7 {
104✔
1059
                components[i] = &world.storage.components[ids[i].id]
91✔
1060
        }
91✔
1061

1062
        return Query7[A, B, C, D, E, F, G]{
13✔
1063
                world:      world,
13✔
1064
                filter:     filter,
13✔
1065
                relations:  relations,
13✔
1066
                cache:      cache,
13✔
1067
                lock:       world.lock(),
13✔
1068
                components: components,
13✔
1069
                cursor: cursor{
13✔
1070
                        archetype: -1,
13✔
1071
                        table:     -1,
13✔
1072
                        index:     0,
13✔
1073
                        maxIndex:  -1,
13✔
1074
                },
13✔
1075
        }
13✔
1076
}
1077

1078
// Next advances the query's cursor to the next entity.
1079
func (q *Query7[A, B, C, D, E, F, G]) Next() bool {
216✔
1080
        q.world.checkQueryNext(&q.cursor)
216✔
1081
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
1082
                q.cursor.index++
187✔
1083
                return true
187✔
1084
        }
187✔
1085
        return q.nextTableOrArchetype()
29✔
1086
}
1087

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

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

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

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

1130
func (q *Query7[A, B, C, D, E, F, G]) nextTableOrArchetype() bool {
29✔
1131
        if q.cache != nil {
36✔
1132
                return q.nextTable(q.cache.tables)
7✔
1133
        }
7✔
1134
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1135
                return true
1✔
1136
        }
1✔
1137
        return q.nextArchetype()
21✔
1138
}
1139

1140
func (q *Query7[A, B, C, D, E, F, G]) nextArchetype() bool {
21✔
1141
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1142
        for q.cursor.archetype < maxArchIndex {
50✔
1143
                q.cursor.archetype++
29✔
1144
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1145
                if !q.filter.matches(&archetype.mask) {
47✔
1146
                        continue
18✔
1147
                }
1148

1149
                if !archetype.HasRelations() {
17✔
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)
3✔
1159
                q.cursor.table = -1
3✔
1160
                if q.nextTable(q.tables) {
6✔
1161
                        return true
3✔
1162
                }
3✔
1163
        }
1164
        q.Close()
10✔
1165
        return false
10✔
1166
}
1167

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

1185
func (q *Query7[A, B, C, D, E, F, G]) setTable(index int, table *table) {
15✔
1186
        q.cursor.table = index
15✔
1187
        q.table = table
15✔
1188
        q.columnA = q.components[0].columns[q.table.id]
15✔
1189
        q.columnB = q.components[1].columns[q.table.id]
15✔
1190
        q.columnC = q.components[2].columns[q.table.id]
15✔
1191
        q.columnD = q.components[3].columns[q.table.id]
15✔
1192
        q.columnE = q.components[4].columns[q.table.id]
15✔
1193
        q.columnF = q.components[5].columns[q.table.id]
15✔
1194
        q.columnG = q.components[6].columns[q.table.id]
15✔
1195
        q.cursor.index = 0
15✔
1196
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
1197
}
15✔
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
        filter     Filter
1204
        relations  []RelationID
1205
        lock       uint8
1206
        cursor     cursor
1207
        tables     []tableID
1208
        table      *table
1209
        cache      *cacheEntry
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
}
1220

1221
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, cache *cacheEntry) Query8[A, B, C, D, E, F, G, H] {
13✔
1222
        components := make([]*componentStorage, 8)
13✔
1223
        for i := range 8 {
117✔
1224
                components[i] = &world.storage.components[ids[i].id]
104✔
1225
        }
104✔
1226

1227
        return Query8[A, B, C, D, E, F, G, H]{
13✔
1228
                world:      world,
13✔
1229
                filter:     filter,
13✔
1230
                relations:  relations,
13✔
1231
                cache:      cache,
13✔
1232
                lock:       world.lock(),
13✔
1233
                components: components,
13✔
1234
                cursor: cursor{
13✔
1235
                        archetype: -1,
13✔
1236
                        table:     -1,
13✔
1237
                        index:     0,
13✔
1238
                        maxIndex:  -1,
13✔
1239
                },
13✔
1240
        }
13✔
1241
}
1242

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

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

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

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

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

1297
func (q *Query8[A, B, C, D, E, F, G, H]) nextTableOrArchetype() bool {
29✔
1298
        if q.cache != nil {
36✔
1299
                return q.nextTable(q.cache.tables)
7✔
1300
        }
7✔
1301
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1302
                return true
1✔
1303
        }
1✔
1304
        return q.nextArchetype()
21✔
1305
}
1306

1307
func (q *Query8[A, B, C, D, E, F, G, H]) nextArchetype() bool {
21✔
1308
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1309
        for q.cursor.archetype < maxArchIndex {
50✔
1310
                q.cursor.archetype++
29✔
1311
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1312
                if !q.filter.matches(&archetype.mask) {
47✔
1313
                        continue
18✔
1314
                }
1315

1316
                if !archetype.HasRelations() {
17✔
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)
3✔
1326
                q.cursor.table = -1
3✔
1327
                if q.nextTable(q.tables) {
6✔
1328
                        return true
3✔
1329
                }
3✔
1330
        }
1331
        q.Close()
10✔
1332
        return false
10✔
1333
}
1334

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

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