mirror of
https://github.com/Ukendio/jecs.git
synced 2025-08-04 19:29:18 +00:00
Add bloom filter
This commit is contained in:
parent
1a7c22d2e6
commit
1085b70882
5 changed files with 1358 additions and 1314 deletions
|
@ -25,9 +25,10 @@ local function observers_new(world, query, callback)
|
|||
end
|
||||
|
||||
local entity_index = world.entity_index :: any
|
||||
local sparse_array = entity_index.sparse_array
|
||||
|
||||
local function emplaced(entity, id, value)
|
||||
local r = jecs.entity_index_try_get_fast(
|
||||
entity_index, entity :: any)
|
||||
local r = sparse_array[jecs.ECS_ID(entity)]
|
||||
|
||||
if not r then
|
||||
return
|
||||
|
@ -98,10 +99,11 @@ local function monitors_new(world, query, callback)
|
|||
terms = ids
|
||||
end
|
||||
|
||||
local entity_index = world.entity_index :: any
|
||||
local entity_index = world.entity_index
|
||||
local sparse_array = entity_index.sparse_array
|
||||
|
||||
local function emplaced(entity: jecs.Entity)
|
||||
local r = jecs.entity_index_try_get_fast(
|
||||
entity_index, entity :: any)
|
||||
local r = sparse_array[jecs.ECS_ID(entity::number)] :: jecs.Record
|
||||
|
||||
if not r then
|
||||
return
|
||||
|
@ -115,8 +117,7 @@ local function monitors_new(world, query, callback)
|
|||
end
|
||||
|
||||
local function removed(entity: jecs.Entity, component: jecs.Id)
|
||||
local r = jecs.entity_index_try_get_fast(
|
||||
entity_index, entity :: any)
|
||||
local r = sparse_array[jecs.ECS_ID(entity::number)] :: jecs.Record
|
||||
|
||||
if not r then
|
||||
return
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
--!native
|
||||
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local Matter = require(ReplicatedStorage.DevPackages.matter)
|
||||
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
||||
local Matter = require(ReplicatedStorage.DevPackages.Matter)
|
||||
local newWorld = Matter.World.new()
|
||||
|
||||
local jecs = require(ReplicatedStorage.Lib:Clone())
|
||||
|
@ -20,15 +19,6 @@ 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 D1 = ecs:component()
|
||||
local D2 = ecs:component()
|
||||
local D3 = ecs:component()
|
||||
|
@ -47,8 +37,6 @@ local E6 = mcs:component()
|
|||
local E7 = mcs:component()
|
||||
local E8 = mcs:component()
|
||||
|
||||
local registry2 = ecr.registry()
|
||||
|
||||
local function flip()
|
||||
return math.random() >= 0.25
|
||||
end
|
||||
|
@ -56,37 +44,42 @@ end
|
|||
local N = 2 ^ 16 - 2
|
||||
local archetypes = {}
|
||||
|
||||
for i = 1, 1000 do
|
||||
ecs:entity()
|
||||
mcs:entity()
|
||||
end
|
||||
|
||||
local hm = 0
|
||||
for i = 1, N do
|
||||
local id = registry2.create()
|
||||
local combination = ""
|
||||
local n = newWorld:spawn()
|
||||
local entity = ecs:entity()
|
||||
local m = mcs:entity()
|
||||
|
||||
if flip() then
|
||||
registry2:set(id, B1, { value = true })
|
||||
ecs:add(entity, math.random(1, 1000) + jecs.Rest + 1)
|
||||
mcs:add(m, math.random(1, 1000) + jecs.Rest + 1)
|
||||
end
|
||||
|
||||
if flip() then
|
||||
ecs:set(entity, D1, { value = true })
|
||||
newWorld:insert(n, A1({ value = true }))
|
||||
mcs:set(m, E1, { value = 2 })
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "B"
|
||||
registry2:set(id, B2, { value = true })
|
||||
ecs:set(entity, D2, { value = true })
|
||||
mcs:set(m, E2, { value = 2 })
|
||||
newWorld:insert(n, A2({ value = true }))
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "C"
|
||||
registry2:set(id, B3, { value = true })
|
||||
ecs:set(entity, D3, { value = true })
|
||||
mcs:set(m, E3, { value = 2 })
|
||||
newWorld:insert(n, A3({ value = true }))
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "D"
|
||||
registry2:set(id, B4, { value = true })
|
||||
ecs:set(entity, D4, { value = true })
|
||||
mcs:set(m, E4, { value = 2 })
|
||||
|
||||
|
@ -94,7 +87,6 @@ for i = 1, N do
|
|||
end
|
||||
if flip() then
|
||||
combination ..= "E"
|
||||
registry2:set(id, B5, { value = true })
|
||||
ecs:set(entity, D5, { value = true })
|
||||
mcs:set(m, E5, { value = 2 })
|
||||
|
||||
|
@ -102,21 +94,18 @@ for i = 1, N do
|
|||
end
|
||||
if flip() then
|
||||
combination ..= "F"
|
||||
registry2:set(id, B6, { value = true })
|
||||
ecs:set(entity, D6, { value = true })
|
||||
mcs:set(m, E6, { value = 2 })
|
||||
newWorld:insert(n, A6({ value = true }))
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "G"
|
||||
registry2:set(id, B7, { value = true })
|
||||
ecs:set(entity, D7, { value = true })
|
||||
mcs:set(m, E7, { value = 2 })
|
||||
newWorld:insert(n, A7({ value = true }))
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "H"
|
||||
registry2:set(id, B8, { value = true })
|
||||
newWorld:insert(n, A8({ value = true }))
|
||||
ecs:set(entity, D8, { value = true })
|
||||
mcs:set(m, E8, { value = 2 })
|
||||
|
@ -134,12 +123,15 @@ print("TEST", hm)
|
|||
|
||||
local count = 0
|
||||
|
||||
for _, archetype in ecs:query(D2, D4, D6, D8):archetypes() do
|
||||
count += #archetype.entities
|
||||
for _, archetype in ecs:query(D2, D4):archetypes() do
|
||||
count += 1
|
||||
end
|
||||
|
||||
print(count)
|
||||
|
||||
local mq = ecs:query(E2, E4, D6, D8, 500):cached()
|
||||
local jq = ecs:query(D2, D4, D6, D8, 500):cached()
|
||||
|
||||
return {
|
||||
ParameterGenerator = function()
|
||||
return
|
||||
|
@ -157,13 +149,24 @@ return {
|
|||
-- end,
|
||||
--
|
||||
Mirror = function()
|
||||
for entityId, firstComponent in mcs:query(E2, E4, E6, E8) do
|
||||
for _, archetype in mq:archetypes() do
|
||||
if mirror.query_match(mq, archetype) then
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- for entityId, firstComponent in mcs:query(E2, E4) do
|
||||
-- end
|
||||
end,
|
||||
|
||||
Jecs = function()
|
||||
for entityId, firstComponent in ecs:query(D2, D4, D6, D8) do
|
||||
for _, archetype in jq:archetypes() do
|
||||
if jecs.query_match(jq, archetype) then
|
||||
|
||||
end
|
||||
end
|
||||
-- for entityId, firstComponent in ecs:query(D2, D4) do
|
||||
-- end
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
|
210
jecs.luau
210
jecs.luau
|
@ -21,6 +21,7 @@ export type Archetype = {
|
|||
columns: { Column },
|
||||
columns_map: { [Id]: Column },
|
||||
dead: boolean,
|
||||
bloom_filter: number
|
||||
}
|
||||
|
||||
export type QueryInner = {
|
||||
|
@ -30,12 +31,12 @@ export type QueryInner = {
|
|||
filter_without: { i53 },
|
||||
next: () -> (number, ...any),
|
||||
world: World,
|
||||
bloom_filter: number
|
||||
}
|
||||
|
||||
export type Entity<T = any> = number | { __T: T }
|
||||
export type Id<T = any> = number | { __T: T }
|
||||
export type Pair<P, O> = Id<P>
|
||||
type ecs_id_t<T=unknown> = Id<T> | Pair<T, "Tag"> | Pair<"Tag", T>
|
||||
export type Item<T...> = (self: Query<T...>) -> (Entity, T...)
|
||||
export type Iter<T...> = (query: Query<T...>) -> () -> (Entity, T...)
|
||||
|
||||
|
@ -48,7 +49,7 @@ export type Query<T...> = typeof(setmetatable(
|
|||
cached: (self: Query<T...>) -> Query<T...>,
|
||||
},
|
||||
{} :: {
|
||||
__iter: Iter<T...>
|
||||
__iter: Iter<T...>,
|
||||
}
|
||||
))
|
||||
|
||||
|
@ -102,7 +103,7 @@ export type World = {
|
|||
|
||||
--- Returns whether the entity has the ID.
|
||||
has: (<T, a>(World, Entity<T>, Id<a>) -> boolean)
|
||||
& (<T, a, b >(World, Entity<T>, Id<a>, Id<a>) -> boolean)
|
||||
& (<T, a, b>(World, Entity<T>, Id<a>, Id<a>) -> boolean)
|
||||
& (<T, a, b, c>(World, Entity<T>, Id<a>, Id<b>, Id<c>) -> boolean)
|
||||
& <T, a, b, c, d>(World, Entity<T>, Id<a>, Id<b>, Id<c>, Id<d>) -> boolean,
|
||||
|
||||
|
@ -126,8 +127,28 @@ export type World = {
|
|||
& (<A, B, C, D>(World, Id<A>, Id<B>, Id<C>, Id<D>) -> Query<A, B, C, D>)
|
||||
& (<A, B, C, D, E>(World, Id<A>, Id<B>, Id<C>, Id<D>, Id<E>) -> Query<A, B, C, D, E>)
|
||||
& (<A, B, C, D, E, F>(World, Id<A>, Id<B>, Id<C>, Id<D>, Id<E>, Id<F>) -> Query<A, B, C, D, E, F>)
|
||||
& (<A, B, C, D, E, F, G>(World, Id<A>, Id<B>, Id<C>, Id<D>, Id<E>, Id<F>, Id<G>) -> Query<A, B, C, D, E, F, G>)
|
||||
& (<A, B, C, D, E, F, G, H>(World, Id<A>, Id<B>, Id<C>, Id<D>, Id<E>, Id<F>, Id<G>, Id<H>, ...Id<any>) -> Query<A, B, C, D, E, F, G, H>)
|
||||
& (<A, B, C, D, E, F, G>(
|
||||
World,
|
||||
Id<A>,
|
||||
Id<B>,
|
||||
Id<C>,
|
||||
Id<D>,
|
||||
Id<E>,
|
||||
Id<F>,
|
||||
Id<G>
|
||||
) -> Query<A, B, C, D, E, F, G>)
|
||||
& (<A, B, C, D, E, F, G, H>(
|
||||
World,
|
||||
Id<A>,
|
||||
Id<B>,
|
||||
Id<C>,
|
||||
Id<D>,
|
||||
Id<E>,
|
||||
Id<F>,
|
||||
Id<G>,
|
||||
Id<H>,
|
||||
...Id<any>
|
||||
) -> Query<A, B, C, D, E, F, G, H>),
|
||||
}
|
||||
|
||||
export type Record = {
|
||||
|
@ -155,7 +176,7 @@ export type EntityIndex = {
|
|||
alive_count: number,
|
||||
max_id: number,
|
||||
range_begin: number?,
|
||||
range_end: number?
|
||||
range_end: number?,
|
||||
}
|
||||
|
||||
-- stylua: ignore start
|
||||
|
@ -184,6 +205,8 @@ local EcsOnArchetypeCreate = HI_COMPONENT_ID + 12
|
|||
local EcsOnArchetypeDelete = HI_COMPONENT_ID + 13
|
||||
local EcsRest = HI_COMPONENT_ID + 14
|
||||
|
||||
-- stylua: ignore end
|
||||
|
||||
local NULL_ARRAY = table.freeze({}) :: Column
|
||||
local NULL = newproxy(false)
|
||||
|
||||
|
@ -285,10 +308,7 @@ local function ECS_PAIR_SECOND(e: i53): i24
|
|||
return (e - ECS_PAIR_OFFSET) % ECS_ENTITY_MASK
|
||||
end
|
||||
|
||||
local function entity_index_try_get_any(
|
||||
entity_index: EntityIndex,
|
||||
entity: number
|
||||
): Record?
|
||||
local function entity_index_try_get_any(entity_index: EntityIndex, entity: number): Record?
|
||||
local r = entity_index.sparse_array[ECS_ENTITY_T_LO(entity)]
|
||||
|
||||
if not r or r.dense == 0 then
|
||||
|
@ -385,10 +405,18 @@ local function ecs_pair_second(world: World, e: i53)
|
|||
return ecs_get_alive(world, obj)
|
||||
end
|
||||
|
||||
local function bloom_filter_check(bloom: number, filter: number): boolean
|
||||
return (bloom % (filter * 2)) >= filter
|
||||
end
|
||||
|
||||
local function query_match(query: QueryInner, archetype: Archetype)
|
||||
local columns_map = archetype.columns_map
|
||||
local with = query.filter_with
|
||||
|
||||
if not bloom_filter_check(query.bloom_filter, archetype.bloom_filter) then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, id in with do
|
||||
if not columns_map[id] then
|
||||
return false
|
||||
|
@ -415,13 +443,8 @@ local function find_observers(world: World, event: Id, component: Id): { Observe
|
|||
return cache[component] :: any
|
||||
end
|
||||
|
||||
local function archetype_move(
|
||||
entity_index: EntityIndex,
|
||||
to: Archetype,
|
||||
dst_row: i24,
|
||||
from: Archetype,
|
||||
src_row: i24
|
||||
)
|
||||
|
||||
local function archetype_move(entity_index: EntityIndex, to: Archetype, dst_row: i24, from: Archetype, src_row: i24)
|
||||
local src_columns = from.columns
|
||||
local dst_entities = to.entities
|
||||
local src_entities = from.entities
|
||||
|
@ -474,33 +497,21 @@ local function archetype_move(
|
|||
record2.row = src_row
|
||||
end
|
||||
|
||||
local function archetype_append(
|
||||
entity: Entity,
|
||||
archetype: Archetype
|
||||
): number
|
||||
local function archetype_append(entity: Entity, archetype: Archetype): number
|
||||
local entities = archetype.entities
|
||||
local length = #entities + 1
|
||||
entities[length] = entity
|
||||
return length
|
||||
end
|
||||
|
||||
local function new_entity(
|
||||
entity: Entity,
|
||||
record: Record,
|
||||
archetype: Archetype
|
||||
): Record
|
||||
local function new_entity(entity: Entity, record: Record, archetype: Archetype): Record
|
||||
local row = archetype_append(entity, archetype)
|
||||
record.archetype = archetype
|
||||
record.row = row
|
||||
return record
|
||||
end
|
||||
|
||||
local function entity_move(
|
||||
entity_index: EntityIndex,
|
||||
entity: Entity,
|
||||
record: Record,
|
||||
to: Archetype
|
||||
)
|
||||
local function entity_move(entity_index: EntityIndex, entity: Entity, record: Record, to: Archetype)
|
||||
local sourceRow = record.row
|
||||
local from = record.archetype
|
||||
local dst_row = archetype_append(entity, to)
|
||||
|
@ -523,8 +534,7 @@ local function fetch(id: Id, columns_map: { [Entity]: Column }, row: number): an
|
|||
return column[row]
|
||||
end
|
||||
|
||||
local function world_get(world: World, entity: Entity,
|
||||
a: Id, b: Id?, c: Id?, d: Id?, e: Id?): ...any
|
||||
local function world_get(world: World, entity: Entity, a: Id, b: Id?, c: Id?, d: Id?, e: Id?): ...any
|
||||
local record = entity_index_try_get(world.entity_index, entity)
|
||||
if not record then
|
||||
return nil
|
||||
|
@ -604,8 +614,7 @@ local function world_target(world: World, entity: Entity, relation: Id, index: n
|
|||
return nil
|
||||
end
|
||||
|
||||
return entity_index_get_alive(entity_index,
|
||||
ECS_PAIR_SECOND(nth :: number))
|
||||
return entity_index_get_alive(entity_index, ECS_PAIR_SECOND(nth :: number))
|
||||
end
|
||||
|
||||
local function ECS_ID_IS_WILDCARD(e: i53): boolean
|
||||
|
@ -640,11 +649,9 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
|||
local is_pair = ECS_IS_PAIR(id :: number)
|
||||
if is_pair then
|
||||
relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id :: number)) :: i53
|
||||
ecs_assert(relation and entity_index_is_alive(
|
||||
entity_index, relation), ECS_INTERNAL_ERROR)
|
||||
ecs_assert(relation and entity_index_is_alive(entity_index, relation), ECS_INTERNAL_ERROR)
|
||||
target = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id :: number)) :: i53
|
||||
ecs_assert(target and entity_index_is_alive(
|
||||
entity_index, target), ECS_INTERNAL_ERROR)
|
||||
ecs_assert(target and entity_index_is_alive(entity_index, target), ECS_INTERNAL_ERROR)
|
||||
end
|
||||
|
||||
local cleanup_policy = world_target(world, relation, EcsOnDelete, 0)
|
||||
|
@ -656,21 +663,15 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
|||
has_delete = true
|
||||
end
|
||||
|
||||
local on_add, on_change, on_remove = world_get(world,
|
||||
relation, EcsOnAdd, EcsOnChange, EcsOnRemove)
|
||||
local on_add, on_change, on_remove = world_get(world, relation, EcsOnAdd, EcsOnChange, EcsOnRemove)
|
||||
|
||||
local is_tag = not world_has_one_inline(world,
|
||||
relation, EcsComponent)
|
||||
local is_tag = not world_has_one_inline(world, relation, EcsComponent)
|
||||
|
||||
if is_tag and is_pair then
|
||||
is_tag = not world_has_one_inline(world, target, EcsComponent)
|
||||
end
|
||||
|
||||
flags = bit32.bor(
|
||||
flags,
|
||||
if has_delete then ECS_ID_DELETE else 0,
|
||||
if is_tag then ECS_ID_IS_TAG else 0
|
||||
)
|
||||
flags = bit32.bor(flags, if has_delete then ECS_ID_DELETE else 0, if is_tag then ECS_ID_IS_TAG else 0)
|
||||
|
||||
idr = {
|
||||
size = 0,
|
||||
|
@ -738,6 +739,15 @@ local function archetype_register(world: World, archetype: Archetype)
|
|||
end
|
||||
end
|
||||
|
||||
local function bloom_filter_add(filter: number, value: number): number
|
||||
local shift = value % 53
|
||||
local bit = 2 ^ shift
|
||||
if filter % (bit * 2) < bit then
|
||||
filter = filter + bit
|
||||
end
|
||||
return filter
|
||||
end
|
||||
|
||||
local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?): Archetype
|
||||
local archetype_id = (world.max_archetype_id :: number) + 1
|
||||
world.max_archetype_id = archetype_id
|
||||
|
@ -747,6 +757,12 @@ local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?):
|
|||
|
||||
local columns_map: { [Id]: Column } = {}
|
||||
|
||||
local filter = 0
|
||||
|
||||
for _, id in id_types do
|
||||
filter = bloom_filter_add(filter, id :: number)
|
||||
end
|
||||
|
||||
local archetype: Archetype = {
|
||||
columns = columns,
|
||||
columns_map = columns_map,
|
||||
|
@ -755,6 +771,7 @@ local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?):
|
|||
type = ty,
|
||||
types = id_types,
|
||||
dead = false,
|
||||
bloom_filter = filter,
|
||||
}
|
||||
|
||||
archetype_register(world, archetype)
|
||||
|
@ -793,7 +810,7 @@ local function world_range(world: World, range_begin: number, range_end: number?
|
|||
for i = max_id + 1, range_begin do
|
||||
dense_array[i] = i
|
||||
sparse_array[i] = {
|
||||
dense = 0
|
||||
dense = 0,
|
||||
} :: Record
|
||||
end
|
||||
entity_index.max_id = range_begin - 1
|
||||
|
@ -832,11 +849,7 @@ local function find_insert(id_types: { i53 }, toAdd: i53): number
|
|||
return #id_types + 1
|
||||
end
|
||||
|
||||
local function find_archetype_without(
|
||||
world: World,
|
||||
node: Archetype,
|
||||
id: Id
|
||||
): Archetype
|
||||
local function find_archetype_without(world: World, node: Archetype, id: Id): Archetype
|
||||
local id_types = node.types
|
||||
local at = table.find(id_types, id)
|
||||
|
||||
|
@ -846,13 +859,7 @@ local function find_archetype_without(
|
|||
return archetype_ensure(world, dst)
|
||||
end
|
||||
|
||||
|
||||
local function create_edge_for_remove(
|
||||
world: World,
|
||||
node: Archetype,
|
||||
edge: Map<Id, Archetype>,
|
||||
id: Id
|
||||
): Archetype
|
||||
local function create_edge_for_remove(world: World, node: Archetype, edge: Map<Id, Archetype>, id: Id): Archetype
|
||||
local to = find_archetype_without(world, node, id)
|
||||
local edges = world.archetype_edges
|
||||
local archetype_id = node.id
|
||||
|
@ -861,11 +868,7 @@ local function create_edge_for_remove(
|
|||
return to
|
||||
end
|
||||
|
||||
local function archetype_traverse_remove(
|
||||
world: World,
|
||||
id: Id,
|
||||
from: Archetype
|
||||
): Archetype
|
||||
local function archetype_traverse_remove(world: World, id: Id, from: Archetype): Archetype
|
||||
local edges = world.archetype_edges
|
||||
local edge = edges[from.id]
|
||||
|
||||
|
@ -882,7 +885,7 @@ end
|
|||
local function find_archetype_with(world: World, id: Id, from: Archetype): Archetype
|
||||
local id_types = from.types
|
||||
|
||||
local at = find_insert(id_types :: { number } , id :: number)
|
||||
local at = find_insert(id_types :: { number }, id :: number)
|
||||
local dst = table.clone(id_types)
|
||||
table.insert(dst, at, id)
|
||||
|
||||
|
@ -919,8 +922,6 @@ local function world_component(world: World): i53
|
|||
return id
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function archetype_fast_delete_last(columns: { Column }, column_count: number)
|
||||
for i, column in columns do
|
||||
if column ~= NULL_ARRAY then
|
||||
|
@ -977,7 +978,6 @@ local function archetype_delete(world: World, archetype: Archetype, row: number)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
local function archetype_destroy(world: World, archetype: Archetype)
|
||||
if archetype == world.ROOT_ARCHETYPE then
|
||||
return
|
||||
|
@ -1020,7 +1020,6 @@ end
|
|||
|
||||
local function NOOP() end
|
||||
|
||||
|
||||
local function query_iter_init(query: QueryInner): () -> (number, ...any)
|
||||
local world_query_iter_next
|
||||
|
||||
|
@ -1862,10 +1861,14 @@ local function world_query(world: World, ...)
|
|||
world = world,
|
||||
}, Query)
|
||||
|
||||
local filter = 0
|
||||
|
||||
for _, id in ids do
|
||||
filter = bloom_filter_add(filter, id)
|
||||
|
||||
local map = component_index[id]
|
||||
if not map then
|
||||
return q
|
||||
continue
|
||||
end
|
||||
|
||||
if idr == nil or (map.size :: number) < (idr.size :: number) then
|
||||
|
@ -1873,12 +1876,17 @@ local function world_query(world: World, ...)
|
|||
end
|
||||
end
|
||||
|
||||
q.bloom_filter = filter
|
||||
|
||||
if idr == nil then
|
||||
return q
|
||||
end
|
||||
|
||||
for archetype_id in idr.records do
|
||||
local compatibleArchetype = archetypes[archetype_id]
|
||||
if not bloom_filter_check(compatibleArchetype.bloom_filter, filter) then
|
||||
continue
|
||||
end
|
||||
if #compatibleArchetype.entities == 0 then
|
||||
continue
|
||||
end
|
||||
|
@ -1940,7 +1948,7 @@ local function world_each<a>(world: World, id: Id<a>): () -> Entity
|
|||
end
|
||||
|
||||
local function world_children<a>(world: World, parent: Id<a>)
|
||||
return world_each(world, ECS_PAIR(EcsChildOf, parent::number))
|
||||
return world_each(world, ECS_PAIR(EcsChildOf, parent :: number))
|
||||
end
|
||||
|
||||
local function world_new()
|
||||
|
@ -1979,7 +1987,6 @@ local function world_new()
|
|||
observable = observable,
|
||||
} :: World
|
||||
|
||||
|
||||
local ROOT_ARCHETYPE = archetype_create(world, {}, "")
|
||||
world.ROOT_ARCHETYPE = ROOT_ARCHETYPE
|
||||
|
||||
|
@ -2017,12 +2024,7 @@ local function world_new()
|
|||
return r
|
||||
end
|
||||
|
||||
|
||||
local function inner_world_add<T, a>(
|
||||
world: World,
|
||||
entity: Entity<T>,
|
||||
id: Id<a>
|
||||
): ()
|
||||
local function inner_world_add<T, a>(world: World, entity: Entity<T>, id: Id<a>): ()
|
||||
local entity_index = world.entity_index
|
||||
local record = inner_entity_index_try_get(entity :: number)
|
||||
if not record then
|
||||
|
@ -2050,9 +2052,8 @@ local function world_new()
|
|||
end
|
||||
end
|
||||
|
||||
local function inner_world_get(world: World, entity: Entity,
|
||||
a: Id, b: Id?, c: Id?, d: Id?, e: Id?): ...any
|
||||
local record = inner_entity_index_try_get(entity::number)
|
||||
local function inner_world_get(world: World, entity: Entity, a: Id, b: Id?, c: Id?, d: Id?, e: Id?): ...any
|
||||
local record = inner_entity_index_try_get(entity :: number)
|
||||
if not record then
|
||||
return nil
|
||||
end
|
||||
|
@ -2080,9 +2081,7 @@ local function world_new()
|
|||
end
|
||||
end
|
||||
|
||||
local function inner_world_has(world: World, entity: i53,
|
||||
a: i53, b: i53?, c: i53?, d: i53?, e: i53?): boolean
|
||||
|
||||
local function inner_world_has(world: World, entity: i53, a: i53, b: i53?, c: i53?, d: i53?, e: i53?): boolean
|
||||
local record = inner_entity_index_try_get(entity)
|
||||
if not record then
|
||||
return false
|
||||
|
@ -2095,11 +2094,11 @@ local function world_new()
|
|||
|
||||
local columns_map = archetype.columns_map
|
||||
|
||||
return columns_map[a] ~= nil and
|
||||
(b == nil or columns_map[b] ~= nil) and
|
||||
(c == nil or columns_map[c] ~= nil) and
|
||||
(d == nil or columns_map[d] ~= nil) and
|
||||
(e == nil or error("args exceeded"))
|
||||
return columns_map[a] ~= nil
|
||||
and (b == nil or columns_map[b] ~= nil)
|
||||
and (c == nil or columns_map[c] ~= nil)
|
||||
and (d == nil or columns_map[d] ~= nil)
|
||||
and (e == nil or error("args exceeded"))
|
||||
end
|
||||
|
||||
local function inner_world_target<T, a>(world: World, entity: Entity<T>, relation: Id<a>, index: number?): Entity?
|
||||
|
@ -2113,7 +2112,7 @@ local function world_new()
|
|||
return nil
|
||||
end
|
||||
|
||||
local r = ECS_PAIR(relation::number, EcsWildcard)
|
||||
local r = ECS_PAIR(relation :: number, EcsWildcard)
|
||||
local idr = world.component_index[r]
|
||||
|
||||
if not idr then
|
||||
|
@ -2138,8 +2137,7 @@ local function world_new()
|
|||
return nil
|
||||
end
|
||||
|
||||
return entity_index_get_alive(world.entity_index,
|
||||
ECS_PAIR_SECOND(nth :: number))
|
||||
return entity_index_get_alive(world.entity_index, ECS_PAIR_SECOND(nth :: number))
|
||||
end
|
||||
|
||||
local function inner_world_parent<T>(world: World, entity: Entity<T>): Entity?
|
||||
|
@ -2293,10 +2291,10 @@ local function world_new()
|
|||
end
|
||||
|
||||
local function inner_world_clear<T>(world: World, entity: Entity<T>)
|
||||
local tgt = ECS_PAIR(EcsWildcard, entity::number)
|
||||
local tgt = ECS_PAIR(EcsWildcard, entity :: number)
|
||||
local idr_t = component_index[tgt]
|
||||
local idr = component_index[entity]
|
||||
local rel = ECS_PAIR(entity::number, EcsWildcard)
|
||||
local rel = ECS_PAIR(entity :: number, EcsWildcard)
|
||||
local idr_r = component_index[rel]
|
||||
|
||||
if idr then
|
||||
|
@ -2327,11 +2325,10 @@ local function world_new()
|
|||
local removal_queued = false
|
||||
|
||||
for _, id in idr_t_types do
|
||||
if not ECS_IS_PAIR(id::number) then
|
||||
if not ECS_IS_PAIR(id :: number) then
|
||||
continue
|
||||
end
|
||||
local object = entity_index_get_alive(
|
||||
entity_index, ECS_PAIR_SECOND(id::number))
|
||||
local object = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id :: number))
|
||||
if object ~= entity then
|
||||
continue
|
||||
end
|
||||
|
@ -2393,7 +2390,7 @@ local function world_new()
|
|||
|
||||
local function inner_world_delete<T>(world: World, entity: Entity<T>)
|
||||
local entity_index = world.entity_index
|
||||
local record = inner_entity_index_try_get(entity::number)
|
||||
local record = inner_entity_index_try_get(entity :: number)
|
||||
if not record then
|
||||
return
|
||||
end
|
||||
|
@ -2409,11 +2406,11 @@ local function world_new()
|
|||
|
||||
local component_index = world.component_index
|
||||
local archetypes = world.archetypes
|
||||
local tgt = ECS_PAIR(EcsWildcard, entity::number)
|
||||
local rel = ECS_PAIR(entity::number, EcsWildcard)
|
||||
local tgt = ECS_PAIR(EcsWildcard, entity :: number)
|
||||
local rel = ECS_PAIR(entity :: number, EcsWildcard)
|
||||
|
||||
local idr_t = component_index[tgt]
|
||||
local idr = component_index[entity::number]
|
||||
local idr = component_index[entity :: number]
|
||||
local idr_r = component_index[rel]
|
||||
|
||||
if idr then
|
||||
|
@ -2457,11 +2454,10 @@ local function world_new()
|
|||
local removal_queued = false
|
||||
|
||||
for _, id in idr_t_types do
|
||||
if not ECS_IS_PAIR(id::number) then
|
||||
if not ECS_IS_PAIR(id :: number) then
|
||||
continue
|
||||
end
|
||||
local object = entity_index_get_alive(
|
||||
entity_index, ECS_PAIR_SECOND(id::number))
|
||||
local object = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id :: number))
|
||||
if object ~= entity then
|
||||
continue
|
||||
end
|
||||
|
|
2379
mirror.luau
2379
mirror.luau
File diff suppressed because it is too large
Load diff
|
@ -4,3 +4,4 @@ rojo = "rojo-rbx/rojo@7.4.4"
|
|||
stylua = "johnnymorganz/stylua@2.0.1"
|
||||
Blink = "1Axen/Blink@0.14.1"
|
||||
wally-package-types = "JohnnyMorganz/wally-package-types@1.4.2"
|
||||
StyLua = "JohnnyMorganz/StyLua@2.1.0"
|
||||
|
|
Loading…
Reference in a new issue