diff --git a/include/packets.h b/include/packets.h index 63d0366..fa0eaa1 100644 --- a/include/packets.h +++ b/include/packets.h @@ -21,6 +21,7 @@ int cs_chat (int client_fd); int cs_interact (int client_fd); int cs_playerInput (int client_fd); int cs_playerCommand (int client_fd); +int cs_playerLoaded (int client_fd); // Clientbound packets int sc_statusResponse (int client_fd); diff --git a/include/procedures.h b/include/procedures.h index 819aa4a..1dde793 100644 --- a/include/procedures.h +++ b/include/procedures.h @@ -15,6 +15,7 @@ void resetPlayerData (PlayerData *player); int reservePlayerData (int client_fd, uint8_t *uuid, char* name); int getPlayerData (int client_fd, PlayerData **output); void handlePlayerDisconnect (int client_fd); +void handlePlayerJoin (PlayerData* player); void disconnectClient (int *client_fd, int cause); 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 cfd24cd..88fc058 100644 --- a/src/main.c +++ b/src/main.c @@ -126,22 +126,13 @@ void handlePacket (int client_fd, int length, int packet_id, int state) { // Send full client spawn sequence spawnPlayer(player); - // Prepare join message for broadcast - uint8_t player_name_len = strlen(player->name); - 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. + // Register all existing players and spawn their entities for (int i = 0; i < MAX_PLAYERS; i ++) { if (player_data[i].client_fd == -1) continue; - if (player_data[i].flags & 0x20 && player_data[i].client_fd != client_fd) continue; + // Note that this will also filter out the joining player + if (player_data[i].flags & 0x20) continue; sc_playerInfoUpdateAddPlayer(client_fd, player_data[i]); - 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]); - sc_spawnEntityPlayer(player_data[i].client_fd, *player); } // Send information about all other entities (mobs) @@ -431,14 +422,9 @@ void handlePacket (int client_fd, int length, int packet_id, int state) { if (state == STATE_PLAY) cs_playerInput(client_fd); break; - case 0x2B: { // Player Loaded - PlayerData *player; - if (getPlayerData(client_fd, &player)) break; - // Clear "client loading" flag and fallback timer - player->flags &= ~0x20; - player->flagval_16 = 0; + case 0x2B: + if (state == STATE_PLAY) cs_playerLoaded(client_fd); break; - } case 0x34: if (state == STATE_PLAY) cs_setHeldItem(client_fd); diff --git a/src/packets.c b/src/packets.c index eb0d448..e712d6b 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1178,6 +1178,18 @@ int sc_pickupItem (int client_fd, int collected, int collector, uint8_t count) { return 0; } +// C->S Player Loaded +int cs_playerLoaded (int client_fd) { + + PlayerData *player; + if (getPlayerData(client_fd, &player)) return 1; + + // Redirect handling to player join procedure + handlePlayerJoin(player); + + return 0; +} + // S->C Registry Data (multiple packets) and Update Tags (configuration, multiple packets) int sc_registries (int client_fd) { diff --git a/src/procedures.c b/src/procedures.c index 2e485b3..f18430e 100644 --- a/src/procedures.c +++ b/src/procedures.c @@ -146,6 +146,29 @@ void handlePlayerDisconnect (int client_fd) { } } +// Marks a client as connected and broadcasts their data to other players +void handlePlayerJoin (PlayerData* player) { + + // Prepare join message for broadcast + uint8_t player_name_len = strlen(player->name); + strcpy((char *)recv_buffer, player->name); + strcpy((char *)recv_buffer + player_name_len, " joined the game"); + + // Inform other clients (and the joining client) of the player's name and entity + for (int i = 0; i < MAX_PLAYERS; i ++) { + sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, 16 + player_name_len); + sc_playerInfoUpdateAddPlayer(player_data[i].client_fd, *player); + if (player_data[i].client_fd != player->client_fd) { + sc_spawnEntityPlayer(player_data[i].client_fd, *player); + } + } + + // Clear "client loading" flag and fallback timer + player->flags &= ~0x20; + player->flagval_16 = 0; + +} + void disconnectClient (int *client_fd, int cause) { if (*client_fd == -1) return; client_count --; @@ -1414,8 +1437,7 @@ void handleServerTick (int64_t time_since_last_tick) { // If 3 seconds (60 vanilla ticks) have passed, assume player has loaded player->flagval_16 ++; if (player->flagval_16 > (uint16_t)(3 * TICKS_PER_SECOND)) { - player->flags &= ~0x20; - player->flagval_16 = 0; + handlePlayerJoin(player); } else continue; } // Reset player attack cooldown