basically, as-is, my engine is somewhat strongly divided between the client and server.
the client is generally responsible for rendering and user/input.
the server basically runs all the game logic (as well as the world-loading: the world contents are streamed to the client).
for example, player movement physics, ... are run on the server, as well as it managing all the animations, events, ...
so, the player tells the server "I want to move in this direction, and the jump and fire keys are held", then the server does the physics, and hands this back to the client.
basically, the client and server (even in a single player game) largely don't share data directly, but communicate via passing messages.
in my engine, these are lists / "S-Expressions" (sort-of: in engine, the lists are passed directly, and over the network, a compressed binary serialization is used for the lists, rather than the using textual S-Expression syntax).
but, then I was thinking some of the matter of the possibility of a server supporting a potentially larger number of clients:
in this case, it makes a lot more sense for the servers to do a lot less work, and offload more work to the clients (the server then wouldn't so much micro-manage everything, but would instead more serve to facilitate communication between clients).
for example, clients could manage many things on their own:
movement physics; animations frames; ...
then they would tell the server: "hey, I am at this location, currently in this position, ...".
the server then doesn't have to do much with the player besides tell all the other players about their current position.
and, also, this largely eliminates the issue of poor ping-times hindering movement.
possibly, the client could partly also take over responsibility for things like taking damage from the environment (stepping in lava, ...), or possibly even handling non-projectile weapon fire (client fires gun, and then tells the server about any damage inflicted, ...).
however, at the same time, a person doesn't really want to have all this hard-coded in the client, since this could hinder some possibilities from existing in the game logic (say, for example, drivable vehicles are added, but then existing clients may have out-of-date logic, making the client and server versions more of an issue).
luckily, in my case there is a likely solution:
server sends script code to the client, and then client runs this logic as script code.
in this case, the hard-coded parts of the client can remain general, and possibly any client-side game logic can then be treated like resource data.
unclear if better here is using files, or just stuffing code directly via messages (both have possible merits).
IOW: (stuffcode "... big gob of script code ...")
then the glob of code is compiled and executed.
another idle thought is if clients should persistently cache parts of the world they have already seen, such that the server then doesn't have to re-send them every time the same client reconnects to the same server.
a guess here is adding a time-stamp to each voxel chunk, such that the client can tell the server which version of the terrain it currently has, and the server can then re-send any chunks which have changed since then (updating the client to the newest time-stamp), and save having to resend all the nearby terrain every time.
also considering other possible tricks as well, like allowing the game to mostly skip fully decompressing "non-interesting" chunks, ... (say, a chunk which is just solid rock or similar and otherwise completely hidden/blocked inside the terrain, ...).