From 9e4e3440bc9135a425df668f48dd3652b34f3c06 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 20 May 2025 17:47:20 +0700 Subject: [PATCH] manual wip --- MANUAL.md | 54 ++++++++++++++++++++++++---- README.md | 106 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 117 insertions(+), 43 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index e881183..6d5f22a 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -193,20 +193,17 @@ function evolved.chunk(fragment, ...) end The [`evolved.chunk`](#evolvedchunk) function takes one or more fragments as arguments and returns the chunk for this combination. After that, you can use the chunk's methods to retrieve their entities, fragments, and components. ```lua ----@param self evolved.chunk ---@return evolved.entity[] entity_list ---@return integer entity_count function chunk_mt:entities() end ----@param self evolved.chunk ---@return evolved.fragment[] fragment_list ---@return integer fragment_count function chunk_mt:fragments() end ----@param self evolved.chunk ---@param ... evolved.fragment fragments ----@return evolved.component[] ... component_lists -function chunk_mt:components(...) end +---@return evolved.storage ... storages +function chunk_mt:components(...) ``` Full example: @@ -348,7 +345,7 @@ All of these functions can be safely called on non-alive entities and non-alive ## Modifying Operations -The library provides a classic set of functions for modifying entities. These functions are used to set, get, remove, and check fragments on entities. +The library provides a classic set of functions for modifying entities. These functions are used to add, override, and remove fragments from entities. ```lua ---@param entity evolved.entity @@ -638,6 +635,47 @@ The prologue and epilogue fragments do not require an explicit query. They will And one more thing about systems. Execution callbacks are called in the [deferred scope](#deferred-operations), this means that all modifying operations inside the callback will be queued and applied after the system processed all chunks. But prologue and epilogue callbacks are not called in the deferred scope, so all modifying operations inside them will be applied immediately. This is done to avoid confusion and to make it clear that prologue and epilogue callbacks are not part of the chunk processing. +## Advanced Topics + +### Fragment Tags + +Sometimes you want to have a fragment without a component. For example, you might want to have some marks that will be used to mark entities for processing. Fragments without components are called `tags`. Such fragments take up less memory, because they do not require any components to be stored. Migration of entities with tags is faster, because the library does not need to migrate components, only the tags themselves. To create a tag, mark the fragment with the [`evolved.TAG`](#evolvedtag) fragment. + +```lua +local evolved = require 'evolved' + +local player_tag = evolved.id() +evolved.set(player_tag, evolved.TAG) + +local player = evolved.id() +evolved.set(player, player_tag) + +-- player has the player_tag fragment +assert(evolved.has(player, player_tag)) + +-- player_tag is a tag, so it doesn't have a component +assert(evolved.get(player, player_tag) == nil) +``` + +### Fragment Hooks + +The library provides a way to execute callbacks when fragments are set, assigned, inserted, or removed from entities. This is done using special fragments: [`evolved.ON_SET`](#evolvedon_set), [`evolved.ON_ASSIGN`](#evolvedon_assign), [`evolved.ON_INSERT`](#evolvedon_insert), and [`evolved.ON_REMOVE`](#evolvedon_remove). These fragments are used to specify the callbacks that will be executed when the corresponding operation is performed on the fragment. + +```lua +local evolved = require 'evolved' + +local health = evolved.builder() + :on_set(function(entity, fragment, component) + print('health set to ' .. component) + end):spawn() + +local player = evolved.id() +evolved.set(player, health, 100) -- prints "health set to 100" +evolved.set(player, health, 200) -- prints "health set to 200" +``` + +Use [`evolved.ON_SET`](#evolvedon_set) for callbacks on fragment insert or override, [`evolved.ON_ASSIGN`](#evolvedon_assign) for overrides, and [`evolved.ON_INSERT`](#evolvedon_insert)/[`evolved.ON_REMOVE`](#evolvedon_remove) for insertions or removals. + # API Reference ## Predefs @@ -940,6 +978,8 @@ function evolved.debug_mode(yesno) end function evolved.collect_garbage() end ``` +## Chunk + ### `evolved.chunk` ```lua @@ -1022,6 +1062,8 @@ function evolved.chunk_mt:fragments() end function evolved.chunk_mt:components(...) end ``` +## Builder + ### `evolved.builder` ```lua diff --git a/README.md b/README.md index d765344..8871b02 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,38 @@ - [lua](https://www.lua.org/) **>= 5.1** - [luajit](https://luajit.org/) **>= 2.0** +## Aliases + +``` +id :: implementation-specific + +entity :: id +fragment :: id +query :: id +system :: id + +component :: any +storage :: component[] + +default :: component +duplicate :: {component -> component} + +execute :: {chunk, entity[], integer} +prologue :: {} +epilogue :: {} + +set_hook :: {entity, fragment, component, component?} +assign_hook :: {entity, fragment, component, component} +insert_hook :: {entity, fragment, component} +remove_hook :: {entity, fragment, component} + +each_state :: implementation-specific +execute_state :: implementation-specific + +each_iterator :: {each_state? -> fragment?, component?} +execute_iterator :: {execute_state? -> chunk?, entity[]?, integer?} +``` + ## Predefs ``` @@ -112,16 +144,16 @@ collect_garbage :: () ``` chunk :: fragment, fragment... -> chunk, entity[], integer -chunk:alive :: boolean -chunk:empty :: boolean +chunk_mt:alive :: boolean +chunk_mt:empty :: boolean -chunk:has :: fragment -> boolean -chunk:has_all :: fragment... -> boolean -chunk:has_any :: fragment... -> boolean +chunk_mt:has :: fragment -> boolean +chunk_mt:has_all :: fragment... -> boolean +chunk_mt:has_any :: fragment... -> boolean -chunk:entities :: entity[], integer -chunk:fragments :: fragment[], integer -chunk:components :: fragment... -> component[]... +chunk_mt:entities :: entity[], integer +chunk_mt:fragments :: fragment[], integer +chunk_mt:components :: fragment... -> storage... ``` ## Builder @@ -129,48 +161,48 @@ chunk:components :: fragment... -> component[]... ``` builder :: builder -builder:spawn :: entity -builder:clone :: entity -> entity +builder_mt:spawn :: entity +builder_mt:clone :: entity -> entity -builder:has :: fragment -> boolean -builder:has_all :: fragment... -> boolean -builder:has_any :: fragment... -> boolean +builder_mt:has :: fragment -> boolean +builder_mt:has_all :: fragment... -> boolean +builder_mt:has_any :: fragment... -> boolean -builder:get :: fragment... -> component... +builder_mt:get :: fragment... -> component... -builder:set :: fragment, component -> builder -builder:remove :: fragment... -> builder -builder:clear :: builder +builder_mt:set :: fragment, component -> builder +builder_mt:remove :: fragment... -> builder +builder_mt:clear :: builder -builder:tag :: builder -builder:name :: string -> builder +builder_mt:tag :: builder +builder_mt:name :: string -> builder -builder:unique :: builder -builder:explicit :: builder +builder_mt:unique :: builder +builder_mt:explicit :: builder -builder:default :: component -> builder -builder:duplicate :: {component -> component} -> builder +builder_mt:default :: component -> builder +builder_mt:duplicate :: {component -> component} -> builder -builder:prefab :: builder -builder:disabled :: builder +builder_mt:prefab :: builder +builder_mt:disabled :: builder -builder:include :: fragment... -> builder -builder:exclude :: fragment... -> builder +builder_mt:include :: fragment... -> builder +builder_mt:exclude :: fragment... -> builder -builder:on_set :: {entity, fragment, component, component?} -> builder -builder:on_assign :: {entity, fragment, component, component} -> builder -builder:on_insert :: {entity, fragment, component} -> builder -builder:on_remove :: {entity, fragment} -> builder +builder_mt:on_set :: {entity, fragment, component, component?} -> builder +builder_mt:on_assign :: {entity, fragment, component, component} -> builder +builder_mt:on_insert :: {entity, fragment, component} -> builder +builder_mt:on_remove :: {entity, fragment} -> builder -builder:group :: system -> builder +builder_mt:group :: system -> builder -builder:query :: query -> builder -builder:execute :: {chunk, entity[], integer} -> builder +builder_mt:query :: query -> builder +builder_mt:execute :: {chunk, entity[], integer} -> builder -builder:prologue :: {} -> builder -builder:epilogue :: {} -> builder +builder_mt:prologue :: {} -> builder +builder_mt:epilogue :: {} -> builder -builder:destroy_policy :: id -> builder +builder_mt:destroy_policy :: id -> builder ``` ## [License (MIT)](./LICENSE.md)