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

mlange-42 / ark / 13661217767

04 Mar 2025 07:16PM CUT coverage: 99.28%. Remained the same
13661217767

push

github

web-flow
User guide chapter on component operations (#125)

5788 of 5830 relevant lines covered (99.28%)

33857.51 hits per line

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

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

10✔
29
        var cache *cacheEntry
10✔
30
        if cacheID != maxCacheID {
11✔
31
                cache = world.storage.getRegisteredFilter(cacheID)
1✔
32
        }
1✔
33

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

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

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

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

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

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

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

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

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

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

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

159
func newQuery1[A any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query1[A] {
1,112✔
160
        components := make([]*componentStorage, 1)
1,112✔
161
        for i := range 1 {
2,224✔
162
                components[i] = &world.storage.components[ids[i].id]
1,112✔
163
        }
1,112✔
164
        var cache *cacheEntry
1,112✔
165
        if cacheID != maxCacheID {
1,115✔
166
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
167
        }
3✔
168

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

185
// Next advances the query's cursor to the next entity.
186
func (q *Query1[A]) Next() bool {
981,546✔
187
        q.world.checkQueryNext(&q.cursor)
981,546✔
188
        if int64(q.cursor.index) < q.cursor.maxIndex {
1,960,858✔
189
                q.cursor.index++
979,312✔
190
                return true
979,312✔
191
        }
979,312✔
192
        return q.nextTableOrArchetype()
2,234✔
193
}
194

195
// Entity returns the current entity.
196
func (q *Query1[A]) Entity() Entity {
1,959,080✔
197
        q.world.checkQueryGet(&q.cursor)
1,959,080✔
198
        return q.table.GetEntity(q.cursor.index)
1,959,080✔
199
}
1,959,080✔
200

201
// Get returns the queried components of the current entity.
202
func (q *Query1[A]) Get() *A {
979,641✔
203
        q.world.checkQueryGet(&q.cursor)
979,641✔
204
        return (*A)(q.columnA.Get(q.cursor.index))
979,641✔
205
}
979,641✔
206

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

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

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

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

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

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

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

284
func (q *Query1[A]) setTable(index int, table *table) {
1,121✔
285
        q.cursor.table = index
1,121✔
286
        q.table = table
1,121✔
287
        q.columnA = q.components[0].columns[q.table.id]
1,121✔
288
        q.cursor.index = 0
1,121✔
289
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
1,121✔
290
}
1,121✔
291

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

308
func newQuery2[A any, B any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query2[A, B] {
14✔
309
        components := make([]*componentStorage, 2)
14✔
310
        for i := range 2 {
42✔
311
                components[i] = &world.storage.components[ids[i].id]
28✔
312
        }
28✔
313
        var cache *cacheEntry
14✔
314
        if cacheID != maxCacheID {
17✔
315
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
316
        }
3✔
317

318
        return Query2[A, B]{
14✔
319
                world:      world,
14✔
320
                filter:     filter,
14✔
321
                relations:  relations,
14✔
322
                cache:      cache,
14✔
323
                lock:       world.lock(),
14✔
324
                components: components,
14✔
325
                cursor: cursor{
14✔
326
                        archetype: -1,
14✔
327
                        table:     -1,
14✔
328
                        index:     0,
14✔
329
                        maxIndex:  -1,
14✔
330
                },
14✔
331
        }
14✔
332
}
333

334
// Next advances the query's cursor to the next entity.
335
func (q *Query2[A, B]) Next() bool {
249✔
336
        q.world.checkQueryNext(&q.cursor)
249✔
337
        if int64(q.cursor.index) < q.cursor.maxIndex {
467✔
338
                q.cursor.index++
218✔
339
                return true
218✔
340
        }
218✔
341
        return q.nextTableOrArchetype()
31✔
342
}
343

344
// Entity returns the current entity.
345
func (q *Query2[A, B]) Entity() Entity {
204✔
346
        q.world.checkQueryGet(&q.cursor)
204✔
347
        return q.table.GetEntity(q.cursor.index)
204✔
348
}
204✔
349

350
// Get returns the queried components of the current entity.
351
func (q *Query2[A, B]) Get() (*A, *B) {
236✔
352
        q.world.checkQueryGet(&q.cursor)
236✔
353
        return (*A)(q.columnA.Get(q.cursor.index)),
236✔
354
                (*B)(q.columnB.Get(q.cursor.index))
236✔
355
}
236✔
356

357
// GetRelation returns the entity relation target of the component at the given index.
358
func (q *Query2[A, B]) GetRelation(index int) Entity {
40✔
359
        return q.components[index].columns[q.table.id].target
40✔
360
}
40✔
361

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

377
func (q *Query2[A, B]) nextTableOrArchetype() bool {
31✔
378
        if q.cache != nil {
38✔
379
                return q.nextTable(q.cache.tables)
7✔
380
        }
7✔
381
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
25✔
382
                return true
1✔
383
        }
1✔
384
        return q.nextArchetype()
23✔
385
}
386

387
func (q *Query2[A, B]) nextArchetype() bool {
23✔
388
        maxArchIndex := len(q.world.storage.archetypes) - 1
23✔
389
        for q.cursor.archetype < maxArchIndex {
54✔
390
                q.cursor.archetype++
31✔
391
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
31✔
392
                if !q.filter.matches(&archetype.mask) {
50✔
393
                        continue
19✔
394
                }
395

396
                if !archetype.HasRelations() {
18✔
397
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
398
                        if table.Len() > 0 {
14✔
399
                                q.setTable(0, table)
7✔
400
                                return true
7✔
401
                        }
7✔
402
                        continue
×
403
                }
404

405
                q.tables = archetype.GetTables(q.relations)
4✔
406
                q.cursor.table = -1
4✔
407
                if q.nextTable(q.tables) {
8✔
408
                        return true
4✔
409
                }
4✔
410
        }
411
        q.Close()
11✔
412
        return false
11✔
413
}
414

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

435
func (q *Query2[A, B]) setTable(index int, table *table) {
16✔
436
        q.cursor.table = index
16✔
437
        q.table = table
16✔
438
        q.columnA = q.components[0].columns[q.table.id]
16✔
439
        q.columnB = q.components[1].columns[q.table.id]
16✔
440
        q.cursor.index = 0
16✔
441
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
16✔
442
}
16✔
443

444
// Query3 is a query for 3 components.
445
// Use a [NewFilter3] to create one.
446
type Query3[A any, B any, C any] struct {
447
        world      *World
448
        filter     Filter
449
        relations  []RelationID
450
        lock       uint8
451
        cursor     cursor
452
        tables     []tableID
453
        table      *table
454
        cache      *cacheEntry
455
        components []*componentStorage
456
        columnA    *column
457
        columnB    *column
458
        columnC    *column
459
}
460

461
func newQuery3[A any, B any, C any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query3[A, B, C] {
16✔
462
        components := make([]*componentStorage, 3)
16✔
463
        for i := range 3 {
64✔
464
                components[i] = &world.storage.components[ids[i].id]
48✔
465
        }
48✔
466
        var cache *cacheEntry
16✔
467
        if cacheID != maxCacheID {
19✔
468
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
469
        }
3✔
470

471
        return Query3[A, B, C]{
16✔
472
                world:      world,
16✔
473
                filter:     filter,
16✔
474
                relations:  relations,
16✔
475
                cache:      cache,
16✔
476
                lock:       world.lock(),
16✔
477
                components: components,
16✔
478
                cursor: cursor{
16✔
479
                        archetype: -1,
16✔
480
                        table:     -1,
16✔
481
                        index:     0,
16✔
482
                        maxIndex:  -1,
16✔
483
                },
16✔
484
        }
16✔
485
}
486

487
// Next advances the query's cursor to the next entity.
488
func (q *Query3[A, B, C]) Next() bool {
289✔
489
        q.world.checkQueryNext(&q.cursor)
289✔
490
        if int64(q.cursor.index) < q.cursor.maxIndex {
539✔
491
                q.cursor.index++
250✔
492
                return true
250✔
493
        }
250✔
494
        return q.nextTableOrArchetype()
39✔
495
}
496

497
// Entity returns the current entity.
498
func (q *Query3[A, B, C]) Entity() Entity {
204✔
499
        q.world.checkQueryGet(&q.cursor)
204✔
500
        return q.table.GetEntity(q.cursor.index)
204✔
501
}
204✔
502

503
// Get returns the queried components of the current entity.
504
func (q *Query3[A, B, C]) Get() (*A, *B, *C) {
204✔
505
        q.world.checkQueryGet(&q.cursor)
204✔
506
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
507
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
508
                (*C)(q.columnC.Get(q.cursor.index))
204✔
509
}
204✔
510

511
// GetRelation returns the entity relation target of the component at the given index.
512
func (q *Query3[A, B, C]) GetRelation(index int) Entity {
40✔
513
        return q.components[index].columns[q.table.id].target
40✔
514
}
40✔
515

516
// Close closes the Query and unlocks the world.
517
//
518
// Automatically called when iteration finishes.
519
// Needs to be called only if breaking out of the query iteration or not iterating at all.
520
func (q *Query3[A, B, C]) Close() {
16✔
521
        q.cursor.archetype = -2
16✔
522
        q.cursor.table = -2
16✔
523
        q.tables = nil
16✔
524
        q.table = nil
16✔
525
        q.cache = nil
16✔
526
        q.columnA = nil
16✔
527
        q.columnB = nil
16✔
528
        q.columnC = nil
16✔
529
        q.world.unlock(q.lock)
16✔
530
}
16✔
531

532
func (q *Query3[A, B, C]) nextTableOrArchetype() bool {
39✔
533
        if q.cache != nil {
46✔
534
                return q.nextTable(q.cache.tables)
7✔
535
        }
7✔
536
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
37✔
537
                return true
5✔
538
        }
5✔
539
        return q.nextArchetype()
27✔
540
}
541

542
func (q *Query3[A, B, C]) nextArchetype() bool {
27✔
543
        maxArchIndex := len(q.world.storage.archetypes) - 1
27✔
544
        for q.cursor.archetype < maxArchIndex {
62✔
545
                q.cursor.archetype++
35✔
546
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
35✔
547
                if !q.filter.matches(&archetype.mask) {
56✔
548
                        continue
21✔
549
                }
550

551
                if !archetype.HasRelations() {
20✔
552
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
553
                        if table.Len() > 0 {
14✔
554
                                q.setTable(0, table)
7✔
555
                                return true
7✔
556
                        }
7✔
557
                        continue
×
558
                }
559

560
                q.tables = archetype.GetTables(q.relations)
6✔
561
                q.cursor.table = -1
6✔
562
                if q.nextTable(q.tables) {
12✔
563
                        return true
6✔
564
                }
6✔
565
        }
566
        q.Close()
13✔
567
        return false
13✔
568
}
569

570
func (q *Query3[A, B, C]) nextTable(tables []tableID) bool {
31✔
571
        maxTableIndex := len(tables) - 1
31✔
572
        for q.cursor.table < maxTableIndex {
51✔
573
                q.cursor.table++
20✔
574
                table := &q.world.storage.tables[tables[q.cursor.table]]
20✔
575
                if table.Len() == 0 {
23✔
576
                        continue
3✔
577
                }
578
                if !table.Matches(q.relations) {
19✔
579
                        continue
2✔
580
                }
581
                q.setTable(q.cursor.table, table)
15✔
582
                return true
15✔
583
        }
584
        if q.cache != nil {
19✔
585
                q.Close()
3✔
586
        }
3✔
587
        return false
16✔
588
}
589

590
func (q *Query3[A, B, C]) setTable(index int, table *table) {
22✔
591
        q.cursor.table = index
22✔
592
        q.table = table
22✔
593
        q.columnA = q.components[0].columns[q.table.id]
22✔
594
        q.columnB = q.components[1].columns[q.table.id]
22✔
595
        q.columnC = q.components[2].columns[q.table.id]
22✔
596
        q.cursor.index = 0
22✔
597
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
22✔
598
}
22✔
599

600
// Query4 is a query for 4 components.
601
// Use a [NewFilter4] to create one.
602
type Query4[A any, B any, C any, D any] struct {
603
        world      *World
604
        filter     Filter
605
        relations  []RelationID
606
        lock       uint8
607
        cursor     cursor
608
        tables     []tableID
609
        table      *table
610
        cache      *cacheEntry
611
        components []*componentStorage
612
        columnA    *column
613
        columnB    *column
614
        columnC    *column
615
        columnD    *column
616
}
617

618
func newQuery4[A any, B any, C any, D any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query4[A, B, C, D] {
13✔
619
        components := make([]*componentStorage, 4)
13✔
620
        for i := range 4 {
65✔
621
                components[i] = &world.storage.components[ids[i].id]
52✔
622
        }
52✔
623
        var cache *cacheEntry
13✔
624
        if cacheID != maxCacheID {
16✔
625
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
626
        }
3✔
627

628
        return Query4[A, B, C, D]{
13✔
629
                world:      world,
13✔
630
                filter:     filter,
13✔
631
                relations:  relations,
13✔
632
                cache:      cache,
13✔
633
                lock:       world.lock(),
13✔
634
                components: components,
13✔
635
                cursor: cursor{
13✔
636
                        archetype: -1,
13✔
637
                        table:     -1,
13✔
638
                        index:     0,
13✔
639
                        maxIndex:  -1,
13✔
640
                },
13✔
641
        }
13✔
642
}
643

644
// Next advances the query's cursor to the next entity.
645
func (q *Query4[A, B, C, D]) Next() bool {
216✔
646
        q.world.checkQueryNext(&q.cursor)
216✔
647
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
648
                q.cursor.index++
187✔
649
                return true
187✔
650
        }
187✔
651
        return q.nextTableOrArchetype()
29✔
652
}
653

654
// Entity returns the current entity.
655
func (q *Query4[A, B, C, D]) Entity() Entity {
204✔
656
        q.world.checkQueryGet(&q.cursor)
204✔
657
        return q.table.GetEntity(q.cursor.index)
204✔
658
}
204✔
659

660
// Get returns the queried components of the current entity.
661
func (q *Query4[A, B, C, D]) Get() (*A, *B, *C, *D) {
204✔
662
        q.world.checkQueryGet(&q.cursor)
204✔
663
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
664
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
665
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
666
                (*D)(q.columnD.Get(q.cursor.index))
204✔
667
}
204✔
668

669
// GetRelation returns the entity relation target of the component at the given index.
670
func (q *Query4[A, B, C, D]) GetRelation(index int) Entity {
40✔
671
        return q.components[index].columns[q.table.id].target
40✔
672
}
40✔
673

674
// Close closes the Query and unlocks the world.
675
//
676
// Automatically called when iteration finishes.
677
// Needs to be called only if breaking out of the query iteration or not iterating at all.
678
func (q *Query4[A, B, C, D]) Close() {
13✔
679
        q.cursor.archetype = -2
13✔
680
        q.cursor.table = -2
13✔
681
        q.tables = nil
13✔
682
        q.table = nil
13✔
683
        q.cache = nil
13✔
684
        q.columnA = nil
13✔
685
        q.columnB = nil
13✔
686
        q.columnC = nil
13✔
687
        q.columnD = nil
13✔
688
        q.world.unlock(q.lock)
13✔
689
}
13✔
690

691
func (q *Query4[A, B, C, D]) nextTableOrArchetype() bool {
29✔
692
        if q.cache != nil {
36✔
693
                return q.nextTable(q.cache.tables)
7✔
694
        }
7✔
695
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
696
                return true
1✔
697
        }
1✔
698
        return q.nextArchetype()
21✔
699
}
700

701
func (q *Query4[A, B, C, D]) nextArchetype() bool {
21✔
702
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
703
        for q.cursor.archetype < maxArchIndex {
50✔
704
                q.cursor.archetype++
29✔
705
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
706
                if !q.filter.matches(&archetype.mask) {
47✔
707
                        continue
18✔
708
                }
709

710
                if !archetype.HasRelations() {
17✔
711
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
712
                        if table.Len() > 0 {
14✔
713
                                q.setTable(0, table)
7✔
714
                                return true
7✔
715
                        }
7✔
716
                        continue
×
717
                }
718

719
                q.tables = archetype.GetTables(q.relations)
3✔
720
                q.cursor.table = -1
3✔
721
                if q.nextTable(q.tables) {
6✔
722
                        return true
3✔
723
                }
3✔
724
        }
725
        q.Close()
10✔
726
        return false
10✔
727
}
728

729
func (q *Query4[A, B, C, D]) nextTable(tables []tableID) bool {
21✔
730
        maxTableIndex := len(tables) - 1
21✔
731
        for q.cursor.table < maxTableIndex {
33✔
732
                q.cursor.table++
12✔
733
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
734
                if table.Len() == 0 {
15✔
735
                        continue
3✔
736
                }
737
                if !table.Matches(q.relations) {
10✔
738
                        continue
1✔
739
                }
740
                q.setTable(q.cursor.table, table)
8✔
741
                return true
8✔
742
        }
743
        if q.cache != nil {
16✔
744
                q.Close()
3✔
745
        }
3✔
746
        return false
13✔
747
}
748

749
func (q *Query4[A, B, C, D]) setTable(index int, table *table) {
15✔
750
        q.cursor.table = index
15✔
751
        q.table = table
15✔
752
        q.columnA = q.components[0].columns[q.table.id]
15✔
753
        q.columnB = q.components[1].columns[q.table.id]
15✔
754
        q.columnC = q.components[2].columns[q.table.id]
15✔
755
        q.columnD = q.components[3].columns[q.table.id]
15✔
756
        q.cursor.index = 0
15✔
757
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
758
}
15✔
759

760
// Query5 is a query for 5 components.
761
// Use a [NewFilter5] to create one.
762
type Query5[A any, B any, C any, D any, E any] struct {
763
        world      *World
764
        filter     Filter
765
        relations  []RelationID
766
        lock       uint8
767
        cursor     cursor
768
        tables     []tableID
769
        table      *table
770
        cache      *cacheEntry
771
        components []*componentStorage
772
        columnA    *column
773
        columnB    *column
774
        columnC    *column
775
        columnD    *column
776
        columnE    *column
777
}
778

779
func newQuery5[A any, B any, C any, D any, E any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query5[A, B, C, D, E] {
13✔
780
        components := make([]*componentStorage, 5)
13✔
781
        for i := range 5 {
78✔
782
                components[i] = &world.storage.components[ids[i].id]
65✔
783
        }
65✔
784
        var cache *cacheEntry
13✔
785
        if cacheID != maxCacheID {
16✔
786
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
787
        }
3✔
788

789
        return Query5[A, B, C, D, E]{
13✔
790
                world:      world,
13✔
791
                filter:     filter,
13✔
792
                relations:  relations,
13✔
793
                cache:      cache,
13✔
794
                lock:       world.lock(),
13✔
795
                components: components,
13✔
796
                cursor: cursor{
13✔
797
                        archetype: -1,
13✔
798
                        table:     -1,
13✔
799
                        index:     0,
13✔
800
                        maxIndex:  -1,
13✔
801
                },
13✔
802
        }
13✔
803
}
804

805
// Next advances the query's cursor to the next entity.
806
func (q *Query5[A, B, C, D, E]) Next() bool {
216✔
807
        q.world.checkQueryNext(&q.cursor)
216✔
808
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
809
                q.cursor.index++
187✔
810
                return true
187✔
811
        }
187✔
812
        return q.nextTableOrArchetype()
29✔
813
}
814

815
// Entity returns the current entity.
816
func (q *Query5[A, B, C, D, E]) Entity() Entity {
204✔
817
        q.world.checkQueryGet(&q.cursor)
204✔
818
        return q.table.GetEntity(q.cursor.index)
204✔
819
}
204✔
820

821
// Get returns the queried components of the current entity.
822
func (q *Query5[A, B, C, D, E]) Get() (*A, *B, *C, *D, *E) {
204✔
823
        q.world.checkQueryGet(&q.cursor)
204✔
824
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
825
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
826
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
827
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
828
                (*E)(q.columnE.Get(q.cursor.index))
204✔
829
}
204✔
830

831
// GetRelation returns the entity relation target of the component at the given index.
832
func (q *Query5[A, B, C, D, E]) GetRelation(index int) Entity {
40✔
833
        return q.components[index].columns[q.table.id].target
40✔
834
}
40✔
835

836
// Close closes the Query and unlocks the world.
837
//
838
// Automatically called when iteration finishes.
839
// Needs to be called only if breaking out of the query iteration or not iterating at all.
840
func (q *Query5[A, B, C, D, E]) Close() {
13✔
841
        q.cursor.archetype = -2
13✔
842
        q.cursor.table = -2
13✔
843
        q.tables = nil
13✔
844
        q.table = nil
13✔
845
        q.cache = nil
13✔
846
        q.columnA = nil
13✔
847
        q.columnB = nil
13✔
848
        q.columnC = nil
13✔
849
        q.columnD = nil
13✔
850
        q.columnE = nil
13✔
851
        q.world.unlock(q.lock)
13✔
852
}
13✔
853

854
func (q *Query5[A, B, C, D, E]) nextTableOrArchetype() bool {
29✔
855
        if q.cache != nil {
36✔
856
                return q.nextTable(q.cache.tables)
7✔
857
        }
7✔
858
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
859
                return true
1✔
860
        }
1✔
861
        return q.nextArchetype()
21✔
862
}
863

864
func (q *Query5[A, B, C, D, E]) nextArchetype() bool {
21✔
865
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
866
        for q.cursor.archetype < maxArchIndex {
50✔
867
                q.cursor.archetype++
29✔
868
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
869
                if !q.filter.matches(&archetype.mask) {
47✔
870
                        continue
18✔
871
                }
872

873
                if !archetype.HasRelations() {
17✔
874
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
875
                        if table.Len() > 0 {
14✔
876
                                q.setTable(0, table)
7✔
877
                                return true
7✔
878
                        }
7✔
879
                        continue
×
880
                }
881

882
                q.tables = archetype.GetTables(q.relations)
3✔
883
                q.cursor.table = -1
3✔
884
                if q.nextTable(q.tables) {
6✔
885
                        return true
3✔
886
                }
3✔
887
        }
888
        q.Close()
10✔
889
        return false
10✔
890
}
891

892
func (q *Query5[A, B, C, D, E]) nextTable(tables []tableID) bool {
21✔
893
        maxTableIndex := len(tables) - 1
21✔
894
        for q.cursor.table < maxTableIndex {
33✔
895
                q.cursor.table++
12✔
896
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
897
                if table.Len() == 0 {
15✔
898
                        continue
3✔
899
                }
900
                if !table.Matches(q.relations) {
10✔
901
                        continue
1✔
902
                }
903
                q.setTable(q.cursor.table, table)
8✔
904
                return true
8✔
905
        }
906
        if q.cache != nil {
16✔
907
                q.Close()
3✔
908
        }
3✔
909
        return false
13✔
910
}
911

912
func (q *Query5[A, B, C, D, E]) setTable(index int, table *table) {
15✔
913
        q.cursor.table = index
15✔
914
        q.table = table
15✔
915
        q.columnA = q.components[0].columns[q.table.id]
15✔
916
        q.columnB = q.components[1].columns[q.table.id]
15✔
917
        q.columnC = q.components[2].columns[q.table.id]
15✔
918
        q.columnD = q.components[3].columns[q.table.id]
15✔
919
        q.columnE = q.components[4].columns[q.table.id]
15✔
920
        q.cursor.index = 0
15✔
921
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
922
}
15✔
923

924
// Query6 is a query for 6 components.
925
// Use a [NewFilter6] to create one.
926
type Query6[A any, B any, C any, D any, E any, F any] struct {
927
        world      *World
928
        filter     Filter
929
        relations  []RelationID
930
        lock       uint8
931
        cursor     cursor
932
        tables     []tableID
933
        table      *table
934
        cache      *cacheEntry
935
        components []*componentStorage
936
        columnA    *column
937
        columnB    *column
938
        columnC    *column
939
        columnD    *column
940
        columnE    *column
941
        columnF    *column
942
}
943

944
func newQuery6[A any, B any, C any, D any, E any, F any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query6[A, B, C, D, E, F] {
13✔
945
        components := make([]*componentStorage, 6)
13✔
946
        for i := range 6 {
91✔
947
                components[i] = &world.storage.components[ids[i].id]
78✔
948
        }
78✔
949
        var cache *cacheEntry
13✔
950
        if cacheID != maxCacheID {
16✔
951
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
952
        }
3✔
953

954
        return Query6[A, B, C, D, E, F]{
13✔
955
                world:      world,
13✔
956
                filter:     filter,
13✔
957
                relations:  relations,
13✔
958
                cache:      cache,
13✔
959
                lock:       world.lock(),
13✔
960
                components: components,
13✔
961
                cursor: cursor{
13✔
962
                        archetype: -1,
13✔
963
                        table:     -1,
13✔
964
                        index:     0,
13✔
965
                        maxIndex:  -1,
13✔
966
                },
13✔
967
        }
13✔
968
}
969

970
// Next advances the query's cursor to the next entity.
971
func (q *Query6[A, B, C, D, E, F]) Next() bool {
216✔
972
        q.world.checkQueryNext(&q.cursor)
216✔
973
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
974
                q.cursor.index++
187✔
975
                return true
187✔
976
        }
187✔
977
        return q.nextTableOrArchetype()
29✔
978
}
979

980
// Entity returns the current entity.
981
func (q *Query6[A, B, C, D, E, F]) Entity() Entity {
204✔
982
        q.world.checkQueryGet(&q.cursor)
204✔
983
        return q.table.GetEntity(q.cursor.index)
204✔
984
}
204✔
985

986
// Get returns the queried components of the current entity.
987
func (q *Query6[A, B, C, D, E, F]) Get() (*A, *B, *C, *D, *E, *F) {
204✔
988
        q.world.checkQueryGet(&q.cursor)
204✔
989
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
990
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
991
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
992
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
993
                (*E)(q.columnE.Get(q.cursor.index)),
204✔
994
                (*F)(q.columnF.Get(q.cursor.index))
204✔
995
}
204✔
996

997
// GetRelation returns the entity relation target of the component at the given index.
998
func (q *Query6[A, B, C, D, E, F]) GetRelation(index int) Entity {
40✔
999
        return q.components[index].columns[q.table.id].target
40✔
1000
}
40✔
1001

1002
// Close closes the Query and unlocks the world.
1003
//
1004
// Automatically called when iteration finishes.
1005
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1006
func (q *Query6[A, B, C, D, E, F]) Close() {
13✔
1007
        q.cursor.archetype = -2
13✔
1008
        q.cursor.table = -2
13✔
1009
        q.tables = nil
13✔
1010
        q.table = nil
13✔
1011
        q.cache = nil
13✔
1012
        q.columnA = nil
13✔
1013
        q.columnB = nil
13✔
1014
        q.columnC = nil
13✔
1015
        q.columnD = nil
13✔
1016
        q.columnE = nil
13✔
1017
        q.columnF = nil
13✔
1018
        q.world.unlock(q.lock)
13✔
1019
}
13✔
1020

1021
func (q *Query6[A, B, C, D, E, F]) nextTableOrArchetype() bool {
29✔
1022
        if q.cache != nil {
36✔
1023
                return q.nextTable(q.cache.tables)
7✔
1024
        }
7✔
1025
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1026
                return true
1✔
1027
        }
1✔
1028
        return q.nextArchetype()
21✔
1029
}
1030

