From f25165472b6828db8ef211620d4cb47d00ecd300 Mon Sep 17 00:00:00 2001 From: Stephen Leitnick Date: Sun, 15 Dec 2019 17:42:31 -0500 Subject: [PATCH] Execution order using __aeroOrder field --- docs/controllers.md | 26 +++++++++++++++++++ docs/execution_model.md | 11 ++++++++ docs/services.md | 26 +++++++++++++++++++ .../Aero/Internal/AeroServer.server.lua | 25 ++++++++++++++---- .../Aero/Internal/AeroClient.client.lua | 25 ++++++++++++++---- 5 files changed, 103 insertions(+), 10 deletions(-) diff --git a/docs/controllers.md b/docs/controllers.md index 478c69a..a3b4b1b 100644 --- a/docs/controllers.md +++ b/docs/controllers.md @@ -165,6 +165,32 @@ end -------------------------- +## Forcing `Init` Order + +By setting the `__aeroOrder` field, the `Init` execution order can be defined. By default, the order of execution is unknown. + +```lua +local MyController = {} +MyController.__aeroOrder = 1 + +function MyController:Init() + print("MyController will be initialized before AnotherController") +end + +... + +local AnotherController = {} +AnotherController.__aeroOrder = 2 + +function AnotherController:Init() + print("AnotherController will be initialized after MyController") +end +``` + +By practice, it is discouraged to utilize another controller before entering into the `Start` phase of the controller (i.e. after all controllers have been initialized). However, using `__aeroOrder` can be used to guarantee initialization order. In the above example, `AnotherController` would be able to safely utilize `MyController`, knowing that `MyController` is guaranteed to have been initialized due to the execution order. + +-------------------------- + ## Other Examples ### Invoking another controller diff --git a/docs/execution_model.md b/docs/execution_model.md index 08c73d6..dd62a1a 100644 --- a/docs/execution_model.md +++ b/docs/execution_model.md @@ -21,6 +21,17 @@ Services and Controllers act as singletons. In other words, only one instance ex -------------------------- +## Forcing `Init` Order + +The order of which `Init` is invoked for services and controllers can be explicitly set. This is done through the `__aeroOrder` field. + +Simply set the service or controller `__aeroOrder` field to a number. The `Init` process will execute based on ascending order. Services and controllers without an `__aeroOrder` field set will be executed last (technically, the default order is set to `math.huge`). + +!!! note + The `__aeroOrder` field can be any valid number, including negatives and non-whole numbers. See the examples under the [Services](services.md) and [Controllers](controllers.md) page. + +-------------------------- + ## Preventing `Init` or `Start` There might be times where it is not desired for the framework to invoke either the `Start` or the `Init` method on a module, service, or controller. In such an instance, a flag can be added to indicate that the method should not be invoked by the framework. diff --git a/docs/services.md b/docs/services.md index 28fe91a..07cfebc 100644 --- a/docs/services.md +++ b/docs/services.md @@ -200,6 +200,32 @@ end -------------------------- +## Forcing `Init` Order + +By setting the `__aeroOrder` field, the `Init` execution order can be defined. By default, the order of execution is unknown. + +```lua +local MyService = {} +MyService.__aeroOrder = 1 + +function MyService:Init() + print("MyService will be initialized before AnotherService") +end + +... + +local AnotherService = {} +AnotherService.__aeroOrder = 2 + +function AnotherService:Init() + print("AnotherService will be initialized after MyService") +end +``` + +By practice, it is discouraged to utilize another service before entering into the `Start` phase of the service (i.e. after all services have been initialized). However, using `__aeroOrder` can be used to guarantee initialization order. In the above example, `AnotherService` would be able to safely utilize `MyService`, knowing that `MyService` is guaranteed to have been initialized due to the execution order. + +-------------------------- + ## Other Examples ### Invoking another service diff --git a/src/ServerScriptService/Aero/Internal/AeroServer.server.lua b/src/ServerScriptService/Aero/Internal/AeroServer.server.lua index ca43fce..a6fb57b 100644 --- a/src/ServerScriptService/Aero/Internal/AeroServer.server.lua +++ b/src/ServerScriptService/Aero/Internal/AeroServer.server.lua @@ -236,13 +236,28 @@ local function Init() -- Initialize services: local function InitAllServices(services) - for _,service in pairs(services) do - if (getmetatable(service) == mt) then - InitService(service) - else - InitAllServices(service) + -- Collect all services: + local serviceTables = {} + local function CollectServices(_services) + for _,service in pairs(_services) do + if (getmetatable(service) == mt) then + serviceTables[#serviceTables + 1] = service + else + CollectServices(service) + end end end + CollectServices(services) + -- Sort services by optional __aeroOrder field: + table.sort(serviceTables, function(a, b) + local aOrder = (type(a.__aeroOrder) == "number" and a.__aeroOrder or math.huge) + local bOrder = (type(b.__aeroOrder) == "number" and b.__aeroOrder or math.huge) + return (aOrder < bOrder) + end) + -- Initialize services: + for _,service in ipairs(serviceTables) do + InitService(service) + end end -- Remove unused folders: diff --git a/src/StarterPlayer/StarterPlayerScripts/Aero/Internal/AeroClient.client.lua b/src/StarterPlayer/StarterPlayerScripts/Aero/Internal/AeroClient.client.lua index d1d8ccc..5b06607 100644 --- a/src/StarterPlayer/StarterPlayerScripts/Aero/Internal/AeroClient.client.lua +++ b/src/StarterPlayer/StarterPlayerScripts/Aero/Internal/AeroClient.client.lua @@ -171,13 +171,28 @@ local function Init() -- Initialize controllers: local function InitAllControllers(controllers) - for _,controller in pairs(controllers) do - if (getmetatable(controller) == mt) then - InitController(controller) - else - InitAllControllers(controller) + -- Collect all controllers: + local controllerTables = {} + local function CollectControllers(_controllers) + for _,controller in pairs(_controllers) do + if (getmetatable(controller) == mt) then + controllerTables[#controllerTables + 1] = controller + else + CollectControllers(controller) + end end end + CollectControllers(controllers) + -- Sort controllers by optional __aeroOrder field: + table.sort(controllerTables, function(a, b) + local aOrder = (type(a.__aeroOrder) == "number" and a.__aeroOrder or math.huge) + local bOrder = (type(b.__aeroOrder) == "number" and b.__aeroOrder or math.huge) + return (aOrder < bOrder) + end) + -- Initialize controllers: + for _,controller in ipairs(controllerTables) do + InitController(controller) + end end -- Start controllers: