Given the current state of the game (the one we keep passing around between client and server), I don't think Erlang is a bottleneck in performance for us, and it won't be in the near future.
Keep in mind this state is not that huge and it is yet not distributed, so it is totally possible that at some point Erlang will slow us down. I will keep your comment in mind, thank you!
Edit: currently with the game running at 60fps, there is no bottleneck from the server side. And we call it every 16ms! I should also mention that Erlang's choice has a learning purpose; we want to try to use the game as a way to learn more about OTP and the BEAM.
No AI-based tools were used to make the lore. One of our developers (not me) is more of an intense reader and retro gamer; he was the one chosen to write it.
We haven't touched the distributed part of the game, but our understanding is that when that time comes, it will be easier to use the BEAM approach given that it was made for this purpose.
Given the experience so far, it seems that using Erlang was the correct choice, not only because of the above, but also because Erlang made the server implementation way easier than we thought.
I see now, you are sending messages directly to Erlang server so you don't have to worry about network sockets.
In my experience the issues with Erlang come with working with data structures, records are not flexible and there is not much one can do to abstract the boilerplate.
Having a potentially untrusted client connect to the erlang node as a c_node (which seems to be what zerl does) is not a good idea generally, as connecting that way essentially allows the client to execute arbitrary code on the server.
As far as I can tell, this is not possible at all; the serialization layer (Zerl) cannot send arbitrary code to another node. Now, assuming we implement this, I also think this is not possible due to how the server is designed; based on supervisors and child processes for user sessions.
We recently became aware that you can indeed send tuples that have fixed effects when using the supervisor behavior, so it may be totally possible and probable that one could exploit this vulnerability to some degree in our server. We plan to investigate more about it as we continue to learn more about OTP and the BEAM.
If you're using zerl on the client and plain dist on the server; the question isn't what Zerl can serialize, but what the server will process.
With stock OTP dist, there is no barrier between nodes. Stock OTP runs an rpc server that you can use to send function calls to run, which can include BEAM code to load (or file I/O to do); and even if that's disabled, you can spawn a process to run a function with arguments on a remote node without needing an rpc server at all.
I'm not aware of anyone running a limited dist to allow for untrusted dist clients. But here's an OTP response to a proposal that's pretty clearly a no [1].
It'd be much simpler to put together a custom protocol to communicate between the client and server. You could use Erlang's External Term Format to exchange data if you want, in which case you'd want to do binary_to_term(Binary, [safe]) to prevent creation of new atoms and new function references which can fill up tables and also consider that just because deserializing is safe for the runtime doesn't mean you can trust the client.
Erlang makes it pretty easy to parse sensible things off of network sockets, if you want to go more custom, too. Binary pattern matching is lovely.
Thanks for the ideas and references!
I gotta say, though, that I will be pretty sad if having to write a custom protocol turns out to be the final solution. So much more convenient to use OTP (especially now that we finally have an infinitely extensible serialization library for it; Zerl). I'm shocked such an oversight would exist in a real commercial solution which is the BEAM.
The original application of dist clustering was dual computers in a single telecom switch. There's not really a need for a security barrier in that case; anyone with access to one computer would be expected to have access to the other.
Additional applications for dist have been explored over the years, but most of them involve clustering servers; where a security barrier isn't necessary; although it might be desirable --- I've used dist clusters where some people had access to only certain types of nodes; bypassing access control using dist clustering was certainly a possibility. Bolting security onto something designed without it often is pretty challenging. Especially if you want to keep all the existing applications working.
As another commenter said, OTP messages are meant to be between processes in the same privilege zone. That said, using a custom protcol via a good library can actually bring benefits relative to core OTP stuff.
For example, several of the gRPC libs I've used for Erlang/Elixir are pretty low-cognitive-overhead to use, and they come with all the added gRPC goodies: RPC semantics are described in one place rather than ad-hoc throughout code, protobufs have at least a documented (if not actually good) process for upgrades and backwards compatibility, multilanguage gets easier (even if your second language is just a tiny sliver of "dump protobufs into a database/Jupyter notebook/Rust program occasionally for offline reporting").
To be clear, this isn't a paean to gRPC; most of those features are table stakes for an IDL-driven protocol definition. Just saying that you do get some things in return for giving up the convenience of OTP, if you pick the right tools.
I think this behavior can be fixed by properly using something like `lib_chan`, but we needed something that worked first for our Func Prog Sweden demo.
Indeed a malicious client can craft an brutal kill message as long as it knows the PID a process (either a worker or a supervisor) for instance.
Take a look at Erlang's "parse transforms" which would allow you to implement some syntactic sugar. That's what is used to implement qlc, the query language for ETS/Mnesia - that one adds new semantics to list comprehensions, but you can modify any part of the syntax you want.
Also, Elixir supports macros and infix operator overloading - have you considered using it? If you know Erlang's stdlib and BEAM, switching to Elixir (and back) is almost painless. Not sure which monads you needed, but `with` macro is built-in, and it's a monadic bind for Option types (well, more or less). Adapting it for other monads shouldn't be hard.
For reference (for the "parse transform" approach in Erlang): https://github.com/rabbitmq/erlando - it doesn't look maintained, but it's probably still usable; otherwise, you might get some inspiration from the code :) This also (ab)uses list comprehension syntax:
The main 3D part of the game is now on pause. We'll implement minigames (2D ones) leveraging all the current game's Zig and Erlang pieces. After getting that done, we may return to developing the main game.
Ada Beat Brazil | SEEKING WORK | UTC +2 to UTC -8 | REMOTE ONLY
Ada Beat Brazil, your functional programming partner, made up of developers, engineers, creators, and leaders – the people doing awesome things. Our services include consulting, contracting, and Team-as-a-Service (TaaS).
About: My fascination with computer science, with a focus on functional programming, will settle your project in peace, without any stress, extra working hours, and regret. Regardless of the tool and nature of your company, you will have in your hands something that works, performs great and you will be proud of how maintainable it is. You will want to frame it and hang it on your wall because of its elegance. End the pain. A quick email or chat will do.
SEEKING WORK | Latin America (GMT-3) | REMOTE ONLY
We are a group of developers with professional experience in software development. Although our expertise is in Functional Programming, we can work with whatever you see fit for your project. Your project is great, hence you are anxious about it. Here is the good news: we are here to join your team. Choose Don’t rely on Nulls for dependable software solutions; something that you can rely on. Together, we will conquer the fear of deploying your treasure into the real world. We have the from-first-principles ideas, the tools, and the will to make it work. Take a deep breath: you are one small step away from a brighter digital horizon — even if it is from zero you should not be afraid. The outcome will be pretty, and maintainable enough that you’d like to frame it. The price will be shocking to you (in a positive way) because of the number of developers you will have taking care of your project. What are you waiting for?
You can also check it out a little demo: https://www.youtube.com/watch?v=ejYcWRERetM&t=2758s