From 5e4462a3bc7915215f5bbd8094553f347b53234c Mon Sep 17 00:00:00 2001 From: p2r3 Date: Sat, 30 Aug 2025 00:14:47 +0300 Subject: [PATCH] broadcast disconnecting players --- include/procedures.h | 2 +- src/main.c | 11 +++++------ src/procedures.c | 33 +++++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/include/procedures.h b/include/procedures.h index 361d033..e2ed5cd 100644 --- a/include/procedures.h +++ b/include/procedures.h @@ -14,7 +14,7 @@ int getClientIndex (int client_fd); void resetPlayerData (PlayerData *player); int reservePlayerData (int client_fd, uint8_t *uuid, char* name); int getPlayerData (int client_fd, PlayerData **output); -void clearPlayerFD (int client_fd); +void handlePlayerDisconnect (int client_fd); int givePlayerItem (PlayerData *player, uint16_t item, uint8_t count); void spawnPlayer (PlayerData *player); diff --git a/src/main.c b/src/main.c index 96f6234..1bb6107 100644 --- a/src/main.c +++ b/src/main.c @@ -95,17 +95,16 @@ void handlePacket (int client_fd, int length, int packet_id, int state) { // Prepare join message for broadcast uint8_t player_name_len = strlen(player->name); - char join_message[16 + player_name_len]; - strcpy(join_message, player->name); - strcpy(join_message + player_name_len, " joined the game"); + strcpy((char *)recv_buffer, player->name); + strcpy((char *)recv_buffer + player_name_len, " joined the game"); // Register all existing players and spawn their entities, and broadcast // information about the joining player to all existing players. for (int i = 0; i < MAX_PLAYERS; i ++) { if (player_data[i].client_fd == -1) continue; - if (player_data[i].flags & 0x20) continue; + if (player_data[i].flags & 0x20 && player_data[i].client_fd != client_fd) continue; sc_playerInfoUpdateAddPlayer(client_fd, player_data[i]); - sc_systemChat(player_data[i].client_fd, join_message, 16 + player_name_len); + sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, 16 + player_name_len); if (player_data[i].client_fd == client_fd) continue; sc_playerInfoUpdateAddPlayer(player_data[i].client_fd, *player); sc_spawnEntityPlayer(client_fd, player_data[i]); @@ -449,7 +448,7 @@ void disconnectClient (int *client_fd, int cause) { if (*client_fd == -1) return; client_count --; setClientState(*client_fd, STATE_NONE); - clearPlayerFD(*client_fd); + handlePlayerDisconnect(*client_fd); close(*client_fd); *client_fd = -1; printf("Disconnected client %d, cause: %d, errno: %d\n\n", *client_fd, cause, errno); diff --git a/src/procedures.c b/src/procedures.c index ec64e76..a2cbf94 100644 --- a/src/procedures.c +++ b/src/procedures.c @@ -106,17 +106,34 @@ int getPlayerData (int client_fd, PlayerData **output) { return 1; } -void clearPlayerFD (int client_fd) { +// Marks a client as disconnected and cleans up player data +void handlePlayerDisconnect (int client_fd) { + // Search for a corresponding player in the player data array for (int i = 0; i < MAX_PLAYERS; i ++) { - if (player_data[i].client_fd == client_fd) { - player_data[i].client_fd = -1; - for (int j = 0; j < VISITED_HISTORY; j ++) { - player_data[i].visited_x[j] = 32767; - player_data[i].visited_z[j] = 32767; - } - break; + if (player_data[i].client_fd != client_fd) continue; + // Mark the player as being offline + player_data[i].client_fd = -1; + // Reset their recently visited chunk list + for (int j = 0; j < VISITED_HISTORY; j ++) { + player_data[i].visited_x[j] = 32767; + player_data[i].visited_z[j] = 32767; } + // Prepare leave message for broadcast + uint8_t player_name_len = strlen(player_data[i].name); + strcpy((char *)recv_buffer, player_data[i].name); + strcpy((char *)recv_buffer + player_name_len, " left the game"); + // Broadcast this player's leave to all other connected clients + for (int j = 0; j < MAX_PLAYERS; j ++) { + if (player_data[j].client_fd == client_fd) continue; + if (player_data[j].flags & 0x20) continue; + // Send chat message + sc_systemChat(player_data[j].client_fd, (char *)recv_buffer, 14 + player_name_len); + // Remove leaving player's entity + sc_removeEntity(player_data[j].client_fd, client_fd); + } + break; } + // Find the client state entry and reset it for (int i = 0; i < MAX_PLAYERS * 2; i += 2) { if (client_states[i] == client_fd) { client_states[i] = -1;