Created
June 6, 2020 19:55
-
-
Save planetis-m/23e97bc315cc3b6829ebfbe9d9cc595f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type | |
Entity = uint16 | |
Version = uint8 | |
Registry = object | |
destroyed: Entity | |
entities: seq[Entity] | |
const | |
entityMask = 0xFFF.uint16 # Mask to use to get the entity number out of an identifier. | |
versionMask = 0xF.uint16 # Mask to use to get the version out of an identifier. | |
entityShift = 12 # Extent of the entity number within an identifier. | |
invalidId = entityMask | |
proc index(entity: Entity): int = | |
## Returns the entity identifier without the version. | |
result = int(entity and entityMask) | |
proc version(entity: Entity): Version = | |
## Returns the version stored along with an entity identifier. | |
result = Version(entity shr entityShift) | |
proc isValid(reg: Registry; entity: Entity): bool = | |
## Checks if an entity identifier refers to a valid entity. | |
let pos = entity.index | |
result = pos < reg.entities.len and reg.entities[pos] == entity | |
proc current(reg: Registry; entity: Entity): Version = | |
## Returns the actual version for an entity identifier. | |
let pos = entity.index | |
assert(pos < reg.entities.len) | |
result = reg.entities[pos].version | |
proc create(reg: var Registry): Entity = | |
## Creates a new entity and returns it. | |
## There are two kinds of possible entity identifiers: | |
## | |
## Newly created ones in case no entities have been previously destroyed. | |
## Recycled ones with updated versions. | |
if reg.destroyed == invalidId: | |
result = Entity(reg.entities.len) | |
reg.entities.add(result) | |
# entityMask is reserved to allow for null identifiers | |
assert(result < entityMask) | |
else: | |
let curr = reg.destroyed | |
let version = reg.entities[curr] and (versionMask shl entityShift) | |
echo version | |
reg.destroyed = Entity(reg.entities[curr] and entityMask) | |
result = Entity(curr or version) | |
reg.entities[curr] = result | |
proc destroy(reg: var Registry; entity: Entity) = | |
## When an entity is destroyed, its version is updated and the identifier | |
## can be recycled at any time. | |
let version = entity.version + 1 | |
# lengthens the implicit list of destroyed entities | |
let index = entity.index | |
reg.entities[index] = Entity(reg.destroyed or (version shl entityShift)) | |
reg.destroyed = Entity(index) | |
proc main = | |
var reg = Registry(destroyed: invalidId) | |
let ent1 = create(reg) | |
let ent2 = create(reg) | |
reg.destroy(ent1) | |
let ent3 = create(reg) | |
reg.destroy(ent2) | |
let ent4 = create(reg) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment