In the "Let's walk it through" section, it seems like the Player-to-LiveView connection will process user input (e.g. a Tic-Tac-Toe move) and update the UI to acknowledge this, at which point the user can be assured that the LiveView server accepted their input. But it seems like this happens before the GameServer has also accepted the input. What if Player 2 made a conflicting play and their change was accepted by the GameServer before Player 1's change reached the GameServer?
Given, in Tic-Tac-Toe, the game is simple enough that this is neatly avoided: each regional LiveView server has enough information to only allow the current player to make a play. But in more complex applications, how might you (anyone; curious for discussion) handle this?
One answer is something like: The LiveView server is effectively producing optimistic updates, and the GameServer would need to produce an authoritative ordering of events and tell the various LiveServers which of the optimistic updates lost a race and should be backed out.
Not sure I understand the question but, I don't see how this would happen.
On the BEAM it's processes all the way down. There's a process for that instance of the game, which is basically a big state machine, and 2 processes representing the client state, one for each player.
When the game (process) starts, it expects a message from player 1 (process), then one from player 2, and so on.
If there's a client timeout or network disconnection, the player process affected crashes, and if the app has been architected well, the other player process and game process are in a supervision tree, so they crash as well, perhaps notifying the other player that the game has ended because of a disconnection from the other peer.
But none of this will accept a move from the player 2 when it's player 1's turn.
This is very interesting - I'm pretty unfamiliar with BEAM. Does this "processes all the way down" span across machines/VMs?
From the article, it seemed like there could be two players, each connecting to different LiveServer instances (on different VMs/hardware in different geographic regions) which in turn communicate async via one central GameServer.
In the article, it seems like a message from Player 1 to LiveServer 1 doesn't need to wait for the message to also reach the central GameServer and be acknowledged before LiveServer 1 acks the change back to Player 1. This seems to allow races, since the central GameServer is the source of truth but the Player1/LiveServer1 communication can complete a message/ack round-trip without waiting for acknowledgement from the GameServer.
I guess an alternative would be for the system to require a message from Player 1 to be passed to LiveServer 1, then passed on to the central Game Server which acks back to LiveServer 1, which finally can ack back to Player 1 -- this means that Player 1 would still need to pay full round-trip latency to LS1 and then to the GameServer for any action.
Thanks for any light you can shed on this!
https://moosecode.nl/blog/how_deltacrdt_can_help_write_distr...
Have you played games like HOMAM 1 or 2? You can't do anything when the CPU is playing its players. You can watch where he goes and what he does but that's it. When he is finished then you go.
When there is a network error - some message or please wait... or loading spinner message should be shown in the meantime.
For turn based RPG games or Chess etc. this is a non issue.
Of course, real time action games etc. is not a good idea for this technology.
It's all done on the server.
I haven't used it yet and am curious about new offerings.
That said, the guide linked from this post requires more config than the competing options.
For example, Render also handles clustered deployment with libcluster setup, and it's very, very simple to set up. http://render.com
Liveview is crazy powerful if you can keep the latency down.
The less latency the better, though, of course. I'm seeing roughly 80ms, which is very good.
Animations are still better off handled client side, though you can go far with web components and liveview updated HTML: https://github.com/hmans/three-elements
Definitely not it's intended use case, but it works perfectly on regular Internet latencies in the 100-300ms ranges.
For example, if you want a 60 fps animation created and the server is far far away, like the other side of the globe that could be an issue or if your connection is bad.
With liveview, you cannot create offline apps without javascript for example. That is a big limitation. But since most apps don't really require offline capabilities that is not really a big issue.
I have however tried to use a liveview hosted in Sweden from Japan (which is basically on the other side of the globe) and I didn't experience any noticable latency for simple html updates.
I think if you're making a game, you'll still need to use javascript. But if you are just making a simple crud app you may not need it for at least most of the stuff.
I still think creating modals or things that the user expects to be instant should perhaps still be done in javascript but for all the server requested data liveview is probably faster than your average SPA.
I couldn't really ask for anything better, as solo dev in less than 100h basic distribution solved(one process per map, one per player. Maps are spread around the erlang cluster using horde, if a map crashes players seeemlesly reconnect in less than a second, and the map may actually be on a whole different system, especially when the node becomes non viable) Basic monster ai, fighting logic. Respawn/monster drops, extensive ddbuggability using observer (gui tool included in erlang, allows me to send messages to processes/see their status/ what they do, maybe kill them in the whole erlang cluster ) Can just use livebooks to do more extensive programming (just connect to cluster, execute a mark down files code blocks, see results live ingame and in the livebook)
It's a very great and easy language for this. I may consider moving couple of things to rust using rustler tho for the fun of learning about nifs
Any chance you mind sharing that code on GitHub?
https://gitlab.com/zen_core/zen_core And u need assets from the original game to use it
I made a small example clip to show how I use livebook to simulate player load(they use exactly the same genserver as real players, just that the packets are already deserialzed )
https://cdn.discordapp.com/attachments/819516082154242048/83...
This is worst case for it, the other maps do not see any load by this and its basically a single core bottleneck, also it's very unoptimized code 500 processes sending messages to a single map process
My first choice was node but the more I use Javascript the more I hate it.
An example:
(FYI there is no actual game here, just pick emojis, place them in the arena and watch them fight to the death via a poorly designed combat system. Yes, those placing emojis other than you are other players.)
This was a prototype that I built to see if real-time multiplayer games were feasible. Apparently LiveView manages high tickrates decently enough to be a valid solution for (quasi) real-time games. This game for example runs at a whopping 8 ticks/s! It can handle more, as I've tried developing with faster tickrates, I think as high as 24 t/s, but I want to avoid server strain. With enough HTML/CSS/SVG wizardry you can get away with quite a lot. But the most amazing thing was the fact that there was no need to fiddle around with state syncing. Everything just works! I have nothing but praise for it.
Try LiveView if you have the chance!
In a nutshell, you compete with other players on creating freestyle piano solos over backing tracks using a MIDI keyboard. Players and audience members then listen through the solos and vote for their favorite.
The Elixir/Phoenix stack has been an absolute superpower for building my game backend. Some examples:
- Phoenix channels as a wonderful abstraction over
managing WS connections. Implementing basic chat took ~3
minutes on the backend.
- The ability to model game logic with a finite state
machine in a GenServer. The lifecycle of a game round is
progressed forward by receiving incoming client events.
- The ability to have many game servers
running simultaneously as a dynamic pool under a
DynamicSupervisor. Games can end and new games can be
created, all isolated and under watchdog-like
supervision.
- ETS as an out-of-the-box memory cache for session data.
Persisting user data between pages and sessions without
needing to deal with an actual persistence layer.
For the curious, the project is called Midi Matches and is currently in public alpha:Game (desktop chromium only): http://midimatches.com/
Gameplay Video: https://www.youtube.com/watch?v=UVD2wOCB_jE&t=41s
LiveView is the nail in that coffin. It doesn’t help that Ember, though I STILL love the technology and framework, is deader than dead community-wise except for a few silos. It’s very tough to find talent. And the benefits just aren’t there anymore compared to using LiveView. I still use ember on about 8 projects but no more.
Have others with this stack reached similar conclusions?
This was well-timed for me - nice to have a reference working config to play around with, especially for clustering. How do you find the BEAM handles a distributed cluster across multiple regions? Are there any oddities that crop up due to inter-site latency?
Can anyone ELI5?