Collaborative online editing of 3D world using Castle Game Engine and mORMot2

Posted on

Castle Game Engine and mORMot 2
Castle Game Engine and mORMot 2
Castle Game Engine and mORMot 2

We’re happy to announce a new demo project, showcasing our Castle Game Engine and mORMot 2 working together!

mORMot (1 and 2) is an open-source Pascal framework (just like our engine!) providing networking and database solutions, at a few layers. You can use it for ORM (easily synchronize and persist objects), classic client-server (HTTP REST communication), peer-to-peer communication (like WebSockets), database access and many other things.

We present a demo showcasing that Castle Game Engine and mORMot 2 can cooperate seamlessly, and together achieve something really cool:

https://github.com/castle-engine/castle-and-mormot-collaborative-editing/

The demo presents a collaborative editing of 3D world. Features:

  • Multiple clients can edit a 3D world online.
  • It’s synchronized using ORM with a server.
  • The server in turn stores the world contents in a database (so it survives server restarts).
  • Each client can add, remove, modify (move, rotate, scale) 3D objects in the world.
  • The changes are immediately visible to all other clients.
  • mORMot 2 takes care of all the network communication and database persistence.
  • Castle Game Engine takes care of displaying: showing and updating the 3D world, allowing user to move/rotate/scale by nice gizmos (using CastleTransformManipulate), allowing camera movement in 3D.

Instructions to build and run the demo are in the README file. You will need the latest Castle Game Engine and mORMot 2. Latest versions, from GIT master branches of both projects, have been tested today.

In related news, we have recently updated our URL and networking documentation, and this was a great moment to mention mORMot at the latter. Check out new:

Enjoy, and as always — any feedback is welcome!

Notable Replies

  1. I have been busy on other fronts, but wanting to get back to my game and move terrain handling into a client/server setup with a terrain server. I was just investigating what CGE had to offer for network and saw the indy code, and then you posted this. It looks mORMot has similar but more capabilities than indy?

  2. Hm, I think the answer is complicated :slight_smile:

    There is some overlap in what they (Indy and mORMot) offer, e.g. they both can give you HTTP client and server. But there are also some differences:

    • Indy focus is on components that expose various network protocols.

      So aside from HTTP, you can find there components for lower-level socket communication (over TCP or UDP), but also for other protocols like SMTP, FTP. You can use Indy for things like developing custom Internet protocols (maybe only for your own client/server), in a way this is also what our CastleClientServer messages using Indy do. Or doing things like sending / receiving emails, as it seems to have full SMTP, POP3, IMAP support (3 protocols important for email).

      I see their website summarizes this, and matches what I say above: Indy – Internet Direct

      Indy is an open source client/server communications library that supports TCP/UDP/RAW sockets, as well as over 100 higher level protocols including SMTP, POP3, IMAP, NNTP, HTTP, FTP, and many more. Indy is written in Delphi but is also available for C++Builder and FreePascal.

    • mORMot provides a ton of things (see GitHub - synopse/mORMot2: OpenSource RESTful ORM/SOA/MVC ToolBox for Delphi and FreePascal for description), but I think the summary would be: you probably want to do networking, using HTTP REST (clients query server) or WebSockets (client-server communication channel open), with database underneath.

      The way I see it, mORMot provides some “higher-level features” that are amazing and indeed not present in Indy (because they are outside of scope of Indy), the main one being ORM (to easily synchronize classes, across network and persist to database).

      From what I can see, you can also use mORMot “lower-level”, by just choosing some pieces. But these “lower level pieces” are different pieces than Indy :slight_smile: E.g. I’m not sure whether mORMor has “raw socket send/receive” (it does seem more focused on higher level communication over HTTP / WebSockets). OTOH, mORMot has a lot of useful things that are outside of “only networking” stuff – it has databases, JSON, cryptography, serialization…

    I admittedly don’t dare to make a full comparison between these 2 projects, as they are both large projects, and I’m sure that in my usage, I just scratched their surface :slight_smile:

    I am definitely impressed by what mORMot enabled in GitHub - castle-engine/castle-and-mormot-collaborative-editing: Collaborative editing of 3D world using Castle Game Engine and mORMot2 . In this case, it would be impossible with Indy (or, rather: it would require a lot of work on top of Indy, to communicate object state, and to add database persistence; these things were zero work when using mORMot).

    And I know mORMot (first mORMot 1, now 2) is very actively developed, for many years now. And it is used by various Pascal companies (which bodes well for the project, you can expect it will remain active for a long time). In fact, part of the GitHub - castle-engine/castle-and-mormot-collaborative-editing: Collaborative editing of 3D world using Castle Game Engine and mORMot2 demo development was sponsored by a company (same company that sponsored IFC support in our engine) that is interested in using both mORMot and CGE for a long term. So, expect more cooperation between CGE and mORMot in the future :slight_smile:

  3. My first thought was “What if 2 people select and try to manipulate the same object?” :thinking: But it’s something desired in co-op games where more people can mine the same resource deposit.

    I understand the example is meant to be simple, and I thank you for that. When I checked the “readme”, I saw that it’s pulling all the time, and you shared some thoughts on optimising it.

    I see you use the revision to hint changes. However, that means the client has to check for every single object’s revisions. If you used a time stamp, the client could query “where last_updated > my_last_check” to get it all at once.

    I assume that games use at least a thousand editable objects. Similarly, engineers working on an architectural project would use more than a few assets. Using revisions to determine the last real-time change would be inefficient. I still like the idea of having the revisions, just not for this purpose.

    Also, when real-time tracking is enabled, the database table needs updating while the user keeps moving/rotating/scaling the object - only to increment the revision. I believe the revision should be updated only when the editing is finished, otherwise the number would get super-inflated. I’d rather use a memory-based temporary table that holds only selected objects (including area-of-effect game mechanics) and updates the main table when editing is done (object selection changes, client logs out, etc). This way, the “last_updated” could be updated many times per second. But that’s a whole different story.

  4. Oh, I agree, and these are valid ways to improve the polling – “where last_updated > my_last_check” would be nice.

    But the real solution is IMHO just WebSockets communication which gives ability to communicate from server → client the moment when something has changed. Then there’s no need to maintain any additional data like revision or last change time. I attended a lecture yesterday about mORMot (Pascal Cafe 2025, I also made a presentation about Castle Game Engine – slides here, full news post soon) where this scenario was explicitly mentioned, i.e. WebSockets are the solution in mORMot when you want server to be able to notify client.

    So my recommendation in README was correct :slight_smile: GitHub - castle-engine/castle-and-mormot-collaborative-editing: Collaborative editing of 3D world using Castle Game Engine and mORMot2

    I deliberately decided to keep this part of the example simple, so I think I’ll keep existing polling mechanism. An alternative version of the example (alternative client/server, maybe toggled using {$ifdef xxx} or some const UseWebSockets = false/true in shared unit) using WebSockets, and thus solving it “completely”, would be welcome if someone wants to make a PR :slight_smile:

Continue the discussion at Castle Game Engine Forum

Participants

Avatar for DiggiDoggi Avatar for edj Avatar for michalis