Compare commits

..

No commits in common. "edb73ca49a7cba7cf2e08743690a88e21a8e6adc" and "bfce07c8810a99d49323285b09329277b1f99f9d" have entirely different histories.

18 changed files with 460 additions and 301 deletions

View file

@ -2,16 +2,18 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService") local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService") local UserInputService = game:GetService("UserInputService")
local jabby = require(ReplicatedStorage.Packages.jabby) local jabby = require(ReplicatedStorage.Packages.jabby)
local std = ReplicatedStorage.std local std = require(ReplicatedStorage.std)
local scheduler = require(std.scheduler) local Scheduler = std.Scheduler
local world = require(std.world) local world = std.world
local function start(modules) local function start(modules)
local scheduler = Scheduler.new(world, require(ReplicatedStorage.std.components))
for _, module in modules do for _, module in modules do
require(module) require(module)(scheduler)
end end
local events = scheduler.COLLECT() local events = scheduler.collect.all()
scheduler.BEGIN(events) scheduler.systems.begin(events)
jabby.set_check_function(function(player) jabby.set_check_function(function(player)
return true return true
end) end)

View file

@ -3,15 +3,15 @@
-- original author @centau -- original author @centau
local FAILURE = -1 local SUCCESS = 0
local RUNNING = 0 local FAILURE = 1
local SUCCESS = 1 local RUNNING = 2
local function SEQUENCE(nodes) local function SEQUENCE(nodes)
return function(...) return function(...)
for _, node in nodes do for _, node in nodes do
local status = node(...) local status = node(...)
if status <= RUNNING then if status == FAILURE or status == RUNNING then
return status return status
end end
end end
@ -23,7 +23,7 @@ local function FALLBACK(nodes)
return function(...) return function(...)
for _, node in nodes do for _, node in nodes do
local status = node(...) local status = node(...)
if status > FAILURE then if status == SUCCESS or status == RUNNING then
return status return status
end end
end end

View file

@ -8,7 +8,7 @@ local components: {
Model: Entity<Model>, Model: Entity<Model>,
Player: Entity, Player: Entity,
Target: Entity, Target: Entity,
Transform: Entity<{ new: CFrame, old: CFrame }>, Transform: Entity<CFrame>,
Velocity: Entity<number>, Velocity: Entity<number>,
Previous: Entity, Previous: Entity,
} = } =
@ -23,8 +23,4 @@ local components: {
Previous = world:component(), Previous = world:component(),
} }
for name, component in components :: {[string]: jecs.Entity} do
world:set(component, jecs.Name, name)
end
return table.freeze(components) return table.freeze(components)

View file

@ -0,0 +1,11 @@
local handle = require(script.Parent.handle)
local world = require(script.Parent.world)
local singleton = world:entity()
local function ctx()
-- Cannot cache handles because they will get invalidated
return handle(singleton)
end
return ctx

View file

@ -0,0 +1,56 @@
local jecs = require(game:GetService("ReplicatedStorage").ecs)
local world = require(script.Parent.world)
type Handle = {
has: (self: Handle, id: jecs.Entity) -> boolean,
get: <T>(self: Handle, id: jecs.Entity<T>) -> T?,
add: <T>(self: Handle, id: jecs.Entity<T>) -> Handle,
set: <T>(self: Handle, id: jecs.Entity<T>, value: T) -> Handle,
id: (self: Handle?) -> jecs.Entity,
}
local handle: (e: jecs.Entity) -> Handle
do
local e
local function has(_, id)
return world:has(e, id)
end
local function get(_, id)
return world:get(e, id)
end
local function set(self, id, value)
world:set(e, id, value)
return self
end
local function add(self, id)
world:add(e, id)
return self
end
local function clear(self)
world:clear(e)
return self
end
local function delete(self)
world:delete(e)
end
local function id()
return e
end
local entity = {
has = has,
get = get,
set = set,
add = add,
clear = clear,
id = id,
}
function handle(id)
e = id
return entity
end
end
return handle

View file

@ -0,0 +1,32 @@
--!native
--!optimize 2
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local jecs = require(ReplicatedStorage.ecs)
local function create_cache(hook)
local columns = setmetatable({}, {
__index = function(self, component)
local column = {}
self[component] = column
return column
end,
})
return function(world, component, fn)
local column = columns[component]
table.insert(column, fn)
world:set(component, hook, function(entity, value)
for _, callback in column do
callback(entity, value)
end
end)
end
end
local hooks = {
OnSet = create_cache(jecs.OnSet),
OnAdd = create_cache(jecs.OnAdd),
OnRemove = create_cache(jecs.OnRemove),
}
return hooks

View file

@ -0,0 +1,25 @@
local jecs = require(game:GetService("ReplicatedStorage").ecs)
local world = require(script.world) :: jecs.World
export type World = jecs.World
local Scheduler = require(script.scheduler)
export type Scheduler = Scheduler.Scheduler
local std = {
ChangeTracker = require(script.changetracker),
Scheduler = Scheduler,
bt = require(script.bt),
collect = require(script.collect),
components = require(script.components),
ctx = require(script.ctx),
handle = require(script.handle),
interval = require(script.interval),
ref = require(script.ref),
world = world :: World,
pair = jecs.pair,
__ = jecs.w,
hooks = require(script.hooks),
}
return std

View file

@ -16,4 +16,4 @@ local function interval(s)
return throttle return throttle
end end
return interval return interval

View file

@ -1,14 +0,0 @@
local std = game:GetService("ReplicatedStorage").std
local Players = game:GetService("Players")
local scheduler = require(std.scheduler)
local PHASE = scheduler.PHASE
return {
PlayerAdded = PHASE({
event = Players.PlayerAdded
}),
PlayerRemoved = PHASE({
event = Players.PlayerRemoving
})
}

View file

@ -1,18 +1,16 @@
local handle = require(script.Parent.handle)
local world = require(script.Parent.world) local world = require(script.Parent.world)
local jecs = require(game:GetService("ReplicatedStorage").ecs) local refs = {}
local refs: {[any]: jecs.Entity} = {}
local function fini(key): () -> () local function fini(key)
return function() return function()
refs[key] = nil refs[key] = nil
end end
end end
local function noop() end local function ref(key): (handle.Handle, (() -> ())?)
local function ref(key): (jecs.Entity, () -> ())
if not key then if not key then
return world:entity(), noop return handle(world:entity())
end end
local e = refs[key] local e = refs[key]
if not e then if not e then
@ -20,7 +18,7 @@ local function ref(key): (jecs.Entity, () -> ())
refs[key] = e refs[key] = e
end end
-- Cannot cache handles because they will get invalidated -- Cannot cache handles because they will get invalidated
return e, fini(key) return handle(e), fini(key)
end end
return ref return ref

View file

@ -0,0 +1,31 @@
local reserved = 0
local function reserve()
reserved += 1
return reserved
end
-- If you don't like passing around a world singleton
-- and you need to register component IDs, just register them.
-- I dont use this because I like adding component traits
--[[
local components = {
Model = registry.reserve(),
Transform = registry.reserve(),
}
local world = registry.register(jecs.World.new())
local e = world:entity()
world:set(e, components.Transform, CFrame)
]]
local function register(world)
for _ = 1, reserved do
world:component()
end
return world
end
return {
reserve = reserve,
register = register,
}

View file

