diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6ad5d912..3b64b387 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,9 +25,9 @@ jobs: name: Styling runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: JohnnyMorganz/stylua-action@v3 with: token: ${{ secrets.GITHUB_TOKEN }} - version: v0.18.2 + version: v0.19.1 args: --check ./src diff --git a/.gitignore b/.gitignore index 09d052ac..7751edfb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ Packages/ src/Packages/ src/wally.lock build/ +sourcemap.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cfc64d6..36bfb0d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.0 + +- Add support for UnreliableRemoteEvents (using `Knit.CreateUnreliableSignal()` on server) +- Update dependencies + ## 1.5.3 - Fix incorrect RunService call diff --git a/aftman.toml b/aftman.toml index 4ea77326..e5b8705a 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1 +1 @@ -tools = { rojo = "rojo-rbx/rojo@7.3.0" , wally = "UpliftGames/wally@0.3.2" , selene = "Kampfkarren/selene@0.25.0" , stylua = "JohnnyMorganz/StyLua@0.18.2" , remodel = "rojo-rbx/remodel@0.11.0" } +tools = { rojo = "rojo-rbx/rojo@7.3.0" , wally = "UpliftGames/wally@0.3.2" , selene = "Kampfkarren/selene@0.26.1" , stylua = "JohnnyMorganz/StyLua@0.19.1" , remodel = "rojo-rbx/remodel@0.11.0" } diff --git a/dev.project.json b/dev.project.json new file mode 100644 index 00000000..b2166652 --- /dev/null +++ b/dev.project.json @@ -0,0 +1,12 @@ +{ + "name": "knit-dev", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Knit": { + "$path": "src" + } + } + } +} diff --git a/docs/gettingstarted.md b/docs/gettingstarted.md index d1f00351..9a79dd5d 100644 --- a/docs/gettingstarted.md +++ b/docs/gettingstarted.md @@ -22,7 +22,7 @@ Installing Knit is very simple. Just drop the module into ReplicatedStorage. Kni **Rojo/Wally workflow:** -- Add Knit to your `wally.toml` dependency list (e.g. `Knit = "sleitnick/knit@^1.5"`) +- Add Knit to your `wally.toml` dependency list (e.g. `Knit = "sleitnick/knit@^1.6"`) - Require Knit like any other module grabbed from Wally :::note Wally diff --git a/docs/services.md b/docs/services.md index 773c5bf6..111321e6 100644 --- a/docs/services.md +++ b/docs/services.md @@ -167,9 +167,9 @@ PointsService:GetPoints():andThen(function(points) end) ``` -### Signals (Server-to-Client) +### Events (Server-to-Client) -We should also create a signal that we can fire events for the clients when their points change. We can use `Knit:CreateSignal()` to indicate we want a signal created for the service. +We can use remote signals to fire events from the server to the clients. Continuing with the previous PointsService example, let's create a signal that fires when a client's points change. We can use `Knit:CreateSignal()` to indicate we want a signal created for the service. ```lua local PointsService = Knit.CreateService { @@ -214,7 +214,7 @@ PointsService.PointsChanged:Connect(function(points) end) ``` -### Signals (Client-to-Server) +### Events (Client-to-Server) Signal events can also be fired from the client. This is useful when the client needs to give the server information, but doesn't care about any response from the server. For instance, maybe the client wants to tell the PointsService that it wants some points. This is an odd use-case, but let's just roll with it. @@ -264,6 +264,25 @@ PointsService.GiveMePoints:Fire() See the [ClientRemoteSignal](https://sleitnick.github.io/RbxUtil/api/ClientRemoteSignal) documentation for more info on how to use the ClientRemoteSignal object. ::: +### Unreliable Events + +Knit also supports [UnreliableRemoteEvents](https://create.roblox.com/docs/reference/engine/classes/UnreliableRemoteEvent), which is a special version of RemoteEvent. UnreliableRemoteEvents are, as the name suggests, unreliable. When an event is fired on an UnreliableRemoteEvent, the order and delivery of the event is not guaranteed. The listener of the event may receive the events out of order, or possibly not at all. + +Having unreliable events is useful in scenarios where the data being sent is not crucial to game state. For example, setting the tilt rotation of each avatar's head: if some packets are dropped, this won't affect actual gameplay. The benefit is that unreliable events take up less network bandwidth. + +To create an unreliable event, use `Knit.CreateUnreliableSignal()` within the client table of a service: + +```lua +local MyService = Knit.CreateService { + Name = "MyService", + Client = { + PlayEffect = Knit.CreateUnreliableSignal(), + }, +} +``` + +Using the unreliable signal is the same as normal ones (see the two sections above on events). + ### Properties It is often useful to replicate data to all or individual players. Instead of creating methods and signals to communicate this data, RemoteProperties diff --git a/foreman.toml b/foreman.toml deleted file mode 100644 index 1c3409df..00000000 --- a/foreman.toml +++ /dev/null @@ -1,5 +0,0 @@ -[tools] -selene = { source = "Kampfkarren/selene", version = "x" } -rojo = { source = "rojo-rbx/rojo", version = "7" } -remodel = { source = "rojo-rbx/remodel", version = "0.9.0" } -wally = { source = "UpliftGames/wally", version = "0.3.1" } diff --git a/src/KnitClient.lua b/src/KnitClient.lua index 42043879..ff48976f 100644 --- a/src/KnitClient.lua +++ b/src/KnitClient.lua @@ -110,7 +110,7 @@ KnitClient.Player = game:GetService("Players").LocalPlayer pulled in via Wally instead of relying on Knit's Util folder, as this folder only contains what is necessary for Knit to run in Wally mode. ]=] -KnitClient.Util = script.Parent.Parent +KnitClient.Util = (script.Parent :: Instance).Parent local Promise = require(KnitClient.Util.Promise) local Comm = require(KnitClient.Util.Comm) @@ -131,7 +131,7 @@ end local function GetServicesFolder() if not servicesFolder then - servicesFolder = script.Parent:WaitForChild("Services") + servicesFolder = (script.Parent :: Instance):WaitForChild("Services") end return servicesFolder end diff --git a/src/KnitServer.lua b/src/KnitServer.lua index 2863bc9a..5d1435c9 100644 --- a/src/KnitServer.lua +++ b/src/KnitServer.lua @@ -117,13 +117,18 @@ local KnitServer = {} pulled in via Wally instead of relying on Knit's Util folder, as this folder only contains what is necessary for Knit to run in Wally mode. ]=] -KnitServer.Util = script.Parent.Parent +KnitServer.Util = (script.Parent :: Instance).Parent local SIGNAL_MARKER = newproxy(true) getmetatable(SIGNAL_MARKER).__tostring = function() return "SIGNAL_MARKER" end +local UNRELIABLE_SIGNAL_MARKER = newproxy(true) +getmetatable(UNRELIABLE_SIGNAL_MARKER).__tostring = function() + return "UNRELIABLE_SIGNAL_MARKER" +end + local PROPERTY_MARKER = newproxy(true) getmetatable(PROPERTY_MARKER).__tostring = function() return "PROPERTY_MARKER" @@ -262,6 +267,29 @@ function KnitServer.CreateSignal() return SIGNAL_MARKER end +--[=[ + @return UNRELIABLE_SIGNAL_MARKER + + Returns a marker that will transform the current key into + an unreliable RemoteSignal once the service is created. Should + only be called within the Client table of a service. + + See [RemoteSignal](https://sleitnick.github.io/RbxUtil/api/RemoteSignal) + documentation for more info. + + :::info Unreliable Events + Internally, this uses UnreliableRemoteEvents, which allows for + network communication that is unreliable and unordered. This is + useful for events that are not crucial for gameplay, since the + delivery of the events may occur out of order or not at all. + + See the documentation for [UnreliableRemoteEvents](https://create.roblox.com/docs/reference/engine/classes/UnreliableRemoteEvent) + for more info. +]=] +function KnitServer.CreateUnreliableSignal() + return UNRELIABLE_SIGNAL_MARKER +end + --[=[ @return PROPERTY_MARKER Returns a marker that will transform the current key into @@ -361,7 +389,9 @@ function KnitServer.Start(options: KnitOptions?) if type(v) == "function" then service.KnitComm:WrapMethod(service.Client, k, inbound, outbound) elseif v == SIGNAL_MARKER then - service.Client[k] = service.KnitComm:CreateSignal(k, inbound, outbound) + service.Client[k] = service.KnitComm:CreateSignal(k, false, inbound, outbound) + elseif v == UNRELIABLE_SIGNAL_MARKER then + service.Client[k] = service.KnitComm:CreateSignal(k, true, inbound, outbound) elseif type(v) == "table" and v[1] == PROPERTY_MARKER then service.Client[k] = service.KnitComm:CreateProperty(k, v[2], inbound, outbound) end diff --git a/src/wally.toml b/src/wally.toml index c3c86bbd..766acced 100644 --- a/src/wally.toml +++ b/src/wally.toml @@ -1,11 +1,11 @@ [package] name = "sleitnick/knit" description = "Knit is a lightweight game framework" -version = "1.5.3" +version = "1.6.0" license = "MIT" registry = "https://github.com/UpliftGames/wally-index" realm = "shared" [dependencies] -Comm = "sleitnick/comm@^0.3" +Comm = "sleitnick/comm@^1" Promise = "evaera/promise@^4" diff --git a/src/wally_bundle.toml b/src/wally_bundle.toml index 8160bad6..bc3a1cd8 100644 --- a/src/wally_bundle.toml +++ b/src/wally_bundle.toml @@ -5,12 +5,12 @@ registry = "https://github.com/UpliftGames/wally-index" realm = "shared" [dependencies] -Comm = "sleitnick/comm@^0.3" +Comm = "sleitnick/comm@^1" Component = "sleitnick/component@^2" EnumList = "sleitnick/enum-list@^2" Input = "sleitnick/input@^2" Option = "sleitnick/option@^1" -Signal = "sleitnick/signal@^1" +Signal = "sleitnick/signal@^2" Streamable = "sleitnick/streamable@^1" TableUtil = "sleitnick/table-util@^1" Timer = "sleitnick/timer@^1"