After the first milestone I started implementing the network using socket.io. The plan was to just copy most of the client side code and remove the unnecessary parts like graphics and input but this did not turn out as I was hoping.
I quickly realized that I used stuff like Three.js vectors and 3d matrices for the paddle movement. So most of yesterday I spent on changing all that to use the PhysicsJS vectors instead and to use 2d transformations which is faster and which I then moved back to the client.
I created two networkmanagers for both the client and the server: LobbyManager and NetworkSession. Even though the game will not feature a traditional lobby, but instead just place you in the first game available and fill the non-player spots with AI opponents, I still need something that manages all the games, how many spots are available in each game and what players are in what game. This is the responsibility of the LobbyManager on the server side. On the client it just creates a socket and connects to the server. Then when it receives an id for which game it was assigned to it starts the GameManager.
The NetworkSession classes are in charge (to some extent) of the communication between the server and the client in-game. They have functions for sending data to all players in a game or just a specific socket. In other network games I have worked on I usually have a networkmanager which is in charge of sending and receiving all network traffic in which other parts of the game adds data to a queue which will be sent. However socket.io is more event-based: you register for a callback on a certain message and execution of that function is then left to the framework and will be done asynchronously. This has led me to do some stuff that at first look quite bad but as the game takes shape seems like a good solution. For example on client disconnect I have registered two callbacks: one in LobbyManager which removes the socket from all lists and one in Player which resets the player to an AI entity. Another example is player movement for which I register and send only in Player. I have not implemented enough code yet to decide if this will work though.
The stable site will probably stay the same for a few days until I have gotten something working without crashing or freezing.