mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
* build: remove project json files Including Rojo project files in packages interferes with certain Wally packages that depend on roblox-ts packages * build: create project files for release
83 lines
1.8 KiB
Text
83 lines
1.8 KiB
Text
local Charm = require(script.Parent.Parent.Parent.charm)
|
|
local patch = require(script.Parent.patch)
|
|
local types = require(script.Parent.types)
|
|
type AtomMap = types.AtomMap
|
|
type SyncPayload = types.SyncPayload
|
|
|
|
type ClientOptions = {
|
|
--[=[
|
|
The atoms to synchronize with the server.
|
|
]=]
|
|
atoms: AtomMap,
|
|
--[=[
|
|
Whether to ignore patches sent before the client has been hydrated.
|
|
Default is `true`.
|
|
]=]
|
|
ignoreUnhydrated: boolean?,
|
|
}
|
|
|
|
type ClientSyncer = {
|
|
--[=[
|
|
Applies a patch or initializes the state of the atoms with the given
|
|
payload from the server.
|
|
|
|
@param ...payloads The patches or hydration payloads to apply.
|
|
]=]
|
|
sync: (self: ClientSyncer, ...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 ignoreUnhydrated = options.ignoreUnhydrated ~= false
|
|
|
|
local self = {} :: ClientSyncer
|
|
local hydrated = false
|
|
|
|
local function hydrate(state: { [string | number]: any })
|
|
hydrated = true
|
|
|
|
for key, value in next, state do
|
|
local atom = atoms[key]
|
|
atom(value)
|
|
end
|
|
end
|
|
|
|
local function apply(data: { [string | number]: any })
|
|
local target = {}
|
|
|
|
for key, atom in next, atoms do
|
|
target[key] = atom()
|
|
end
|
|
|
|
target = patch.apply(target, data)
|
|
|
|
for key, atom in next, atoms do
|
|
atom(target[key])
|
|
end
|
|
end
|
|
|
|
function self:sync(...)
|
|
for index = 1, select("#", ...) do
|
|
local payload: SyncPayload = select(index, ...)
|
|
|
|
Charm.batch(function()
|
|
if payload.type == "init" then
|
|
hydrate(payload.data)
|
|
elseif not ignoreUnhydrated or hydrated then
|
|
apply(payload.data)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
return client
|