MavonEngine - Single / Multiplayer Game Engine for ThreeJs

Hey everyone,

Been tinkering with this for a while. Its an abstraction to have the main gameloop up and running on the client & server and basic entity synchronization between the two.

The important part here: The threejs scene runs on both the server (headless) and the client (with rendering of course). So the scene can be traversed / queried on the server too for hit detection or anything you need.

Currently have a node 24 demo up and running:

npx @mavonengine/create-bootstrap

Would love some feedback if anyone has time to play around with it.

Threejs game engine

Interesting architecture. Running the same Three.js scene on both client and server is a strong approach for multiplayer because it keeps the world state deterministic and makes things like hit detection, spatial queries, and entity validation much easier on the server side.

Using a headless scene on the server also opens up possibilities for things like authoritative physics, AI simulation, or server side world logic while the client focuses purely on rendering and input.

The entity synchronization layer is probably the most important part in setups like this. If it’s structured well it can scale nicely for multiplayer interactions, prediction systems, and partial scene updates rather than syncing full objects.

I’ve been experimenting with similar browser based environments and world systems built on Three.js where large scenes, entities, and interactions are streamed dynamically.

Example environment
https://theneoverse.web.app/#threeviewer&&crateria

Curious how you’re currently handling things like entity ownership, prediction, and reconciliation between client and server. That part usually becomes the interesting challenge once multiple players interact with the same scene.

2 Likes

Hi @Umbawa_Sarosong im afraid im getting an error on your page so I couldn’t check it out: Uncaught TypeError: The specifier “three” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”.

Thanks! Prediction and reconciliation are definitely on the list and I want it to be abstracted away into the NetworkedEntity as much as possible with some hooks so you can have control over how it is handled with some parameters. Can you explain what you mean by ownership?

I have this engine running in Strain Zero and for proof of concept I have lootable “box” objects spread around the map that players can pick up. On that side its basically just a reliable tcp message that gets sent to the server to say a player clicked on a lootable entity and gets that entity put into their inventory. In that case its whatever packet gets to the server first but the server is in control of it. Not sure if thats what you mean tho?

Hi! Thanks for letting me know about the error

The issue you’re seeing usually happens when the browser can’t resolve the Three.js module import. Some browsers require an import map or a bundled build, otherwise the bare specifier "three" isn’t automatically mapped. I’ll fix that shortly so it works consistently across browsers.

Regarding ownership, what I mean is a system where a specific client temporarily becomes the authoritative controller of a networked entity. For example:

• If a player picks up or interacts with an object, that client becomes the owner of that entity.
• The client can then send movement/state updates for that object.
• The server still validates and reconciles state, but the owner handles most of the frequent updates.

This helps reduce latency and server load, especially for things like physics objects, interactable items, or vehicles. Without ownership, every interaction has to fully round-trip through the server before the client can update anything visually.

Your loot box example actually fits well with server authority. In that case the object state is simple and discrete, so letting the server decide who got it first (like you described with the reliable TCP message) is probably the correct approach.

Where ownership becomes useful is more in cases like:

• moving objects
• physics interactions
• draggable entities
• vehicles or player-controlled world objects

Basically anything where continuous updates would feel laggy if every frame had to wait for server confirmation.

Your approach with NetworkedEntity abstraction sounds really solid by the way. Having hooks so developers can customize reconciliation or prediction behavior is probably the cleanest way to design it.

1 Like