the new evolved.cancel public function

This commit is contained in:
BlackMATov
2025-09-22 02:34:37 +07:00
parent e564be46fb
commit 2250bd64ce
4 changed files with 173 additions and 1 deletions

View File

@@ -599,6 +599,9 @@ function evolved.defer() end
---@return boolean committed
function evolved.commit() end
---@return boolean cancelled
function evolved.cancel() end
```
The [`evolved.defer`](#evolveddefer) function starts a deferred scope. This means that all changes made inside the scope will be queued and applied after leaving the scope. The [`evolved.commit`](#evolvedcommit) function closes the last deferred scope and applies all queued changes. These functions can be nested, so you can start a new deferred scope inside an existing one. The [`evolved.commit`](#evolvedcommit) function will apply all queued changes only when the last deferred scope is closed.
@@ -629,6 +632,34 @@ evolved.commit()
assert(not evolved.has(player, poisoned))
```
The [`evolved.cancel`](#evolvedcancel) function can be used to cancel all queued changes in the current deferred scope. This is useful if you want to discard all changes made inside the scope and revert to the previous state on an error or some other condition.
```lua
local evolved = require 'evolved'
local health, poisoned = evolved.id(2)
local player = evolved.builder()
:set(health, 100)
:set(poisoned, true)
:spawn()
-- start a deferred scope
evolved.defer()
-- this removal will be queued, not applied immediately
evolved.remove(player, poisoned)
-- the player still has the poisoned fragment inside the deferred scope
assert(evolved.has(player, poisoned))
-- cancel the deferred operations
evolved.cancel()
-- the poisoned fragment is still there
assert(evolved.has(player, poisoned))
```
#### Batch Operations
The library provides a set of functions for batch operations. These functions are used to perform modifying operations on multiple chunks at once. This is very useful for performance reasons.
@@ -1101,6 +1132,7 @@ unpack :: id -> integer, integer
defer :: boolean
commit :: boolean
cancel :: boolean
spawn :: <fragment, component>? -> entity
multi_spawn :: integer, <fragment, component>? -> entity[]
@@ -1223,6 +1255,7 @@ builder_mt:destruction_policy :: id -> builder
## vX.X.X
- The internal garbage collector now collects more garbage
- Added the new [`evolved.cancel`](#evolvedcancel) function
## v1.2.0
@@ -1345,6 +1378,13 @@ function evolved.defer() end
function evolved.commit() end
```
### `evolved.cancel`
```lua
---@return boolean cancelled
function evolved.cancel() end
```
### `evolved.spawn`
```lua

View File

@@ -1,5 +1,6 @@
require 'develop.samples.systems'
require 'develop.testing.cancel_tests'
require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests'
require 'develop.testing.requires_fragment_tests'

View File

@@ -0,0 +1,105 @@
local evo = require 'evolved'
do
assert(evo.defer())
assert(evo.cancel())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.commit())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.cancel())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.commit())
end
do
local e, f = evo.id(2)
assert(evo.defer())
do
evo.set(e, f)
assert(not evo.has(e, f))
end
assert(evo.cancel())
assert(not evo.has(e, f))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.cancel())
end
assert(evo.commit())
assert(evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.cancel())
end
assert(evo.cancel())
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.commit())
end
assert(evo.cancel())
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end

View File

@@ -118,6 +118,7 @@ local __acquired_count = 0 ---@type integer
local __available_primary = 0 ---@type integer
local __defer_depth = 0 ---@type integer
local __defer_points = {} ---@type integer[]
local __defer_length = 0 ---@type integer
local __defer_bytecode = {} ---@type any[]
@@ -790,6 +791,7 @@ local __evolved_unpack
local __evolved_defer
local __evolved_commit
local __evolved_cancel
local __evolved_spawn
local __evolved_multi_spawn
@@ -4606,13 +4608,14 @@ end
---@return boolean started
function __evolved_defer()
__defer_depth = __defer_depth + 1
__defer_points[__defer_depth] = __defer_length
return __defer_depth == 1
end
---@return boolean committed
function __evolved_commit()
if __defer_depth <= 0 then
__error_fmt('unbalanced defer/commit')
__error_fmt('unbalanced defer/commit/cancel')
end
__defer_depth = __defer_depth - 1
@@ -4641,6 +4644,17 @@ function __evolved_commit()
return true
end
---@return boolean cancelled
function __evolved_cancel()
if __defer_depth <= 0 then
__error_fmt('unbalanced defer/commit/cancel')
end
__defer_length = __defer_points[__defer_depth]
return __evolved_commit()
end
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity entity
function __evolved_spawn(components)
@@ -5951,6 +5965,17 @@ function __evolved_collect_garbage()
__entity_places = new_entity_places
end
do
---@type integer[]
local new_defer_points = __lua_table_new(__defer_depth, 0)
__lua_table_move(
__defer_points, 1, __defer_depth,
1, new_defer_points)
__defer_points = new_defer_points
end
do
---@type any[]
local new_defer_bytecode = __lua_table_new(__defer_length, 0)
@@ -6894,6 +6919,7 @@ evolved.unpack = __evolved_unpack
evolved.defer = __evolved_defer
evolved.commit = __evolved_commit
evolved.cancel = __evolved_cancel
evolved.spawn = __evolved_spawn
evolved.multi_spawn = __evolved_multi_spawn