Multiplayer in SolidJS
Hi,
More of a theoretical question, than a practical one:
How would one best handle various amounts of async messages from a single websocket connection using the solidjs reactivity graph?
As how this case is different a chat room - not really. However any message needs to be made available to any amount of "listeners" within the same dom (so a lot of passing an Accessor to a signal around potentially), and there is also a performance requirement. So it would be nice if any handlers of some event did so in a defferred fashion - as to not have the ui stutter or accidentally handling events linearly rather than concurrently.
Also, I admit I havn't investigated WebWorkers much, would it be possible to dispatch a pool of those for handling events? And is SolidJS able to handle potentially parrallel updates to the graph?
Any input is appreciated. 😄
5 Replies
I dont have experience implementing multiplayer in solid, but there is no such thing as truly parallel updates to signals, as they are synchronously updated on the main thread. An async function can update signals, but it still schedules sync work, so there should be no issues.
An optimization you might do if making a game is to queue these events and handle them per frame in a batch, so you dont schedule more work than necessary.
Alright, well that's good to know. As for your second point - exactly, how would I go about doing that? I mean, you have the stores, but those have eluded me for some time now.
Also, most primitives require the allocation of a new object for them to trigger. Which I'd like to avoid if possible
There are two ways to go about this:
1. You can have a very complex web socket message listener that sets different signals depending on the payload (a bit like a reducer)
2. You use a signal for the message and use memos (so only changes trigger effects) to filter for changes; have early returns with the same value for non-change messages
I prefer the latter, as it allows you to separate concerns better.
Any ideas on getting a queue like structure or could one simply memo the signal individually for all listeners. Also, is it possible to defer memo updates as to ensure that a previous event is handled fully before a listener reacts to a new update?
I see two cases where you could get into trouble:
1. a reactive value (e.g position of other player) is derived from the socket message
{ x: ..., y:..., ...}
.
If you are afraid messages might go out of sync, add an index counter and check inside the memo if the current message comes after the previous.
2. The derivation of a state might be taking longer (is async). Use the createAbortController primitive from the solid-primitives resource package and enjoy automatic aborting whenever a new controller is requested.
Another method is to put a queue in between that holds messages yet not derived.