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

mlange-42 / ark / 13528862241

25 Feb 2025 07:00PM CUT coverage: 94.795% (+0.008%) from 94.787%
13528862241

push

github

web-flow
Add Map.GetRelationUnchecked (#75)

6 of 6 new or added lines in 2 files covered. (100.0%)

3406 of 3593 relevant lines covered (94.8%)

51323.81 hits per line

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

90.48
/ecs/world_internal.go
1
package ecs
2

3
import (
4
        "reflect"
5
        "unsafe"
6
)
7

8
func (w *World) newEntityWith(ids []ID, comps []unsafe.Pointer, relations []relationID) Entity {
494,605✔
9
        w.checkLocked()
494,605✔
10

494,605✔
11
        mask := All(ids...)
494,605✔
12
        newTable := w.storage.findOrCreateTable(&w.storage.tables[0], &mask, relations)
494,605✔
13
        entity, idx := w.storage.createEntity(newTable.id)
494,605✔
14

494,605✔
15
        if comps != nil {
989,210✔
16
                if len(ids) != len(comps) {
494,605✔
17
                        panic("lengths of IDs and components to add do not match")
×
18
                }
19
                for i, id := range ids {
992,136✔
20
                        newTable.Set(id, idx, comps[i])
497,531✔
21
                }
497,531✔
22
        }
23
        w.storage.registerTargets(relations)
494,605✔
24
        return entity
494,605✔
25
}
26

27
func (w *World) newEntitiesWith(count int, ids []ID, comps []unsafe.Pointer, relations []relationID) {
8✔
28
        w.checkLocked()
8✔
29

8✔
30
        mask := All(ids...)
8✔
31
        newTable := w.storage.findOrCreateTable(&w.storage.tables[0], &mask, relations)
8✔
32

8✔
33
        startIdx := newTable.Len()
8✔
34
        w.storage.createEntities(newTable, count)
8✔
35

8✔
36
        if comps != nil {
16✔
37
                if len(ids) != len(comps) {
8✔
38
                        panic("lengths of IDs and components to add do not match")
×
39
                }
40
                for i := range count {
200✔
41
                        for j, id := range ids {
1,056✔
42
                                newTable.Set(id, uint32(startIdx+i), comps[j])
864✔
43
                        }
864✔
44
                }
45
        }
46
        w.storage.registerTargets(relations)
8✔
47
}
48

49
func (w *World) newEntities(count int, ids []ID, relations []relationID) (tableID, int) {
8✔
50
        w.checkLocked()
8✔
51

8✔
52
        mask := All(ids...)
8✔
53
        newTable := w.storage.findOrCreateTable(&w.storage.tables[0], &mask, relations)
8✔
54

8✔
55
        startIdx := newTable.Len()
8✔
56
        w.storage.createEntities(newTable, count)
8✔
57
        w.storage.registerTargets(relations)
8✔
58

8✔
59
        return newTable.id, startIdx
8✔
60
}
8✔
61

62
func (w *World) get(entity Entity, component ID) unsafe.Pointer {
2✔
63
        if !w.storage.entityPool.Alive(entity) {
2✔
64
                panic("can't get component of a dead entity")
×
65
        }
66
        index := w.storage.entities[entity.id]
2✔
67
        return w.storage.tables[index.table].Get(component, uintptr(index.row))
2✔
68
}
69

70
func (w *World) has(entity Entity, component ID) bool {
6✔
71
        if !w.storage.entityPool.Alive(entity) {
6✔
72
                panic("can't get component of a dead entity")
×
73
        }
74
        index := w.storage.entities[entity.id]
6✔
75
        return w.storage.tables[index.table].Has(component)
6✔
76
}
77

78
func (w *World) exchange(entity Entity, add []ID, rem []ID, addComps []unsafe.Pointer, relations []relationID) {
852✔
79
        w.checkLocked()
852✔
80

852✔
81
        if !w.Alive(entity) {
852✔
82
                panic("can't exchange components on a dead entity")
×
83
        }
84
        if len(add) == 0 && len(rem) == 0 {
852✔
85
                return
×
86
        }
×
87

88
        index := &w.storage.entities[entity.id]
852✔
89
        oldTable := &w.storage.tables[index.table]
852✔
90
        oldArchetype := &w.storage.archetypes[oldTable.archetype]
852✔
91

852✔
92
        mask := oldArchetype.mask
852✔
93
        w.storage.getExchangeMask(&mask, add, rem)
852✔
94

852✔
95
        oldIDs := oldArchetype.components
852✔
96

852✔
97
        newTable := w.storage.findOrCreateTable(oldTable, &mask, relations)
852✔
98
        newIndex := newTable.Add(entity)
852✔
99

852✔
100
        for _, id := range oldIDs {
3,572✔
101
                if mask.Get(id) {
4,462✔
102
                        comp := oldTable.Get(id, uintptr(index.row))
1,742✔
103
                        newTable.Set(id, newIndex, comp)
1,742✔
104
                }
1,742✔
105
        }
106
        if addComps != nil {
1,419✔
107
                if len(add) != len(addComps) {
567✔
108
                        panic("lengths of IDs and components to add do not match")
×
109
                }
110
                for i, id := range add {
1,526✔
111
                        newTable.Set(id, newIndex, addComps[i])
959✔
112
                }
959✔
113
        }
114

115
        swapped := oldTable.Remove(index.row)
852✔
116

852✔
117
        if swapped {
950✔
118
                swapEntity := oldTable.GetEntity(uintptr(index.row))
98✔
119
                w.storage.entities[swapEntity.id].row = index.row
98✔
120
        }
98✔
121
        w.storage.entities[entity.id] = entityIndex{table: newTable.id, row: newIndex}
852✔
122

852✔
123
        w.storage.registerTargets(relations)
852✔
124
}
125

126
// setRelations sets the target entities for an entity relations.
127
func (w *World) setRelations(entity Entity, relations []relationID) {
34✔
128
        w.checkLocked()
34✔
129

34✔
130
        if !w.storage.entityPool.Alive(entity) {
34✔
131
                panic("can't set relation for a dead entity")
×
132
        }
133

134
        index := &w.storage.entities[entity.id]
34✔
135
        oldTable := &w.storage.tables[index.table]
34✔
136

34✔
137
        newRelations, changed := w.storage.getExchangeTargets(oldTable, relations)
34✔
138
        if !changed {
34✔
139
                return
×
140
        }
×
141

142
        oldArch := &w.storage.archetypes[oldTable.archetype]
34✔
143
        newTable, ok := oldArch.GetTable(&w.storage, newRelations)
34✔
144
        if !ok {
37✔
145
                newTable = w.storage.createTable(oldArch, newRelations)
3✔
146
        }
3✔
147
        newIndex := newTable.Add(entity)
34✔
148

34✔
149
        for _, id := range oldArch.components {
101✔
150
                comp := oldTable.Get(id, uintptr(index.row))
67✔
151
                newTable.Set(id, newIndex, comp)
67✔
152
        }
67✔
153

154
        swapped := oldTable.Remove(index.row)
34✔
155

34✔
156
        if swapped {
50✔
157
                swapEntity := oldTable.GetEntity(uintptr(index.row))
16✔
158
                w.storage.entities[swapEntity.id].row = index.row
16✔
159
        }
16✔
160
        w.storage.entities[entity.id] = entityIndex{table: newTable.id, row: newIndex}
34✔
161

34✔
162
        w.storage.registerTargets(relations)
34✔
163
}
164

165
func (w *World) componentID(tp reflect.Type) ID {
1,873✔
166
        id, newID := w.storage.registry.ComponentID(tp)
1,873✔
167
        if newID {
2,300✔
168
                if w.IsLocked() {
427✔
169
                        w.storage.registry.unregisterLastComponent()
×
170
                        panic("attempt to register a new component in a locked world")
×
171
                }
172
                w.storage.AddComponent(id)
427✔
173
        }
174
        return ID{id: id}
1,873✔
175
}
176

177
func (w *World) resourceID(tp reflect.Type) ResID {
3✔
178
        id, _ := w.resources.registry.ComponentID(tp)
3✔
179
        return ResID{id: id}
3✔
180
}
3✔
181

182
// lock the world and get the lock bit for later unlocking.
183
func (w *World) lock() uint8 {
1,076✔
184
        return w.locks.Lock()
1,076✔
185
}
1,076✔
186

187
// unlock unlocks the given lock bit.
188
func (w *World) unlock(l uint8) {
1,076✔
189
        w.locks.Unlock(l)
1,076✔
190
}
1,076✔
191

192
// checkLocked checks if the world is locked, and panics if so.
193
func (w *World) checkLocked() {
989,087✔
194
        if w.IsLocked() {
989,087✔
195
                panic("attempt to modify a locked world")
×
196
        }
197
}
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