I'm currently thinking about implementing a first prototype of the multiplayer aspect of the game and I've started to restructure parts of the current architecture to support networking more easily. This prototype is very important in my opinion, since any further changes on my list might have a direct influence on the network performance (thinking of multiple depth layers for example) and have to be optimized accordingly.
With the mentioned changes, the forthcoming server application can use an instance of the class LocalWorldProvider to generate worlds (and chunks of course) and the class World is responsible for all the fancy rendering stuff, mapping the player to the world and so on and so on.
My architectural goal is the following: a client application should only differ from the local version in the type of WorldProvider assigned to the World.
To summarize: A local game uses an instance of the class World with an assigned instance of the class LocalWorldProvider as a world provider. A server application works the same way (but the World class can be skipped since no rendering will be needed). The client application will use an instance of World in combination with some kind of new world provider (a RemoteWorldProvider maybe) bound to a remote server. This new provider will manage the requesting of new chunks from the server, applying remote changes sent from the server. The generation of chunks can be split in an arbitrary amount of threads, since the current architecture supports the complete parallelization of the chunk generation process. The goal is to minimize the overall data transferred. If a chunk has not been touched on the server, it can be easily generated locally (to reduce the server load). Modifications of chunks will be transferred in the form of setBlock(x,y,z, 0x66) and the lighting will be calculated locally and so on and so on. Thinking of... Lighting can even be completely ignored on the server, since it can be fully reproduced on the side of the clients. But that's another story.
Any thoughts on this approach?
I also need some ideas regarding the network protocol. I would start using an self-specified protocol using TCP or UDP. But maybe there is a much more sophisticated way that takes away all the hassle? Maybe Rasmus got a good idea here... But wait – I'm sure he has.

With the mentioned changes, the forthcoming server application can use an instance of the class LocalWorldProvider to generate worlds (and chunks of course) and the class World is responsible for all the fancy rendering stuff, mapping the player to the world and so on and so on.
My architectural goal is the following: a client application should only differ from the local version in the type of WorldProvider assigned to the World.
To summarize: A local game uses an instance of the class World with an assigned instance of the class LocalWorldProvider as a world provider. A server application works the same way (but the World class can be skipped since no rendering will be needed). The client application will use an instance of World in combination with some kind of new world provider (a RemoteWorldProvider maybe) bound to a remote server. This new provider will manage the requesting of new chunks from the server, applying remote changes sent from the server. The generation of chunks can be split in an arbitrary amount of threads, since the current architecture supports the complete parallelization of the chunk generation process. The goal is to minimize the overall data transferred. If a chunk has not been touched on the server, it can be easily generated locally (to reduce the server load). Modifications of chunks will be transferred in the form of setBlock(x,y,z, 0x66) and the lighting will be calculated locally and so on and so on. Thinking of... Lighting can even be completely ignored on the server, since it can be fully reproduced on the side of the clients. But that's another story.
Any thoughts on this approach?
I also need some ideas regarding the network protocol. I would start using an self-specified protocol using TCP or UDP. But maybe there is a much more sophisticated way that takes away all the hassle? Maybe Rasmus got a good idea here... But wait – I'm sure he has.