1031
func (q *Query6[A, B, C, D, E, F]) nextArchetype() bool {
21✔
1032
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1033
        for q.cursor.archetype < maxArchIndex {
50✔
1034
                q.cursor.archetype++
29✔
1035
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1036
                if !q.filter.matches(&archetype.mask) {
47✔
1037
                        continue
18✔
1038
                }
1039

1040
                if !archetype.HasRelations() {
17✔
1041
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1042
                        if table.Len() > 0 {
14✔
1043
                                q.setTable(0, table)
7✔
1044
                                return true
7✔
1045
                        }
7✔
1046
                        continue
×
1047
                }
1048

1049
                q.tables = archetype.GetTables(q.relations)
3✔
1050
                q.cursor.table = -1
3✔
1051
                if q.nextTable(q.tables) {
6✔
1052
                        return true
3✔
1053
                }
3✔
1054
        }
1055
        q.Close()
10✔
1056
        return false
10✔
1057
}
1058

1059
func (q *Query6[A, B, C, D, E, F]) nextTable(tables []tableID) bool {
21✔
1060
        maxTableIndex := len(tables) - 1
21✔
1061
        for q.cursor.table < maxTableIndex {
33✔
1062
                q.cursor.table++
12✔
1063
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
1064
                if table.Len() == 0 {
15✔
1065
                        continue
3✔
1066
                }
1067
                if !table.Matches(q.relations) {
10✔
1068
                        continue
1✔
1069
                }
1070
                q.setTable(q.cursor.table, table)
8✔
1071
                return true
8✔
1072
        }
1073
        if q.cache != nil {
16✔
1074
                q.Close()
3✔
1075
        }
3✔
1076
        return false
13✔
1077
}
1078

