Noir
  • πŸšΆβ€β™‚οΈIntro
  • πŸ“Tutorials
    • πŸŽ“Starting Noir
    • πŸ“–Libraries
    • πŸ–₯️Services
    • ❔Libraries VS Services
    • πŸ’¬Callbacks
    • πŸ’₯Classes
    • πŸ”ŽDebugging
  • πŸ“šExamples
  • β˜„οΈAPI Reference
    • Bootstrapper
    • Built-Ins
      • Classes
        • AITarget
        • Body
        • Command
        • Connection
        • Event
        • HTTPRequest
        • HTTPResponse
        • Library
        • Message
        • Object
        • Player
        • Service
        • Task
        • TickIterationProcess
        • Tracker
        • Vehicle
        • Widgets
          • MapLabelWidget
          • MapLineWidget
          • MapObjectWidget
          • PopupWidget
          • ScreenPopupWidget
          • Widget
      • Libraries
        • Base64
        • Dataclasses
        • Deprecation
        • Events
        • HTTP
        • JSON
        • Logging
        • Matrix
        • Number
        • String
        • Table
      • Services
        • CommandService
        • GameSettingsService
        • HTTPService
        • MessageService
        • NotificationService
        • ObjectService
        • PlayerService
        • TaskService
        • TPSService
        • UIService
        • VehicleService
    • Callbacks
    • Class
    • Classes
    • Debugging
    • Definition
    • Libraries
    • Noir
    • Services
    • TypeChecking
Powered by GitBook
On this page
  • What Are Services?
  • Built-In Services
  • Creating A Service
  • :ServiceInit()
  • :ServiceStart()
  • Adding Credit
  • What's The Point?
  • Intellisense Support
Edit on GitHub
  1. Tutorials

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.

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:

MyService.lua
local MyService = Noir.Services:CreateService("MyService")

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()

MyService.lua
function MyService:ServiceInit()
    self.Something = true
end

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:

MyService:ServiceInit()

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

: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.

MyService.lua
function MyService:ServiceStart()
    Noir.Callbacks:Connect("onPlayerJoin", function(...)
        server.announce("Server", "A player joined!")
    end)
end

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().

Noir.Services:CreateService(
    "Name", -- The name of your service
    false, -- Whether or not this service is built into Noir. Always have this set to false
    "Short Description", -- A short description of your service
    "Loooongg description", -- A long description of your service
    {"Cuh4"} -- The authors of your service
)

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.

script.lua
-- Unclean. Globals are cluttered.
kickedPlayers = {}
bannedPlayers = {}

function Kick(peer_id)
    server.kickPlayer(peer_id)
    table.insert(kickedPlayers, peer_id)
end

function Ban(peer_id)
    server.banPlayer(peer_id)
    table.insert(bannedPlayers, peer_id)
end
ModerationService.lua
-- Clean. Globals aren't cluttered. Functions are all bundled together in a service.
local ModerationService = Noir.Services:CreateService("ModerationService")

function ModerationService:ServiceInit() 
    self.kickedPlayers = {}
    self.bannedPlayers = {}
end

function ModerationService:Kick(peer_id)
    server.kickPlayer(peer_id)
    table.insert(self.kickedPlayers, peer_id)
end

function ModerationService:Ban(peer_id)
    server.banPlayer(peer_id)
    table.insert(self.bannedPlayers, peer_id)
end

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:

local MyService = Noir.Services:CreateService("MyService")

function MyService:ServiceInit()
    self.something = true
end

function MyService:ServiceStart()
    
end

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

You would add this directly above :CreateService():

---@class MyService: NoirService
---@field something boolean A service attribute

The final result should look like:

---@class MyService: NoirService
---@field something boolean A service attribute
local MyService = Noir.Services:CreateService("MyService")

function MyService:ServiceInit()
    self.something = true
end

function MyService:ServiceStart()
    
end

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

Alternatively, you can also do:

---@class MyService: NoirService
local MyService = Noir.Services:CreateService("MyService")

function MyService:ServiceInit()
    -- A service attribute
    ---@type boolean
    self.something = true
end

function MyService:ServiceStart()
    
end

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

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

PreviousLibrariesNextLibraries VS Services

Last updated 2 months ago

Now, we're not all done. We can optionally add a 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.

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

For intellisense, you'll need this .

method
this
VSCode extension
πŸ“
πŸ–₯️
Page cover image