- Create server class, that can handle connections and messaging
- Create client class, that can handle connecting to server with ip and port
- Ask player if he wants to create or join server
- if create, then start server and join with client on that
- if join, then join server that is ran somewhere
Minecraft singleplayer can be opened to lan, with just clicking that option. So it is already running singleplayer with server client setup. It works, because latency is basically 0. It adds a bit overhead, but nothing noticeable if done decently.
Coding it
You should definitely run the server in it's own thread.
You handle all the actions with network messages. Instead directly calling (for example) WalkForward(), you would do:
client.SendInput(inputSnapshot);
and in server
while(server.ReadMessages())
Handle(server.messages.next())
////
void Handle(MessageBase message)
{
if(message.readByte() == InputMessageType
HandleInputSnapshot(message);
}
void HandInputSnapshot(..)
{
world.Update(message.getConnection(), message)
server.CreateAndSendWorldStateUpdateMessageForPlayer(message.getConnection());
}
Server would have world state in it and that would have all the objects in the world, their locations, rotations etc. Server calculates each clients local area for objects that they should know and send personal message for each client, worldStateMessage ( or something).
Client would have world state also, but from it's own view. It would not know about all the objects around it, only those that server has sent for it. Client receives worldStateMessages constantly, something like 20 times per second.
With this kind of system, you would not send "DestroyBlockXY", but "Client X targeted xyz and clicked mouse 1". When server would receive previous message, it would execute that action in it's own world model. It would notify other clients, that "Client X just targeted xyz and clicked mouse 1. Then clients would pick up this message ( if its in their local area) and update their view of the world, to mirror servers world.
As you see, you can't just plug server client model in. You have to code your game around it. But when done like this, you can play on local server or internet server, using exactly the same code.