+ stored_player[index_nr].connected_locally = FALSE;
+ stored_player[index_nr].connected_network = FALSE;
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ char message[100];
+
+ sprintf(message, "Player %d left network server! Network game stopped!",
+ player_nr);
+
+ Request(message, REQ_CONFIRM | REQ_STAY_CLOSED);
+
+ SetGameStatus(GAME_MODE_MAIN);
+
+ DrawMainMenu();
+ }
+ else if (game_status == GAME_MODE_MAIN)
+ {
+ DrawNetworkPlayers();
+ }
+}
+
+static void Handle_OP_START_PLAYING()
+{
+ LevelDirTree *new_leveldir;
+ int new_level_nr;
+ unsigned int new_random_seed;
+ char *new_leveldir_identifier;
+
+ new_level_nr = (buffer[2] << 8) + buffer[3];
+ new_random_seed =
+ (buffer[6] << 24) | (buffer[7] << 16) | (buffer[8] << 8) | (buffer[9]);
+ new_leveldir_identifier = (char *)&buffer[10];
+
+ new_leveldir = getTreeInfoFromIdentifier(leveldir_first,
+ new_leveldir_identifier);
+ if (new_leveldir == NULL)
+ {
+ Error(ERR_WARN, "no such level identifier: '%s'", new_leveldir_identifier);
+
+ stop_network_game = TRUE;
+
+ return;
+ }
+
+ printf("OP_START_PLAYING: %d\n", buffer[0]);
+ Error(ERR_NETWORK_CLIENT,
+ "client %d starts game [level %d from level identifier '%s']\n",
+ buffer[0], new_level_nr, new_leveldir->identifier);
+
+ leveldir_current = new_leveldir;
+ level_nr = new_level_nr;
+
+ TapeErase();
+ LoadTape(level_nr);
+ LoadLevel(level_nr);
+
+ StartGameActions(FALSE, setup.autorecord, new_random_seed);
+}
+
+static void Handle_OP_PAUSE_PLAYING()
+{
+ printf("OP_PAUSE_PLAYING: %d\n", buffer[0]);
+ Error(ERR_NETWORK_CLIENT, "client %d pauses game", buffer[0]);
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ tape.pausing = TRUE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
+ }
+}
+
+static void Handle_OP_CONTINUE_PLAYING()
+{
+ printf("OP_CONTINUE_PLAYING: %d\n", buffer[0]);
+ Error(ERR_NETWORK_CLIENT, "client %d continues game", buffer[0]);
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+ }
+}
+
+static void Handle_OP_STOP_PLAYING()
+{
+ printf("OP_STOP_PLAYING: %d [%d]\n", buffer[0], buffer[2]);
+ Error(ERR_NETWORK_CLIENT, "client %d stops game [%d]", buffer[0], buffer[2]);
+
+ if (game_status == GAME_MODE_PLAYING)
+ {
+ int client_nr = buffer[0];
+ int index_nr = client_nr - 1;
+ struct PlayerInfo *client_player = &stored_player[index_nr];
+ boolean stopped_by_remote_player = (!client_player->connected_locally);
+ char message[100];
+
+ sprintf(message, (buffer[2] == NETWORK_STOP_BY_PLAYER ?
+ "Network game stopped by player %d!" :
+ buffer[2] == NETWORK_STOP_BY_ERROR ?
+ "Network game stopped due to internal error!" :
+ "Network game stopped!"), client_nr);
+
+ if (buffer[2] != NETWORK_STOP_BY_PLAYER || stopped_by_remote_player)
+ Request(message, REQ_CONFIRM | REQ_STAY_CLOSED);
+
+ SetGameStatus(GAME_MODE_MAIN);
+
+ DrawMainMenu();
+ }
+}
+
+static void Handle_OP_MOVE_PLAYER(unsigned int len)
+{
+ int server_frame_counter;
+ int i;
+
+ if (!network_playing)
+ return;
+
+ server_frame_counter =
+ (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | (buffer[5]);
+
+ if (server_frame_counter != FrameCounter)
+ {
+ Error(ERR_INFO, "client and servers frame counters out of sync");
+ Error(ERR_INFO, "frame counter of client is %d", FrameCounter);
+ Error(ERR_INFO, "frame counter of server is %d", server_frame_counter);
+ Error(ERR_INFO, "this should not happen -- please debug");
+
+ stop_network_game = TRUE;
+
+ return;
+ }
+
+ /* copy valid player actions */
+ for (i = 0; i < MAX_PLAYERS; i++)
+ stored_player[i].effective_action =
+ (i < len - 6 ? buffer[6 + i] : 0);
+
+ network_player_action_received = TRUE;
+}
+
+static void HandleNetworkingMessages()
+{
+ unsigned int message_length;
+
+ stop_network_game = FALSE;
+
+ while (nread >= 4 && nread >= 4 + readbuffer[3])
+ {
+ message_length = readbuffer[3];
+ if (readbuffer[0] || readbuffer[1] || readbuffer[2])
+ Error(ERR_EXIT, "wrong network server line length");
+
+ memcpy(buffer, &readbuffer[4], message_length);
+ nread -= 4 + message_length;
+ memmove(readbuffer, readbuffer + 4 + message_length, nread);
+
+ switch (buffer[1])
+ {
+ case OP_BAD_PROTOCOL_VERSION:
+ Handle_OP_BAD_PROTOCOL_VERSION();