mirror of
https://github.com/littensy/charm.git
synced 2026-10-23 05:46:27 +00:00
feat: add effect cleanups, add docs (#2)
* docs: update readme * feat: add cleanup function to effects * refactor: move peek function to store module * test: add nested atom check * docs: add doc comments * fix: `effect()` type * refactor: remove divider comment
This commit is contained in:
parent
1a65a4a0de
commit
6a9c580bd7
24 changed files with 805 additions and 76 deletions
|
|
@ -4,13 +4,29 @@ type SyncPayload = types.SyncPayload
|
|||
local patch = require(script.Parent.patch)
|
||||
|
||||
type ClientOptions = {
|
||||
--[=[
|
||||
The atoms to synchronize with the server.
|
||||
]=]
|
||||
atoms: { [string]: Atom<any> },
|
||||
}
|
||||
|
||||
type ClientSyncer = {
|
||||
--[=[
|
||||
Applies a patch or initializes the state of the atoms with the given
|
||||
payload from the server.
|
||||
|
||||
@param payload The patch or hydration payload to apply.
|
||||
]=]
|
||||
sync: (self: ClientSyncer, payload: SyncPayload) -> (),
|
||||
}
|
||||
|
||||
--[=[
|
||||
Creates a `ClientSyncer` object that receives patches from the server and
|
||||
applies them to the local state.
|
||||
|
||||
@param options The atoms to synchronize with the server.
|
||||
@return A `ClientSyncer` object.
|
||||
]=]
|
||||
local function client(options: ClientOptions): ClientSyncer
|
||||
local atoms = options.atoms
|
||||
local self = {} :: ClientSyncer
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
local client = require(script.client)
|
||||
local server = require(script.server)
|
||||
|
||||
--[=[
|
||||
Synchronizes state between the client and server. The server sends patches
|
||||
to the client, which applies them to its local state.
|
||||
]=]
|
||||
return {
|
||||
client = client,
|
||||
server = server,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
local validate = require(script.Parent.validate)
|
||||
|
||||
--[=[
|
||||
A special value that denotes the absence of a value. Used to represent
|
||||
undefined values in patches.
|
||||
]=]
|
||||
local NONE = { __none = "__none" }
|
||||
|
||||
local function diff(prevState: { [any]: any }, nextState: { [any]: any })
|
||||
|
|
|
|||
|
|
@ -8,16 +8,51 @@ local setInterval = require(script.Parent.Parent.utils.setInterval)
|
|||
local patch = require(script.Parent.patch)
|
||||
|
||||
type ServerOptions = {
|
||||
--[=[
|
||||
The atoms to synchronize with the client.
|
||||
]=]
|
||||
atoms: { [string]: Atom<any> },
|
||||
--[=[
|
||||
The interval at which to send patches to the client, in seconds.
|
||||
Defaults to `0` (patches are sent up to once per frame). Set to a
|
||||
negative value to disable automatic syncing.
|
||||
]=]
|
||||
interval: number?,
|
||||
}
|
||||
|
||||
type ServerSyncer = {
|
||||
--[=[
|
||||
Sets up a subscription to each atom that schedules a patch to be sent to
|
||||
the client whenever the state changes. When a change occurs, the `callback`
|
||||
is called with the player and the payload to send.
|
||||
|
||||
Note that the `payload` object should not be mutated. If you need to
|
||||
modify the payload, apply the changes to a copy of the object.
|
||||
|
||||
@param callback The function to call when the state changes.
|
||||
@return A cleanup function that unsubscribes all listeners.
|
||||
]=]
|
||||
connect: (self: ServerSyncer, callback: (player: Player, payload: SyncPayload) -> ()) -> () -> (),
|
||||
--[=[
|
||||
Hydrates the client's state with the server's state. This should be
|
||||
called when a player joins the game and requires the server's state.
|
||||
|
||||
@param player The player to hydrate.
|
||||
]=]
|
||||
hydrate: (self: ServerSyncer, player: Player) -> (),
|
||||
--[=[
|
||||
@deprecated For internal use only.
|
||||
]=]
|
||||
_sendPatch: (self: ServerSyncer, player: Player) -> (),
|
||||
}
|
||||
|
||||
--[=[
|
||||
Creates a `ServerSyncer` object that sends patches to the client and
|
||||
hydrates the client's state.
|
||||
|
||||
@param options The atoms to synchronize with the client.
|
||||
@return A `ServerSyncer` object.
|
||||
]=]
|
||||
local function server(options: ServerOptions): ServerSyncer
|
||||
local atoms = options.atoms
|
||||
local interval = options.interval or 0
|
||||
|
|
@ -42,7 +77,7 @@ local function server(options: ServerOptions): ServerSyncer
|
|||
end)
|
||||
|
||||
state[key] = atom()
|
||||
stateSnapshot[key] = atom()
|
||||
stateSnapshot[key] = state[key]
|
||||
end
|
||||
|
||||
local disconnect = setInterval(function()
|
||||
|
|
@ -51,7 +86,7 @@ local function server(options: ServerOptions): ServerSyncer
|
|||
end
|
||||
|
||||
local diffs = patch.diff(stateSnapshot, state)
|
||||
stateSnapshot = table.clone(state)
|
||||
stateSnapshot = state
|
||||
changed = false
|
||||
|
||||
for _, player in Players:GetPlayers() do
|
||||
|
|
|
|||
|
|
@ -29,6 +29,13 @@ local function isUnsafeTable(object: { [any]: any })
|
|||
return false
|
||||
end
|
||||
|
||||
--[=[
|
||||
Validates a value to ensure it can be synced over a remote event.
|
||||
|
||||
@param value The value to validate.
|
||||
@param key The key of the value in the table.
|
||||
@error Throws an error if the value cannot be synced.
|
||||
]=]
|
||||
local function validate(value: any, key: any)
|
||||
local typeOfKey = type(key)
|
||||
local typeOfValue = type(value)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue