diff --git a/lib/command_buffer.luau b/lib/command_buffer.luau index d3aa898..a1e48ca 100644 --- a/lib/command_buffer.luau +++ b/lib/command_buffer.luau @@ -4,16 +4,27 @@ local jecs = require("./jecs") type entity = jecs.Entity type id = jecs.Id -local WORLD = require("./world").get +local _world = require("./world") +local WORLD = _world.get + +-- luau-lsp literally dies if you use the actual world type +type jecs_world = any --- `map>` -local add_commands: { [id]: { entity } } = {} +local add_commands: { [jecs_world]: { [id]: { entity } } } = {} --- `map>` -local set_commands: { [id]: { [entity]: any } } = {} +local set_commands: { [jecs_world]: { [id]: { [entity]: any } } } = {} --- `map>` -local remove_commands: { [id]: { entity } } = {} +local remove_commands: { [jecs_world]: { [id]: { entity } } } = {} --- `array` -local delete_commands: { entity } = {} +local delete_commands: { [jecs_world]: { entity } } = {} + +_world.on_set(function(world) + add_commands[world] = {} + set_commands[world] = {} + remove_commands[world] = {} + delete_commands[world] = {} +end) export type command_buffer = { --- Execute all buffered commands and clear the buffer @@ -30,74 +41,86 @@ export type command_buffer = { } local function flush() - local world = WORLD() - - for _, entity in delete_commands do - world:delete(entity) - end - - for component, entities in add_commands do + for world, entities in delete_commands do for _, entity in entities do - if delete_commands[entity] then - continue - end - - world:add(entity, component) + world:delete(entity) end end - table.clear(add_commands) - for component, entities in set_commands do - for entity, value in entities do - if delete_commands[entity] then - continue + for world, commands in add_commands do + for component, entities in commands do + for _, entity in entities do + if delete_commands[world][entity] then + continue + end + + world:add(entity, component) end - - world:set(entity, component, value) end + table.clear(add_commands[world]) end - table.clear(set_commands) - for component, entities in remove_commands do - for _, entity in entities do - if delete_commands[entity] then - continue + for world, commands in set_commands do + for component, entities in commands do + for entity, value in entities do + if delete_commands[world][entity] then + continue + end + + world:set(entity, component, value) end - - world:remove(entity, component) end + table.clear(set_commands[world]) end - table.clear(remove_commands) - table.clear(delete_commands) + for world, commands in remove_commands do + for component, entities in commands do + for _, entity in entities do + if delete_commands[world][entity] then + continue + end + + world:remove(entity, component) + end + end + table.clear(remove_commands[world]) + end + + for world in delete_commands do + table.clear(delete_commands) + end end local function add(entity: entity, component: id) - if not add_commands[component] then - add_commands[component] = {} + local world = WORLD() + if not add_commands[world][component] then + add_commands[world][component] = {} end - table.insert(add_commands[component], entity) + table.insert(add_commands[world][component], entity) end local function set(entity: entity, component: id, data: T) - if not set_commands[component] then - set_commands[component] = {} + local world = WORLD() + if not set_commands[world][component] then + set_commands[world][component] = {} end - set_commands[component][entity] = data + set_commands[world][component][entity] = data end local function remove(entity: entity, component: id) - if not remove_commands[component] then - remove_commands[component] = {} + local world = WORLD() + if not remove_commands[world][component] then + remove_commands[world][component] = {} end - table.insert(remove_commands[component], entity) + table.insert(remove_commands[world][component], entity) end local function delete(entity: entity) - table.insert(delete_commands, entity) + local world = WORLD() + table.insert(delete_commands[world], entity) end local command_buffer: command_buffer = { diff --git a/lib/handle.luau b/lib/handle.luau index 8369f1a..b4a8948 100644 --- a/lib/handle.luau +++ b/lib/handle.luau @@ -30,7 +30,7 @@ type interface = { id: (self: handle) -> entity, } -export type handle = typeof(setmetatable({} :: { entity: entity }, {} :: interface)) +export type handle = typeof(setmetatable({} :: { entity: entity, world: jecs.World }, {} :: interface)) local handle = {} :: interface handle.__index = handle @@ -38,26 +38,27 @@ handle.__index = handle function handle.new(entity: entity) local self = { entity = entity, + world = world(), } return setmetatable(self, handle) end function handle:has(...: id): boolean - return world():has(self.entity, ...) + return self.world:has(self.entity, ...) end handle.get = function(self: handle, a: id, b: id?, c: id?, d: id?) - return world():get(self.entity, a, b :: any, c :: any, d :: any) + return self.world:get(self.entity, a, b :: any, c :: any, d :: any) end :: any function handle:add(id: id): handle - world():add(self.entity, id) + self.world:add(self.entity, id) return self end function handle:set(id: id, value: T): handle - world():set(self.entity, id, value) + self.world:set(self.entity, id, value) return self end @@ -67,7 +68,7 @@ function handle:remove(id: id): handle end function handle:delete() - world():delete(self.entity) + self.world:delete(self.entity) end function handle:id(): entity diff --git a/lib/ref.luau b/lib/ref.luau index 6c462e0..9a1e5f4 100644 --- a/lib/ref.luau +++ b/lib/ref.luau @@ -1,9 +1,10 @@ --!strict --!optimize 2 local handle = require("./handle") +local jecs = require("./jecs") local WORLD = require("./world").get -local refs = {} +local refs: { [jecs.World]: { [any]: jecs.Entity } } = {} --- Gets an entity the given key references to. --- If the key is nil, an entirely new entity is created and returned. @@ -16,10 +17,14 @@ local function ref(key: any): handle.handle return handle(world:entity()) end - local entity = refs[key] + if not refs[world] then + refs[world] = {} + end + + local entity = refs[world][key] if not entity then entity = world:entity() - refs[key] = entity + refs[world][key] = entity end return handle(entity) diff --git a/lib/world.luau b/lib/world.luau index 1f2ee25..9d5de0b 100644 --- a/lib/world.luau +++ b/lib/world.luau @@ -4,15 +4,26 @@ local jecs = require("./jecs") local WORLD: jecs.World +local listeners: { (jecs.World) -> () } = {} + local function get(): jecs.World return WORLD end local function set(world: jecs.World) WORLD = world + + for _, fn in listeners do + fn(world) + end +end + +local function on_set(fn: (jecs.World) -> ()) + table.insert(listeners, fn) end return { get = get, set = set, + on_set = on_set, }