Releases: cuhHub/Noir
Noir 1.14.0
📚 Details
Version: 1.14.0
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
A decently large update update, woohoo.
Additions
-
Added
OnSit
andOnUnsit
events to thePlayerService
. -
The project manager tool now adds example services and libraries.
-
Added an
OnBodyDamage
event to theVehicleService
. AnOnDamage
event has been added to theNoirBody
class too. As the name suggests, this event is fired when the body takes damage. -
Added
:SpawnExplosion()
method to theObjectService
. This method doesn't return an object, just purely spawns an explosion. -
RecognizedIDs
inPlayerService
'sg_savedata
table is now cleared when players are loaded to preventg_savedata
build-up. -
Added a task types system to the
TaskService
. This allows you to create tasks that trigger differently. For example, time tasks are triggered byserver.getTimeMillisec()
, while tick tasks are triggered by total ticks. This additions comes with new methods::SecondsToTicks()
,:TicksToSeconds()
,:AddTimeTask()
and:AddTickTask()
. Unfortunately, this addition deprecates:AddTask()
which will be removed in a future update, please use:AddTimeTask()
instead.Rule of thumb: For precision, use
:AddTickTask()
. For time accuracy, use:AddTimeTask()
.It is also important you use the new
DeltaTicks
attribute ofTaskService
in calculations in tasks being ran in a task that uses ticks to account for time speeding up (eg: when all players sleep).
local last = Noir.Services.TaskService:GetTimeSeconds()
local time = 0
Noir.Services.TaskService:AddTickTask(function()
local now = Noir.Services.TaskService:GetTimeSeconds()
time = time + ((now - last) * Noir.Services.TaskService.DeltaTicks)
last = now
print(("%.1f seconds passed"):format(time))
end, 1, nil, true) -- This task is repeating every tick
- Added
Deprecation
, a new built-in library. This library allows you to mark functions as deprecated.
---@deprecated <-- for intellisense. recommended to add
function HelloWorld()
Noir.Libraries.Deprecation:Deprecated("HelloWorld", "AnOptionalReplacementFunction", "An optional note appended to the deprecation message")
print("Hello World")
end
HelloWorld()
-- [Noir] [Warning] [Deprecated] 'HelloWorld' is deprecated. Please use 'AnOptionalReplacementFunction' instead.
-- [Noir] [Warning] [Deprecated] An optional note appended to the deprecation message
- Added
RawTPS
toTPSService
. This is simply the TPS divided by the amount of ticks peronTick
call.
Changes
- Notification methods in
NotificationService
now acceptnil
for theplayer
parameter - The project manager tool now places
main.lua
into asrc
folder - Players, objects, etc, are now loaded before
Noir.Started
is fired. This means you can now fetch something like the host player directly inNoir.Started
instead of having to wait a tick or wait for an event likePlayerService
'sOnJoin
event. - Event argument descriptions are now consistent across Noir. Example:
Arguments: player (NoirPlayer), vehicle (NoirVehicle)
- IDs in classes like
NoirPlayer
andNoirObject
are now converted to integers sinceg_savedata
turns integers into floats. Noir.Libraries.JSON:Decode()
no longer errors if the string to decode is invalid JSON. This change was made because HTTP request responses, a commonly JSON-decoded thing, are unpredictable and can sometimes not be JSON-decoded due to invalid JSON, etc. Especially with the lack of apcall
function in SW Lua for error handling, the errors just weren't needed.
Fixes
- Fixed
NoirMessage
serialization regarding the recipient.
Removals
- Removed unnecessary duplicate
:_LoadSavedMessages()
call inMessageService
that may have caused issues.
Noir 1.13.1
📚 Details
Version: 1.13.1
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
Quick hotfix for the project manager tool.
Fixes
- Fixed error during project creation.
- Fixed combiner tool being placed into a
.py
file instead of a.exe
file. - Fixed invalid combiner tool destination created by the project manager.
Noir 1.13.0
📚 Details
Version: 1.13.0
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
This update comes with more services, notably the VehicleService
. All of these services internally persist across reloads so you don't need to worry about saving vehicles, etc.
Additions
- Added a new
VehicleService
. Along with this, two new classes have been added:NoirBody
andNoirVehicle
.NoirVehicle
represents a Stormworks vehicle group, whileNoirBody
represents a vehicle in a vehicle group.- Vehicle data persists in the service across reloads and world exits. The service handles all the hard bits for you. :-)
---@param body NoirBody
Noir.Services.VehicleService.OnBodyLoad:Connect(function(body)
-- Set tooltip
body:SetTooltip("#"..body.ID)
-- Empty all tanks
local tanks = body:GetComponents().components.tanks
for _, tank in pairs(tanks) do
body:SetTankByVoxel(tank.pos.x, tank.pos.y, tank.pos.z, 0, tank.fluid_type)
end
-- Send notification when the vehicle body despawns
body.OnDespawn:Once(function()
Noir.Services.NotificationService:Error("Body Despawned", "A vehicle body belonging to you despawned!", body.Owner)
end)
end)
- Added a new service,
MessageService
. This service keeps tracks of messages sent by your addon or players. Messages persist across reloads and world exits.
---@param message NoirMessage
Noir.Services.MessageService.OnMessage:Connect(function(message)
Noir.Libraries.Logging:Info("Message", "(%s) > %s (%s)", message.Title, message.Content, message.IsAddon and "Sent by addon" or "Sent by player")
end)
Noir.Services.MessageService:SendMessage(nil, "[Server]", "Hello world!")
- Added
Noir.Libraries.Events.DismissAction
. Returning this in a callback to an event will disconnect the callback from the event. Thanks to Avril112113 for the suggestion!
local MyEvent = Noir.Libraries.Events:Create()
MyEvent:Connect(function()
print("Fired")
return Noir.Libraries.Events.DismissAction
end)
MyEvent:Fire()
-- "Fired"
MyEvent:Fire()
-- N/A
- Added
:IterateOverTicks()
toTaskService
. This method allows you to iterate through a table in chunks ofx
over how ever many needed.
local tbl = {}
for value = 1, 100 do
table.insert(tbl, value)
end
Noir.Services.TaskService:IterateOverTicks(tbl, 10, function(value, currentTick, completed) -- iterate over the table in chunks of 10
print(("%s @ tick %d"):format(value, currentTick))
if completed then
print("Completed!")
end
end)
- Added
:GetTasks()
toTaskService
. This returns all active tasks in theTaskService
. - Added
:GetAITarget()
to theNoirObject
class. This returns aNoirAITarget
class object containing the vehicle, character, and/or position the character AI is targeting. - Added
:SetAIPositionTarget()
to theNoirObject
class. - Added
:StartsWith()
and:EndsWith()
to the built-in string library. - Added
:GetPlayerByCharacter()
to thePlayerService
. This allows you to retrieve a player by their character (duh). - Added a new project manager tool for easily creating addons with Noir. See the documentation for more info.
Fixes
- Fixed "Invalid key to 'next'" error with nested tasks in
TaskService
.
Changes
- API reference automation now updates
SUMMARY.md
meaning the API reference docs will actually be shown. Doubles as a fix. - Renamed all libraries to
[LibraryName]Library
, eg:NoirHTTP
-->HTTPLibrary
Removals
- Removed
Noir.Services.ObjectClass:SetAIVehicleTarget()
. It has been replaced by:SetAIBodyTarget()
instead.
Noir 1.12.0
📚 Details
Version: 1.12.0
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
More features!! 🥳
Additions
- Added an
:EnsuredLoad()
method to theNoirService
class. This method is similar toNoirService:Load()
, but if the value retrieved doesn't exist, the default value passed to the method is saved and then returned.
-- Instead of:
function Service:ServiceInit()
local value = self:Load("MyValue", 0)
self:Save("MyValue", value)
end
-- You can do:
function Service:ServiceInit()
local value = self:EnsuredLoad("MyValue", 0)
-- And to show the value is 100% saved:
value = self:Load("MyValue")
print(value) -- 0
end
- Added a new service,
HTTPService
. As the name suggests, this service allows you to send HTTP requests the Noir way. 😎
Noir.Services.HTTPService:GET("/items/5", 8000, function(response)
if not response:IsOk() then
return
end
local item = response:JSON()
Noir.Libraries.Logging:Info("Item", item.Name)
end)
- The API reference in the documentation is now fully automated. This means the API reference will get updated at the exact same time as new releases.
Fixes
- Fixed the
:Warning()
method of the built-inNotificationService
sending a notification that would more fit an error notification (way too red). The new color now fits a warning color.
Changes
- The combiner tool has been completely remade. The CLI arguments remain the same, so updating should no longer be a biggie. Code matches the standard of Noir's code.
- Services are now initialized and started before
Noir.Started
is fire. Previously, services were only initialized beforeNoir.Started
being fired then started after.⚠️ | This may affect some people who aren't making services correctly. Please ensure that anything that needs to be accessed by the addon is set up in:ServiceInit()
. Things like game event connections or actual service logic can be placed in:ServiceStart()
.
- Changed
_LastTimeSec
to_Last
in the built-inTPSService
.
Removals
- Removed a log message that was displayed when a
g_savedata
table for a service was missing. This always happens when an addon using Noir is loaded for the first time hence the log message removal.
Noir 1.11.0
📚 Details
Version: 1.11.0
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
A bunch of things have been added in this release. All of these additions should not impact your addon whatsoever if you was to update Noir.
Additions
- Added a new library called Dataclasses. This library allows you to easily create classes that represent things but don't need any methods and such. This is inspired by Python's built-in dataclasses module.
local InventoryItem = Noir.Libraries.Dataclasses:New("InventoryItem", {
Noir.Libraries.Dataclasses:Field("Name", "String"),
Noir.Libraries.Dataclasses:Field("Weight", "Number"),
Noir.Libraries.Dataclasses:Field("Stackable", "Boolean")
})
local item = InventoryItem:New("Sword", 5, true)
print(item.Name, item.Weight, item.Stackable)
- Added a
:Remove()
method to theNoirTask
class. This method simply removes the task from the built-in Task Service if the task is registered. - Added
Noir.Libraries.Number:Average()
. This method returns the average of the given numbers.
local numbers = {1, 5, 7}
print(Noir.Libraries.Number:Average(numbers)) -- 4.333...
- Added a new service,
NotificationService
. This is a minimal service that allows you to send customizable notifications to players.
local everyone = Noir.Services.PlayerService:GetPlayers() -- table of players. note that the NotificationService methods accept a player as an argument instead of a table of players
Noir.Services.NotificationService:Info("Title", "Hello, %s!", everyone, "world") -- due to string formatting, the message becomes: "Hello, world!"
- Added a new service,
TPSService
. This service allows your addon to get the TPS of the server, including the average TPS. The service also has support for slowing the game down until a specified TPS is achieved.
local TPS = Noir.Services.TPSService:GetTPS() -- 62.0
local AvgTPS = Noir.Services.TPSService:GetAverageTPS() -- 62.0
Noir.Services.TPSService:SetTPS(30) -- Slows the game down to 30 TPS
- Added an
usePeerIDsAsIndex
argument toNoir.Services.PlayerService:GetPlayers()
. This argument is optional and defaults to false. Setting it as true is very slightly faster however.
print(Noir.Services.PlayerService:GetPlayers(false)) -- false by default, you can leave the argument out. it is optional
{
[1] = NoirPlayer(ID = 5, ...),
...
}
print(Noir.Services.PlayerService:GetPlayers(true))
{
[5] = NoirPlayer(ID = 5, ...),
...
}
Fixes
- Fixed class inheritance not bringing down methods from the parent (if any).
- Fixed incorrect
if
statements within the internal class method:_Descend()
. - Fixed incorrect title for an error message in the logging library.
Changes
- Connections to game events in services are now prefixed by
_
to indicate it is used internally. - Renamed
OnCustomCommand
to_OnCustomCommandConnection
in the built-inCommandService
to stay consistent with other services. - Renamed
OnLoadConnection
to_OnObjectLoadConnection
in the built-inObjectService
. The same was done forOnUnloadConnection
.
Noir 1.10.0
📚 Details
Version: 1.10.0
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
A bunch of things have been added in this release. All of these additions should not impact your addon whatsoever if you was to update Noir.
Additions
- Added
LongDescription
,ShortDescription
, andAuthors
attributes to theNoirService
class. You can optionally fill out these attributes by passing new arguments toNoir.Services:CreateService()
. - Added descriptions and credit to every built-in service and library.
- Added
Noir.Services:RemoveService()
. - Added
:GetSaveData()
method to theNoirService
class. Now you can directly modify the table instead of using:Save()
,:Remove()
and:Load()
. - Added a command example to the comment description of
Noir.Services.CommandService:CreateCommand()
. - Added a
:Notify()
method to the player class. This allows you to easily send notifications to players. - Added
Noir.IsDedicatedServer
. Noir's bootstrapper automatically sets this upon Noir starting. As a result, do not modify this yourself. Treat it as a read-only variable. - Added a basic type checking module to Noir accessible via
Noir.TypeChecking
. - Added type checking to every Noir function and method. This took a while.
- Added
Noir.Services:FormatService()
. This is used in the bootstrapper to display the authors of services that are being initialized/started. It is also used to show whether or not a service is built-in. - Added
:GiveItem()
to theNoirObject
class. This method allows you to give SW characters items, including players.
Fixes
- Fixed
Noir.Services.PlayerService.OnLeave
event being fired for all players whenonDestroy
was called for an addon reload. Unfortunately,OnLeave
doesn't get called at all if players leave because the save was exited, or because players left while your addon errored. This will have to stay the case for now unfortunately.
Changes
- When an object gets unloaded and removed from the game, it is removed from
g_savedata
. This is to prevent memory leaks. - Libraries are now classes instead of raw tables. The above attributes have also been added to the class and can simiarly be filled out by passing new arguments to
Noir.Libraries:Create()
- The
:ServiceInit()
method is no longer mandatory for services. Likewise, warnings will no longer appear if a service doesn't have the:ServiceStart()
method. - If the addon is being ran in a dedicated server, the built-in
PlayerService
will no longer count the server itself as a player. This is another Stormworks quirk that Noir now builds around. :-)
Removals
- Removed unnecessary logging when Noir starts (eg: when an object is loaded from service save data, when a player is loaded from server.getPlayers(), etc).
Noir 1.9.0
📚 Details
Version: 1.9.0
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
This release comes with a few new additions.
Additions
- Added two new libraries,
Noir.Libraries.JSON
andNoir.Libraries.Base64
.- The JSON library allows you to encode Lua objects into JSON strings and vice versa.
- The Base64 allows you to encode strings in Base64 format, and decode Base64 strings into regular strings.
- Added
:IsInteger()
method toNoir.Libraries.Number
. As the name shows, the method returns whether or not the provided number is an integer. - Added return annotation to
Noir.Class
.
Fixes
- Fixed a description typo with a method in
Noir.Services
. - Fixed a description typo with the
NoirService
class.
Noir 1.8.5
📚 Details
Version: 1.8.5
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
💬 Description
This release comes with a few minor additions, changes, and fixes.
Additions
-
Noir:GetVersion()
: This has been added that returns theMAJOR
,MINOR
, andPATCH
from the current Noir version as separate values. -
Noir.Services.GameSettingsService:GetSettings()
: This is simply a method that returns the result ofserver.getGameSettings()
. Exists to keep everything settings-related within the service.
Changes
- A few minor changes have been made to method descriptions to clarify things.
Fixes
-
Noir.Services.GameSettingsService:GetSetting()
: Fixed this method returningnil
if the setting retrieved wasfalse
. -
Noir.Services.GameSettingsService:SetSetting()
: Fixed this method returningnil
and logging an error if the setting name provided was valid but the setting wasfalse
.
Noir 1.8.4
📚 Details
Version: 1.8.4
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.
Noir 1.8.3
📚 Details
Version: 1.8.3
❔ Installation
Check out the documentation for information on how to install and use Noir in your addon.