+ printf("OP_PLAYER_CONNECTED: %d\n", new_client_nr);
+ Error(ERR_NETWORK_CLIENT, "new client %d connected", new_client_nr);
+
+ for (player = &first_player; player; player = player->next)
+ {
+ if (player->nr == new_client_nr)
+ Error(ERR_EXIT, "multiplayer server sent duplicate player id");
+
+ last_player = player;
+ }
+
+ last_player->next = player =
+ checked_malloc(sizeof(struct NetworkClientPlayerInfo));
+ player->nr = new_client_nr;
+ player->name[0] = '\0';
+ player->next = NULL;
+
+ stored_player[new_index_nr].connected = TRUE;
+}
+
+static void Handle_OP_PLAYER_DISCONNECTED()
+{
+ struct NetworkClientPlayerInfo *player, *player_disconnected;
+ int player_nr = (int)buffer[0];
+
+ printf("OP_PLAYER_DISCONNECTED: %d\n", player_nr);
+ player_disconnected = getNetworkPlayer(player_nr);
+ Error(ERR_NETWORK_CLIENT, "client %d (%s) disconnected",
+ player_nr, getNetworkPlayerName(buffer[0]));
+
+ for (player = &first_player; player; player = player->next)
+ if (player->next == player_disconnected)
+ player->next = player_disconnected->next;
+ free(player_disconnected);
+}
+
+static void Handle_OP_START_PLAYING()
+{
+ LevelDirTree *new_leveldir;
+ int new_level_nr;
+ int dummy;
+ unsigned long new_random_seed;
+ char *new_leveldir_identifier;
+
+ new_level_nr = (buffer[2] << 8) + buffer[3];
+ dummy = (buffer[4] << 8) + buffer[5]; /* (obsolete) */
+ 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);
+
+ new_leveldir = leveldir_first;
+ Error(ERR_WARN, "using default level set: '%s'", new_leveldir->identifier);
+ }
+
+ 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]);
+
+ 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]);
+
+ 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)
+ {
+ if (buffer[2] == NETWORK_STOP_BY_PLAYER)
+ Request("Network game stopped by player!", REQ_CONFIRM);
+ else if (buffer[2] == NETWORK_STOP_BY_ERROR)
+ Request("Network game stopped due to internal error!", REQ_CONFIRM);
+ else
+ Request("Network game stopped !", REQ_CONFIRM);
+ }
+
+ game_status = 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 0
+ Error(ERR_NETWORK_CLIENT, "receiving server frame counter value %d [%d]",
+ server_frame_counter, FrameCounter);
+#endif
+
+ 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 && stored_player[i].active ? 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();