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

mlange-42 / ark / 14191219880

01 Apr 2025 08:44AM CUT coverage: 99.832%. Remained the same
14191219880

push

github

web-flow
Add awesome-go badge (#229)

8298 of 8312 relevant lines covered (99.83%)

20284.26 hits per line

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

97.92
/ecs/world_internal.go
1
package ecs
2

3
import (
4
        "reflect"
5
)
6

7
func (w *World) newEntity(ids []ID, relations []RelationID) Entity {
494,360✔
8
        w.checkLocked()
494,360✔
9
        mask := bitMask{}
494,360✔
10
        newTable := w.storage.findOrCreateTable(&w.storage.tables[0], ids, nil, relations, &mask)
494,360✔
11
        entity, _ := w.storage.createEntity(newTable.id)
494,360✔
12
        w.storage.registerTargets(relations)
494,360✔
13
        return entity
494,360✔
14
}
494,360✔
15

16
func (w *World) newEntities(count int, ids []ID, relations []RelationID) (tableID, int) {
195✔
17
        w.checkLocked()
195✔
18
        mask := bitMask{}
195✔
19
        newTable := w.storage.findOrCreateTable(&w.storage.tables[0], ids, nil, relations, &mask)
195✔
20
        startIdx := newTable.Len()
195✔
21
        w.storage.createEntities(newTable, count)
195✔
22
        w.storage.registerTargets(relations)
195✔
23
        return newTable.id, startIdx
195✔
24
}
195✔
25

26
func (w *World) exchange(entity Entity, add []ID, rem []ID, relations []RelationID) {
998✔
27
        w.checkLocked()
998✔
28

998✔
29
        if !w.Alive(entity) {
1,034✔
30
                panic("can't exchange components on a dead entity")
36✔
31
        }
32
        if len(add) == 0 && len(rem) == 0 {
964✔
33
                if len(relations) > 0 {
3✔
34
                        panic("exchange operation has no effect, but relations were specified. Use SetRelation(s) instead")
1✔
35
                }
36
                return
1✔
37
        }
38

39
        index := w.storage.entities[entity.id]
960✔
40
        oldTable := &w.storage.tables[index.table]
960✔
41
        oldArchetype := &w.storage.archetypes[oldTable.archetype]
960✔
42

960✔
43
        mask := *oldArchetype.mask
960✔
44
        newTable := w.storage.findOrCreateTable(oldTable, add, rem, relations, &mask)
960✔
45
        newIndex := newTable.Add(entity)
960✔
46

960✔
47
        for _, id := range oldArchetype.components {
3,711✔
48
                if mask.Get(id) {
3,481✔
49
                        comp := oldTable.Get(id, uintptr(index.row))
730✔
50
                        newTable.Set(id, newIndex, comp)
730✔
51
                }
730✔
52
        }
53

54
        swapped := oldTable.Remove(index.row)
960✔
55

960✔
56
        if swapped {
1,106✔
57
                swapEntity := oldTable.GetEntity(uintptr(index.row))
146✔
58
                w.storage.entities[swapEntity.id].row = index.row
146✔
59
        }
146✔
60
        w.storage.entities[entity.id] = entityIndex{table: newTable.id, row: newIndex}
960✔
61

960✔
62
        w.storage.registerTargets(relations)
960✔
63
}
64

65
func (w *World) exchangeBatch(batch *Batch, add []ID, rem []ID,
66
        relations []RelationID, fn func(table tableID, start, len int)) {
102✔
67
        w.checkLocked()
102✔
68

102✔
69
        if len(add) == 0 && len(rem) == 0 {
104✔
70
                if len(relations) > 0 {
3✔
71
                        panic("exchange operation has no effect, but relations were specified. Use SetRelationBatch instead")
1✔
72
                }
73
                return
1✔
74
        }
75

76
        tables := w.storage.getTables(batch)
100✔
77
        lengths := make([]uint32, len(tables))
100✔
78
        var totalEntities uint32 = 0
100✔
79
        for i, table := range tables {
300✔
80
                lengths[i] = uint32(table.Len())
200✔
81
                totalEntities += uint32(table.Len())
200✔
82
        }
200✔
83

84
        for i, table := range tables {
300✔
85
                tableLen := lengths[i]
200✔
86

200✔
87
                if tableLen == 0 {
200✔
88
                        continue
×
89
                }
90
                t, start, len := w.exchangeTable(table, int(tableLen), add, rem, relations)
200✔
91
                if fn != nil {
358✔
92
                        fn(t, start, len)
158✔
93
                }
158✔
94
        }
95
}
96

97
func (w *World) exchangeTable(oldTable *table, oldLen int, add []ID, rem []ID, relations []RelationID) (tableID, int, int) {
200✔
98
        oldArchetype := &w.storage.archetypes[oldTable.archetype]
200✔
99

200✔
100
        oldIDs := oldArchetype.components
200✔
101

200✔
102
        mask := *oldArchetype.mask
200✔
103
        newTable := w.storage.findOrCreateTable(oldTable, add, rem, relations, &mask)
200✔
104
        startIdx := uintptr(newTable.Len())
200✔
105
        count := uintptr(oldLen)
200✔
106

200✔
107
        var i uintptr
200✔
108
        for i = 0; i < count; i++ {
2,600✔
109
                idx := startIdx + i
2,400✔
110
                entity := oldTable.GetEntity(i)
2,400✔
111
                index := &w.storage.entities[entity.id]
2,400✔
112
                index.table = newTable.id
2,400✔
113
                index.row = uint32(idx)
2,400✔
114
        }
2,400✔
115

116
        newTable.AddAllEntities(oldTable, uint32(oldLen))
200✔
117
        for _, id := range oldIDs {
960✔
118
                if mask.Get(id) {
1,140✔
119
                        oldCol := oldTable.GetColumn(id)
380✔
120
                        newCol := newTable.GetColumn(id)
380✔
121
                        newCol.SetLast(oldCol, newTable.len, uint32(oldLen))
380✔
122
                }
380✔
123
        }
124

125
        oldTable.Reset()
200✔
126
        w.storage.registerTargets(relations)
200✔
127

200✔
128
        return newTable.id, int(startIdx), int(count)
200✔
129
}
130

131
// setRelations sets the target entities for an entity relations.
132
func (w *World) setRelations(entity Entity, relations []RelationID) {
76✔
133
        w.checkLocked()
76✔
134

76✔
135
        if !w.storage.entityPool.Alive(entity) {
88✔
136
                panic("can't set relation for a dead entity")
12✔
137
        }
138
        if len(relations) == 0 {
76✔
139
                panic("no relations specified")
12✔
140
        }
141

142
        index := &w.storage.entities[entity.id]
52✔
143
        oldTable := &w.storage.tables[index.table]
52✔
144

52✔
145
        newRelations, changed := w.storage.getExchangeTargets(oldTable, relations)
52✔
146
        if !changed {
53✔
147
                return
1✔
148
        }
1✔
149

150
        oldArch := &w.storage.archetypes[oldTable.archetype]
50✔
151
        newTable, ok := oldArch.GetTable(&w.storage, newRelations)
50✔
152
        if !ok {
67✔
153
                newTable = w.storage.createTable(oldArch, newRelations)
17✔
154
        }
17✔
155
        newIndex := newTable.Add(entity)
50✔
156

50✔
157
        for _, id := range oldArch.components {
203✔
158
                comp := oldTable.Get(id, uintptr(index.row))
153✔
159
                newTable.Set(id, newIndex, comp)
153✔
160
        }
153✔
161

162
        swapped := oldTable.Remove(index.row)
50✔
163

50✔
164
        if swapped {
66✔
165
                swapEntity := oldTable.GetEntity(uintptr(index.row))
16✔
166
                w.storage.entities[swapEntity.id].row = index.row
16✔
167
        }
16✔
168
        w.storage.entities[entity.id] = entityIndex{table: newTable.id, row: newIndex}
50✔
169

50✔
170
        w.storage.registerTargets(relations)
50✔
171
}
172

173
func (w *World) setRelationsBatch(batch *Batch, relations []RelationID, fn func(table tableID, start, len int)) {
25✔
174
        w.checkLocked()
25✔
175

25✔
176
        if len(relations) == 0 {
37✔
177
                panic("no relations specified")
12✔
178
        }
179

180
        tables := w.storage.getTables(batch)
13✔
181
        lengths := make([]uint32, len(tables))
13✔
182
        var totalEntities uint32 = 0
13✔
183
        for i, table := range tables {
26✔
184
                lengths[i] = uint32(table.Len())
13✔
185
                totalEntities += uint32(table.Len())
13✔
186
        }
13✔
187

188
        for i, table := range tables {
26✔
189
                tableLen := lengths[i]
13✔
190

13✔
191
                if tableLen == 0 {
13✔
192
                        continue
×
193
                }
194
                t, start, len := w.setRelationsTable(table, int(tableLen), relations)
13✔
195
                if fn != nil {
26✔
196
                        fn(t, start, len)
13✔
197
                }
13✔
198
        }
199

200
        w.storage.registerTargets(relations)
13✔
201
}
202

203
func (w *World) setRelationsTable(oldTable *table, oldLen int, relations []RelationID) (tableID, int, int) {
13✔
204
        newRelations, changed := w.storage.getExchangeTargets(oldTable, relations)
13✔
205

13✔
206
        if !changed {
13✔
207
                return oldTable.id, 0, oldLen
×
208
        }
×
209
        oldArch := &w.storage.archetypes[oldTable.archetype]
13✔
210
        newTable, ok := oldArch.GetTable(&w.storage, newRelations)
13✔
211
        if !ok {
26✔
212
                newTable = w.storage.createTable(oldArch, newRelations)
13✔
213
        }
13✔
214
        startIdx := newTable.Len()
13✔
215
        w.storage.moveEntities(oldTable, newTable, uint32(oldLen))
13✔
216

13✔
217
        return newTable.id, startIdx, oldLen
13✔
218

219
}
220

221
func (w *World) componentID(tp reflect.Type) ID {
3,388✔
222
        id, newID := w.storage.registry.ComponentID(tp)
3,388✔
223
        if newID {
4,709✔
224
                if w.IsLocked() {
1,322✔
225
                        w.storage.registry.unregisterLastComponent()
1✔
226
                        panic("attempt to register a new component in a locked world")
1✔
227
                }
228
                w.storage.AddComponent(id)
1,320✔
229
        }
230
        return ID{id: id}
3,387✔
231
}
232

233
func (w *World) resourceID(tp reflect.Type) ResID {
15✔
234
        id, _ := w.resources.registry.ComponentID(tp)
15✔
235
        return ResID{id: id}
15✔
236
}
15✔
237

238
// lock the world and get the lock bit for later unlocking.
239
func (w *World) lock() uint8 {
1,622✔
240
        return w.locks.Lock()
1,622✔
241
}
1,622✔
242

243
// unlock unlocks the given lock bit.
244
func (w *World) unlock(l uint8) {
1,621✔
245
        w.locks.Unlock(l)
1,621✔
246
}
1,621✔
247

248
// checkLocked checks if the world is locked, and panics if so.
249
func (w *World) checkLocked() {
989,690✔
250
        if w.IsLocked() {
989,691✔
251
                panic("attempt to modify a locked world")
1✔
252
        }
253
}
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