forked from EXTERNAL/bareiron
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:
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user