1079
func (q *Query6[A, B, C, D, E, F]) setTable(index int, table *table) {
15✔
1080
        q.cursor.table = index
15✔
1081
        q.table = table
15✔
1082
        q.columnA = q.components[0].columns[q.table.id]
15✔
1083
        q.columnB = q.components[1].columns[q.table.id]
15✔
1084
        q.columnC = q.components[2].columns[q.table.id]
15✔
1085
        q.columnD = q.components[3].columns[q.table.id]
15✔
1086
        q.columnE = q.components[4].columns[q.table.id]
15✔
1087
        q.columnF = q.components[5].columns[q.table.id]
15✔
1088
        q.cursor.index = 0
15✔
1089
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
1090
}
15✔
1091

1092
// Query7 is a query for 7 components.
1093
// Use a [NewFilter7] to create one.
1094
type Query7[A any, B any, C any, D any, E any, F any, G any] struct {
1095
        world      *World
1096
        filter     Filter
1097
        relations  []RelationID
1098
        lock       uint8
1099
        cursor     cursor
1100
        tables     []tableID
1101
        table      *table
1102
        cache      *cacheEntry
1103
        components []*componentStorage
1104
        columnA    *column
1105
        columnB    *column
1106
        columnC    *column
1107
        columnD    *column
1108
        columnE    *column
1109
        columnF    *column
1110
        columnG    *column
1111
}
1112

