Simpler scheduler

This commit is contained in:
Ukendio 2025-10-14 00:41:22 +02:00
parent 57e653fa78
commit 3f47ea922e
3 changed files with 73 additions and 118 deletions

View file

@ -2,12 +2,9 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
local jecs = require(ReplicatedStorage.ecs) local jecs = require(ReplicatedStorage.ecs)
local schedule = require(ReplicatedStorage.schedule) local schedule = require(ReplicatedStorage.schedule)
local SYSTEM = schedule.SYSTEM local heartbeat = schedule(world,
local RUN = schedule.RUN systems.entities_delete,
require(ReplicatedStorage.components) systems.replication
local world = jecs.world() )
local systems = ReplicatedStorage.systems game:GetService("RunService").Heartbeat:Connect(heartbeat)
SYSTEM(world, systems.receive_replication)
SYSTEM(world, systems.entities_delete)
RUN(world)

View file

@ -1,10 +1,12 @@
--!strict
local ReplicatedStorage = game:GetService("ReplicatedStorage") local ReplicatedStorage = game:GetService("ReplicatedStorage")
local jabby = require(ReplicatedStorage.Packages.jabby) local jabby = require(ReplicatedStorage.Packages.jabby)
local ct = require(ReplicatedStorage.components)
local jecs = require(ReplicatedStorage.ecs) local jecs = require(ReplicatedStorage.ecs)
jabby.set_check_function(function() return true end) jabby.set_check_function(function(player) return true end)
local scheduler = jabby.scheduler.create("jabby scheduler") local scheduler = jabby.scheduler.create()
jabby.register({ jabby.register({
applet = jabby.applets.scheduler, applet = jabby.applets.scheduler,
@ -12,125 +14,78 @@ jabby.register({
configuration = { configuration = {
scheduler = scheduler, scheduler = scheduler,
}, },
}) }::any)
local ContextActionService = game:GetService("ContextActionService") local ContextActionService = game:GetService("ContextActionService")
local function create_widget(_, state: Enum.UserInputState) local function create_widget(_, state: Enum.UserInputState): Enum.ContextActionResult
local client = jabby.obtain_client() local client = jabby.obtain_client()
if state ~= Enum.UserInputState.Begin then return end if state ~= Enum.UserInputState.Begin then
client.spawn_app(client.apps.home, nil) return Enum.ContextActionResult.Pass
end
client.spawn_app(client.apps.home::any, nil)
return Enum.ContextActionResult.Sink
end end
local RunService = game:GetService("RunService") local RunService = game:GetService("RunService")
local System = jecs.component() :: jecs.Id<{ local function schedule(world, ...)
fn: () -> (), local function get_entity_from_part(part: BasePart): (jecs.Entity<any>?, PVInstance?)
name: string, for id, model in world:query(ct.Renderable) do
}> if not part:IsDescendantOf(model) then continue end
local DependsOn = jecs.component() return id, model
local Phase = jecs.tag() end
local Event = jecs.component() :: jecs.Id<RBXScriptSignal> return nil, nil
local pair = jecs.pair
local types = require(ReplicatedStorage.types)
local function ECS_PHASE(world, after: types.Entity)
local phase = world:entity()
world:add(phase, Phase)
if after then
local dependency = pair(DependsOn, after)
world:add(phase, dependency)
end end
return phase
end
local Heartbeat = jecs.tag()
jecs.meta(Heartbeat, Phase)
jecs.meta(Heartbeat, Event, RunService.Heartbeat)
local PreSimulation = jecs.tag()
jecs.meta(PreSimulation, Phase)
jecs.meta(PreSimulation, Event, RunService.PreSimulation)
local PreAnimation = jecs.tag()
jecs.meta(PreAnimation, Phase)
jecs.meta(PreAnimation, Event, RunService.PreAnimation)
local PreRender = jecs.tag()
jecs.meta(PreRender, Phase)
jecs.meta(PreRender, Event, RunService.PreRender)
local function ECS_SYSTEM(world: types.World, mod: ModuleScript, phase: types.Entity?)
local system = world:entity()
local p = phase or Heartbeat
local fn = require(mod) :: (...any) -> ()
world:set(system, System, {
fn = fn(world, 0) or fn,
name = mod.Name,
})
local depends_on = DependsOn :: jecs.Entity
world:add(system, pair(depends_on, p))
end
local function find_systems_w_phase(world: types.World, systems, phase: types.Entity)
local phase_name = world:get(phase, jecs.Name) :: string
for _, s in world:query(System):with(pair(DependsOn, phase)) do
table.insert(systems, {
id = scheduler:register_system({
phase = phase_name,
name = s.name,
}),
fn = s.fn
})
end
for after in world:query(Phase, pair(DependsOn, phase)) do
find_systems_w_phase(world, systems, after)
end
return systems
end
local function ECS_RUN(world: types.World)
jabby.register({ jabby.register({
applet = jabby.applets.world, applet = jabby.applets.world,
name = "MyWorld", name = "World",
configuration = { configuration = {
world = world, world = world,
get_entity_from_part = get_entity_from_part,
}, },
}) }::any)
local systems = { ... }
local function systems_load(mod: ModuleScript, ...)
local fn = require(mod) :: (...any) -> ()
local system = fn(...) or fn
local system_id = scheduler:register_system({
name = mod.Name,
module = mod,
})
return {
system = system,
id = system_id
}
end
for i, mod in systems do
systems[i] = systems_load(mod, world, 0)
end
if RunService:IsClient() then if RunService:IsClient() then
ContextActionService:BindAction("Open Jabby Home", create_widget, false, Enum.KeyCode.F4) ContextActionService:BindAction(
"Open Jabby Home",
create_widget,
false,
Enum.KeyCode.F4
)
end end
for phase, event in world:query(Event, Phase) do return function(dt: number, input: InputObject?)
local systems = find_systems_w_phase(world, {}, phase) for i, config in systems do
event:Connect(function(...) -- config.system(world, dt, input)
for _, system in systems do local system = config.system
scheduler:run(system.id, system.fn, world, ...) local id = config.id
end scheduler:run(id, system,
end) world, dt, input)
end
end end
end end
return { return schedule
PHASE = ECS_PHASE,
SYSTEM = ECS_SYSTEM,
RUN = ECS_RUN,
phases = {
Heartbeat = Heartbeat,
PreSimulation = PreSimulation,
PreAnimation = PreAnimation,
PreRender = PreRender
},
components = {
System = System,
DependsOn = DependsOn,
Phase = Phase,
Event = Event,
}
}

View file

@ -11,11 +11,14 @@ local world = jecs.world()
local systems = ServerScriptService.systems local systems = ServerScriptService.systems
SYSTEM(world, systems.replication) local heartbeat = schedule(world,
SYSTEM(world, systems.players_added) systems.players_added,
SYSTEM(world, systems.poison_hurts) systems.poison_hurts,
SYSTEM(world, systems.health_regen) systems.health_regen,
SYSTEM(world, systems.lifetimes_expire) systems.lifetimes_expire,
SYSTEM(world, systems.life_is_painful) systems.life_is_painful,
SYSTEM(world, ReplicatedStorage.systems.entities_delete) systems.entities_delete,
RUN(world, 0) systems.replication
)
game:GetService("RunService").Heartbeat:Connect(heartbeat)