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 <p2r3@p2r3.com>
This commit is contained in:
M6a5x98
2025-09-19 00:20:50 +02:00
committed by GitHub
parent ba86dfd927
commit b23e19ecd4
3 changed files with 98 additions and 15 deletions

View File

@@ -14,6 +14,7 @@ int getClientIndex (int client_fd);
void resetPlayerData (PlayerData *player); void resetPlayerData (PlayerData *player);
int reservePlayerData (int client_fd, uint8_t *uuid, char* name); int reservePlayerData (int client_fd, uint8_t *uuid, char* name);
int getPlayerData (int client_fd, PlayerData **output); int getPlayerData (int client_fd, PlayerData **output);
PlayerData *getPlayerByName (int start_offset, int end_offset, uint8_t *buffer);
void handlePlayerDisconnect (int client_fd); void handlePlayerDisconnect (int client_fd);
void handlePlayerJoin (PlayerData* player); void handlePlayerJoin (PlayerData* player);
void disconnectClient (int *client_fd, int cause); void disconnectClient (int *client_fd, int cause);

View File

@@ -1131,29 +1131,95 @@ int cs_chat (int client_fd) {
message_len = 224; message_len = 224;
} }
// Shift message contents forward to make space for player name tag if (recv_buffer[0] != '!') { // Standard chat message
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 // Shift message contents forward to make space for player name tag
for (int i = 0; i < MAX_PLAYERS; i ++) { memmove(recv_buffer + name_len + 3, recv_buffer, message_len + 1);
if (player_data[i].client_fd == -1) continue; // Copy player name to index 1
if (player_data[i].flags & 0x20) continue; memcpy(recv_buffer + 1, player->name, name_len);
sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, message_len + name_len + 3); // 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 <player> <message>", 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 <player> <message> - 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 timestamp
readUint64(client_fd); // Ignore salt readUint64(client_fd); // Ignore salt
// Ignore signature (if any) // Ignore signature (if any)
uint8_t has_signature = readByte(client_fd); uint8_t has_signature = readByte(client_fd);
if (has_signature) recv_all(client_fd, recv_buffer, 256, false); if (has_signature) recv_all(client_fd, recv_buffer, 256, false);
readVarInt(client_fd); // Ignore message count readVarInt(client_fd); // Ignore message count
// Ignore acknowledgement bitmask and checksum // Ignore acknowledgement bitmask and checksum
recv_all(client_fd, recv_buffer, 4, false); recv_all(client_fd, recv_buffer, 4, false);

View File

@@ -125,6 +125,22 @@ int getPlayerData (int client_fd, PlayerData **output) {
return 1; 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 // Marks a client as disconnected and cleans up player data
void handlePlayerDisconnect (int client_fd) { void handlePlayerDisconnect (int client_fd) {
// Search for a corresponding player in the player data array // Search for a corresponding player in the player data array