1113
func newQuery7[A any, B any, C any, D any, E any, F any, G any](world *World, filter Filter, ids []ID, relations []RelationID, cacheID cacheID) Query7[A, B, C, D, E, F, G] {
13✔
1114
        components := make([]*componentStorage, 7)
13✔
1115
        for i := range 7 {
104✔
1116
                components[i] = &world.storage.components[ids[i].id]
91✔
1117
        }
91✔
1118
        var cache *cacheEntry
13✔
1119
        if cacheID != maxCacheID {
16✔
1120
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
1121
        }
3✔
1122

1123
        return Query7[A, B, C, D, E, F, G]{
13✔
1124
                world:      world,
13✔
1125
                filter:     filter,
13✔
1126
                relations:  relations,
13✔
1127
                cache:      cache,
13✔
1128
                lock:       world.lock(),
13✔
1129
                components: components,
13✔
1130
                cursor: cursor{
13✔
1131
                        archetype: -1,
13✔
1132
                        table:     -1,
13✔
1133
                        index:     0,
13✔
1134
                        maxIndex:  -1,
13✔
1135
                },
13✔
1136
        }
13✔
1137
}
1138

1139
// Next advances the query's cursor to the next entity.
1140
func (q *Query7[A, B, C, D, E, F, G]) Next() bool {
216✔
1141
        q.world.checkQueryNext(&q.cursor)
216✔
1142
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
1143
                q.cursor.index++
187✔
1144
                return true
187✔
1145
        }
187✔
1146
        return q.nextTableOrArchetype()
29✔
1147
}
1148

1149
// Entity returns the current entity.
1150
func (q *Query7[A, B, C, D, E, F, G]) Entity() Entity {
204✔
1151
        q.world.checkQueryGet(&q.cursor)
204✔
1152
        return q.table.GetEntity(q.cursor.index)
204✔
1153
}
204✔
1154

1155
// Get returns the queried components of the current entity.
1156
func (q *Query7[A, B, C, D, E, F, G]) Get() (*A, *B, *C, *D, *E, *F, *G) {
204✔
1157
        q.world.checkQueryGet(&q.cursor)
204✔
1158
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
1159
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
1160
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
1161
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
1162
                (*E)(q.columnE.Get(q.cursor.index)),
204✔
1163
                (*F)(q.columnF.Get(q.cursor.index)),
204✔
1164
                (*G)(q.columnG.Get(q.cursor.index))
204✔
1165
}
204✔
1166

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

1172
// Close closes the Query and unlocks the world.
1173
//
1174
// Automatically called when iteration finishes.
1175
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1176
func (q *Query7[A, B, C, D, E, F, G]) Close() {
13✔
1177
        q.cursor.archetype = -2
13✔
1178
        q.cursor.table = -2
13✔
1179
        q.tables = nil
13✔
1180
        q.table = nil
13✔
1181
        q.cache = nil
13✔
1182
        q.columnA = nil
13✔
1183
        q.columnB = nil
13✔
1184
        q.columnC = nil
13✔
1185
        q.columnD = nil
13✔
1186
        q.columnE = nil
13✔
1187
        q.columnF = nil
13✔
1188
        q.columnG = nil
13✔
1189
        q.world.unlock(q.lock)
13✔
1190
}
13✔
1191

