mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2026-01-06 03:21:18 +07:00
first defer impl
This commit is contained in:
29
README.md
29
README.md
@@ -1,5 +1,32 @@
|
||||
# evolved.lua
|
||||
|
||||
## Module `defers`
|
||||
|
||||
```
|
||||
defers.defer -> (defer)
|
||||
defers.set -> defer -> entity -> entity -> any -> (defer)
|
||||
defers.apply -> defer -> entity -> {any -> any} -> entity -> (defer)
|
||||
defers.assign -> defer -> entity -> entity -> any -> (defer)
|
||||
defers.insert -> defer -> entity -> entity -> any -> (defer)
|
||||
defers.remove -> defer -> entity -> entity... -> (defer)
|
||||
defers.detach -> defer -> entity -> (defer)
|
||||
defers.destroy -> defer -> entity -> (defer)
|
||||
defers.playback -> defer -> (defer)
|
||||
```
|
||||
|
||||
### Instance `defer`
|
||||
|
||||
```
|
||||
defer:set -> entity -> entity -> any -> (defer)
|
||||
defer:apply -> entity -> {any -> any} -> entity -> (defer)
|
||||
defer:assign -> entity -> entity -> any -> (defer)
|
||||
defer:insert -> entity -> entity -> any -> (defer)
|
||||
defer:remove -> entity -> entity... -> (defer)
|
||||
defer:detach -> entity -> (defer)
|
||||
defer:destroy -> entity -> (defer)
|
||||
defer:playback -> (defer)
|
||||
```
|
||||
|
||||
## Module `idpools`
|
||||
|
||||
```
|
||||
@@ -71,7 +98,7 @@ entity:apply -> {any -> any} -> entity -> (boolean)
|
||||
entity:assign -> entity -> any -> (boolean)
|
||||
entity:insert -> entity -> any -> (boolean)
|
||||
entity:remove -> entity... -> (boolean)
|
||||
entity:detach -> (entity)
|
||||
entity:detach -> (boolean)
|
||||
entity:destroy -> (boolean)
|
||||
```
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require 'develop.untests.defer_untests'
|
||||
require 'develop.untests.idpools_untests'
|
||||
require 'develop.untests.registry_untests'
|
||||
require 'develop.untests.singles_untests'
|
||||
|
||||
108
develop/untests/defer_untests.lua
Normal file
108
develop/untests/defer_untests.lua
Normal file
@@ -0,0 +1,108 @@
|
||||
---@diagnostic disable: invisible
|
||||
local evo = require 'evolved.evolved'
|
||||
|
||||
do
|
||||
local f = evo.registry.entity()
|
||||
local e = evo.registry.entity()
|
||||
local d = evo.defers.defer():set(e, f, 42)
|
||||
assert(not e:has(f))
|
||||
assert(d == d:playback())
|
||||
assert(e:get(f) == 42)
|
||||
|
||||
evo.defers.defer():set(e, f, 84):playback()
|
||||
assert(e:get(f) == 84)
|
||||
end
|
||||
|
||||
do
|
||||
local mul2 = function(v) return v * 2 end
|
||||
|
||||
local f1, f2 = evo.registry.entity(), evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f1, 21)
|
||||
local d = evo.defers.defer():apply(e, mul2, f1)
|
||||
assert(e:get(f1) == 21)
|
||||
assert(d == d:playback())
|
||||
assert(e:get(f1) == 42)
|
||||
|
||||
evo.defers.defer():apply(e, mul2, f2):playback()
|
||||
assert(not e:has(f2) and e:get(f1) == 42)
|
||||
end
|
||||
|
||||
do
|
||||
local mul2 = function(v) return v * 2 end
|
||||
local mul3 = function(v) return v * 3 end
|
||||
|
||||
local f1, f2 = evo.registry.entity(), evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f1, 21):set(f2, 42)
|
||||
local d = evo.defers.defer():apply(e, mul2, f1):apply(e, mul3, f2)
|
||||
assert(e:get(f1) == 21 and e:get(f2) == 42)
|
||||
assert(d == d:playback())
|
||||
assert(e:get(f1) == 42 and e:get(f2) == 126)
|
||||
end
|
||||
|
||||
do
|
||||
local f = evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f, 21)
|
||||
local d = evo.defers.defer():assign(e, f, 42)
|
||||
assert(e:get(f) == 21)
|
||||
assert(d == d:playback())
|
||||
assert(e:get(f) == 42)
|
||||
|
||||
evo.defers.defer():assign(e, f, 84):playback()
|
||||
assert(e:get(f) == 84)
|
||||
end
|
||||
|
||||
do
|
||||
local f = evo.registry.entity()
|
||||
local e = evo.registry.entity()
|
||||
local d = evo.defers.defer():insert(e, f, 42)
|
||||
assert(not e:has(f))
|
||||
assert(d == d:playback())
|
||||
assert(e:get(f) == 42)
|
||||
|
||||
evo.defers.defer():insert(e, f, 84):playback()
|
||||
assert(e:get(f) == 42)
|
||||
end
|
||||
|
||||
do
|
||||
local f = evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f, 21)
|
||||
local d = evo.defers.defer():remove(e)
|
||||
assert(e:get(f) == 21)
|
||||
assert(d == d:playback())
|
||||
assert(e:get(f) == 21)
|
||||
end
|
||||
|
||||
do
|
||||
local f = evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f, 21)
|
||||
local d = evo.defers.defer():remove(e, f)
|
||||
assert(e:get(f) == 21)
|
||||
assert(d == d:playback())
|
||||
assert(not e:has(f))
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2 = evo.registry.entity(), evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f1, 21):set(f2, 42)
|
||||
assert(e:get(f1) == 21 and e:get(f2) == 42)
|
||||
evo.defers.defer():remove(e, f1, f2):playback()
|
||||
assert(not e:has(f1) and not e:has(f2))
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2 = evo.registry.entity(), evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f1, 4):set(f2, 2)
|
||||
local d = evo.defers.defer():detach(e)
|
||||
assert(e:alive() and e:has_all(f1, f2))
|
||||
assert(d == d:playback())
|
||||
assert(e:alive() and not e:has_any(f1, f2))
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2 = evo.registry.entity(), evo.registry.entity()
|
||||
local e = evo.registry.entity():set(f1, 4):set(f2, 2)
|
||||
local d = evo.defers.defer():destroy(e)
|
||||
assert(e:alive() and e:has_all(f1, f2))
|
||||
assert(d == d:playback())
|
||||
assert(not e:alive() and not e:has_any(f1, f2))
|
||||
end
|
||||
260
evolved/defers.lua
Normal file
260
evolved/defers.lua
Normal file
@@ -0,0 +1,260 @@
|
||||
local compat = require 'evolved.compat'
|
||||
local registry = require 'evolved.registry'
|
||||
|
||||
---@class evolved.defers
|
||||
local defers = {}
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
---@enum evolved.defer_op
|
||||
local evolved_defer_op = {
|
||||
set = 1,
|
||||
apply = 2,
|
||||
assign = 3,
|
||||
insert = 4,
|
||||
remove = 5,
|
||||
detach = 6,
|
||||
destroy = 7,
|
||||
}
|
||||
|
||||
---@class evolved.defer
|
||||
---@field operations any[]
|
||||
---@field operation_count integer
|
||||
local evolved_defer_mt = {}
|
||||
evolved_defer_mt.__index = evolved_defer_mt
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
---@type table<evolved.defer_op, fun(ops: any[], idx: integer): integer>
|
||||
local __operation_processors = {
|
||||
[evolved_defer_op.set] = function(ops, idx)
|
||||
local entity = ops[idx + 1]
|
||||
local fragment = ops[idx + 2]
|
||||
local component = ops[idx + 3]
|
||||
registry.set(entity, fragment, component)
|
||||
return 4
|
||||
end,
|
||||
[evolved_defer_op.apply] = function(ops, idx)
|
||||
local entity = ops[idx + 1]
|
||||
local apply = ops[idx + 2]
|
||||
local fragment = ops[idx + 3]
|
||||
registry.apply(entity, apply, fragment)
|
||||
return 4
|
||||
end,
|
||||
[evolved_defer_op.assign] = function(ops, idx)
|
||||
local entity = ops[idx + 1]
|
||||
local fragment = ops[idx + 2]
|
||||
local component = ops[idx + 3]
|
||||
registry.assign(entity, fragment, component)
|
||||
return 4
|
||||
end,
|
||||
[evolved_defer_op.insert] = function(ops, ids)
|
||||
local entity = ops[ids + 1]
|
||||
local fragment = ops[ids + 2]
|
||||
local component = ops[ids + 3]
|
||||
registry.insert(entity, fragment, component)
|
||||
return 4
|
||||
end,
|
||||
[evolved_defer_op.remove] = function(ops, idx)
|
||||
local entity = ops[idx + 1]
|
||||
local fragment_count = ops[idx + 2]
|
||||
registry.remove(entity, compat.unpack(ops, idx + 3, idx + 3 + fragment_count))
|
||||
return 3 + fragment_count
|
||||
end,
|
||||
[evolved_defer_op.detach] = function(ops, idx)
|
||||
local entity = ops[idx + 1]
|
||||
registry.detach(entity)
|
||||
return 2
|
||||
end,
|
||||
[evolved_defer_op.destroy] = function(ops, idx)
|
||||
local entity = ops[idx + 1]
|
||||
registry.destroy(entity)
|
||||
return 2
|
||||
end,
|
||||
}
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
---@return evolved.defer
|
||||
---@nodiscard
|
||||
function defers.defer()
|
||||
---@type evolved.defer
|
||||
local defer = {
|
||||
operations = {},
|
||||
operation_count = 0,
|
||||
}
|
||||
return setmetatable(defer, evolved_defer_mt)
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return evolved.defer
|
||||
function defers.set(defer, entity, fragment, component)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.set
|
||||
operations[operation_count + 2] = entity
|
||||
operations[operation_count + 3] = fragment
|
||||
operations[operation_count + 4] = component
|
||||
|
||||
defer.operation_count = operation_count + 4
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@param apply fun(any): any
|
||||
---@param fragment evolved.entity
|
||||
---@return evolved.defer
|
||||
function defers.apply(defer, entity, apply, fragment)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.apply
|
||||
operations[operation_count + 2] = entity
|
||||
operations[operation_count + 3] = apply
|
||||
operations[operation_count + 4] = fragment
|
||||
|
||||
defer.operation_count = operation_count + 4
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return evolved.defer
|
||||
function defers.assign(defer, entity, fragment, component)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.assign
|
||||
operations[operation_count + 2] = entity
|
||||
operations[operation_count + 3] = fragment
|
||||
operations[operation_count + 4] = component
|
||||
|
||||
defer.operation_count = operation_count + 4
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return evolved.defer
|
||||
function defers.insert(defer, entity, fragment, component)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.insert
|
||||
operations[operation_count + 2] = entity
|
||||
operations[operation_count + 3] = fragment
|
||||
operations[operation_count + 4] = component
|
||||
|
||||
defer.operation_count = operation_count + 4
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@param ... evolved.entity fragments
|
||||
---@return evolved.defer
|
||||
function defers.remove(defer, entity, ...)
|
||||
local fragment_count = select('#', ...)
|
||||
if fragment_count == 0 then return defer end
|
||||
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.remove
|
||||
operations[operation_count + 2] = entity
|
||||
operations[operation_count + 3] = fragment_count
|
||||
|
||||
for i = 1, fragment_count do
|
||||
operations[operation_count + 3 + i] = select(i, ...)
|
||||
end
|
||||
|
||||
defer.operation_count = operation_count + 3 + fragment_count
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@return evolved.defer
|
||||
function defers.detach(defer, entity)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.detach
|
||||
operations[operation_count + 2] = entity
|
||||
|
||||
defer.operation_count = operation_count + 2
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@param entity evolved.entity
|
||||
---@return evolved.defer
|
||||
function defers.destroy(defer, entity)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
operations[operation_count + 1] = evolved_defer_op.destroy
|
||||
operations[operation_count + 2] = entity
|
||||
|
||||
defer.operation_count = operation_count + 2
|
||||
return defer
|
||||
end
|
||||
|
||||
---@param defer evolved.defer
|
||||
---@return evolved.defer
|
||||
function defers.playback(defer)
|
||||
local operations = defer.operations
|
||||
local operation_count = defer.operation_count
|
||||
|
||||
local operation_index = 1; while operation_index <= operation_count do
|
||||
local operation = operations[operation_index]
|
||||
local processor = __operation_processors[operation]
|
||||
operation_index = operation_index + processor(operations, operation_index)
|
||||
end
|
||||
|
||||
return defer
|
||||
end
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
evolved_defer_mt.set = defers.set
|
||||
evolved_defer_mt.apply = defers.apply
|
||||
evolved_defer_mt.assign = defers.assign
|
||||
evolved_defer_mt.insert = defers.insert
|
||||
evolved_defer_mt.remove = defers.remove
|
||||
evolved_defer_mt.detach = defers.detach
|
||||
evolved_defer_mt.destroy = defers.destroy
|
||||
evolved_defer_mt.playback = defers.playback
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
return defers
|
||||
@@ -1,5 +1,6 @@
|
||||
return {
|
||||
compat = require 'evolved.compat',
|
||||
defers = require 'evolved.defers',
|
||||
idpools = require 'evolved.idpools',
|
||||
registry = require 'evolved.registry',
|
||||
singles = require 'evolved.singles',
|
||||
|
||||
Reference in New Issue
Block a user