Page cover

πŸ–₯️Services

Services are a fundamental part of Noir. This page will go over them.

What Are Services?

Services, when simplified, are simply tables containing methods you can use throughout your code.

Unlike libraries, services tend to interact with the game and store data within itself or through g_savedata.

Services can utilize one another as well as libraries and classes.

Example:

MyService.lua
local MyService = Noir.Services:CreateService("MyService") -- Create a service

-- Called when the service is initialized. This is to be used for setting up the service
function MyService:ServiceInit()
    self.AVariable = 5
end

-- Called when the service is started. This is to be used for setting up things that may require event connections, etc
function MyService:ServiceStart()
    Noir.Callbacks:Connect("onPlayerJoin", function()
        server.announce("Server", "A player joined!")
    end)
end

function MyService:ACustomMethod()
    server.announce("Server", "Hello World")
end

You probably noticed in the example that there are two strange methods - ServiceInit, and ServiceStart. These methods are strictly for service initialization and are actually quite useful.

Here's a quick rundown:

ServiceInit is called when the service is initialized by Noir after Noir:Start() is called. This method is called just before Noir.Started is fired.

ServiceStart is called when the service is started by Noir after Noir:Start() is called. This method is called straight after Noir.Started is fired.

Both of these methods are optional, but be sure to use ServiceInit if you need to store data within your service, setup things like events, or load data from your service's g_savedata accessible via Service:GetSaveData(), Service:Load(), etc.

Services can be stored as a variable and retrieved at anytime throughout your code, but you can also use Noir.Services:GetService("MyService") to retrieve a service. Note that this method only works if the service has been initialized (always the case after Noir has started).

Built-In Services

Noir comes with built-in services to prevent you from writing a lot of code. They can be found under Noir.Services along with everything else relating to services.

A very notable built-in service is Noir.Services.PlayerService that wraps players in classes to make interacting with players more OOP than not.

Creating A Service

Creating a service is simple. First, you need to give it a name. For this example, we'll assume the name of "MyService". Now, add the following code to your addon:

It is recommended to create a separate .lua file for each service you create. These files can be bundled together into one using the tools provided by Noir or by using the Stormworks Lua VSCode extension.

:ServiceInit()

Now, we're not all done. We can optionally add a method to our service called ServiceInit. This isn't required but is often used to setup events and setup attributes, etc. See the code sample below.

As mentioned under What Are Services?, ServiceInit is called when the service is initialized by Noir's bootstrapper after Noir:Start() is called but before the Noir.Started event is fired. This method is often used to store values in the service for later use.

You may be wondering what self is. Well, :ServiceInit() is a method, and self is automatically added as an argument because of the colon before ServiceInit(). Behind the scenes, Noir calls ServiceInit like so:

Due to the :, Service is passed as the first argument to ServiceInit. This means that self in the example above is equivalent to MyService.

This is known as OOP (Object-Oriented Programming). Check this out for more information.

:ServiceStart()

Optionally, we can add another method to our service called ServiceStart which is called when the service is started by Noir which happens straight after the Noir.Started event is fired.

Noir.Callbacks will be talked about in a future page.

Adding Credit

This is not necessary, but if you would like to add credit to your service for whatever reason, you can add a few extra parameters to :CreateService().

Note that everything beyond the "Name" is optional. See Services.

What's The Point?

Services help you structure your addon neatly. Instead of having 6 functions all in your script environment that interact with the same things but differently, you can bundle all of these functions into a service.

You can see this sort of format in games like Roblox.

Intellisense Support

Intellisense represents code auto-completion, linting, etc.

Services do have support for intellisense, but you do need to put some work into making your service intellisense-compatible.

Assuming your service looks like:

You would add this directly above :CreateService():

The final result should look like:

Alternatively, you can also do:

However if the attribute is clearly defined, you can remove the ---@typedeclaration.

Last updated