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

mlange-42 / ark / 13592982208

28 Feb 2025 05:09PM CUT coverage: 92.671% (-2.1%) from 94.795%
13592982208

Pull #79

github

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

30 of 121 new or added lines in 6 files covered. (24.79%)

44 existing lines in 1 file now uncovered.

3414 of 3684 relevant lines covered (92.67%)

50384.73 hits per line

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

95.16
/ecs/query_gen.go
1
package ecs
2

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

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

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

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

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

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

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

63
// Get returns the queried components of the current entity.
64
func (q *Query0) Get() {
83✔
65
        checkQueryGet(&q.cursor)
83✔
66
        return
83✔
67
}
83✔
68

69
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
70
func (q *Query0) GetRelation(index int) Entity {
×
NEW
UNCOV
71
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
72
}
×
73

74
// Close closes the Query and unlocks the world.
75
//
76
// Automatically called when iteration finishes.
77
// Needs to be called only if breaking out of the query iteration or not iterating at all.
78
func (q *Query0) Close() {
8✔
79
        q.cursor.archetype = -2
8✔
80
        q.cursor.table = -2
8✔
81
        q.tables = nil
8✔
82
        q.table = nil
8✔
83
        q.world.unlock(q.lock)
8✔
84
}
8✔
85

86
func (q *Query0) nextTableOrArchetype() bool {
19✔
87
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
88
                return true
2✔
89
        }
2✔
90
        return q.nextArchetype()
17✔
91
}
92

93
func (q *Query0) nextArchetype() bool {
17✔
94
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
95
        for q.cursor.archetype < maxArchIndex {
34✔
96
                q.cursor.archetype++
17✔
97
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
17✔
98
                if !archetype.mask.Contains(&q.mask) ||
17✔
99
                        archetype.mask.ContainsAny(&q.without) {
21✔
100
                        continue
4✔
101
                }
102

103
                if !archetype.HasRelations() {
23✔
104
                        table := &q.world.storage.tables[archetype.tables[0]]
11✔
105
                        if table.Len() > 0 {
18✔
106
                                q.setTable(0, table)
7✔
107
                                return true
7✔
108
                        }
7✔
109
                        continue
4✔
110
                }
111

112
                q.tables = archetype.GetTables(q.relations)
1✔
113
                q.cursor.table = -1
1✔
114
                if q.nextTable() {
2✔
115
                        return true
1✔
116
                }
1✔
117
        }
118
        q.Close()
8✔
119
        return false
8✔
120
}
121

122
func (q *Query0) nextTable() bool {
11✔
123
        maxTableIndex := len(q.tables) - 1
11✔
124
        for q.cursor.table < maxTableIndex {
14✔
125
                q.cursor.table++
3✔
126
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
127
                if table.Len() == 0 {
3✔
UNCOV
128
                        continue
×
129
                }
130
                if !table.Matches(q.relations) {
3✔
UNCOV
131
                        continue
×
132
                }
133
                q.setTable(q.cursor.table, table)
3✔
134
                return true
3✔
135
        }
136
        return false
8✔
137
}
138

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

146
// Query1 is a query for 1 components.
147
// Use a [NewFilter1] to create one.
148
type Query1[A any] struct {
149
        world      *World
150
        mask       Mask
151
        without    Mask
152
        relations  []relationID
153
        lock       uint8
154
        cursor     cursor
155
        tables     []tableID
156
        table      *table
157
        components []*componentStorage
158
        columnA    *column
159
        hasWithout bool
160
}
161

162
func newQuery1[A any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query1[A] {
1,008✔
163
        components := make([]*componentStorage, 1)
1,008✔
164
        for i := range 1 {
2,016✔
165
                components[i] = &world.storage.components[ids[i].id]
1,008✔
166
        }
1,008✔
167

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

185
// Next advances the query's cursor to the next entity.
186
func (q *Query1[A]) Next() bool {
1,015,842✔
187
        checkQueryNext(&q.cursor)
1,015,842✔
188
        if int64(q.cursor.index) < q.cursor.maxIndex {
2,029,665✔
189
                q.cursor.index++
1,013,823✔
190
                return true
1,013,823✔
191
        }
1,013,823✔
192
        return q.nextTableOrArchetype()
2,019✔
193
}
194

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

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

207
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
208
func (q *Query1[A]) GetRelation(index int) Entity {
×
NEW
UNCOV
209
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
210
}
×
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,008✔
217
        q.cursor.archetype = -2
1,008✔
218
        q.cursor.table = -2
1,008✔
219
        q.tables = nil
1,008✔
220
        q.table = nil
1,008✔
221
        q.columnA = nil
1,008✔
222
        q.world.unlock(q.lock)
1,008✔
223
}
1,008✔
224

225
func (q *Query1[A]) nextTableOrArchetype() bool {
2,019✔
226
        if q.cursor.archetype >= 0 && q.nextTable() {
2,021✔
227
                return true
2✔
228
        }
2✔
229
        return q.nextArchetype()
2,017✔
230
}
231

232
func (q *Query1[A]) nextArchetype() bool {
2,017✔
233
        maxArchIndex := len(q.world.storage.archetypes) - 1
2,017✔
234
        for q.cursor.archetype < maxArchIndex {
4,039✔
235
                q.cursor.archetype++
2,022✔
236
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
2,022✔
237
                if !archetype.mask.Contains(&q.mask) ||
2,022✔
238
                        archetype.mask.ContainsAny(&q.without) {
3,034✔
239
                        continue
1,012✔
240
                }
241

242
                if !archetype.HasRelations() {
2,017✔
243
                        table := &q.world.storage.tables[archetype.tables[0]]
1,008✔
244
                        if table.Len() > 0 {
2,015✔
245
                                q.setTable(0, table)
1,007✔
246
                                return true
1,007✔
247
                        }
1,007✔
248
                        continue
1✔
249
                }
250

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

261
func (q *Query1[A]) nextTable() bool {
1,011✔
262
        maxTableIndex := len(q.tables) - 1
1,011✔
263
        for q.cursor.table < maxTableIndex {
1,014✔
264
                q.cursor.table++
3✔
265
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
266
                if table.Len() == 0 {
3✔
UNCOV
267
                        continue
×
268
                }
269
                if !table.Matches(q.relations) {
3✔
UNCOV
270
                        continue
×
271
                }
272
                q.setTable(q.cursor.table, table)
3✔
273
                return true
3✔
274
        }
275
        return false
1,008✔
276
}
277

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

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

303
func newQuery2[A any, B any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query2[A, B] {
9✔
304
        components := make([]*componentStorage, 2)
9✔
305
        for i := range 2 {
27✔
306
                components[i] = &world.storage.components[ids[i].id]
18✔
307
        }
18✔
308

309
        return Query2[A, B]{
9✔
310
                world:      world,
9✔
311
                mask:       mask,
9✔
312
                without:    without,
9✔
313
                relations:  relations,
9✔
314
                hasWithout: !without.IsZero(),
9✔
315
                lock:       world.lock(),
9✔
316
                components: components,
9✔
317
                cursor: cursor{
9✔
318
                        archetype: -1,
9✔
319
                        table:     -1,
9✔
320
                        index:     0,
9✔
321
                        maxIndex:  -1,
9✔
322
                },
9✔
323
        }
9✔
324
}
325

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

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

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

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

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

368
func (q *Query2[A, B]) nextTableOrArchetype() bool {
21✔
369
        if q.cursor.archetype >= 0 && q.nextTable() {
23✔
370
                return true
2✔
371
        }
2✔
372
        return q.nextArchetype()
19✔
373
}
374

375
func (q *Query2[A, B]) nextArchetype() bool {
19✔
376
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
377
        for q.cursor.archetype < maxArchIndex {
47✔
378
                q.cursor.archetype++
28✔
379
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
28✔
380
                if !archetype.mask.Contains(&q.mask) ||
28✔
381
                        archetype.mask.ContainsAny(&q.without) {
45✔
382
                        continue
17✔
383
                }
384

385
                if !archetype.HasRelations() {
18✔
386
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
387
                        if table.Len() > 0 {
15✔
388
                                q.setTable(0, table)
7✔
389
                                return true
7✔
390
                        }
7✔
391
                        continue
1✔
392
                }
393

394
                q.tables = archetype.GetTables(q.relations)
2✔
395
                q.cursor.table = -1
2✔
396
                if q.nextTable() {
4✔
397
                        return true
2✔
398
                }
2✔
399
        }
400
        q.Close()
9✔
401
        return false
9✔
402
}
403

404
func (q *Query2[A, B]) nextTable() bool {
13✔
405
        maxTableIndex := len(q.tables) - 1
13✔
406
        for q.cursor.table < maxTableIndex {
17✔
407
                q.cursor.table++
4✔
408
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
409
                if table.Len() == 0 {
4✔
UNCOV
410
                        continue
×
411
                }
412
                if !table.Matches(q.relations) {
4✔
UNCOV
413
                        continue
×
414
                }
415
                q.setTable(q.cursor.table, table)
4✔
416
                return true
4✔
417
        }
418
        return false
9✔
419
}
420

421
func (q *Query2[A, B]) setTable(index int, table *table) {
11✔
422
        q.cursor.table = index
11✔
423
        q.table = table
11✔
424
        q.columnA = q.components[0].columns[q.table.id]
11✔
425
        q.columnB = q.components[1].columns[q.table.id]
11✔
426
        q.cursor.index = 0
11✔
427
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
11✔
428
}
11✔
429

430
// Query3 is a query for 3 components.
431
// Use a [NewFilter3] to create one.
432
type Query3[A any, B any, C any] struct {
433
        world      *World
434
        mask       Mask
435
        without    Mask
436
        relations  []relationID
437
        lock       uint8
438
        cursor     cursor
439
        tables     []tableID
440
        table      *table
441
        components []*componentStorage
442
        columnA    *column
443
        columnB    *column
444
        columnC    *column
445
        hasWithout bool
446
}
447

448
func newQuery3[A any, B any, C any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query3[A, B, C] {
11✔
449
        components := make([]*componentStorage, 3)
11✔
450
        for i := range 3 {
44✔
451
                components[i] = &world.storage.components[ids[i].id]
33✔
452
        }
33✔
453

454
        return Query3[A, B, C]{
11✔
455
                world:      world,
11✔
456
                mask:       mask,
11✔
457
                without:    without,
11✔
458
                relations:  relations,
11✔
459
                hasWithout: !without.IsZero(),
11✔
460
                lock:       world.lock(),
11✔
461
                components: components,
11✔
462
                cursor: cursor{
11✔
463
                        archetype: -1,
11✔
464
                        table:     -1,
11✔
465
                        index:     0,
11✔
466
                        maxIndex:  -1,
11✔
467
                },
11✔
468
        }
11✔
469
}
470

471
// Next advances the query's cursor to the next entity.
472
func (q *Query3[A, B, C]) Next() bool {
234✔
473
        checkQueryNext(&q.cursor)
234✔
474
        if int64(q.cursor.index) < q.cursor.maxIndex {
439✔
475
                q.cursor.index++
205✔
476
                return true
205✔
477
        }
205✔
478
        return q.nextTableOrArchetype()
29✔
479
}
480

481
// Entity returns the current entity.
482
func (q *Query3[A, B, C]) Entity() Entity {
154✔
483
        checkQueryGet(&q.cursor)
154✔
484
        return q.table.GetEntity(q.cursor.index)
154✔
485
}
154✔
486

487
// Get returns the queried components of the current entity.
488
func (q *Query3[A, B, C]) Get() (*A, *B, *C) {
154✔
489
        checkQueryGet(&q.cursor)
154✔
490
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
491
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
492
                (*C)(q.columnC.Get(q.cursor.index))
154✔
493
}
154✔
494

495
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
496
func (q *Query3[A, B, C]) GetRelation(index int) Entity {
×
NEW
UNCOV
497
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
498
}
×
499

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

515
func (q *Query3[A, B, C]) nextTableOrArchetype() bool {
29✔
516
        if q.cursor.archetype >= 0 && q.nextTable() {
35✔
517
                return true
6✔
518
        }
6✔
519
        return q.nextArchetype()
23✔
520
}
521

522
func (q *Query3[A, B, C]) nextArchetype() bool {
23✔
523
        maxArchIndex := len(q.world.storage.archetypes) - 1
23✔
524
        for q.cursor.archetype < maxArchIndex {
55✔
525
                q.cursor.archetype++
32✔
526
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
32✔
527
                if !archetype.mask.Contains(&q.mask) ||
32✔
528
                        archetype.mask.ContainsAny(&q.without) {
51✔
529
                        continue
19✔
530
                }
531

532
                if !archetype.HasRelations() {
20✔
533
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
534
                        if table.Len() > 0 {
15✔
535
                                q.setTable(0, table)
7✔
536
                                return true
7✔
537
                        }
7✔
538
                        continue
1✔
539
                }
540

541
                q.tables = archetype.GetTables(q.relations)
4✔
542
                q.cursor.table = -1
4✔
543
                if q.nextTable() {
8✔
544
                        return true
4✔
545
                }
4✔
546
        }
547
        q.Close()
11✔
548
        return false
11✔
549
}
550

551
func (q *Query3[A, B, C]) nextTable() bool {
21✔
552
        maxTableIndex := len(q.tables) - 1
21✔
553
        for q.cursor.table < maxTableIndex {
32✔
554
                q.cursor.table++
11✔
555
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
11✔
556
                if table.Len() == 0 {
11✔
UNCOV
557
                        continue
×
558
                }
559
                if !table.Matches(q.relations) {
12✔
560
                        continue
1✔
561
                }
562
                q.setTable(q.cursor.table, table)
10✔
563
                return true
10✔
564
        }
565
        return false
11✔
566
}
567

568
func (q *Query3[A, B, C]) setTable(index int, table *table) {
17✔
569
        q.cursor.table = index
17✔
570
        q.table = table
17✔
571
        q.columnA = q.components[0].columns[q.table.id]
17✔
572
        q.columnB = q.components[1].columns[q.table.id]
17✔
573
        q.columnC = q.components[2].columns[q.table.id]
17✔
574
        q.cursor.index = 0
17✔
575
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
17✔
576
}
17✔
577

578
// Query4 is a query for 4 components.
579
// Use a [NewFilter4] to create one.
580
type Query4[A any, B any, C any, D any] struct {
581
        world      *World
582
        mask       Mask
583
        without    Mask
584
        relations  []relationID
585
        lock       uint8
586
        cursor     cursor
587
        tables     []tableID
588
        table      *table
589
        components []*componentStorage
590
        columnA    *column
591
        columnB    *column
592
        columnC    *column
593
        columnD    *column
594
        hasWithout bool
595
}
596

597
func newQuery4[A any, B any, C any, D any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query4[A, B, C, D] {
8✔
598
        components := make([]*componentStorage, 4)
8✔
599
        for i := range 4 {
40✔
600
                components[i] = &world.storage.components[ids[i].id]
32✔
601
        }
32✔
602

603
        return Query4[A, B, C, D]{
8✔
604
                world:      world,
8✔
605
                mask:       mask,
8✔
606
                without:    without,
8✔
607
                relations:  relations,
8✔
608
                hasWithout: !without.IsZero(),
8✔
609
                lock:       world.lock(),
8✔
610
                components: components,
8✔
611
                cursor: cursor{
8✔
612
                        archetype: -1,
8✔
613
                        table:     -1,
8✔
614
                        index:     0,
8✔
615
                        maxIndex:  -1,
8✔
616
                },
8✔
617
        }
8✔
618
}
619

620
// Next advances the query's cursor to the next entity.
621
func (q *Query4[A, B, C, D]) Next() bool {
161✔
622
        checkQueryNext(&q.cursor)
161✔
623
        if int64(q.cursor.index) < q.cursor.maxIndex {
303✔
624
                q.cursor.index++
142✔
625
                return true
142✔
626
        }
142✔
627
        return q.nextTableOrArchetype()
19✔
628
}
629

630
// Entity returns the current entity.
631
func (q *Query4[A, B, C, D]) Entity() Entity {
154✔
632
        checkQueryGet(&q.cursor)
154✔
633
        return q.table.GetEntity(q.cursor.index)
154✔
634
}
154✔
635

636
// Get returns the queried components of the current entity.
637
func (q *Query4[A, B, C, D]) Get() (*A, *B, *C, *D) {
154✔
638
        checkQueryGet(&q.cursor)
154✔
639
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
640
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
641
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
642
                (*D)(q.columnD.Get(q.cursor.index))
154✔
643
}
154✔
644

645
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
646
func (q *Query4[A, B, C, D]) GetRelation(index int) Entity {
×
NEW
UNCOV
647
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
648
}
×
649

650
// Close closes the Query and unlocks the world.
651
//
652
// Automatically called when iteration finishes.
653
// Needs to be called only if breaking out of the query iteration or not iterating at all.
654
func (q *Query4[A, B, C, D]) Close() {
8✔
655
        q.cursor.archetype = -2
8✔
656
        q.cursor.table = -2
8✔
657
        q.tables = nil
8✔
658
        q.table = nil
8✔
659
        q.columnA = nil
8✔
660
        q.columnB = nil
8✔
661
        q.columnC = nil
8✔
662
        q.columnD = nil
8✔
663
        q.world.unlock(q.lock)
8✔
664
}
8✔
665

666
func (q *Query4[A, B, C, D]) nextTableOrArchetype() bool {
19✔
667
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
668
                return true
2✔
669
        }
2✔
670
        return q.nextArchetype()
17✔
671
}
672

673
func (q *Query4[A, B, C, D]) nextArchetype() bool {
17✔
674
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
675
        for q.cursor.archetype < maxArchIndex {
43✔
676
                q.cursor.archetype++
26✔
677
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
26✔
678
                if !archetype.mask.Contains(&q.mask) ||
26✔
679
                        archetype.mask.ContainsAny(&q.without) {
42✔
680
                        continue
16✔
681
                }
682

683
                if !archetype.HasRelations() {
17✔
684
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
685
                        if table.Len() > 0 {
15✔
686
                                q.setTable(0, table)
7✔
687
                                return true
7✔
688
                        }
7✔
689
                        continue
1✔
690
                }
691

692
                q.tables = archetype.GetTables(q.relations)
1✔
693
                q.cursor.table = -1
1✔
694
                if q.nextTable() {
2✔
695
                        return true
1✔
696
                }
1✔
697
        }
698
        q.Close()
8✔
699
        return false
8✔
700
}
701

702
func (q *Query4[A, B, C, D]) nextTable() bool {
11✔
703
        maxTableIndex := len(q.tables) - 1
11✔
704
        for q.cursor.table < maxTableIndex {
14✔
705
                q.cursor.table++
3✔
706
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
707
                if table.Len() == 0 {
3✔
UNCOV
708
                        continue
×
709
                }
710
                if !table.Matches(q.relations) {
3✔
UNCOV
711
                        continue
×
712
                }
713
                q.setTable(q.cursor.table, table)
3✔
714
                return true
3✔
715
        }
716
        return false
8✔
717
}
718

719
func (q *Query4[A, B, C, D]) setTable(index int, table *table) {
10✔
720
        q.cursor.table = index
10✔
721
        q.table = table
10✔
722
        q.columnA = q.components[0].columns[q.table.id]
10✔
723
        q.columnB = q.components[1].columns[q.table.id]
10✔
724
        q.columnC = q.components[2].columns[q.table.id]
10✔
725
        q.columnD = q.components[3].columns[q.table.id]
10✔
726
        q.cursor.index = 0
10✔
727
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
728
}
10✔
729

730
// Query5 is a query for 5 components.
731
// Use a [NewFilter5] to create one.
732
type Query5[A any, B any, C any, D any, E any] struct {
733
        world      *World
734
        mask       Mask
735
        without    Mask
736
        relations  []relationID
737
        lock       uint8
738
        cursor     cursor
739
        tables     []tableID
740
        table      *table
741
        components []*componentStorage
742
        columnA    *column
743
        columnB    *column
744
        columnC    *column
745
        columnD    *column
746
        columnE    *column
747
        hasWithout bool
748
}
749

750
func newQuery5[A any, B any, C any, D any, E any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query5[A, B, C, D, E] {
8✔
751
        components := make([]*componentStorage, 5)
8✔
752
        for i := range 5 {
48✔
753
                components[i] = &world.storage.components[ids[i].id]
40✔
754
        }
40✔
755

756
        return Query5[A, B, C, D, E]{
8✔
757
                world:      world,
8✔
758
                mask:       mask,
8✔
759
                without:    without,
8✔
760
                relations:  relations,
8✔
761
                hasWithout: !without.IsZero(),
8✔
762
                lock:       world.lock(),
8✔
763
                components: components,
8✔
764
                cursor: cursor{
8✔
765
                        archetype: -1,
8✔
766
                        table:     -1,
8✔
767
                        index:     0,
8✔
768
                        maxIndex:  -1,
8✔
769
                },
8✔
770
        }
8✔
771
}
772

773
// Next advances the query's cursor to the next entity.
774
func (q *Query5[A, B, C, D, E]) Next() bool {
161✔
775
        checkQueryNext(&q.cursor)
161✔
776
        if int64(q.cursor.index) < q.cursor.maxIndex {
303✔
777
                q.cursor.index++
142✔
778
                return true
142✔
779
        }
142✔
780
        return q.nextTableOrArchetype()
19✔
781
}
782

783
// Entity returns the current entity.
784
func (q *Query5[A, B, C, D, E]) Entity() Entity {
154✔
785
        checkQueryGet(&q.cursor)
154✔
786
        return q.table.GetEntity(q.cursor.index)
154✔
787
}
154✔
788

789
// Get returns the queried components of the current entity.
790
func (q *Query5[A, B, C, D, E]) Get() (*A, *B, *C, *D, *E) {
154✔
791
        checkQueryGet(&q.cursor)
154✔
792
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
793
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
794
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
795
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
796
                (*E)(q.columnE.Get(q.cursor.index))
154✔
797
}
154✔
798

799
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
800
func (q *Query5[A, B, C, D, E]) GetRelation(index int) Entity {
×
NEW
UNCOV
801
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
802
}
×
803

804
// Close closes the Query and unlocks the world.
805
//
806
// Automatically called when iteration finishes.
807
// Needs to be called only if breaking out of the query iteration or not iterating at all.
808
func (q *Query5[A, B, C, D, E]) Close() {
8✔
809
        q.cursor.archetype = -2
8✔
810
        q.cursor.table = -2
8✔
811
        q.tables = nil
8✔
812
        q.table = nil
8✔
813
        q.columnA = nil
8✔
814
        q.columnB = nil
8✔
815
        q.columnC = nil
8✔
816
        q.columnD = nil
8✔
817
        q.columnE = nil
8✔
818
        q.world.unlock(q.lock)
8✔
819
}
8✔
820

821
func (q *Query5[A, B, C, D, E]) nextTableOrArchetype() bool {
19✔
822
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
823
                return true
2✔
824
        }
2✔
825
        return q.nextArchetype()
17✔
826
}
827

828
func (q *Query5[A, B, C, D, E]) nextArchetype() bool {
17✔
829
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
830
        for q.cursor.archetype < maxArchIndex {
43✔
831
                q.cursor.archetype++
26✔
832
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
26✔
833
                if !archetype.mask.Contains(&q.mask) ||
26✔
834
                        archetype.mask.ContainsAny(&q.without) {
42✔
835
                        continue
16✔
836
                }
837

838
                if !archetype.HasRelations() {
17✔
839
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
840
                        if table.Len() > 0 {
15✔
841
                                q.setTable(0, table)
7✔
842
                                return true
7✔
843
                        }
7✔
844
                        continue
1✔
845
                }
846

847
                q.tables = archetype.GetTables(q.relations)
1✔
848
                q.cursor.table = -1
1✔
849
                if q.nextTable() {
2✔
850
                        return true
1✔
851
                }
1✔
852
        }
853
        q.Close()
8✔
854
        return false
8✔
855
}
856

857
func (q *Query5[A, B, C, D, E]) nextTable() bool {
11✔
858
        maxTableIndex := len(q.tables) - 1
11✔
859
        for q.cursor.table < maxTableIndex {
14✔
860
                q.cursor.table++
3✔
861
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
862
                if table.Len() == 0 {
3✔
UNCOV
863
                        continue
×
864
                }
865
                if !table.Matches(q.relations) {
3✔
UNCOV
866
                        continue
×
867
                }
868
                q.setTable(q.cursor.table, table)
3✔
869
                return true
3✔
870
        }
871
        return false
8✔
872
}
873

874
func (q *Query5[A, B, C, D, E]) setTable(index int, table *table) {
10✔
875
        q.cursor.table = index
10✔
876
        q.table = table
10✔
877
        q.columnA = q.components[0].columns[q.table.id]
10✔
878
        q.columnB = q.components[1].columns[q.table.id]
10✔
879
        q.columnC = q.components[2].columns[q.table.id]
10✔
880
        q.columnD = q.components[3].columns[q.table.id]
10✔
881
        q.columnE = q.components[4].columns[q.table.id]
10✔
882
        q.cursor.index = 0
10✔
883
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
884
}
10✔
885

886
// Query6 is a query for 6 components.
887
// Use a [NewFilter6] to create one.
888
type Query6[A any, B any, C any, D any, E any, F any] struct {
889
        world      *World
890
        mask       Mask
891
        without    Mask
892
        relations  []relationID
893
        lock       uint8
894
        cursor     cursor
895
        tables     []tableID
896
        table      *table
897
        components []*componentStorage
898
        columnA    *column
899
        columnB    *column
900
        columnC    *column
901
        columnD    *column
902
        columnE    *column
903
        columnF    *column
904
        hasWithout bool
905
}
906

907
func newQuery6[A any, B any, C any, D any, E any, F any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query6[A, B, C, D, E, F] {
8✔
908
        components := make([]*componentStorage, 6)
8✔
909
        for i := range 6 {
56✔
910
                components[i] = &world.storage.components[ids[i].id]
48✔
911
        }
48✔
912

913
        return Query6[A, B, C, D, E, F]{
8✔
914
                world:      world,
8✔
915
                mask:       mask,
8✔
916
                without:    without,
8✔
917
                relations:  relations,
8✔
918
                hasWithout: !without.IsZero(),
8✔
919
                lock:       world.lock(),
8✔
920
                components: components,
8✔
921
                cursor: cursor{
8✔
922
                        archetype: -1,
8✔
923
                        table:     -1,
8✔
924
                        index:     0,
8✔
925
                        maxIndex:  -1,
8✔
926
                },
8✔
927
        }
8✔
928
}
929

930
// Next advances the query's cursor to the next entity.
931
func (q *Query6[A, B, C, D, E, F]) Next() bool {
161✔
932
        checkQueryNext(&q.cursor)
161✔
933
        if int64(q.cursor.index) < q.cursor.maxIndex {
303✔
934
                q.cursor.index++
142✔
935
                return true
142✔
936
        }
142✔
937
        return q.nextTableOrArchetype()
19✔
938
}
939

940
// Entity returns the current entity.
941
func (q *Query6[A, B, C, D, E, F]) Entity() Entity {
154✔
942
        checkQueryGet(&q.cursor)
154✔
943
        return q.table.GetEntity(q.cursor.index)
154✔
944
}
154✔
945

946
// Get returns the queried components of the current entity.
947
func (q *Query6[A, B, C, D, E, F]) Get() (*A, *B, *C, *D, *E, *F) {
154✔
948
        checkQueryGet(&q.cursor)
154✔
949
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
950
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
951
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
952
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
953
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
954
                (*F)(q.columnF.Get(q.cursor.index))
154✔
955
}
154✔
956

957
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
958
func (q *Query6[A, B, C, D, E, F]) GetRelation(index int) Entity {
×
NEW
UNCOV
959
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
960
}
×
961

962
// Close closes the Query and unlocks the world.
963
//
964
// Automatically called when iteration finishes.
965
// Needs to be called only if breaking out of the query iteration or not iterating at all.
966
func (q *Query6[A, B, C, D, E, F]) Close() {
8✔
967
        q.cursor.archetype = -2
8✔
968
        q.cursor.table = -2
8✔
969
        q.tables = nil
8✔
970
        q.table = nil
8✔
971
        q.columnA = nil
8✔
972
        q.columnB = nil
8✔
973
        q.columnC = nil
8✔
974
        q.columnD = nil
8✔
975
        q.columnE = nil
8✔
976
        q.columnF = nil
8✔
977
        q.world.unlock(q.lock)
8✔
978
}
8✔
979

980
func (q *Query6[A, B, C, D, E, F]) nextTableOrArchetype() bool {
19✔
981
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
982
                return true
2✔
983
        }
2✔
984
        return q.nextArchetype()
17✔
985
}
986

987
func (q *Query6[A, B, C, D, E, F]) nextArchetype() bool {
17✔
988
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
989
        for q.cursor.archetype < maxArchIndex {
43✔
990
                q.cursor.archetype++
26✔
991
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
26✔
992
                if !archetype.mask.Contains(&q.mask) ||
26✔
993
                        archetype.mask.ContainsAny(&q.without) {
42✔
994
                        continue
16✔
995
                }
996

997
                if !archetype.HasRelations() {
17✔
998
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
999
                        if table.Len() > 0 {
15✔
1000
                                q.setTable(0, table)
7✔
1001
                                return true
7✔
1002
                        }
7✔
1003
                        continue
1✔
1004
                }
1005

1006
                q.tables = archetype.GetTables(q.relations)
1✔
1007
                q.cursor.table = -1
1✔
1008
                if q.nextTable() {
2✔
1009
                        return true
1✔
1010
                }
1✔
1011
        }
1012
        q.Close()
8✔
1013
        return false
8✔
1014
}
1015

1016
func (q *Query6[A, B, C, D, E, F]) nextTable() bool {
11✔
1017
        maxTableIndex := len(q.tables) - 1
11✔
1018
        for q.cursor.table < maxTableIndex {
14✔
1019
                q.cursor.table++
3✔
1020
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
1021
                if table.Len() == 0 {
3✔
UNCOV
1022
                        continue
×
1023
                }
1024
                if !table.Matches(q.relations) {
3✔
UNCOV
1025
                        continue
×
1026
                }
1027
                q.setTable(q.cursor.table, table)
3✔
1028
                return true
3✔
1029
        }
1030
        return false
8✔
1031
}
1032

1033
func (q *Query6[A, B, C, D, E, F]) setTable(index int, table *table) {
10✔
1034
        q.cursor.table = index
10✔
1035
        q.table = table
10✔
1036
        q.columnA = q.components[0].columns[q.table.id]
10✔
1037
        q.columnB = q.components[1].columns[q.table.id]
10✔
1038
        q.columnC = q.components[2].columns[q.table.id]
10✔
1039
        q.columnD = q.components[3].columns[q.table.id]
10✔
1040
        q.columnE = q.components[4].columns[q.table.id]
10✔
1041
        q.columnF = q.components[5].columns[q.table.id]
10✔
1042
        q.cursor.index = 0
10✔
1043
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1044
}
10✔
1045

1046
// Query7 is a query for 7 components.
1047
// Use a [NewFilter7] to create one.
1048
type Query7[A any, B any, C any, D any, E any, F any, G any] struct {
1049
        world      *World
1050
        mask       Mask
1051
        without    Mask
1052
        relations  []relationID
1053
        lock       uint8
1054
        cursor     cursor
1055
        tables     []tableID
1056
        table      *table
1057
        components []*componentStorage
1058
        columnA    *column
1059
        columnB    *column
1060
        columnC    *column
1061
        columnD    *column
1062
        columnE    *column
1063
        columnF    *column
1064
        columnG    *column
1065
        hasWithout bool
1066
}
1067

1068
func newQuery7[A any, B any, C any, D any, E any, F any, G any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query7[A, B, C, D, E, F, G] {
8✔
1069
        components := make([]*componentStorage, 7)
8✔
1070
        for i := range 7 {
64✔
1071
                components[i] = &world.storage.components[ids[i].id]
56✔
1072
        }
56✔
1073

1074
        return Query7[A, B, C, D, E, F, G]{
8✔
1075
                world:      world,
8✔
1076
                mask:       mask,
8✔
1077
                without:    without,
8✔
1078
                relations:  relations,
8✔
1079
                hasWithout: !without.IsZero(),
8✔
1080
                lock:       world.lock(),
8✔
1081
                components: components,
8✔
1082
                cursor: cursor{
8✔
1083
                        archetype: -1,
8✔
1084
                        table:     -1,
8✔
1085
                        index:     0,
8✔
1086
                        maxIndex:  -1,
8✔
1087
                },
8✔
1088
        }
8✔
1089
}
1090

1091
// Next advances the query's cursor to the next entity.
1092
func (q *Query7[A, B, C, D, E, F, G]) Next() bool {
161✔
1093
        checkQueryNext(&q.cursor)
161✔
1094
        if int64(q.cursor.index) < q.cursor.maxIndex {
303✔
1095
                q.cursor.index++
142✔
1096
                return true
142✔
1097
        }
142✔
1098
        return q.nextTableOrArchetype()
19✔
1099
}
1100

1101
// Entity returns the current entity.
1102
func (q *Query7[A, B, C, D, E, F, G]) Entity() Entity {
154✔
1103
        checkQueryGet(&q.cursor)
154✔
1104
        return q.table.GetEntity(q.cursor.index)
154✔
1105
}
154✔
1106

1107
// Get returns the queried components of the current entity.
1108
func (q *Query7[A, B, C, D, E, F, G]) Get() (*A, *B, *C, *D, *E, *F, *G) {
154✔
1109
        checkQueryGet(&q.cursor)
154✔
1110
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
1111
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
1112
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
1113
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
1114
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
1115
                (*F)(q.columnF.Get(q.cursor.index)),
154✔
1116
                (*G)(q.columnG.Get(q.cursor.index))
154✔
1117
}
154✔
1118

1119
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
1120
func (q *Query7[A, B, C, D, E, F, G]) GetRelation(index int) Entity {
×
NEW
UNCOV
1121
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
1122
}
×
1123

1124
// Close closes the Query and unlocks the world.
1125
//
1126
// Automatically called when iteration finishes.
1127
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1128
func (q *Query7[A, B, C, D, E, F, G]) Close() {
8✔
1129
        q.cursor.archetype = -2
8✔
1130
        q.cursor.table = -2
8✔
1131
        q.tables = nil
8✔
1132
        q.table = nil
8✔
1133
        q.columnA = nil
8✔
1134
        q.columnB = nil
8✔
1135
        q.columnC = nil
8✔
1136
        q.columnD = nil
8✔
1137
        q.columnE = nil
8✔
1138
        q.columnF = nil
8✔
1139
        q.columnG = nil
8✔
1140
        q.world.unlock(q.lock)
8✔
1141
}
8✔
1142

1143
func (q *Query7[A, B, C, D, E, F, G]) nextTableOrArchetype() bool {
19✔
1144
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
1145
                return true
2✔
1146
        }
2✔
1147
        return q.nextArchetype()
17✔
1148
}
1149

1150
func (q *Query7[A, B, C, D, E, F, G]) nextArchetype() bool {
17✔
1151
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
1152
        for q.cursor.archetype < maxArchIndex {
43✔
1153
                q.cursor.archetype++
26✔
1154
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
26✔
1155
                if !archetype.mask.Contains(&q.mask) ||
26✔
1156
                        archetype.mask.ContainsAny(&q.without) {
42✔
1157
                        continue
16✔
1158
                }
1159

1160
                if !archetype.HasRelations() {
17✔
1161
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
1162
                        if table.Len() > 0 {
15✔
1163
                                q.setTable(0, table)
7✔
1164
                                return true
7✔
1165
                        }
7✔
1166
                        continue
1✔
1167
                }
1168

1169
                q.tables = archetype.GetTables(q.relations)
1✔
1170
                q.cursor.table = -1
1✔
1171
                if q.nextTable() {
2✔
1172
                        return true
1✔
1173
                }
1✔
1174
        }
1175
        q.Close()
8✔
1176
        return false
8✔
1177
}
1178

1179
func (q *Query7[A, B, C, D, E, F, G]) nextTable() bool {
11✔
1180
        maxTableIndex := len(q.tables) - 1
11✔
1181
        for q.cursor.table < maxTableIndex {
14✔
1182
                q.cursor.table++
3✔
1183
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
1184
                if table.Len() == 0 {
3✔
UNCOV
1185
                        continue
×
1186
                }
1187
                if !table.Matches(q.relations) {
3✔
UNCOV
1188
                        continue
×
1189
                }
1190
                q.setTable(q.cursor.table, table)
3✔
1191
                return true
3✔
1192
        }
1193
        return false
8✔
1194
}
1195

1196
func (q *Query7[A, B, C, D, E, F, G]) setTable(index int, table *table) {
10✔
1197
        q.cursor.table = index
10✔
1198
        q.table = table
10✔
1199
        q.columnA = q.components[0].columns[q.table.id]
10✔
1200
        q.columnB = q.components[1].columns[q.table.id]
10✔
1201
        q.columnC = q.components[2].columns[q.table.id]
10✔
1202
        q.columnD = q.components[3].columns[q.table.id]
10✔
1203
        q.columnE = q.components[4].columns[q.table.id]
10✔
1204
        q.columnF = q.components[5].columns[q.table.id]
10✔
1205
        q.columnG = q.components[6].columns[q.table.id]
10✔
1206
        q.cursor.index = 0
10✔
1207
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1208
}
10✔
1209

1210
// Query8 is a query for 8 components.
1211
// Use a [NewFilter8] to create one.
1212
type Query8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1213
        world      *World
1214
        mask       Mask
1215
        without    Mask
1216
        relations  []relationID
1217
        lock       uint8
1218
        cursor     cursor
1219
        tables     []tableID
1220
        table      *table
1221
        components []*componentStorage
1222
        columnA    *column
1223
        columnB    *column
1224
        columnC    *column
1225
        columnD    *column
1226
        columnE    *column
1227
        columnF    *column
1228
        columnG    *column
1229
        columnH    *column
1230
        hasWithout bool
1231
}
1232

1233
func newQuery8[A any, B any, C any, D any, E any, F any, G any, H any](world *World, mask Mask, without Mask, ids []ID, relations []relationID) Query8[A, B, C, D, E, F, G, H] {
8✔
1234
        components := make([]*componentStorage, 8)
8✔
1235
        for i := range 8 {
72✔
1236
                components[i] = &world.storage.components[ids[i].id]
64✔
1237
        }
64✔
1238

1239
        return Query8[A, B, C, D, E, F, G, H]{
8✔
1240
                world:      world,
8✔
1241
                mask:       mask,
8✔
1242
                without:    without,
8✔
1243
                relations:  relations,
8✔
1244
                hasWithout: !without.IsZero(),
8✔
1245
                lock:       world.lock(),
8✔
1246
                components: components,
8✔
1247
                cursor: cursor{
8✔
1248
                        archetype: -1,
8✔
1249
                        table:     -1,
8✔
1250
                        index:     0,
8✔
1251
                        maxIndex:  -1,
8✔
1252
                },
8✔
1253
        }
8✔
1254
}
1255

1256
// Next advances the query's cursor to the next entity.
1257
func (q *Query8[A, B, C, D, E, F, G, H]) Next() bool {
161✔
1258
        checkQueryNext(&q.cursor)
161✔
1259
        if int64(q.cursor.index) < q.cursor.maxIndex {
303✔
1260
                q.cursor.index++
142✔
1261
                return true
142✔
1262
        }
142✔
1263
        return q.nextTableOrArchetype()
19✔
1264
}
1265

1266
// Entity returns the current entity.
1267
func (q *Query8[A, B, C, D, E, F, G, H]) Entity() Entity {
154✔
1268
        checkQueryGet(&q.cursor)
154✔
1269
        return q.table.GetEntity(q.cursor.index)
154✔
1270
}
154✔
1271

1272
// Get returns the queried components of the current entity.
1273
func (q *Query8[A, B, C, D, E, F, G, H]) Get() (*A, *B, *C, *D, *E, *F, *G, *H) {
154✔
1274
        checkQueryGet(&q.cursor)
154✔
1275
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
1276
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
1277
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
1278
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
1279
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
1280
                (*F)(q.columnF.Get(q.cursor.index)),
154✔
1281
                (*G)(q.columnG.Get(q.cursor.index)),
154✔
1282
                (*H)(q.columnH.Get(q.cursor.index))
154✔
1283
}
154✔
1284

1285
// GetRelation returns the entity relation target of the component at the given index.
NEW
UNCOV
1286
func (q *Query8[A, B, C, D, E, F, G, H]) GetRelation(index int) Entity {
×
NEW
UNCOV
1287
        return q.components[index].columns[q.table.id].target
×
NEW
UNCOV
1288
}
×
1289

1290
// Close closes the Query and unlocks the world.
1291
//
1292
// Automatically called when iteration finishes.
1293
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1294
func (q *Query8[A, B, C, D, E, F, G, H]) Close() {
8✔
1295
        q.cursor.archetype = -2
8✔
1296
        q.cursor.table = -2
8✔
1297
        q.tables = nil
8✔
1298
        q.table = nil
8✔
1299
        q.columnA = nil
8✔
1300
        q.columnB = nil
8✔
1301
        q.columnC = nil
8✔
1302
        q.columnD = nil
8✔
1303
        q.columnE = nil
8✔
1304
        q.columnF = nil
8✔
1305
        q.columnG = nil
8✔
1306
        q.columnH = nil
8✔
1307
        q.world.unlock(q.lock)
8✔
1308
}
8✔
1309

1310
func (q *Query8[A, B, C, D, E, F, G, H]) nextTableOrArchetype() bool {
19✔
1311
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
1312
                return true
2✔
1313
        }
2✔
1314
        return q.nextArchetype()
17✔
1315
}
1316

1317
func (q *Query8[A, B, C, D, E, F, G, H]) nextArchetype() bool {
17✔
1318
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
1319
        for q.cursor.archetype < maxArchIndex {
43✔
1320
                q.cursor.archetype++
26✔
1321
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
26✔
1322
                if !archetype.mask.Contains(&q.mask) ||
26✔
1323
                        archetype.mask.ContainsAny(&q.without) {
42✔
1324
                        continue
16✔
1325
                }
1326

1327
                if !archetype.HasRelations() {
17✔
1328
                        table := &q.world.storage.tables[archetype.tables[0]]
8✔
1329
                        if table.Len() > 0 {
15✔
1330
                                q.setTable(0, table)
7✔
1331
                                return true
7✔
1332
                        }
7✔
1333
                        continue
1✔
1334
                }
1335

1336
                q.tables = archetype.GetTables(q.relations)
1✔
1337
                q.cursor.table = -1
1✔
1338
                if q.nextTable() {
2✔
1339
                        return true
1✔
1340
                }
1✔
1341
        }
1342
        q.Close()
8✔
1343
        return false
8✔
1344
}
1345

1346
func (q *Query8[A, B, C, D, E, F, G, H]) nextTable() bool {
11✔
1347
        maxTableIndex := len(q.tables) - 1
11✔
1348
        for q.cursor.table < maxTableIndex {
14✔
1349
                q.cursor.table++
3✔
1350
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
1351
                if table.Len() == 0 {
3✔
UNCOV
1352
                        continue
×
1353
                }
1354
                if !table.Matches(q.relations) {
3✔
UNCOV
1355
                        continue
×
1356
                }
1357
                q.setTable(q.cursor.table, table)
3✔
1358
                return true
3✔
1359
        }
1360
        return false
8✔
1361
}
1362

1363
func (q *Query8[A, B, C, D, E, F, G, H]) setTable(index int, table *table) {
10✔
1364
        q.cursor.table = index
10✔
1365
        q.table = table
10✔
1366
        q.columnA = q.components[0].columns[q.table.id]
10✔
1367
        q.columnB = q.components[1].columns[q.table.id]
10✔
1368
        q.columnC = q.components[2].columns[q.table.id]
10✔
1369
        q.columnD = q.components[3].columns[q.table.id]
10✔
1370
        q.columnE = q.components[4].columns[q.table.id]
10✔
1371
        q.columnF = q.components[5].columns[q.table.id]
10✔
1372
        q.columnG = q.components[6].columns[q.table.id]
10✔
1373
        q.columnH = q.components[7].columns[q.table.id]
10✔
1374
        q.cursor.index = 0
10✔
1375
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1376
}
10✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc