Skip to content
This repository has been archived by the owner on Jul 31, 2024. It is now read-only.

Commit

Permalink
Merge pull request #237 from Sleitnick/feature/unreliable-events
Browse files Browse the repository at this point in the history
Use unreliable events
  • Loading branch information
Sleitnick authored Nov 30, 2023
2 parents 6a12f89 + fbe4d22 commit bb3c717
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 20 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ Packages/
src/Packages/
src/wally.lock
build/
sourcemap.json
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion aftman.toml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
tools = { rojo = "rojo-rbx/[email protected]" , wally = "UpliftGames/[email protected]" , selene = "Kampfkarren/selene@0.25.0" , stylua = "JohnnyMorganz/StyLua@0.18.2" , remodel = "rojo-rbx/[email protected]" }
tools = { rojo = "rojo-rbx/[email protected]" , wally = "UpliftGames/[email protected]" , selene = "Kampfkarren/selene@0.26.1" , stylua = "JohnnyMorganz/StyLua@0.19.1" , remodel = "rojo-rbx/[email protected]" }
12 changes: 12 additions & 0 deletions dev.project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "knit-dev",
"tree": {
"$className": "DataModel",
"ReplicatedStorage": {
"$className": "ReplicatedStorage",
"Knit": {
"$path": "src"
}
}
}
}
2 changes: 1 addition & 1 deletion docs/gettingstarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 22 additions & 3 deletions docs/services.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions foreman.toml

This file was deleted.

4 changes: 2 additions & 2 deletions src/KnitClient.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
34 changes: 32 additions & 2 deletions src/KnitServer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/wally.toml
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 2 additions & 2 deletions src/wally_bundle.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit bb3c717

Please sign in to comment.