mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2025-12-13 11:38:15 +07:00
additional oop-like api
This commit is contained in:
52
README.md
52
README.md
@@ -1,8 +1,6 @@
|
||||
# evolved.lua
|
||||
|
||||
## API Reference
|
||||
|
||||
### Module `idpools`
|
||||
## Module `idpools`
|
||||
|
||||
```
|
||||
idpools.idpool -> (idpool)
|
||||
@@ -13,7 +11,17 @@ idpools.release -> idpool -> id -> ()
|
||||
idpools.is_alive -> idpool -> id -> (boolean)
|
||||
```
|
||||
|
||||
### Module `registry`
|
||||
### Instance `idpool`
|
||||
|
||||
```
|
||||
idpool.pack -> integer -> integer -> (id)
|
||||
idpool.unpack -> id -> (integer, integer)
|
||||
idpool:acquire -> (id)
|
||||
idpool:release -> id -> ()
|
||||
idpool:is_alive -> id -> (boolean)
|
||||
```
|
||||
|
||||
## Module `registry`
|
||||
|
||||
```
|
||||
registry.entity -> (entity)
|
||||
@@ -30,11 +38,39 @@ registry.remove -> entity -> entity -> ()
|
||||
registry.query -> entity -> entity... -> (query)
|
||||
registry.execute -> query -> (() -> (chunk?))
|
||||
registry.chunk -> entity -> entity... -> (chunk)
|
||||
registry.chunk_entities -> chunk -> entity -> (entity[])
|
||||
registry.chunk_components -> chunk -> entity -> (any[])
|
||||
registry.entities -> chunk -> entity -> (entity[])
|
||||
registry.components -> chunk -> entity -> (any[])
|
||||
```
|
||||
|
||||
### Module `singles`
|
||||
### Instance `entity`
|
||||
|
||||
```
|
||||
enity:is_alive -> (boolean)
|
||||
enity:destroy -> ()
|
||||
enity:get -> entity -> (any)
|
||||
enity:get_or -> entity -> any -> (any)
|
||||
enity:has -> entity -> (boolean)
|
||||
enity:has_all -> entity -> entity... -> (boolean)
|
||||
enity:has_any -> entity -> entity... -> (boolean)
|
||||
enity:assign -> entity -> any -> ()
|
||||
enity:insert -> entity -> any -> ()
|
||||
enity:remove -> entity -> ()
|
||||
```
|
||||
|
||||
### Instance `query`
|
||||
|
||||
```
|
||||
query:execute -> (() -> (chunk?))
|
||||
```
|
||||
|
||||
### Instance `chunk`
|
||||
|
||||
```
|
||||
chunk:entities -> entity -> (entity[])
|
||||
chunk:components -> entity -> (any[])
|
||||
```
|
||||
|
||||
## Module `singles`
|
||||
|
||||
```
|
||||
singles.single -> any -> (entity)
|
||||
@@ -43,7 +79,7 @@ singles.has -> entity -> (boolean)
|
||||
singles.assign -> entity -> any -> ()
|
||||
```
|
||||
|
||||
### Module `vectors`
|
||||
## Module `vectors`
|
||||
|
||||
```
|
||||
vectors.vector2 -> number -> number -> (vector2)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
## Backlog
|
||||
|
||||
- [ ] add oop-like api for entities and queries
|
||||
- [x] add additional oop-like api
|
||||
- [ ] add fluent interface for oop-like api
|
||||
- [ ] cache matched chunks in queries
|
||||
- [ ] cache transitions between chunks
|
||||
- [ ] chunk's children should be sorted by id and stored in an array instead of a table
|
||||
@@ -17,19 +17,17 @@ local queries = {
|
||||
|
||||
do
|
||||
local entity = evo.registry.entity()
|
||||
local position = evo.vectors.vector2(512, 50)
|
||||
local velocity = evo.vectors.vector2(math.random(-20, 20), 20)
|
||||
evo.registry.insert(entity, fragments.position, position)
|
||||
evo.registry.insert(entity, fragments.velocity, velocity)
|
||||
entity:insert(fragments.position, evo.vectors.vector2(512, 50))
|
||||
entity:insert(fragments.velocity, evo.vectors.vector2(math.random(-20, 20), 20))
|
||||
end
|
||||
|
||||
do
|
||||
local dt = evo.singles.get(singles.delta_time)
|
||||
|
||||
for chunk in evo.registry.execute(queries.bodies) do
|
||||
local es = evo.registry.chunk_entities(chunk)
|
||||
local ps = evo.registry.chunk_components(chunk, fragments.position)
|
||||
local vs = evo.registry.chunk_components(chunk, fragments.velocity)
|
||||
for chunk in queries.bodies:execute() do
|
||||
local es = chunk:entities()
|
||||
local ps = chunk:components(fragments.position)
|
||||
local vs = chunk:components(fragments.velocity)
|
||||
|
||||
for i = 1, #es do
|
||||
ps[i] = ps[i] + vs[i] * dt
|
||||
|
||||
@@ -10,19 +10,19 @@ end
|
||||
do
|
||||
local p = evo.idpools.idpool()
|
||||
|
||||
local i1_1 = evo.idpools.acquire(p)
|
||||
local i1_1 = p:acquire()
|
||||
assert(i1_1 == 0x100001)
|
||||
|
||||
local i2_1 = evo.idpools.acquire(p)
|
||||
local i2_1 = p:acquire()
|
||||
assert(i2_1 == 0x100002)
|
||||
|
||||
do
|
||||
local i, v = evo.idpools.unpack(i1_1)
|
||||
local i, v = p.unpack(i1_1)
|
||||
assert(i == 1 and v == 1)
|
||||
end
|
||||
|
||||
do
|
||||
local i, v = evo.idpools.unpack(i2_1)
|
||||
local i, v = p.unpack(i2_1)
|
||||
assert(i == 2 and v == 1)
|
||||
end
|
||||
end
|
||||
@@ -30,39 +30,39 @@ end
|
||||
do
|
||||
local p = evo.idpools.idpool()
|
||||
|
||||
local i1_1 = evo.idpools.acquire(p)
|
||||
local i2_1 = evo.idpools.acquire(p)
|
||||
assert(evo.idpools.is_alive(p, i1_1))
|
||||
assert(evo.idpools.is_alive(p, i2_1))
|
||||
local i1_1 = p:acquire()
|
||||
local i2_1 = p:acquire()
|
||||
assert(p:is_alive(i1_1))
|
||||
assert(p:is_alive(i2_1))
|
||||
|
||||
evo.idpools.release(p, i1_1)
|
||||
assert(not evo.idpools.is_alive(p, i1_1))
|
||||
assert(evo.idpools.is_alive(p, i2_1))
|
||||
p:release(i1_1)
|
||||
assert(not p:is_alive(i1_1))
|
||||
assert(p:is_alive(i2_1))
|
||||
|
||||
evo.idpools.release(p, i2_1)
|
||||
assert(not evo.idpools.is_alive(p, i1_1))
|
||||
assert(not evo.idpools.is_alive(p, i2_1))
|
||||
p:release(i2_1)
|
||||
assert(not p:is_alive(i1_1))
|
||||
assert(not p:is_alive(i2_1))
|
||||
|
||||
local i2_2 = evo.idpools.acquire(p)
|
||||
local i2_2 = p:acquire()
|
||||
assert(i2_2 == 0x200002)
|
||||
|
||||
local i1_2 = evo.idpools.acquire(p)
|
||||
local i1_2 = p:acquire()
|
||||
assert(i1_2 == 0x200001)
|
||||
|
||||
assert(not evo.idpools.is_alive(p, i1_1))
|
||||
assert(not evo.idpools.is_alive(p, i2_1))
|
||||
assert(evo.idpools.is_alive(p, i1_2))
|
||||
assert(evo.idpools.is_alive(p, i2_2))
|
||||
assert(not p:is_alive(i1_1))
|
||||
assert(not p:is_alive(i2_1))
|
||||
assert(p:is_alive(i1_2))
|
||||
assert(p:is_alive(i2_2))
|
||||
end
|
||||
|
||||
do
|
||||
local p = evo.idpools.idpool()
|
||||
|
||||
for _ = 1, 0xFFFFF - 1 do
|
||||
_ = evo.idpools.acquire(p)
|
||||
_ = p:acquire()
|
||||
end
|
||||
|
||||
assert(evo.idpools.acquire(p) == 0x1FFFFF)
|
||||
assert(p:acquire() == 0x1FFFFF)
|
||||
|
||||
if not os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") then
|
||||
assert(not pcall(evo.idpools.acquire, p))
|
||||
@@ -73,16 +73,16 @@ do
|
||||
local p = evo.idpools.idpool()
|
||||
|
||||
for _ = 1, 0x7FF - 1 do
|
||||
evo.idpools.release(p, evo.idpools.acquire(p))
|
||||
p:release(p:acquire())
|
||||
end
|
||||
|
||||
local i1_7FF = evo.idpools.acquire(p)
|
||||
local i1_7FF = p:acquire()
|
||||
assert(i1_7FF == 0x7FF00001)
|
||||
evo.idpools.release(p, i1_7FF)
|
||||
p:release(i1_7FF)
|
||||
|
||||
local i1_1 = evo.idpools.acquire(p)
|
||||
local i1_1 = p:acquire()
|
||||
assert(i1_1 == 0x100001)
|
||||
evo.idpools.release(p, i1_1)
|
||||
p:release(i1_1)
|
||||
end
|
||||
|
||||
for _ = 1, 100 do
|
||||
|
||||
@@ -7,21 +7,21 @@ do
|
||||
local e = evo.registry.entity()
|
||||
assert(e.__chunk == nil)
|
||||
|
||||
evo.registry.insert(e, f1)
|
||||
assert(evo.registry.has(e, f1))
|
||||
assert(not evo.registry.has(e, f2))
|
||||
e:insert(f1)
|
||||
assert(e:has(f1))
|
||||
assert(not e:has(f2))
|
||||
|
||||
evo.registry.insert(e, f2)
|
||||
assert(evo.registry.has(e, f1))
|
||||
assert(evo.registry.has(e, f2))
|
||||
e:insert(f2)
|
||||
assert(e:has(f1))
|
||||
assert(e:has(f2))
|
||||
|
||||
evo.registry.remove(e, f1)
|
||||
assert(not evo.registry.has(e, f1))
|
||||
assert(evo.registry.has(e, f2))
|
||||
e:remove(f1)
|
||||
assert(not e:has(f1))
|
||||
assert(e:has(f2))
|
||||
|
||||
evo.registry.remove(e, f2)
|
||||
assert(not evo.registry.has(e, f1))
|
||||
assert(not evo.registry.has(e, f2))
|
||||
e:remove(f2)
|
||||
assert(not e:has(f1))
|
||||
assert(not e:has(f2))
|
||||
end
|
||||
|
||||
do
|
||||
@@ -29,28 +29,28 @@ do
|
||||
local e = evo.registry.entity()
|
||||
|
||||
if not os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") then
|
||||
assert(not pcall(evo.registry.get, e, f))
|
||||
assert(not pcall(evo.registry.assign, e, f, 42))
|
||||
assert(not pcall(e.get, e, f))
|
||||
assert(not pcall(e.assign, e, f, 42))
|
||||
end
|
||||
|
||||
assert(evo.registry.get_or(e, f) == nil)
|
||||
assert(evo.registry.get_or(e, f, 42) == 42)
|
||||
assert(e:get_or(f) == nil)
|
||||
assert(e:get_or(f, 42) == 42)
|
||||
|
||||
evo.registry.insert(e, f, 84)
|
||||
e:insert(f, 84)
|
||||
|
||||
assert(evo.registry.get(e, f) == 84)
|
||||
assert(evo.registry.get_or(e, f) == 84)
|
||||
assert(evo.registry.get_or(e, f, 42) == 84)
|
||||
assert(e:get(f) == 84)
|
||||
assert(e:get_or(f) == 84)
|
||||
assert(e:get_or(f, 42) == 84)
|
||||
|
||||
if not os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") then
|
||||
assert(not pcall(evo.registry.insert, e, f, 42))
|
||||
assert(not pcall(e.insert, e, f, 42))
|
||||
end
|
||||
|
||||
evo.registry.assign(e, f)
|
||||
assert(evo.registry.get(e, f) == true)
|
||||
e:assign(f)
|
||||
assert(e:get(f) == true)
|
||||
|
||||
evo.registry.assign(e, f, 21)
|
||||
assert(evo.registry.get(e, f) == 21)
|
||||
e:assign(f, 21)
|
||||
assert(e:get(f) == 21)
|
||||
end
|
||||
|
||||
do
|
||||
@@ -58,7 +58,7 @@ do
|
||||
|
||||
local e = evo.registry.entity()
|
||||
|
||||
evo.registry.insert(e, f1, f1.__guid)
|
||||
e:insert(f1, f1.__guid)
|
||||
assert(e.__chunk == evo.registry.chunk(f1))
|
||||
|
||||
do
|
||||
@@ -67,7 +67,7 @@ do
|
||||
assert(#chunk_f1.__components[f1] == 1)
|
||||
end
|
||||
|
||||
evo.registry.insert(e, f2, f2.__guid)
|
||||
e:insert(f2, f2.__guid)
|
||||
assert(e.__chunk == evo.registry.chunk(f1, f2))
|
||||
|
||||
do
|
||||
@@ -81,7 +81,7 @@ do
|
||||
assert(#chunk_f1_f2.__components[f2] == 1)
|
||||
end
|
||||
|
||||
evo.registry.remove(e, f1)
|
||||
e:remove(f1)
|
||||
assert(e.__chunk == evo.registry.chunk(f2))
|
||||
|
||||
do
|
||||
@@ -134,40 +134,40 @@ for _ = 1, 100 do
|
||||
|
||||
shuffle_array(insert_fragments)
|
||||
for _, f in ipairs(insert_fragments) do
|
||||
evo.registry.insert(e1, f, f.__guid)
|
||||
e1:insert(f, f.__guid)
|
||||
end
|
||||
|
||||
shuffle_array(insert_fragments)
|
||||
for _, f in ipairs(insert_fragments) do
|
||||
evo.registry.insert(e2, f, f.__guid)
|
||||
e2:insert(f, f.__guid)
|
||||
end
|
||||
|
||||
assert(e1.__chunk == e2.__chunk)
|
||||
assert(evo.registry.has_all(e1, evo.compat.unpack(insert_fragments)))
|
||||
assert(evo.registry.has_all(e2, evo.compat.unpack(insert_fragments)))
|
||||
assert(e1:has_all(evo.compat.unpack(insert_fragments)))
|
||||
assert(e2:has_all(evo.compat.unpack(insert_fragments)))
|
||||
|
||||
shuffle_array(remove_fragments)
|
||||
for _, f in ipairs(remove_fragments) do
|
||||
if evo.registry.has(e1, f) then
|
||||
evo.registry.remove(e1, f)
|
||||
if e1:has(f) then
|
||||
e1:remove(f)
|
||||
end
|
||||
end
|
||||
|
||||
shuffle_array(remove_fragments)
|
||||
for _, f in ipairs(remove_fragments) do
|
||||
if evo.registry.has(e2, f) then
|
||||
evo.registry.remove(e2, f)
|
||||
if e2:has(f) then
|
||||
e2:remove(f)
|
||||
end
|
||||
end
|
||||
|
||||
assert(e1.__chunk == e2.__chunk)
|
||||
assert(not evo.registry.has_any(e1, evo.compat.unpack(remove_fragments)))
|
||||
assert(not evo.registry.has_any(e2, evo.compat.unpack(remove_fragments)))
|
||||
assert(not e1:has_any(evo.compat.unpack(remove_fragments)))
|
||||
assert(not e2:has_any(evo.compat.unpack(remove_fragments)))
|
||||
|
||||
if e1.__chunk ~= nil then
|
||||
for f, _ in pairs(e1.__chunk.__components) do
|
||||
assert(evo.registry.get(e1, f) == f.__guid)
|
||||
assert(evo.registry.get(e2, f) == f.__guid)
|
||||
assert(e1:get(f) == f.__guid)
|
||||
assert(e2:get(f) == f.__guid)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -177,34 +177,34 @@ do
|
||||
local f1, f2, f3 = evo.registry.entity(), evo.registry.entity(), evo.registry.entity()
|
||||
|
||||
local e1 = evo.registry.entity()
|
||||
evo.registry.insert(e1, f1)
|
||||
e1:insert(f1)
|
||||
|
||||
local e2 = evo.registry.entity()
|
||||
evo.registry.insert(e2, f1)
|
||||
evo.registry.insert(e2, f2)
|
||||
e2:insert(f1)
|
||||
e2:insert(f2)
|
||||
|
||||
local e3 = evo.registry.entity()
|
||||
evo.registry.insert(e3, f1)
|
||||
evo.registry.insert(e3, f2)
|
||||
evo.registry.insert(e3, f3)
|
||||
e3:insert(f1)
|
||||
e3:insert(f2)
|
||||
e3:insert(f3)
|
||||
|
||||
do
|
||||
local e = evo.registry.entity()
|
||||
|
||||
evo.registry.insert(e, f1)
|
||||
evo.registry.remove(e, f1)
|
||||
e:insert(f1)
|
||||
e:remove(f1)
|
||||
|
||||
evo.registry.insert(e, f1)
|
||||
evo.registry.insert(e, f2)
|
||||
evo.registry.remove(e, f1)
|
||||
evo.registry.remove(e, f2)
|
||||
e:insert(f1)
|
||||
e:insert(f2)
|
||||
e:remove(f1)
|
||||
e:remove(f2)
|
||||
|
||||
evo.registry.insert(e, f1)
|
||||
evo.registry.insert(e, f2)
|
||||
evo.registry.insert(e, f3)
|
||||
evo.registry.remove(e, f1)
|
||||
evo.registry.remove(e, f2)
|
||||
evo.registry.remove(e, f3)
|
||||
e:insert(f1)
|
||||
e:insert(f2)
|
||||
e:insert(f3)
|
||||
e:remove(f1)
|
||||
e:remove(f2)
|
||||
e:remove(f3)
|
||||
end
|
||||
|
||||
local q1 = evo.registry.query(f1)
|
||||
@@ -216,8 +216,8 @@ do
|
||||
---@nodiscard
|
||||
local function collect_query_entities(query)
|
||||
local entities = {} ---@type evolved.entity[]
|
||||
for chunk in evo.registry.execute(query) do
|
||||
for _, e in ipairs(chunk.__entities) do
|
||||
for chunk in query:execute() do
|
||||
for _, e in ipairs(chunk:entities()) do
|
||||
table.insert(entities, e)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
---@class evolved.idpools
|
||||
local idpools = {}
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
---@alias evolved.id integer
|
||||
|
||||
---@class evolved.idpool
|
||||
@@ -9,6 +15,12 @@ local idpools = {}
|
||||
local evolved_idpool_mt = {}
|
||||
evolved_idpool_mt.__index = evolved_idpool_mt
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
---@return evolved.idpool
|
||||
function idpools.idpool()
|
||||
---@type evolved.idpool
|
||||
@@ -91,4 +103,22 @@ function idpools.is_alive(idpool, id)
|
||||
return idpool.__freelist_ids[index] == id
|
||||
end
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
evolved_idpool_mt.pack = idpools.pack
|
||||
evolved_idpool_mt.unpack = idpools.unpack
|
||||
evolved_idpool_mt.acquire = idpools.acquire
|
||||
evolved_idpool_mt.release = idpools.release
|
||||
evolved_idpool_mt.is_alive = idpools.is_alive
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
return idpools
|
||||
|
||||
@@ -495,7 +495,7 @@ end
|
||||
---@param chunk evolved.chunk
|
||||
---@return evolved.entity[]
|
||||
---@nodiscard
|
||||
function registry.chunk_entities(chunk)
|
||||
function registry.entities(chunk)
|
||||
return chunk.__entities
|
||||
end
|
||||
|
||||
@@ -503,7 +503,7 @@ end
|
||||
---@param fragment evolved.entity
|
||||
---@return any[]
|
||||
---@nodiscard
|
||||
function registry.chunk_components(chunk, fragment)
|
||||
function registry.components(chunk, fragment)
|
||||
local components = chunk.__components[fragment]
|
||||
|
||||
if components == nil then
|
||||
@@ -525,6 +525,17 @@ function evolved_entity_mt:__tostring()
|
||||
return string.format('[%d;%d]', index, version)
|
||||
end
|
||||
|
||||
evolved_entity_mt.is_alive = registry.is_alive
|
||||
evolved_entity_mt.destroy = registry.destroy
|
||||
evolved_entity_mt.get = registry.get
|
||||
evolved_entity_mt.get_or = registry.get_or
|
||||
evolved_entity_mt.has = registry.has
|
||||
evolved_entity_mt.has_all = registry.has_all
|
||||
evolved_entity_mt.has_any = registry.has_any
|
||||
evolved_entity_mt.assign = registry.assign
|
||||
evolved_entity_mt.insert = registry.insert
|
||||
evolved_entity_mt.remove = registry.remove
|
||||
|
||||
function evolved_query_mt:__tostring()
|
||||
local fragment_ids = ''
|
||||
|
||||
@@ -535,6 +546,8 @@ function evolved_query_mt:__tostring()
|
||||
return string.format('(%s)', fragment_ids)
|
||||
end
|
||||
|
||||
evolved_query_mt.execute = registry.execute
|
||||
|
||||
function evolved_chunk_mt:__tostring()
|
||||
local fragment_ids = ''
|
||||
|
||||
@@ -546,6 +559,9 @@ function evolved_chunk_mt:__tostring()
|
||||
return string.format('{%s}', fragment_ids)
|
||||
end
|
||||
|
||||
evolved_chunk_mt.entities = registry.entities
|
||||
evolved_chunk_mt.components = registry.components
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user