From b23e19ecd4f7a33e6cd03ab53103b65ccf4f8f1d Mon Sep 17 00:00:00 2001 From: M6a5x98 Date: Fri, 19 Sep 2025 00:20:50 +0200 Subject: [PATCH] implement !msg and !help chat commands * Added the !msg and !help command * Started fixing issues * Rewrote !msg processing in chat system * cleanup --------- Co-authored-by: p2r3 --- include/procedures.h | 1 + src/packets.c | 96 +++++++++++++++++++++++++++++++++++++------- src/procedures.c | 16 ++++++++ 3 files changed, 98 insertions(+), 15 deletions(-) diff --git a/include/procedures.h b/include/procedures.h index f3aa331..b7273c8 100644 --- a/include/procedures.h +++ b/include/procedures.h @@ -14,6 +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); +PlayerData *getPlayerByName (int start_offset, int end_offset, uint8_t *buffer); void handlePlayerDisconnect (int client_fd); void handlePlayerJoin (PlayerData* player); void disconnectClient (int *client_fd, int cause); diff --git a/src/packets.c b/src/packets.c index 5cec9d5..cbb1109 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1131,29 +1131,95 @@ int cs_chat (int client_fd) { message_len = 224; } - // Shift message contents forward to make space for player name tag - memmove(recv_buffer + name_len + 3, recv_buffer, message_len + 1); - // Copy player name to index 1 - memcpy(recv_buffer + 1, player->name, name_len); - // Surround player name with brackets and a space - recv_buffer[0] = '<'; - recv_buffer[name_len + 1] = '>'; - recv_buffer[name_len + 2] = ' '; + if (recv_buffer[0] != '!') { // Standard chat message - // Forward message to all connected players - for (int i = 0; i < MAX_PLAYERS; i ++) { - if (player_data[i].client_fd == -1) continue; - if (player_data[i].flags & 0x20) continue; - sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, message_len + name_len + 3); + // Shift message contents forward to make space for player name tag + memmove(recv_buffer + name_len + 3, recv_buffer, message_len + 1); + // Copy player name to index 1 + memcpy(recv_buffer + 1, player->name, name_len); + // Surround player name with brackets and a space + recv_buffer[0] = '<'; + recv_buffer[name_len + 1] = '>'; + recv_buffer[name_len + 2] = ' '; + + // Forward message to all connected players + for (int i = 0; i < MAX_PLAYERS; i ++) { + if (player_data[i].client_fd == -1) continue; + if (player_data[i].flags & 0x20) continue; + sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, message_len + name_len + 3); + } + + goto cleanup; } + // Handle chat commands + + if (!strncmp(recv_buffer, "!msg", 4)) { + + int target_offset = 5; + int target_end_offset = 0; + int text_offset = 0; + + // Skip spaces after "!msg" + while (recv_buffer[target_offset] == ' ') target_offset++; + target_end_offset = target_offset; + // Extract target name + while (recv_buffer[target_end_offset] != ' ' && recv_buffer[target_end_offset] != '\0' && target_end_offset < 21) target_end_offset++; + text_offset = target_end_offset; + // Skip spaces before message + while (recv_buffer[text_offset] == ' ') text_offset++; + + // Send usage guide if arguments are missing + if (target_offset == target_end_offset || target_end_offset == text_offset) { + sc_systemChat(client_fd, "§7Usage: !msg ", 33); + goto cleanup; + } + + // Query the target player + PlayerData *target = getPlayerByName(target_offset, target_end_offset, recv_buffer); + if (target == NULL) { + sc_systemChat(client_fd, "Player not found", 16); + goto cleanup; + } + + // Format output as a vanilla whisper + int name_len = strlen(player->name); + int text_len = message_len - text_offset; + memmove(recv_buffer + name_len + 24, recv_buffer + text_offset, text_len); + snprintf(recv_buffer, sizeof(recv_buffer), "§7§o%s whispers to you:", player->name); + recv_buffer[name_len + 23] = ' '; + // Send message to target player + sc_systemChat(target->client_fd, (char *)recv_buffer, (uint16_t)(name_len + 24 + text_len)); + + // Format output for sending player + int target_len = target_end_offset - target_offset; + memmove(recv_buffer + target_len + 23, recv_buffer + name_len + 24, text_len); + snprintf(recv_buffer, sizeof(recv_buffer), "§7§oYou whisper to %s:", target->name); + recv_buffer[target_len + 22] = ' '; + // Report back to sending player + sc_systemChat(client_fd, (char *)recv_buffer, (uint16_t)(target_len + 23 + text_len)); + + goto cleanup; + } + + if (!strncmp(recv_buffer, "!help", 5)) { + // Send command guide + const char help_msg[] = "§7Commands:\n" + " !msg - Send a private message\n" + " !help - Show this help message"; + sc_systemChat(client_fd, (char *)help_msg, (uint16_t)sizeof(help_msg) - 1); + goto cleanup; + } + + // Handle fall-through case + sc_systemChat(client_fd, "§7Unknown command", 18); + +cleanup: readUint64(client_fd); // Ignore timestamp readUint64(client_fd); // Ignore salt - // Ignore signature (if any) uint8_t has_signature = readByte(client_fd); if (has_signature) recv_all(client_fd, recv_buffer, 256, false); - readVarInt(client_fd); // Ignore message count // Ignore acknowledgement bitmask and checksum recv_all(client_fd, recv_buffer, 4, false); diff --git a/src/procedures.c b/src/procedures.c index 4048bba..7bc5d9d 100644 --- a/src/procedures.c +++ b/src/procedures.c @@ -125,6 +125,22 @@ int getPlayerData (int client_fd, PlayerData **output) { return 1; } +// Returns the player with the given name, or NULL if not found +PlayerData *getPlayerByName (int start_offset, int end_offset, uint8_t *buffer) { + for (int i = 0; i < MAX_PLAYERS; i ++) { + if (player_data[i].client_fd == -1) continue; + int j; + for (j = start_offset; j < end_offset && j < 256 && buffer[j] != ' '; j++) { + if (player_data[i].name[j - start_offset] != buffer[j]) break; + } + if ((j == end_offset || buffer[j] == ' ') && j < 256) { + return &player_data[i]; + } + } + return NULL; +} + + // 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