Optimize column access
Cleanup
0
.gitattributes
vendored
Normal file → Executable file
0
.github/ISSUE_TEMPLATE/BUG-REPORT.md
vendored
Normal file → Executable file
0
.github/ISSUE_TEMPLATE/DOCUMENTATION.md
vendored
Normal file → Executable file
0
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.md
vendored
Normal file → Executable file
0
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file → Executable file
0
.github/workflows/analysis.yaml
vendored
Normal file → Executable file
0
.github/workflows/dependabot.yml
vendored
Normal file → Executable file
0
.github/workflows/deploy-docs.yaml
vendored
Normal file → Executable file
0
.github/workflows/publish-npm.yml
vendored
Normal file → Executable file
0
.github/workflows/release.yaml
vendored
Normal file → Executable file
0
.github/workflows/unit-testing.yaml
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
.luaurc
Normal file → Executable file
0
.prettierrc
Normal file → Executable file
0
.stylua.toml
Normal file → Executable file
10
CHANGELOG.md
Normal file → Executable file
|
@ -2,6 +2,16 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `jecs.component_record` for retrieving the component_record of a component.
|
||||||
|
- `Column<T>` and `ColumnsMap<T>` types for typescript.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The fields `archetype.records[id]` and `archetype.counts[id` have been removed from the archetype struct and been moved to the component record `component_index[id].records[archetype.id]` and `component_index[id].counts[archetype.id]` respectively.
|
||||||
|
- Removed the metatable `jecs.World`. Use `jecs.world()` to create your World.
|
||||||
|
- Archetypes will no longer be garbage collected when invalidated, allowing them to be recycled to save a lot of performance during frequent deletion.
|
||||||
|
- Removed `jecs.entity_index_try_get_fast`. Use `jecs.entity_index_try_get` instead.
|
||||||
|
|
||||||
## 0.6.1
|
## 0.6.1
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
0
LICENSE
Normal file → Executable file
0
README.md
Normal file → Executable file
0
addons/observers.luau
Normal file → Executable file
0
assets/image-1.png
Normal file → Executable file
Before Width: | Height: | Size: 392 KiB After Width: | Height: | Size: 392 KiB |
0
assets/image-2.png
Normal file → Executable file
Before Width: | Height: | Size: 391 KiB After Width: | Height: | Size: 391 KiB |
0
assets/image-3.png
Normal file → Executable file
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
0
assets/image-4.png
Normal file → Executable file
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
0
assets/image-5.png
Normal file → Executable file
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
0
assets/jecs_darkmode.svg
Normal file → Executable file
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
assets/jecs_lightmode.svg
Normal file → Executable file
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
assets/logo_old.png
Normal file → Executable file
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
0
bench.project.json
Normal file → Executable file
0
benches/cached.luau
Normal file → Executable file
34
benches/general.luau
Normal file → Executable file
|
@ -14,7 +14,7 @@ local pair = jecs.pair
|
||||||
|
|
||||||
do
|
do
|
||||||
TITLE("create")
|
TITLE("create")
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
BENCH("entity", function()
|
BENCH("entity", function()
|
||||||
for i = 1, START(N) do
|
for i = 1, START(N) do
|
||||||
|
@ -35,7 +35,7 @@ end
|
||||||
do
|
do
|
||||||
TITLE("set")
|
TITLE("set")
|
||||||
|
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
|
|
||||||
local entities = table.create(N)
|
local entities = table.create(N)
|
||||||
|
@ -69,7 +69,7 @@ end
|
||||||
do
|
do
|
||||||
TITLE("set relationship")
|
TITLE("set relationship")
|
||||||
|
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
|
|
||||||
local entities = table.create(N)
|
local entities = table.create(N)
|
||||||
|
@ -103,7 +103,7 @@ end
|
||||||
do
|
do
|
||||||
TITLE("get")
|
TITLE("get")
|
||||||
|
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
local C = world:component()
|
local C = world:component()
|
||||||
|
@ -147,7 +147,7 @@ do
|
||||||
TITLE("target")
|
TITLE("target")
|
||||||
|
|
||||||
BENCH("1st target", function()
|
BENCH("1st target", function()
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
local C = world:component()
|
local C = world:component()
|
||||||
|
@ -179,7 +179,7 @@ do
|
||||||
|
|
||||||
local function view_bench(n: number)
|
local function view_bench(n: number)
|
||||||
BENCH(`{n} entities per archetype`, function()
|
BENCH(`{n} entities per archetype`, function()
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
|
@ -205,7 +205,7 @@ do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
BENCH(`inlined query`, function()
|
BENCH(`inlined query`, function()
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
local C = world:component()
|
local C = world:component()
|
||||||
|
@ -225,12 +225,22 @@ do
|
||||||
|
|
||||||
local archetypes = world:query(A, B, C, D):archetypes()
|
local archetypes = world:query(A, B, C, D):archetypes()
|
||||||
START()
|
START()
|
||||||
|
-- for _, archetype in archetypes do
|
||||||
|
-- local columns, records = archetype.columns, archetype.records
|
||||||
|
-- local a = columns[records[A]]
|
||||||
|
-- local b = columns[records[B]]
|
||||||
|
-- local c = columns[records[C]]
|
||||||
|
-- local d = columns[records[D]]
|
||||||
|
-- for row in archetype.entities do
|
||||||
|
-- local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
for _, archetype in archetypes do
|
for _, archetype in archetypes do
|
||||||
local columns, records = archetype.columns, archetype.records
|
local columns_map = archetype.columns_map
|
||||||
local a = columns[records[A]]
|
local a = columns_map[A]
|
||||||
local b = columns[records[B]]
|
local b = columns_map[B]
|
||||||
local c = columns[records[C]]
|
local c = columns_map[C]
|
||||||
local d = columns[records[D]]
|
local d = columns_map[D]
|
||||||
for row in archetype.entities do
|
for row in archetype.entities do
|
||||||
local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
|
local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
|
||||||
end
|
end
|
||||||
|
|
2
benches/query.luau
Normal file → Executable file
|
@ -15,7 +15,7 @@ type i53 = number
|
||||||
|
|
||||||
do
|
do
|
||||||
TITLE(testkit.color.white_underline("Jecs query"))
|
TITLE(testkit.color.white_underline("Jecs query"))
|
||||||
local ecs = jecs.World.new()
|
local ecs = jecs.world()
|
||||||
do
|
do
|
||||||
TITLE("one component in common")
|
TITLE("one component in common")
|
||||||
|
|
||||||
|
|
5
benches/visual/despawn.bench.luau
Normal file → Executable file
|
@ -6,8 +6,7 @@ local Matter = require(ReplicatedStorage.DevPackages.Matter)
|
||||||
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
||||||
local jecs = require(ReplicatedStorage.Lib)
|
local jecs = require(ReplicatedStorage.Lib)
|
||||||
local pair = jecs.pair
|
local pair = jecs.pair
|
||||||
local newWorld = Matter.World.new()
|
local ecs = jecs.world()
|
||||||
local ecs = jecs.World.new()
|
|
||||||
local mirror = require(ReplicatedStorage.mirror)
|
local mirror = require(ReplicatedStorage.mirror)
|
||||||
local mcs = mirror.World.new()
|
local mcs = mirror.World.new()
|
||||||
|
|
||||||
|
@ -26,8 +25,6 @@ mcs:add(E3, pair(jecs.OnDeleteTarget, jecs.Delete))
|
||||||
local E4 = mcs:entity()
|
local E4 = mcs:entity()
|
||||||
mcs:add(E4, pair(jecs.OnDeleteTarget, jecs.Delete))
|
mcs:add(E4, pair(jecs.OnDeleteTarget, jecs.Delete))
|
||||||
|
|
||||||
local registry2 = ecr.registry()
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ParameterGenerator = function()
|
ParameterGenerator = function()
|
||||||
local j = ecs:entity()
|
local j = ecs:entity()
|
||||||
|
|
22
benches/visual/insertion.bench.luau
Normal file → Executable file
|
@ -2,30 +2,11 @@
|
||||||
--!native
|
--!native
|
||||||
|
|
||||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||||
local Matter = require(ReplicatedStorage.DevPackages.Matter)
|
|
||||||
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
|
||||||
local jecs = require(ReplicatedStorage.Lib:Clone())
|
local jecs = require(ReplicatedStorage.Lib:Clone())
|
||||||
local ecs = jecs.World.new()
|
local ecs = jecs.world()
|
||||||
local mirror = require(ReplicatedStorage.mirror:Clone())
|
local mirror = require(ReplicatedStorage.mirror:Clone())
|
||||||
local mcs = mirror.World.new()
|
local mcs = mirror.World.new()
|
||||||
|
|
||||||
local A1 = Matter.component()
|
|
||||||
local A2 = Matter.component()
|
|
||||||
local A3 = Matter.component()
|
|
||||||
local A4 = Matter.component()
|
|
||||||
local A5 = Matter.component()
|
|
||||||
local A6 = Matter.component()
|
|
||||||
local A7 = Matter.component()
|
|
||||||
local A8 = Matter.component()
|
|
||||||
|
|
||||||
local B1 = ecr.component()
|
|
||||||
local B2 = ecr.component()
|
|
||||||
local B3 = ecr.component()
|
|
||||||
local B4 = ecr.component()
|
|
||||||
local B5 = ecr.component()
|
|
||||||
local B6 = ecr.component()
|
|
||||||
local B7 = ecr.component()
|
|
||||||
local B8 = ecr.component()
|
|
||||||
|
|
||||||
local C1 = ecs:component()
|
local C1 = ecs:component()
|
||||||
local C2 = ecs:component()
|
local C2 = ecs:component()
|
||||||
|
@ -44,7 +25,6 @@ local E6 = mcs:component()
|
||||||
local E7 = mcs:component()
|
local E7 = mcs:component()
|
||||||
local E8 = mcs:component()
|
local E8 = mcs:component()
|
||||||
|
|
||||||
local registry2 = ecr.registry()
|
|
||||||
return {
|
return {
|
||||||
ParameterGenerator = function()
|
ParameterGenerator = function()
|
||||||
return
|
return
|
||||||
|
|
45
benches/visual/query.bench.luau
Normal file → Executable file
|
@ -2,14 +2,14 @@
|
||||||
--!native
|
--!native
|
||||||
|
|
||||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||||
local Matter = require(ReplicatedStorage.DevPackages["_Index"]["matter-ecs_matter@0.8.1"].matter)
|
local Matter = require(ReplicatedStorage.DevPackages.matter)
|
||||||
local ecr = require(ReplicatedStorage.DevPackages["_Index"]["centau_ecr@0.8.0"].ecr)
|
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
||||||
local newWorld = Matter.World.new()
|
local newWorld = Matter.World.new()
|
||||||
|
|
||||||
local jecs = require(ReplicatedStorage.Lib)
|
local jecs = require(ReplicatedStorage.Lib:Clone())
|
||||||
local mirror = require(ReplicatedStorage.mirror)
|
local mirror = require(ReplicatedStorage.mirror:Clone())
|
||||||
local mcs = mirror.World.new()
|
local mcs = mirror.world()
|
||||||
local ecs = jecs.World.new()
|
local ecs = jecs.world()
|
||||||
|
|
||||||
local A1 = Matter.component()
|
local A1 = Matter.component()
|
||||||
local A2 = Matter.component()
|
local A2 = Matter.component()
|
||||||
|
@ -38,14 +38,14 @@ local D6 = ecs:component()
|
||||||
local D7 = ecs:component()
|
local D7 = ecs:component()
|
||||||
local D8 = ecs:component()
|
local D8 = ecs:component()
|
||||||
|
|
||||||
local E1 = mcs:entity()
|
local E1 = mcs:component()
|
||||||
local E2 = mcs:entity()
|
local E2 = mcs:component()
|
||||||
local E3 = mcs:entity()
|
local E3 = mcs:component()
|
||||||
local E4 = mcs:entity()
|
local E4 = mcs:component()
|
||||||
local E5 = mcs:entity()
|
local E5 = mcs:component()
|
||||||
local E6 = mcs:entity()
|
local E6 = mcs:component()
|
||||||
local E7 = mcs:entity()
|
local E7 = mcs:component()
|
||||||
local E8 = mcs:entity()
|
local E8 = mcs:component()
|
||||||
|
|
||||||
local registry2 = ecr.registry()
|
local registry2 = ecr.registry()
|
||||||
|
|
||||||
|
@ -146,13 +146,18 @@ return {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
Functions = {
|
Functions = {
|
||||||
Matter = function()
|
-- Matter = function()
|
||||||
for entityId, firstComponent in newWorld:query(A2, A4, A6, A8) do
|
-- for entityId, firstComponent in newWorld:query(A2, A4, A6, A8) do
|
||||||
end
|
-- end
|
||||||
end,
|
-- end,
|
||||||
|
|
||||||
ECR = function()
|
-- ECR = function()
|
||||||
for entityId, firstComponent in registry2:view(B2, B4, B6, B8) do
|
-- for entityId, firstComponent in registry2:view(B2, B4, B6, B8) do
|
||||||
|
-- end
|
||||||
|
-- end,
|
||||||
|
--
|
||||||
|
Mirror = function()
|
||||||
|
for entityId, firstComponent in mcs:query(E2, E4, E6, E8) do
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
2
benches/visual/remove.bench.luau
Normal file → Executable file
|
@ -6,7 +6,7 @@ local Matter = require(ReplicatedStorage.DevPackages.Matter)
|
||||||
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
||||||
local jecs = require(ReplicatedStorage.Lib)
|
local jecs = require(ReplicatedStorage.Lib)
|
||||||
local pair = jecs.pair
|
local pair = jecs.pair
|
||||||
local ecs = jecs.World.new()
|
local ecs = jecs.world()
|
||||||
local mirror = require(ReplicatedStorage.mirror)
|
local mirror = require(ReplicatedStorage.mirror)
|
||||||
local mcs = mirror.World.new()
|
local mcs = mirror.World.new()
|
||||||
|
|
||||||
|
|
0
benches/visual/spawn.bench.luau
Normal file → Executable file
0
benches/visual/wally.toml
Normal file → Executable file
0
default.project.json
Normal file → Executable file
0
demo/.gitignore
vendored
Normal file → Executable file
0
demo/README.md
Normal file → Executable file
0
demo/default.project.json
Normal file → Executable file
0
demo/src/ReplicatedStorage/collect.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/components.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/main.client.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/observers_add.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/remotes.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/schedule.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/systems/receive_replication.luau
Normal file → Executable file
0
demo/src/ReplicatedStorage/types.luau
Normal file → Executable file
0
demo/src/ServerScriptService/main.server.luau
Normal file → Executable file
0
demo/src/ServerScriptService/systems/life_is_painful.luau
Normal file → Executable file
0
demo/src/ServerScriptService/systems/players_added.luau
Normal file → Executable file
0
demo/src/ServerScriptService/systems/poison_hurts.luau
Normal file → Executable file
0
demo/src/ServerScriptService/systems/replication.luau
Normal file → Executable file
0
demo/wally.toml
Normal file → Executable file
0
docs/.vitepress/config.mts
Normal file → Executable file
0
docs/api/jecs.md
Normal file → Executable file
0
docs/api/query.md
Normal file → Executable file
0
docs/api/world.md
Normal file → Executable file
0
docs/index.md
Normal file → Executable file
0
docs/learn/contributing/coverage.md
Normal file → Executable file
0
docs/learn/contributing/guidelines.md
Normal file → Executable file
0
docs/learn/contributing/issues.md
Normal file → Executable file
0
docs/learn/contributing/pull-requests.md
Normal file → Executable file
0
docs/learn/overview.md
Normal file → Executable file
0
docs/learn/public/jecs_logo.svg
Normal file → Executable file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
0
docs/public/coverage/ansi.luau.html
vendored
Normal file → Executable file
0
docs/public/coverage/entity_visualiser.luau.html
vendored
Normal file → Executable file
0
docs/public/coverage/index.html
vendored
Normal file → Executable file
0
docs/public/coverage/jecs.luau.html
vendored
Normal file → Executable file
0
docs/public/coverage/lifetime_tracker.luau.html
vendored
Normal file → Executable file
0
docs/public/coverage/testkit.luau.html
vendored
Normal file → Executable file
0
docs/public/coverage/tests.luau.html
vendored
Normal file → Executable file
0
docs/public/jecs_logo.svg
Normal file → Executable file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
0
docs/resources.md
Normal file → Executable file
0
examples/README.md
Normal file → Executable file
0
examples/luau/entities/basics.luau
Normal file → Executable file
0
examples/luau/entities/hierarchy.luau
Normal file → Executable file
0
examples/luau/hooks/cleanup.luau
Normal file → Executable file
0
examples/luau/queries/basics.luau
Normal file → Executable file
0
examples/luau/queries/changetracking.luau
Normal file → Executable file
0
examples/luau/queries/spatial_grids.luau
Normal file → Executable file
0
examples/luau/queries/wildcards.luau
Normal file → Executable file
21
jecs.d.ts
vendored
Normal file → Executable file
|
@ -41,16 +41,15 @@ type Nullable<T extends unknown[]> = { [K in keyof T]: T[K] | undefined };
|
||||||
type InferComponents<A extends Id[]> = { [K in keyof A]: InferComponent<A[K]> };
|
type InferComponents<A extends Id[]> = { [K in keyof A]: InferComponent<A[K]> };
|
||||||
|
|
||||||
type ArchetypeId = number;
|
type ArchetypeId = number;
|
||||||
type Column = unknown[];
|
export type Column<T> = T[];
|
||||||
|
|
||||||
export type Archetype = {
|
export type Archetype<T extends unknown[]> = {
|
||||||
id: number;
|
id: number;
|
||||||
types: number[];
|
types: number[];
|
||||||
type: string;
|
type: string;
|
||||||
entities: number[];
|
entities: number[];
|
||||||
columns: Column[];
|
columns: Column<unknown>[];
|
||||||
records: number[];
|
columns_map: { [K in keyof T]: Column<T[K]> }
|
||||||
counts: number[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Iter<T extends unknown[]> = IterableFunction<LuaTuple<[Entity, ...T]>>;
|
type Iter<T extends unknown[]> = IterableFunction<LuaTuple<[Entity, ...T]>>;
|
||||||
|
@ -65,7 +64,7 @@ export type CachedQuery<T extends unknown[]> = {
|
||||||
* Returns the matched archetypes of the query
|
* Returns the matched archetypes of the query
|
||||||
* @returns An array of archetypes of the query
|
* @returns An array of archetypes of the query
|
||||||
*/
|
*/
|
||||||
archetypes(): Archetype[];
|
archetypes(): Archetype<T>[];
|
||||||
} & Iter<T>;
|
} & Iter<T>;
|
||||||
|
|
||||||
export type Query<T extends unknown[]> = {
|
export type Query<T extends unknown[]> = {
|
||||||
|
@ -99,7 +98,7 @@ export type Query<T extends unknown[]> = {
|
||||||
* Returns the matched archetypes of the query
|
* Returns the matched archetypes of the query
|
||||||
* @returns An array of archetypes of the query
|
* @returns An array of archetypes of the query
|
||||||
*/
|
*/
|
||||||
archetypes(): Archetype[];
|
archetypes(): Archetype<T>[];
|
||||||
} & Iter<T>;
|
} & Iter<T>;
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
|
@ -310,3 +309,11 @@ export declare const Delete: Tag;
|
||||||
export declare const Remove: Tag;
|
export declare const Remove: Tag;
|
||||||
export declare const Name: Entity<string>;
|
export declare const Name: Entity<string>;
|
||||||
export declare const Rest: Entity;
|
export declare const Rest: Entity;
|
||||||
|
|
||||||
|
export type ComponentRecord = {
|
||||||
|
records: Map<Id, number>,
|
||||||
|
counts: Map<Id, number>,
|
||||||
|
size: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function component_record(world: World, id: Id): ComponentRecord
|
||||||
|
|
2987
mirror.luau
Normal file → Executable file
0
package-lock.json
generated
Normal file → Executable file
0
package.json
Normal file → Executable file
0
rokit.toml
Normal file → Executable file
0
test/addons/observers.luau
Normal file → Executable file
0
test/lol.luau
Normal file → Executable file
0
test/stress.client.luau
Normal file → Executable file
0
test/stress.project.json
Normal file → Executable file
69
test/tests.luau
Normal file → Executable file
|
@ -64,7 +64,7 @@ TEST("world:add()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE("archetype move")
|
do CASE("archetype move")
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local d = dwi(world)
|
local d = dwi(world)
|
||||||
|
|
||||||
|
@ -609,7 +609,7 @@ TEST("world:delete()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "fast delete"
|
do CASE "fast delete"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local entities = {}
|
local entities = {}
|
||||||
local Health = world:component()
|
local Health = world:component()
|
||||||
|
@ -635,7 +635,7 @@ TEST("world:delete()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "cycle"
|
do CASE "cycle"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local Likes = world:component()
|
local Likes = world:component()
|
||||||
world:add(Likes, pair(jecs.OnDeleteTarget, jecs.Delete))
|
world:add(Likes, pair(jecs.OnDeleteTarget, jecs.Delete))
|
||||||
local bob = world:entity()
|
local bob = world:entity()
|
||||||
|
@ -800,7 +800,7 @@ end)
|
||||||
|
|
||||||
TEST("world:has()", function()
|
TEST("world:has()", function()
|
||||||
do CASE "should find Tag on entity"
|
do CASE "should find Tag on entity"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local Tag = world:entity()
|
local Tag = world:entity()
|
||||||
|
|
||||||
|
@ -811,7 +811,7 @@ TEST("world:has()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should return false when missing one tag"
|
do CASE "should return false when missing one tag"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local A = world:entity()
|
local A = world:entity()
|
||||||
local B = world:entity()
|
local B = world:entity()
|
||||||
|
@ -866,7 +866,7 @@ TEST("world:query()", function()
|
||||||
CHECK(#q:archetypes() == 0)
|
CHECK(#q:archetypes() == 0)
|
||||||
end
|
end
|
||||||
do CASE "multiple iter"
|
do CASE "multiple iter"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component() :: jecs.Entity<string>
|
local A = world:component() :: jecs.Entity<string>
|
||||||
local B = world:component() :: jecs.Entity<string>
|
local B = world:component() :: jecs.Entity<string>
|
||||||
local e = world:entity()
|
local e = world:entity()
|
||||||
|
@ -883,7 +883,7 @@ TEST("world:query()", function()
|
||||||
CHECK(counter == 2)
|
CHECK(counter == 2)
|
||||||
end
|
end
|
||||||
do CASE "tag"
|
do CASE "tag"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:entity()
|
local A = world:entity()
|
||||||
local e = world:entity()
|
local e = world:entity()
|
||||||
CHECK_EXPECT_ERR(function()
|
CHECK_EXPECT_ERR(function()
|
||||||
|
@ -897,7 +897,7 @@ TEST("world:query()", function()
|
||||||
CHECK(count == 1)
|
CHECK(count == 1)
|
||||||
end
|
end
|
||||||
do CASE "pairs"
|
do CASE "pairs"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local C1 = world:component() :: jecs.Id<boolean>
|
local C1 = world:component() :: jecs.Id<boolean>
|
||||||
local C2 = world:component() :: jecs.Id<boolean>
|
local C2 = world:component() :: jecs.Id<boolean>
|
||||||
|
@ -969,7 +969,7 @@ TEST("world:query()", function()
|
||||||
|
|
||||||
do CASE "query single component"
|
do CASE "query single component"
|
||||||
do
|
do
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
|
|
||||||
|
@ -1125,7 +1125,7 @@ TEST("world:query()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should query all entities without B"
|
do CASE "should query all entities without B"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
|
|
||||||
|
@ -1149,7 +1149,7 @@ TEST("world:query()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should allow querying for relations"
|
do CASE "should allow querying for relations"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local Eats = world:component()
|
local Eats = world:component()
|
||||||
local Apples = world:component()
|
local Apples = world:component()
|
||||||
local bob = world:entity()
|
local bob = world:entity()
|
||||||
|
@ -1162,7 +1162,7 @@ TEST("world:query()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should allow wildcards in queries"
|
do CASE "should allow wildcards in queries"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local Eats = world:component()
|
local Eats = world:component()
|
||||||
local Apples = world:entity()
|
local Apples = world:entity()
|
||||||
local bob = world:entity()
|
local bob = world:entity()
|
||||||
|
@ -1181,7 +1181,7 @@ TEST("world:query()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should match against multiple pairs"
|
do CASE "should match against multiple pairs"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local Eats = world:component()
|
local Eats = world:component()
|
||||||
local Apples = world:entity()
|
local Apples = world:entity()
|
||||||
local Oranges = world:entity()
|
local Oranges = world:entity()
|
||||||
|
@ -1213,7 +1213,7 @@ TEST("world:query()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should only relate alive entities"
|
do CASE "should only relate alive entities"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local Eats = world:entity()
|
local Eats = world:entity()
|
||||||
local Apples = world:component()
|
local Apples = world:component()
|
||||||
local Oranges = world:component()
|
local Oranges = world:component()
|
||||||
|
@ -1241,7 +1241,7 @@ TEST("world:query()", function()
|
||||||
|
|
||||||
do
|
do
|
||||||
CASE("should error when setting invalid pair")
|
CASE("should error when setting invalid pair")
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local Eats = world:component()
|
local Eats = world:component()
|
||||||
local Apples = world:component()
|
local Apples = world:component()
|
||||||
local bob = world:entity()
|
local bob = world:entity()
|
||||||
|
@ -1254,7 +1254,7 @@ TEST("world:query()", function()
|
||||||
|
|
||||||
do
|
do
|
||||||
CASE("should find target for ChildOf")
|
CASE("should find target for ChildOf")
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local ChildOf = jecs.ChildOf
|
local ChildOf = jecs.ChildOf
|
||||||
|
|
||||||
local Name = world:component()
|
local Name = world:component()
|
||||||
|
@ -1278,7 +1278,7 @@ TEST("world:query()", function()
|
||||||
|
|
||||||
do
|
do
|
||||||
CASE("despawning while iterating")
|
CASE("despawning while iterating")
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local B = world:component()
|
local B = world:component()
|
||||||
|
|
||||||
|
@ -1297,7 +1297,7 @@ TEST("world:query()", function()
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "should not find any entities"
|
do CASE "should not find any entities"
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local Hello = world:component()
|
local Hello = world:component()
|
||||||
local Bob = world:component()
|
local Bob = world:component()
|
||||||
|
@ -1316,7 +1316,7 @@ TEST("world:query()", function()
|
||||||
|
|
||||||
do CASE "world:query():without()"
|
do CASE "world:query():without()"
|
||||||
-- REGRESSION TEST
|
-- REGRESSION TEST
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
local _1, _2, _3 = world:component(), world:component(), world:component()
|
local _1, _2, _3 = world:component(), world:component(), world:component()
|
||||||
|
|
||||||
local counter = 0
|
local counter = 0
|
||||||
|
@ -1330,7 +1330,7 @@ end)
|
||||||
TEST("world:remove()", function()
|
TEST("world:remove()", function()
|
||||||
do
|
do
|
||||||
CASE("should allow remove a component that doesn't exist on entity")
|
CASE("should allow remove a component that doesn't exist on entity")
|
||||||
local world = jecs.World.new()
|
local world = jecs.world()
|
||||||
|
|
||||||
local Health = world:component()
|
local Health = world:component()
|
||||||
local Poison = world:component()
|
local Poison = world:component()
|
||||||
|
@ -1444,10 +1444,15 @@ TEST("world:target", function()
|
||||||
CHECK(jecs.pair_first(world, pair(B, C)) == B)
|
CHECK(jecs.pair_first(world, pair(B, C)) == B)
|
||||||
local r = (jecs.entity_index_try_get(world.entity_index :: any, e :: any) :: any) :: jecs.Record
|
local r = (jecs.entity_index_try_get(world.entity_index :: any, e :: any) :: any) :: jecs.Record
|
||||||
local archetype = r.archetype
|
local archetype = r.archetype
|
||||||
local records = archetype.records
|
local function cdr(id)
|
||||||
local counts = archetype.counts
|
return assert(jecs.component_record(world, id))
|
||||||
CHECK(counts[pair(A, __)] == 4)
|
end
|
||||||
CHECK(records[pair(B, C)] > records[pair(A, E)])
|
local idr_b_c = cdr(pair(B, C))
|
||||||
|
local idr_a_wc = cdr(pair(A, __))
|
||||||
|
local idr_a_e = cdr(pair(A, E))
|
||||||
|
|
||||||
|
CHECK(idr_a_wc.counts[archetype.id] == 4)
|
||||||
|
CHECK(idr_b_c.records[archetype.id] > idr_a_e.records[archetype.id])
|
||||||
CHECK(world:target(e, A, 0) == B)
|
CHECK(world:target(e, A, 0) == B)
|
||||||
CHECK(world:target(e, A, 1) == C)
|
CHECK(world:target(e, A, 1) == C)
|
||||||
CHECK(world:target(e, A, 2) == D)
|
CHECK(world:target(e, A, 2) == D)
|
||||||
|
@ -1457,10 +1462,10 @@ TEST("world:target", function()
|
||||||
CHECK(world:target(e, C, 0) == D)
|
CHECK(world:target(e, C, 0) == D)
|
||||||
CHECK(world:target(e, C, 1) == nil)
|
CHECK(world:target(e, C, 1) == nil)
|
||||||
|
|
||||||
CHECK(archetype.records[pair(A, B):: any] == 1)
|
CHECK(cdr(pair(A, B)).records[archetype.id] == 1)
|
||||||
CHECK(archetype.records[pair(A, C):: any] == 2)
|
CHECK(cdr(pair(A, C)).records[archetype.id] == 2)
|
||||||
CHECK(archetype.records[pair(A, D):: any] == 3)
|
CHECK(cdr(pair(A, D)).records[archetype.id] == 3)
|
||||||
CHECK(archetype.records[pair(A, E):: any] == 4)
|
CHECK(cdr(pair(A, E)).records[archetype.id] == 4)
|
||||||
|
|
||||||
CHECK(world:target(e, C, 0) == D)
|
CHECK(world:target(e, C, 0) == D)
|
||||||
CHECK(world:target(e, C, 1) == nil)
|
CHECK(world:target(e, C, 1) == nil)
|
||||||
|
@ -1582,9 +1587,13 @@ TEST("#repro", function()
|
||||||
local function getTargets(relation)
|
local function getTargets(relation)
|
||||||
local tgts = {}
|
local tgts = {}
|
||||||
local pairwildcard = pair(relation, jecs.Wildcard)
|
local pairwildcard = pair(relation, jecs.Wildcard)
|
||||||
|
local idr = assert(jecs.component_record(world, pairwildcard))
|
||||||
|
local counts = idr.counts
|
||||||
|
local records = idr.records
|
||||||
for _, archetype in world:query(pairwildcard):archetypes() do
|
for _, archetype in world:query(pairwildcard):archetypes() do
|
||||||
local tr = archetype.records[pairwildcard]
|
local archetype_id = archetype.id
|
||||||
local count = archetype.counts[pairwildcard]
|
local count = counts[archetype_id]
|
||||||
|
local tr = records[archetype_id]
|
||||||
local types = archetype.types
|
local types = archetype.types
|
||||||
for _, entity in archetype.entities do
|
for _, entity in archetype.entities do
|
||||||
for i = 0, count - 1 do
|
for i = 0, count - 1 do
|
||||||
|
|