mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
chore: housekeeping
This commit is contained in:
parent
3134136e70
commit
c842926abe
6 changed files with 44 additions and 36 deletions
40
README.md
40
README.md
|
|
@ -640,25 +640,19 @@ return {
|
|||
}
|
||||
```
|
||||
|
||||
When a player joins on the server, call `server.addSignalsToClient` with the keyed signals that the client should receive updates for. Once they leave, call `server.removeClient` to unsubscribe them from all updates.
|
||||
When a player notifies the server that they're ready to start syncing, call `server.addSignalsToClient` with the signals that the client should receive updates for. Once they leave, call `server.removeClient` to unsubscribe them from all updates.
|
||||
|
||||
Then, use `server.connect` to specify how state updates should be sent to each client. Pass a callback function that fires a remote with the given target player and the state updates they subscribed to.
|
||||
Then, use `server.connect` to specify how state updates should be sent to each client. Pass a callback function that fires a remote with the given target player and the state updates they subscribed to:
|
||||
|
||||
```luau
|
||||
local function onPlayerAdded(player: Player)
|
||||
-- Add signal getters, computed signals, atoms, or reactive objects
|
||||
playerReadyEvent.OnServerEvent:Connect(function(player)
|
||||
-- Sync signal getters, computed signals, atoms, or reactive proxies
|
||||
server.addSignalsToClient(player, {
|
||||
name = nameStore.getName,
|
||||
surname = nameStore.getSurname,
|
||||
age = nameStore.ageAtom,
|
||||
})
|
||||
end
|
||||
|
||||
for _, player in Players:GetPlayers() do
|
||||
onPlayerAdded(player)
|
||||
end
|
||||
|
||||
Players.PlayerAdded:Connect(onPlayerAdded)
|
||||
end)
|
||||
|
||||
Players.PlayerRemoving:Connect(function(player)
|
||||
server.removeClient(player)
|
||||
|
|
@ -671,7 +665,7 @@ end)
|
|||
```
|
||||
|
||||
> [!NOTE]
|
||||
> On the server, make sure each key corresponds to the same signal across all players. If two players subscribe to the same key, but were given different signals, Charm will output a warning.
|
||||
> On the server, make sure each key corresponds to the same data across all players. If two players subscribe to the same key, but were given different signals, Charm will output a warning.
|
||||
|
||||
To sync the client with the server's state, call `client.addSignals` with a table of writable signals (setter functions or atoms) whose keys match their server counterparts.
|
||||
|
||||
|
|
@ -701,8 +695,8 @@ A configuration table that customizes the behavior of Charm Sync on the server.
|
|||
| --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| interval | `0` | The frequency at which the server will send patches to the client, in seconds. A value of `0` sends updates on the next frame. Set to a negative value to disable the interval. |
|
||||
| preserveHistory | `false` | Whether to preserve a full history of state changes since the last sync, at the cost of performance. This is useful if you need to replicate each individual change that occurs between sync events. |
|
||||
| fixArrays | `true` | When `true`, Charm will attempt to work around Roblox remote event limitations regarding array patches. Disable this if your networking library serializes remote arguments (Zap, ByteNet, etc.). |
|
||||
| validatePatches | `true` | When `true`, and both `fixArrays` and strict mode are enabled, synced values containing unsafe sparse arrays or mixed tables will throw an error. See the [remote argument limitations](https://create.roblox.com/docs/scripting/events/remote#argument-limitations). |
|
||||
| fixArrays | `true` | When `true`, Charm will attempt to work around remote event limitations that cause data loss in array patches. Disable this if your networking library serializes remote arguments (Zap, ByteNet, etc.). |
|
||||
| validatePatches | `true` | When `true`, and both `fixArrays` and strict mode are enabled, synced values containing unsafe sparse arrays or mixed tables will emit a warning. See the [remote argument limitations](https://create.roblox.com/docs/scripting/events/remote#argument-limitations). |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -713,7 +707,7 @@ The `addSignalsToClient` function subscribes a client to updates in the given si
|
|||
You can pass signal getter functions, computed signals, atoms, and [reactive objects](#reactiveinitialvalue) in the `getters` table. This function can also be called multiple times on the same client to subscribe to new signals.
|
||||
|
||||
```luau
|
||||
Players.PlayerAdded:Connect(function(player)
|
||||
playerReadyEvent.OnServerEvent:Connect(function(player)
|
||||
server.addSignalsToClient(player, {
|
||||
name = nameStore.getName,
|
||||
surname = nameStore.getSurname,
|
||||
|
|
@ -722,14 +716,22 @@ Players.PlayerAdded:Connect(function(player)
|
|||
end)
|
||||
```
|
||||
|
||||
You're also allowed to create new signals to sync to specific players, as long as the key is unique to that player:
|
||||
You're also allowed to create new signals to sync to specific players, as long as the key is unique to that data:
|
||||
|
||||
```luau
|
||||
server.addSignalsToClient(player, {
|
||||
playerReadyEvent.OnServerEvent:Connect(function(player)
|
||||
server.addSignalsToClient(player, {
|
||||
-- 🟢 Good: Player-specific data is synced with a unique key
|
||||
[`data-{player.UserId}`] = computed(function()
|
||||
return getPlayerData(player.UserId)
|
||||
end),
|
||||
})
|
||||
|
||||
-- 🔴 Bad: Syncing different data with the same keys does not work
|
||||
playerData = computed(function()
|
||||
return getPlayerData(player.UserId)
|
||||
end),
|
||||
})
|
||||
end)
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -754,7 +756,7 @@ server.removeSignalsFromClient(player, "surname")
|
|||
The `removeClient` function unsubscribes a client from receiving all state updates from the server. You should call this function when a player leaves the game.
|
||||
|
||||
```luau
|
||||
Players.PlayerAdded:Connect(function(player)
|
||||
playerReadyEvent.OnServerEvent:Connect(function(player)
|
||||
server.addSignalsToClient(player, signals)
|
||||
end)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,22 @@ return {
|
|||
Whether the history of state changes since the client's last update
|
||||
should be preserved. This is useful for values that change multiple
|
||||
times per frame, where each individual change is important. Defaults
|
||||
to `false`.
|
||||
to `false` for performance reasons.
|
||||
]]
|
||||
preserveHistory = false,
|
||||
--[[
|
||||
When `true`, Charm will apply validation and serialize unsafe arrays
|
||||
to address remote event argument limitations. Defaults to `true`.
|
||||
When `true`, Charm will modify sparse arrays to prevent data loss from
|
||||
remote event limitations. When an unsafe array is detected, numeric
|
||||
indices will be converted to string keys so that the array can be sent
|
||||
safely and then converted back to an array on the receiving end.
|
||||
|
||||
This option should be disabled if your network library uses a custom
|
||||
serialization method (i.e. Zap, ByteNet) to prevent interference.
|
||||
]]
|
||||
fixArrays = true,
|
||||
--[[
|
||||
When `true`, synced state containing unsafe sparse arrays or mixed
|
||||
tables will throw an error. Only checked in strict mode and if
|
||||
tables will emit a warning. Only checked in strict mode and if
|
||||
`fixArrays` is enabled. Defaults to `true`.
|
||||
]]
|
||||
validatePatches = true,
|
||||
|
|
|
|||
13
packages/charm-sync/src/index.d.ts
vendored
13
packages/charm-sync/src/index.d.ts
vendored
|
|
@ -78,14 +78,17 @@ export const config: {
|
|||
* Whether the history of state changes since the client's last update
|
||||
* should be preserved. This is useful for values that change multiple
|
||||
* times per frame, where each individual change is important. Defaults
|
||||
* to `false`.
|
||||
* to `false` for performance reasons.
|
||||
*
|
||||
* @server
|
||||
*/
|
||||
preserveHistory: boolean;
|
||||
/**
|
||||
* When `true`, Charm will apply validation and serialize unsafe arrays
|
||||
* to address remote event argument limitations. Defaults to `true`.
|
||||
* When `true`, Charm will modify sparse arrays to prevent data loss from
|
||||
* remote event limitations. When an unsafe array is detected, numeric
|
||||
* indices will be converted to string keys so that the array can be sent
|
||||
* safely and then converted back to an array on the receiving end.
|
||||
*
|
||||
* This option should be disabled if your network library uses a custom
|
||||
* serialization method (i.e. Zap, ByteNet) to prevent interference.
|
||||
*
|
||||
|
|
@ -94,7 +97,7 @@ export const config: {
|
|||
fixArrays: boolean;
|
||||
/**
|
||||
* When `true`, synced state containing unsafe sparse arrays or mixed
|
||||
* tables will throw an error. Only checked in strict mode and if
|
||||
* tables will emit a warning. Only checked in strict mode and if
|
||||
* `fixArrays` is enabled. Defaults to `true`.
|
||||
*
|
||||
* @server
|
||||
|
|
@ -242,7 +245,7 @@ export namespace patch {
|
|||
* @param statePatch The patches to apply.
|
||||
* @returns The new state with the patch applied.
|
||||
*/
|
||||
export function apply<State, FixArrays extends boolean = true>(
|
||||
export function applyImmutable<State, FixArrays extends boolean = true>(
|
||||
currentState: State,
|
||||
statePatch: SyncPatch<State, FixArrays>,
|
||||
): State;
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ end)
|
|||
|
||||
test("recursive effects should run and cleanup in order", function()
|
||||
local a, setA = signal(0)
|
||||
local order = {}
|
||||
local order: { string } = {}
|
||||
|
||||
effect(function()
|
||||
local value = a()
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ end)
|
|||
|
||||
test("should handle recursive additions and removals", function()
|
||||
local items, setItems = signal({ 1 })
|
||||
local edits = {}
|
||||
local edits: { string } = {}
|
||||
|
||||
observe(items, function(item)
|
||||
if item < 5 then
|
||||
|
|
@ -114,7 +114,7 @@ end)
|
|||
|
||||
test("should handle self removal", function()
|
||||
local items, setItems = signal({ 1, 2, 3, 4 })
|
||||
local edits = {}
|
||||
local edits: { string } = {}
|
||||
|
||||
observe(items, function(item, index)
|
||||
setItems(function(state: { number })
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ test("should run in untracked", function()
|
|||
end)
|
||||
|
||||
test("should ensure correct execution order", function()
|
||||
local order = {}
|
||||
local order: { number } = {}
|
||||
local n1, setN1 = signal(0)
|
||||
local n2, setN2 = signal(0)
|
||||
local sum = computed(function()
|
||||
|
|
@ -72,7 +72,7 @@ test("should ensure correct execution order", function()
|
|||
end)
|
||||
|
||||
test("should skip redundant updates", function()
|
||||
local order = {}
|
||||
local order: { "even" | "odd" } = {}
|
||||
local a, setA = signal(0)
|
||||
|
||||
subscribe(function(): "even" | "odd"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue