diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2203ea25..af5030d3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -60,13 +60,13 @@ jobs: uses: actions/checkout@v3 - name: Download Matter Build - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4.1.7 with: name: build path: build - name: Download Example Game Build - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4.1.7 with: name: build-example path: build-example diff --git a/aftman.toml b/aftman.toml index a45b76bb..a21f1a15 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1,5 +1,6 @@ [tools] wally = "upliftgames/wally@0.3.2" -rojo = "rojo-rbx/rojo@7.4.1" +rojo = "rojo-rbx/rojo@7.4.4" stylua = "johnnymorganz/stylua@0.20.0" selene = "kampfkarren/selene@0.27.1" +testez = "jacktabscode/testez-companion-cli@0.1.3" diff --git a/example/src/shared/start.luau b/example/src/shared/start.luau index c3b19762..0cb24861 100644 --- a/example/src/shared/start.luau +++ b/example/src/shared/start.luau @@ -24,6 +24,7 @@ local function start(containers) end local loop = Matter.Loop.new(world, state, debugger:getWidgets()) + loop:setWorlds({ World = world }) -- Set up hot reloading diff --git a/lib/Loop.luau b/lib/Loop.luau index eccb2698..05cc1b17 100644 --- a/lib/Loop.luau +++ b/lib/Loop.luau @@ -54,6 +54,7 @@ function Loop.new(...) _skipSystems = {}, _orderedSystemsByEvent = {}, _state = { ... }, + _worlds = {}, _stateLength = select("#", ...), _systemState = {}, _middlewares = {}, @@ -324,6 +325,15 @@ function Loop:_sortSystems() end end +--[=[ + Sets the Worlds to be used by the Loop for deferring commands, and the Debugger for profiling. + + @param worlds {World} | {[string]: World} -- An array or dictionary of Worlds to be used by the Loop. If a dictionary is passed, the keys are used as the names of the Worlds for the Debugger. +]=] +function Loop:setWorlds(worlds: { World.World } | { [string]: World.World }) + self._worlds = worlds +end + --[=[ Connects to frame events and starts invoking your systems. @@ -369,14 +379,7 @@ function Loop:begin(events) local profiling = self.profiling - local worlds: { World.World } = {} - for _, stateArgument in self._state do - if typeof(stateArgument) == "table" and getmetatable(stateArgument) == World then - table.insert(worlds, stateArgument) - end - end - - for _, world in worlds do + for _, world in self._worlds do world:startDeferring() end @@ -406,7 +409,7 @@ function Loop:begin(events) local thread = coroutine.create(function(...) fn(...) - for _, world in worlds do + for _, world in self._worlds do local ok, err = pcall(world.commitCommands, world) if not ok then commitFailed = true diff --git a/lib/debugger/debugger.luau b/lib/debugger/debugger.luau index bf5b410a..acc0f956 100644 --- a/lib/debugger/debugger.luau +++ b/lib/debugger/debugger.luau @@ -3,7 +3,6 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") local hookWidgets = require(script.Parent.hookWidgets) -local World = require(script.Parent.Parent.World) local EventBridge = require(script.Parent.EventBridge) local ui = require(script.Parent.ui) local mouseHighlight = require(script.Parent.mouseHighlight) @@ -271,16 +270,6 @@ function Debugger:_enable() return end - -- TODO: Find a better way for the user to specify the world. - if not self.debugWorld then - for _, object in self.loop._state do - if getmetatable(object) == World then - self.debugWorld = object - break - end - end - end - self.enabled = true self.loop.profiling = self.loop.profiling or {} diff --git a/lib/debugger/ui.luau b/lib/debugger/ui.luau index aa671a1d..24acde95 100644 --- a/lib/debugger/ui.luau +++ b/lib/debugger/ui.luau @@ -1,6 +1,6 @@ local RunService = game:GetService("RunService") -local World = require(script.Parent.Parent.World) local rollingAverage = require(script.Parent.Parent.rollingAverage) +local World = require(script.Parent.Parent.World) local function systemName(system) local systemFn = if type(system) == "table" then system.system else system @@ -41,12 +41,17 @@ local function ui(debugger, loop) }) local objectStack = plasma.useState({}) - local worldViewOpen, setWorldViewOpen = plasma.useState(false) - local worldExists = debugger.debugWorld ~= nil + local openWorld, setOpenWorld = plasma.useState() + + local debugEntityWorld + + for _, world in loop._worlds do + if debugger.hoverEntity and world:contains(debugger.hoverEntity) then + custom.hoverInspect(world, debugger.hoverEntity, custom) + end - if debugger.hoverEntity and worldExists then - if debugger.debugWorld:contains(debugger.hoverEntity) then - custom.hoverInspect(debugger.debugWorld, debugger.hoverEntity, custom) + if debugger.debugEntity and world:contains(debugger.debugEntity) then + debugEntityWorld = world end end @@ -79,25 +84,36 @@ local function ui(debugger, loop) local items = {} - for index, object in loop._state do - if type(object) ~= "table" then - continue - end + for index, world in loop._worlds do + local selected = openWorld == world - local isWorld = getmetatable(object) == World + local name = if type(index) == "number" then `World {index}` else index - local selected = (#objectStack > 0 and object == objectStack[#objectStack].value) - or (debugger.debugWorld == object and worldViewOpen) + table.insert(items, { + text = name, + icon = "🌐", + object = world, + selected = selected, + isWorld = true, + }) + end + + for index, value in loop._state do + if type(value) ~= "table" or getmetatable(value) == World then + continue + end local name = debugger.loopParameterNames[index] - local defaultName = (if isWorld then "World" else "table") .. " " .. index + local defaultName = if name then name else `table {index}` + + local selected = (#objectStack > 0 and value == objectStack[#objectStack].value) table.insert(items, { - text = if name then name else defaultName, - icon = if isWorld then "🌐" else "{}", - object = object, + text = defaultName, + icon = "{}", + object = value, selected = selected, - isWorld = isWorld, + isWorld = false, }) end @@ -105,12 +121,10 @@ local function ui(debugger, loop) if selectedState then if selectedState.isWorld then - if worldViewOpen and debugger.debugWorld == selectedState.object then - debugger.debugWorld = nil - setWorldViewOpen(false) + if openWorld == selectedState.object then + setOpenWorld(nil) else - debugger.debugWorld = selectedState.object - setWorldViewOpen(true) + setOpenWorld(selectedState.object) end else local previousFirstValue = if objectStack[1] then objectStack[1].value else nil @@ -228,16 +242,16 @@ local function ui(debugger, loop) end) debugger.parent = custom.container(function() - if debugger.debugWorld and worldViewOpen then - local closed = custom.worldInspect(debugger, objectStack) + if openWorld then + local closed = custom.worldInspect(debugger, openWorld, objectStack) if closed then - setWorldViewOpen(false) + setOpenWorld(nil) end end - if debugger.debugWorld and debugger.debugEntity then - custom.entityInspect(debugger) + if debugEntityWorld and debugger.debugEntity then + custom.entityInspect(debugger, debugEntityWorld) end if #objectStack > 0 then diff --git a/lib/debugger/widgets/entityInspect.luau b/lib/debugger/widgets/entityInspect.luau index 817f87aa..b6d94493 100644 --- a/lib/debugger/widgets/entityInspect.luau +++ b/lib/debugger/widgets/entityInspect.luau @@ -3,7 +3,7 @@ local formatTable = formatTableModule.formatTable local FormatMode = formatTableModule.FormatMode return function(plasma) - return plasma.widget(function(debugger) + return plasma.widget(function(debugger, world) local style = plasma.useStyle() local closed = plasma @@ -11,7 +11,7 @@ return function(plasma) title = string.format("Entity %d", debugger.debugEntity), closable = true, }, function() - if not debugger.debugWorld:contains(debugger.debugEntity) then + if not world:contains(debugger.debugEntity) then debugger.debugEntity = nil return end @@ -28,7 +28,7 @@ return function(plasma) plasma.row(function() if plasma.button("despawn"):clicked() then - debugger.debugWorld:despawn(debugger.debugEntity) + world:despawn(debugger.debugEntity) debugger.debugEntity = nil end end) @@ -39,7 +39,7 @@ return function(plasma) local items = { { "Component", "Data" } } - for component, data in debugger.debugWorld:_getEntity(debugger.debugEntity) do + for component, data in world:_getEntity(debugger.debugEntity) do table.insert(items, { tostring(component), formatTable(data, FormatMode.Long), diff --git a/lib/debugger/widgets/worldInspect.luau b/lib/debugger/widgets/worldInspect.luau index 094ae13c..a23c0ecd 100644 --- a/lib/debugger/widgets/worldInspect.luau +++ b/lib/debugger/widgets/worldInspect.luau @@ -5,11 +5,9 @@ local BY_COMPONENT_NAME = "ComponentName" local BY_ENTITY_COUNT = "EntityCount" return function(plasma) - return plasma.widget(function(debugger, objectStack) + return plasma.widget(function(debugger, world, objectStack) local style = plasma.useStyle() - local world = debugger.debugWorld - local cache, setCache = plasma.useState() local sortType, setSortType = plasma.useState(BY_COMPONENT_NAME)