Live data from Hacker News

Reflect – Multiplayer web app framework with game-style synchronization

rocicorp.dev

71–80 of 159 posts

Re: Reflect – Multiplayer web app framework with game-style synchronization

#72

For reference, this strategy is called "deterministic lockstep" in the gamedev world, and is used especially often in games which have many entities which need their state synced. The canonical example is rtses, which pretty much all use it.

Specifically "Deterministic Rollback", as the clients don't wait for the server's response before displaying the change locally.

For an in-depth explanation, see this excellent GDC talk on its implementation in Mortal Kombat and Injustice 2: https://youtu.be/7jb0FOcImdg

Re: Reflect – Multiplayer web app framework with game-style synchronization

#73

Earlier quoted context omitted.

Is the solution to that, a) [1, 5] or b) [1, , 5] ?

By your example, 5 was marked as deleted, so it would just be [1, ]. Most likely this would be implemented with a single mutator for each element. But if you implemented a "range delete", then it would depend on what the order of arrival was. Notably, the server has to sequence actions somehow, so there isn't going to be an issue of "all actions arriving at the same time". If C arrived last in that case, the new elem…

Whoops, you're right,

Is the solution to that,

a) [1]

or

b) [1, ]

?

>Notably, the server has to sequence actions somehow [...]

Yes, that's my whole point, you have to fallback to something like LLW, and then it's over for the transactional model :P.

Edit: Btw, I'm not trying to be the snarky, pessimistic dude. This kind of models are really interesting and I love working with them. I am just trying to illustrate how things could go awry without much complexity involved.

Re: Reflect – Multiplayer web app framework with game-style synchronization

#74

The demo at the top of the homepage ( https://reflect.net/ ) is a lot of fun. While I was watching, every time the puzzle got completed, people would shake their cursor in excitement, like saying, "yay we did it!!"

There's a visual bug where you can hide pieces of the 'e' behind the completed portions of the 'e' - it doesn't work for other letters because they still show the outline.

Re: Reflect – Multiplayer web app framework with game-style synchronization

#75

I worked extensively on this (also implemented it on JS) about 15 years ago, to escape boredom while on my grandma's place. I wish I had open sourced something, but back then I was a young boy with no ulterior motivations :^). Anyway, I want to comment on this: >For example, any kind of arithmetic just works: Of course, it is extremely trivial to set those up as idempotent operations. >List operations just work: Nope…

You don’t even need to involve deletes; if all of these happen “simultaneously”:

  - client A appends “a” to list L
  - client B appends “b” to list L
  - client C appends “c” to list L
the server will arbitrarily apply the appends in some order, and then send the result back to the clients. But, each of the clients has applied its append locally and is showing those results until it gets different information from the server, so the next time step might be

  - client A thinks L is [“a”]
  - client B thinks L is [“b”]
  - client C thinks L is [“c”]
  - server sends state event to clients saying that L is [“c”,”b”,”a”]

Then when the clients receive the state from the server, I guess they all discard their pending mutations and use the state from the server as their state of the world. But what if each of the three appends results in that client winning the game if their mutation gets applied first? Do all the clients display “you win” for 300ms while waiting for the server’s update?

Re: Reflect – Multiplayer web app framework with game-style synchronization

#76

I worked extensively on this (also implemented it on JS) about 15 years ago, to escape boredom while on my grandma's place. I wish I had open sourced something, but back then I was a young boy with no ulterior motivations :^). Anyway, I want to comment on this: >For example, any kind of arithmetic just works: Of course, it is extremely trivial to set those up as idempotent operations. >List operations just work: Nope…

You don’t even need to involve deletes; if all of these happen “simultaneously”: - client A appends “a” to list L - client B appends “b” to list L - client C appends “c” to list L the server will arbitrarily apply the appends in some order, and then send the result back to the clients. But, each of the clients has applied its append locally and is showing those results until it gets different information from the ser…

You modified the operations, I specifically chose a scenario where User C (in my example) introduces an undecidable situation. Appends are trivial to solve.

>If your answer is like "we just send them the whole array again", this breaks the transactional model (x2).

You also did that, whoops.

Re: Reflect – Multiplayer web app framework with game-style synchronization

#77

The demo at the top of the homepage ( https://reflect.net/ ) is a lot of fun. While I was watching, every time the puzzle got completed, people would shake their cursor in excitement, like saying, "yay we did it!!"

There's a visual bug where you can hide pieces of the 'e' behind the completed portions of the 'e' - it doesn't work for other letters because they still show the outline.

Hm, good point. Thanks!

Re: Reflect – Multiplayer web app framework with game-style synchronization

#78

Earlier quoted context omitted.

There's a visual bug where you can hide pieces of the 'e' behind the completed portions of the 'e' - it doesn't work for other letters because they still show the outline.

Hm, good point. Thanks!

It's very fun to troll other players with, especially that middle bar piece is easy to hide. I've also seen someone play keep-away with the last piece. Just overall very funny how much you can goof off with a simple puzzle!

Re: Reflect – Multiplayer web app framework with game-style synchronization

#79

I worked extensively on this (also implemented it on JS) about 15 years ago, to escape boredom while on my grandma's place. I wish I had open sourced something, but back then I was a young boy with no ulterior motivations :^). Anyway, I want to comment on this: >For example, any kind of arithmetic just works: Of course, it is extremely trivial to set those up as idempotent operations. >List operations just work: Nope…

Hi! Thanks for the thoughtful question.

>List operations just work:

Fair point. Will change. What I really meant here was "(Many) list operations just work" (just like above I said "all kinds of things just work".

> All updates reach the server at the same time. What is the solution to that? Timestamps? Fallback to LLW?

There are a number of issues you might be pointing out, and I'm not sure which one you mean.

In general, you can't use list indexes as identifiers for edit/delete in Reflect because they aren't stable. That's why in this example I commented to use the item itself (if atomic) or more likely a stable ID: https://i.imgur.com/IKzmf0q.png

There is also the potential issue of User C's inserts getting deleted. This seems like a problem at first, but in a realtime collaborative context, nothing can fix this. User C's insert can land just before User A or B's delete. In this case, sync would be correct to delete user C's insert, no matter the protocol. But User C might still be sad. From her perspective, she just wrote something and it got deleted. This is the nature of two humans working in the same place at the same time and potentially having different intentions. For these problems, undo and presence indicators go a long way to avoid these problems through human/social mechanisms.

Re: Reflect – Multiplayer web app framework with game-style synchronization

#80

As someone who's casually been eyeing up CRDTs for two years I've wondered continually what the story for authorization is, and this article seems to suggest (in line with my own understanding) that a CRDT library on its own like Y.js can't really handle applications where mutations need to be checked for authorization because it lacks a central authority (i.e., the server) while Reflect assumes that a server will be…

CRDTs can still involve a server, just not necessarily in the middle of everything. Consider you could have connections authenticated by the server, for one.

E.g., someone connects peer to peer to you and claims some privilege etc., you could use the server to verify their claim.

Also, I don't think CRDT necessarily implies peer to peer, as you can use a central server for message passing, but keep the CRDT model for resolving the current state on both server and client.

Post reply on HN