1192
func (q *Query7[A, B, C, D, E, F, G]) nextTableOrArchetype() bool {
29✔
1193
        if q.cache != nil {
36✔
1194
                return q.nextTable(q.cache.tables)
7✔
1195
        }
7✔
1196
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1197
                return true
1✔
1198
        }
1✔
1199
        return q.nextArchetype()
21✔
1200
}
1201

1202
func (q *Query7[A, B, C, D, E, F, G]) nextArchetype() bool {
21✔
1203
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1204
        for q.cursor.archetype < maxArchIndex {
50✔
1205
                q.cursor.archetype++
29✔
1206
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1207
                if !q.filter.matches(&archetype.mask) {
47✔
1208
                        continue
18✔
1209
                }
1210

1211
                if !archetype.HasRelations() {
17✔
1212
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1213
                        if table.Len() > 0 {
14✔
1214
                                q.setTable(0, table)
7✔
1215
                                return true
7✔
1216
                        }
7✔
1217
                        continue
×
1218
                }
1219

1220
                q.tables = archetype.GetTables(q.relations)
3✔
1221
                q.cursor.table = -1
3✔
1222
                if q.nextTable(q.tables) {
6✔
1223
                        return true
3✔
1224
                }
3✔
1225
        }
1226
        q.Close()
10✔
1227
        return false
10✔
1228
}
1229

1230
func (q *Query7[A, B, C, D, E, F, G]) nextTable(tables []tableID) bool {
21✔
1231
        maxTableIndex := len(tables) - 1
21✔
1232
        for q.cursor.table < maxTableIndex {
33✔
1233
                q.cursor.table++
12✔
1234
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
1235
                if table.Len() == 0 {
15✔
1236
                        continue
3✔
1237
                }
1238
                if !table.Matches(q.relations) {
10✔
1239
                        continue
1✔
1240
                }
1241
                q.setTable(q.cursor.table, table)
8✔
1242
                return true
8✔
1243
        }
1244
        if q.cache != nil {
16✔
1245
                q.Close()
3✔
1246
        }
3✔
1247
        return false
13✔
1248
}
1249

1250
func (q *Query7[A, B, C, D, E, F, G]) setTable(index int, table *table) {
15✔
1251
        q.cursor.table = index
15✔
1252
        q.table = table
15✔
1253
        q.columnA = q.components[0].columns[q.table.id]
15✔
1254
        q.columnB = q.components[1].columns[q.table.id]
15✔
1255
        q.columnC = q.components[2].columns[q.table.id]
15✔
1256
        q.columnD = q.components[3].columns[q.table.id]
15✔
1257
        q.columnE = q.components[4].columns[q.table.id]
15✔
1258
        q.columnF = q.components[5].columns[q.table.id]
15✔
1259
        q.columnG = q.components[6].columns[q.table.id]
15✔
1260
        q.cursor.index = 0
15✔
1261
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
1262
}
15✔
1263

1264
// Query8 is a query for 8 components.
1265
// Use a [NewFilter8] to create one.
1266
type Query8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1267
        world      *World
1268
        filter     Filter
1269
        relations  []RelationID
1270
        lock       uint8
1271
        cursor     cursor
1272
        tables     []tableID
1273
        table      *table
1274
        cache      *cacheEntry
1275
        components []*componentStorage
1276
        columnA    *column
1277
        columnB    *column
1278
        columnC    *column
1279
        columnD    *column
1280
        columnE    *column
1281
        columnF    *column
1282
        columnG    *column
1283
        columnH    *column
1284
}
1285

1286
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, cacheID cacheID) Query8[A, B, C, D, E, F, G, H] {
13✔
1287
        components := make([]*componentStorage, 8)
13✔
1288
        for i := range 8 {
117✔
1289
                components[i] = &world.storage.components[ids[i].id]
104✔
1290
        }
104✔
1291
        var cache *cacheEntry
13✔
1292
        if cacheID != maxCacheID {
16✔
1293
                cache = world.storage.getRegisteredFilter(cacheID)
3✔
1294
        }
3✔
1295

1296
        return Query8[A, B, C, D, E, F, G, H]{
13✔
1297
                world:      world,
13✔
1298
                filter:     filter,
13✔
1299
                relations:  relations,
13✔
1300
                cache:      cache,
13✔
1301
                lock:       world.lock(),
13✔
1302
                components: components,
13✔
1303
                cursor: cursor{
13✔
1304
                        archetype: -1,
13✔
1305
                        table:     -1,
13✔
1306
                        index:     0,
13✔
1307
                        maxIndex:  -1,
13✔
1308
                },
13✔
1309
        }
13✔
1310
}
1311

1312
// Next advances the query's cursor to the next entity.
1313
func (q *Query8[A, B, C, D, E, F, G, H]) Next() bool {
216✔
1314
        q.world.checkQueryNext(&q.cursor)
216✔
1315
        if int64(q.cursor.index) < q.cursor.maxIndex {
403✔
1316
                q.cursor.index++
187✔
1317
                return true
187✔
1318
        }
187✔
1319
        return q.nextTableOrArchetype()
29✔
1320
}
1321

1322
// Entity returns the current entity.
1323
func (q *Query8[A, B, C, D, E, F, G, H]) Entity() Entity {
204✔
1324
        q.world.checkQueryGet(&q.cursor)
204✔
1325
        return q.table.GetEntity(q.cursor.index)
204✔
1326
}
204✔
1327

1328
// Get returns the queried components of the current entity.
1329
func (q *Query8[A, B, C, D, E, F, G, H]) Get() (*A, *B, *C, *D, *E, *F, *G, *H) {
204✔
1330
        q.world.checkQueryGet(&q.cursor)
204✔
1331
        return (*A)(q.columnA.Get(q.cursor.index)),
204✔
1332
                (*B)(q.columnB.Get(q.cursor.index)),
204✔
1333
                (*C)(q.columnC.Get(q.cursor.index)),
204✔
1334
                (*D)(q.columnD.Get(q.cursor.index)),
204✔
1335
                (*E)(q.columnE.Get(q.cursor.index)),
204✔
1336
                (*F)(q.columnF.Get(q.cursor.index)),
204✔
1337
                (*G)(q.columnG.Get(q.cursor.index)),
204✔
1338
                (*H)(q.columnH.Get(q.cursor.index))
204✔
1339
}
204✔
1340

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

1346
// Close closes the Query and unlocks the world.
1347
//
1348
// Automatically called when iteration finishes.
1349
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1350
func (q *Query8[A, B, C, D, E, F, G, H]) Close() {
13✔
1351
        q.cursor.archetype = -2
13✔
1352
        q.cursor.table = -2
13✔
1353
        q.tables = nil
13✔
1354
        q.table = nil
13✔
1355
        q.cache = nil
13✔
1356
        q.columnA = nil
13✔
1357
        q.columnB = nil
13✔
1358
        q.columnC = nil
13✔
1359
        q.columnD = nil
13✔
1360
        q.columnE = nil
13✔
1361
        q.columnF = nil
13✔
1362
        q.columnG = nil
13✔
1363
        q.columnH = nil
13✔
1364
        q.world.unlock(q.lock)
13✔
1365
}
13✔
1366

1367
func (q *Query8[A, B, C, D, E, F, G, H]) nextTableOrArchetype() bool {
29✔
1368
        if q.cache != nil {
36✔
1369
                return q.nextTable(q.cache.tables)
7✔
1370
        }
7✔
1371
        if q.cursor.archetype >= 0 && q.nextTable(q.tables) {
23✔
1372
                return true
1✔
1373
        }
1✔
1374
        return q.nextArchetype()
21✔
1375
}
1376

1377
func (q *Query8[A, B, C, D, E, F, G, H]) nextArchetype() bool {
21✔
1378
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
1379
        for q.cursor.archetype < maxArchIndex {
50✔
1380
                q.cursor.archetype++
29✔
1381
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
1382
                if !q.filter.matches(&archetype.mask) {
47✔
1383
                        continue
18✔
1384
                }
1385

1386
                if !archetype.HasRelations() {
17✔
1387
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1388
                        if table.Len() > 0 {
14✔
1389
                                q.setTable(0, table)
7✔
1390
                                return true
7✔
1391
                        }
7✔
1392
                        continue
×
1393
                }
1394

1395
                q.tables = archetype.GetTables(q.relations)
3✔
1396
                q.cursor.table = -1
3✔
1397
                if q.nextTable(q.tables) {
6✔
1398
                        return true
3✔
1399
                }
3✔
1400
        }
1401
        q.Close()
10✔
1402
        return false
10✔
1403
}
1404

1405
func (q *Query8[A, B, C, D, E, F, G, H]) nextTable(tables []tableID) bool {
21✔
1406
        maxTableIndex := len(tables) - 1
21✔
1407
        for q.cursor.table < maxTableIndex {
33✔
1408
                q.cursor.table++
12✔
1409
                table := &q.world.storage.tables[tables[q.cursor.table]]
12✔
1410
                if table.Len() == 0 {
15✔
1411
                        continue
3✔
1412
                }
1413
                if !table.Matches(q.relations) {
10✔
1414
                        continue
1✔
1415
                }
1416
                q.setTable(q.cursor.table, table)
8✔
1417
                return true
8✔
1418
        }
1419
        if q.cache != nil {
16✔
1420
                q.Close()
3✔
1421
        }
3✔
1422
        return false
13✔
1423
}
1424

1425
func (q *Query8[A, B, C, D, E, F, G, H]) setTable(index int, table *table) {
15✔
1426
        q.cursor.table = index
15✔
1427
        q.table = table
15✔
1428
        q.columnA = q.components[0].columns[q.table.id]
15✔
1429
        q.columnB = q.components[1].columns[q.table.id]
15✔
1430
        q.columnC = q.components[2].columns[q.table.id]
15✔
1431
        q.columnD = q.components[3].columns[q.table.id]
15✔
1432
        q.columnE = q.components[4].columns[q.table.id]
15✔
1433
        q.columnF = q.components[5].columns[q.table.id]
15✔
1434
        q.columnG = q.components[6].columns[q.table.id]
15✔
1435
        q.columnH = q.components[7].columns[q.table.id]
15✔
1436
        q.cursor.index = 0
15✔
1437
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
15✔
1438
}
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