@ -1,7 +1,6 @@
--!native --!native
--!optimize 2 --!optimize 2
local ReplicatedStorage = game:GetService("ReplicatedStorage") local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local jabby = require(ReplicatedStorage.Packages.jabby) local jabby = require(ReplicatedStorage.Packages.jabby)
local jecs = require(ReplicatedStorage.ecs) local jecs = require(ReplicatedStorage.ecs)
local pair = jecs.pair local pair = jecs.pair
@ -9,7 +8,6 @@ local Name = jecs.Name
type World = jecs.World type World = jecs.World
type Entity<T = nil> = jecs.Entity<T> type Entity<T = nil> = jecs.Entity<T>
type Id<T = unknown> = jecs.Id<T>
type System = { type System = {
callback: (world: World) -> (), callback: (world: World) -> (),
@ -23,145 +21,226 @@ type Events = {
Heartbeat: Systems, Heartbeat: Systems,
} }
local world = require(script.Parent.world) export type Scheduler = {
local Disabled = world:entity() components: {
local System = world:component() :: Id<{ callback: (any) -> (), name: string}> Disabled: Entity,
local DependsOn = world:entity() System: Entity<System>,
local Event = world:component() :: Id<RBXScriptSignal> Phase: Entity,
local Phase = world:entity() DependsOn: Entity,
},
local PreRender = world:entity() collect: {
local Heartbeat = world:entity() under_event: (event: Entity) -> Systems,
local PreAnimation = world:entity() all: () -> Events,
local PreSimulation = world:entity() },
local sys: System systems: {
local dt: number begin: (events: Events) -> { [Entity]: thread },
new: (callback: (dt: number) -> (), phase: Entity) -> Entity,
},
local jabby_scheduler = jabby.scheduler.create("Scheduler") phases: {
RenderStepped: Entity,
Heartbeat: Entity,
},
local a, b, c, d phase: (after: Entity) -> Entity,
local function run()
local id = sys.id
jabby_scheduler:run(id, sys.callback, a, b, c, d)
return nil
end
world:add(Heartbeat, Phase) debugging: boolean,
world:set(Heartbeat, Event, RunService.Heartbeat) }
world:add(PreSimulation, Phase) local scheduler_new: (w: World, components: { [string]: Entity }) -> Scheduler
world:set(PreSimulation, Event, RunService.PreSimulation)
world:add(PreAnimation, Phase) do
world:set(PreAnimation, Event, RunService.PreAnimation) local world: World
local Disabled: Entity
local System: Entity<System>
local DependsOn: Entity
local Phase: Entity
local Event: Entity<RBXScriptSignal>
table.insert(jabby.public, { local scheduler
class_name = "World",
name = "MyWorld",
world = world,
debug = Name,
entities = {},
})
jabby.public.updated = true local RenderStepped
local Heartbeat
local PreAnimation
local PreSimulation
table.insert(jabby.public, jabby_scheduler) local sys: System
local dt
if RunService:IsClient() then local function run()
world:add(PreRender, Phase) local id = sys.id
world:set(PreRender, Event, (RunService :: RunService).PreRender) scheduler:run(id, sys.callback, dt)
end end
local function begin(events: { [RBXScriptSignal]: Systems })
local connections = {}
for event, systems in events do
if not event then
continue
end
local event_name = tostring(event)
connections[event] = event:Connect(function(...)
debug.profilebegin(event_name)
for _, s in systems do
sys = s
a, b, c, d = ...
for _ in run do
break
end
local function panic(str)
-- We don't want to interrupt the loop when we error
task.spawn(error, str)
end
local function begin(events: { Systems })
local connections = {}
for event, systems in events do
if not event then
continue
end end
debug.profileend() local event_name = tostring(event)
end) connections[event] = event:Connect(function(delta)
end debug.profilebegin(event_name)
return connections for _, s in systems do
end sys = s
dt = delta
local didNotYield, why = xpcall(function()
for _ in run do
break
end
end, debug.traceback)
local function scheduler_collect_systems_under_phase_recursive(systems, phase: Entity) if didNotYield then
local phase_name = world:get(phase, Name) continue
for _, s in world:query(System):with(pair(DependsOn, phase)) do end
table.insert(systems, {
id = jabby_scheduler:register_system({
name = s.name,
phase = phase_name,
} :: any),
callback = s.callback,
})
end
for after in world:query(Phase):with(pair(DependsOn, phase)):iter() do
scheduler_collect_systems_under_phase_recursive(systems, after)
end
end
local function scheduler_collect_systems_under_event(event) if string.find(why, "thread is not yieldable") then
local systems = {} panic(
scheduler_collect_systems_under_phase_recursive(systems, event) "Not allowed to yield in the systems."
return systems .. "\n"
end .. "System: "
.. debug.info(s.callback, "n")
local function scheduler_collect_systems_all() .. " has been ejected"
local events = {} )
for phase, event in world:query(Event):with(Phase) do continue
events[event] = scheduler_collect_systems_under_event(phase) end
panic(why)
end
debug.profileend()
end)
end
return threads
end end
return events
end
local function scheduler_phase_new(d: { after: Entity?, event: RBXScriptSignal? }) local function scheduler_collect_systems_under_phase_recursive(systems, phase)
local phase = world:entity() local phase_name = world:get(phase, Name)
world:add(phase, Phase) for _, s in world:query(System):with(pair(DependsOn, phase)) do
local after = d.after table.insert(systems, {
if after then id = scheduler:register_system({
local dependency = pair(DependsOn, after :: Entity) name = s.name,
phase = phase_name,
}),
callback = s.callback,
})
end
for after in world:query(Phase):with(pair(DependsOn, phase)) do
scheduler_collect_systems_under_phase_recursive(systems, after)
end
end
local function scheduler_collect_systems_under_event(event)
local systems = {}
scheduler_collect_systems_under_phase_recursive(systems, event)
return systems
end
local function scheduler_collect_systems_all()
local events = {}
for phase, event in world:query(Event):with(Phase) do
events[event] = scheduler_collect_systems_under_event(phase)
end
return events
end
local function scheduler_phase_new(after)
local phase = world:entity()
world:add(phase, Phase)
local dependency = pair(DependsOn, after)
world:add(phase, dependency) world:add(phase, dependency)
return phase
end end
local event = d.event
if event then
world:set(phase, Event, event)
end
return phase
end
local function scheduler_systems_new(callback: (any) -> (), phase: Entity?) local function scheduler_systems_new(callback, phase)
local system = world:entity() local system = world:entity()
world:set(system, System, { callback = callback, name = debug.info(callback, "n") }) local name = debug.info(callback, "n")
local depends_on = DependsOn :: jecs.Entity world:set(system, System, { callback = callback, name = name })
local p: Entity = phase or Heartbeat world:add(system, pair(DependsOn, phase))
world:add(system, pair(depends_on, p)) return system
end
return system
function scheduler_new(w: World, components: { [string]: Entity })
world = w
Disabled = world:component()
System = world:component()
Phase = world:component()
DependsOn = world:component()
Event = world:component()
RenderStepped = world:component()
Heartbeat = world:component()
PreSimulation = world:component()
PreAnimation = world:component()
local RunService = game:GetService("RunService")
if RunService:IsClient() then
world:add(RenderStepped, Phase)
world:set(RenderStepped, Event, RunService.RenderStepped)
end
world:add(Heartbeat, Phase)
world:set(Heartbeat, Event, RunService.Heartbeat)
world:add(PreSimulation, Phase)
world:set(PreSimulation, Event, RunService.PreSimulation)
world:add(PreAnimation, Phase)
world:set(PreAnimation, Event, RunService.PreAnimation)
for name, component in components do
world:set(component, Name, name)
end
table.insert(jabby.public, {
class_name = "World",
name = "MyWorld",
world = world,
debug = Name,
entities = {},
})
jabby.public.updated = true
scheduler = jabby.scheduler.create("scheduler")
table.insert(jabby.public, scheduler)
return {
phase = scheduler_phase_new,
phases = {
RenderStepped = RenderStepped,
PreSimulation = PreSimulation,
Heartbeat = Heartbeat,
PreAnimation = PreAnimation,
},
world = world,
components = {
DependsOn = DependsOn,
Disabled = Disabled,
Phase = Phase,
System = System,
},
collect = {
under_event = scheduler_collect_systems_under_event,
all = scheduler_collect_systems_all,
},
systems = {
new = scheduler_systems_new,
begin = begin,
},
}
end
end end
return { return {
SYSTEM = scheduler_systems_new, new = scheduler_new,
BEGIN = begin,
PHASE = scheduler_phase_new,
COLLECT = scheduler_collect_systems_all,
phases = {
Heartbeat = Heartbeat,
PreSimulation = PreSimulation,
PreAnimation = PreAnimation,
PreRender = PreRender
}
} }

View file

@ -6,12 +6,13 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
local blink = require(game:GetService("ServerScriptService").net) local blink = require(game:GetService("ServerScriptService").net)
local jecs = require(ReplicatedStorage.ecs) local jecs = require(ReplicatedStorage.ecs)
local __ = jecs.Wildcard local __ = jecs.Wildcard
local std = ReplicatedStorage.std
local ref = require(std.ref)
local interval = require(std.interval)
local world = require(std.world) local std = require(ReplicatedStorage.std)
local cts = require(std.components) local ref = std.ref
local interval = std.interval
local world: std.World = std.world
local cts = std.components
local Mob = cts.Mob local Mob = cts.Mob
local Transform = cts.Transform local Transform = cts.Transform
@ -19,26 +20,13 @@ local Velocity = cts.Velocity
local Player = cts.Player local Player = cts.Player
local Character = cts.Character local Character = cts.Character
local characters = world
:query(Character)
:with(Player)
:cached()
local moving_mobs = world
:query(Transform, Velocity)
:with(Mob)
:cached()
local function mobsMove(dt: number) local function mobsMove(dt: number)
local targets = {} local targets = {}
for _, character in world:query(Character):with(Player):iter() do
for _, character in characters do
table.insert(targets, (character.PrimaryPart :: Part).Position) table.insert(targets, (character.PrimaryPart :: Part).Position)
end end
for mob, transform, v in moving_mobs do for mob, transform, v in world:query(Transform, Velocity):with(Mob):iter() do
local cf = transform.new local cf = transform.new
local p = cf.Position local p = cf.Position
@ -65,24 +53,21 @@ end
local throttle = interval(5) local throttle = interval(5)
local function spawnMobs() local function spawnMobs()
if throttle() then if throttle() then
local p = Vector3.new(0, 5, 0) local p = Vector3.new(0, 5, 0)
local cf = CFrame.new(p) local cf = CFrame.new(p)
local v = 5 local v = 5
local e = world:entity() local id = ref():set(Velocity, v):set(Transform, { new = cf }):add(Mob).id()
world:set(e, Velocity, v)
world:set(e, Transform, { new = cf })
world:add(e, Mob)
blink.SpawnMob.FireAll(e, cf, v) blink.SpawnMob.FireAll(id, cf, v)
end end
end end
local scheduler = require(std.scheduler) return function(scheduler: std.Scheduler)
local phases = scheduler.phases
scheduler.SYSTEM(spawnMobs) local system_new = scheduler.systems.new
scheduler.SYSTEM(mobsMove) system_new(mobsMove, phases.Heartbeat)
system_new(spawnMobs, phases.Heartbeat)
return 0 end

View file

@ -1,40 +1,43 @@
local Players = game:GetService("Players") local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage") local ReplicatedStorage = game:GetService("ReplicatedStorage")
local std = ReplicatedStorage.std local std = require(ReplicatedStorage.std)
local ref = require(std.ref) local ref = std.ref
local collect = require(std.collect) local collect = std.collect
local cts = require(std.components) local cts = std.components
local world = require(std.world)
local Player = cts.Player local Player = cts.Player
local Character = cts.Character local Character = cts.Character
local playersAdded = collect(Players.PlayerAdded)
local playersRemoved = collect(Players.PlayerRemoving)
local world: std.World = std.world
local conn = {} local conn = {}
local function playersAdded(player: Player) local function players()
local e = ref(player.UserId) for _, player in playersAdded do
world:set(e, Player, player) world:set(std.world:entity(), cts.Transform)
local characterAdd = player.CharacterAdded
conn[e] = characterAdd:Connect(function(rig) local e = ref(player.UserId):set(Player, player)
while rig.Parent ~= workspace do local characterAdd = player.CharacterAdded
task.wait() conn[e.id()] = characterAdd:Connect(function(rig)
end while rig.Parent ~= workspace do
world:set(e, Character, rig) task.wait()
end) end
e:set(Character, rig)
end)
end
for _, player in playersRemoved do
local id = ref(player.UserId):clear().id()
conn[id]:Disconnect()
conn[id] = nil
end
end end
local function playersRemoved(player: Player) return function(scheduler: std.Scheduler)
local e = ref(player.UserId) local phases = scheduler.phases
world:clear(e) local system_new = scheduler.systems.new
local connection = conn[e] system_new(players, phases.Heartbeat)
connection:Disconnect()
conn[e] = nil
end end
local scheduler = require(std.scheduler)
local phases = require(std.phases)
scheduler.SYSTEM(playersAdded, phases.PlayerAdded)
scheduler.SYSTEM(playersRemoved, phases.PlayerRemoved)
return 0

View file

@ -1,22 +1,20 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage") local ReplicatedStorage = game:GetService("ReplicatedStorage")
local blink = require(ReplicatedStorage.net) local blink = require(ReplicatedStorage.net)
local std = ReplicatedStorage.std local std = require(ReplicatedStorage.std)
local world = require(std.world) local world = std.world
local ref = require(std.ref) local ref = std.ref
local cts = require(std.components) local cts = std.components
local Model = cts.Model local Model = cts.Model
local Transform = cts.Transform local Transform = cts.Transform
local moving_models = world:query(Transform, Model):cached()
local function move(dt: number) local function move(dt: number)
for _, transform, model in moving_models do for _, transform, model in world:query(Transform, Model):iter() do
local cf = transform.new local cf = transform.new
if cf ~= transform.old then if cf ~= transform.old then
local part = model.PrimaryPart :: BasePart local origo = model.PrimaryPart.CFrame
local origo = part.CFrame model.PrimaryPart.CFrame = origo:Lerp(cf, 1)
part.CFrame = origo:Lerp(cf, 1)
transform.old = cf transform.old = cf
end end
end end
@ -24,8 +22,8 @@ end
local function syncTransforms() local function syncTransforms()
for _, id, cf in blink.UpdateTransform.Iter() do for _, id, cf in blink.UpdateTransform.Iter() do
local e = ref("server-" .. tostring(id)) local e = ref("server-" .. id)
local transform = world:get(e, Transform) local transform = e:get(cts.Transform)
if not transform then if not transform then
continue continue
end end
@ -33,9 +31,9 @@ local function syncTransforms()
end end
end end
local scheduler = require(std.scheduler) return function(scheduler: std.Scheduler)
local phases = scheduler.phases
scheduler.SYSTEM(move) local system_new = scheduler.systems.new
scheduler.SYSTEM(syncTransforms) system_new(move, phases.Heartbeat)
system_new(syncTransforms, phases.RenderStepped)
return 0 end

View file

@ -1,9 +1,9 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage") local ReplicatedStorage = game:GetService("ReplicatedStorage")
local blink = require(ReplicatedStorage.net) local blink = require(ReplicatedStorage.net)
local std = ReplicatedStorage.std local std = require(ReplicatedStorage.std)
local ref = require(std.ref) local ref = std.ref
local world = require(std.world) local world = std.world
local cts = require(std.components) local cts = std.components
local function syncMobs() local function syncMobs()
for _, id, cf, vel in blink.SpawnMob.Iter() do for _, id, cf, vel in blink.SpawnMob.Iter() do
@ -16,16 +16,16 @@ local function syncMobs()
part.Parent = model part.Parent = model
model.Parent = workspace model.Parent = workspace
local e = ref("server-" .. tostring(id)) ref("server-" .. id)
world:set(e, cts.Transform, { new = cf, old = cf }) :set(cts.Transform, { new = cf, old = cf })
world:set(e, cts.Velocity, vel) :set(cts.Velocity, vel)
world:set(e, cts.Model, model) :set(cts.Model, model)
world:add(e, cts.Mob) :add(cts.Mob)
end end
end end
local scheduler = require(std.scheduler) return function(scheduler: std.Scheduler)
scheduler.SYSTEM(syncMobs) local phases = scheduler.phases
local system_new = scheduler.systems.new
return 0 system_new(syncMobs, phases.RenderStepped)
end

View file

@ -1,44 +0,0 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local std = ReplicatedStorage.std
local world = require(std.world)
local A = world:component()
local B = world:component()
local C = world:component()
local D = world:component()
local function flip()
return math.random() >= 0.15
end
for i = 1, 2^8 do
local e = world:entity()
if flip() then
world:set(e, A, true)
end
if flip() then
world:set(e, B, true)
end
if flip() then
world:set(e, C, true)
end
if flip() then
world:set(e, D, true)
end
end
local function uncached()
for _ in world:query(A, B, C, D) do
end
end
local q = world:query(A, B, C, D):cached()
local function cached()
for _ in q do
end
end
local scheduler = require(std.scheduler)
scheduler.SYSTEM(uncached)
scheduler.SYSTEM(cached)
return 0

View file

@ -263,7 +263,7 @@ local function query_match(query, archetype: Archetype)
end end
local without = query.filter_without local without = query.filter_without
if without then if not without then
for _, id in without do for _, id in without do
if records[id] then if records[id] then
return false return false
@ -1843,12 +1843,13 @@ local function query_cached(query: QueryInner)
return world_query_iter_next return world_query_iter_next
end end
local cached_query = query :: any return setmetatable(query, {
cached_query.archetypes = query_archetypes __index = {
cached_query.__iter = cached_query_iter archetypes = query_archetypes,
cached_query.iter = cached_query_iter __iter = cached_query_iter,
setmetatable(cached_query, cached_query) iter = cached_query_iter
return cached_query }
})
end end
local Query = {} local Query = {}