Skip to content

Commit b23e19e

Browse files
M6a5x98p2r3
andauthored
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>
1 parent ba86dfd commit b23e19e

3 files changed

Lines changed: 99 additions & 16 deletions

File tree

include/procedures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ int getClientIndex (int client_fd);
1414
void resetPlayerData (PlayerData *player);
1515
int reservePlayerData (int client_fd, uint8_t *uuid, char* name);
1616
int getPlayerData (int client_fd, PlayerData **output);
17+
PlayerData *getPlayerByName (int start_offset, int end_offset, uint8_t *buffer);
1718
void handlePlayerDisconnect (int client_fd);
1819
void handlePlayerJoin (PlayerData* player);
1920
void disconnectClient (int *client_fd, int cause);

src/packets.c

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,29 +1131,95 @@ int cs_chat (int client_fd) {
11311131
message_len = 224;
11321132
}
11331133

1134-
// Shift message contents forward to make space for player name tag
1135-
memmove(recv_buffer + name_len + 3, recv_buffer, message_len + 1);
1136-
// Copy player name to index 1
1137-
memcpy(recv_buffer + 1, player->name, name_len);
1138-
// Surround player name with brackets and a space
1139-
recv_buffer[0] = '<';
1140-
recv_buffer[name_len + 1] = '>';
1141-
recv_buffer[name_len + 2] = ' ';
1142-
1143-
// Forward message to all connected players
1144-
for (int i = 0; i < MAX_PLAYERS; i ++) {
1145-
if (player_data[i].client_fd == -1) continue;
1146-
if (player_data[i].flags & 0x20) continue;
1147-
sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, message_len + name_len + 3);
1134+
if (recv_buffer[0] != '!') { // Standard chat message
1135+
1136+
// Shift message contents forward to make space for player name tag
1137+
memmove(recv_buffer + name_len + 3, recv_buffer, message_len + 1);
1138+
// Copy player name to index 1
1139+
memcpy(recv_buffer + 1, player->name, name_len);
1140+
// Surround player name with brackets and a space
1141+
recv_buffer[0] = '<';
1142+
recv_buffer[name_len + 1] = '>';
1143+
recv_buffer[name_len + 2] = ' ';
1144+
1145+
// Forward message to all connected players
1146+
for (int i = 0; i < MAX_PLAYERS; i ++) {
1147+
if (player_data[i].client_fd == -1) continue;
1148+
if (player_data[i].flags & 0x20) continue;
1149+
sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, message_len + name_len + 3);
1150+
}
1151+
1152+
goto cleanup;
1153+
}
1154+
1155+
// Handle chat commands
1156+
1157+
if (!strncmp(recv_buffer, "!msg", 4)) {
1158+
1159+
int target_offset = 5;
1160+
int target_end_offset = 0;
1161+
int text_offset = 0;
1162+
1163+
// Skip spaces after "!msg"
1164+
while (recv_buffer[target_offset] == ' ') target_offset++;
1165+
target_end_offset = target_offset;
1166+
// Extract target name
1167+
while (recv_buffer[target_end_offset] != ' ' && recv_buffer[target_end_offset] != '\0' && target_end_offset < 21) target_end_offset++;
1168+
text_offset = target_end_offset;
1169+
// Skip spaces before message
1170+
while (recv_buffer[text_offset] == ' ') text_offset++;
1171+
1172+
// Send usage guide if arguments are missing
1173+
if (target_offset == target_end_offset || target_end_offset == text_offset) {
1174+
sc_systemChat(client_fd, "§7Usage: !msg <player> <message>", 33);
1175+
goto cleanup;
1176+
}
1177+
1178+
// Query the target player
1179+
PlayerData *target = getPlayerByName(target_offset, target_end_offset, recv_buffer);
1180+
if (target == NULL) {
1181+
sc_systemChat(client_fd, "Player not found", 16);
1182+
goto cleanup;
1183+
}
1184+
1185+
// Format output as a vanilla whisper
1186+
int name_len = strlen(player->name);
1187+
int text_len = message_len - text_offset;
1188+
memmove(recv_buffer + name_len + 24, recv_buffer + text_offset, text_len);
1189+
snprintf(recv_buffer, sizeof(recv_buffer), "§7§o%s whispers to you:", player->name);
1190+
recv_buffer[name_len + 23] = ' ';
1191+
// Send message to target player
1192+
sc_systemChat(target->client_fd, (char *)recv_buffer, (uint16_t)(name_len + 24 + text_len));
1193+
1194+
// Format output for sending player
1195+
int target_len = target_end_offset - target_offset;
1196+
memmove(recv_buffer + target_len + 23, recv_buffer + name_len + 24, text_len);
1197+
snprintf(recv_buffer, sizeof(recv_buffer), "§7§oYou whisper to %s:", target->name);
1198+
recv_buffer[target_len + 22] = ' ';
1199+
// Report back to sending player
1200+
sc_systemChat(client_fd, (char *)recv_buffer, (uint16_t)(target_len + 23 + text_len));
1201+
1202+
goto cleanup;
11481203
}
11491204

1205+
if (!strncmp(recv_buffer, "!help", 5)) {
1206+
// Send command guide
1207+
const char help_msg[] = "§7Commands:\n"
1208+
" !msg <player> <message> - Send a private message\n"
1209+
" !help - Show this help message";
1210+
sc_systemChat(client_fd, (char *)help_msg, (uint16_t)sizeof(help_msg) - 1);
1211+
goto cleanup;
1212+
}
1213+
1214+
// Handle fall-through case
1215+
sc_systemChat(client_fd, "§7Unknown command", 18);
1216+
1217+
cleanup:
11501218
readUint64(client_fd); // Ignore timestamp
11511219
readUint64(client_fd); // Ignore salt
1152-
11531220
// Ignore signature (if any)
11541221
uint8_t has_signature = readByte(client_fd);
11551222
if (has_signature) recv_all(client_fd, recv_buffer, 256, false);
1156-
11571223
readVarInt(client_fd); // Ignore message count
11581224
// Ignore acknowledgement bitmask and checksum
11591225
recv_all(client_fd, recv_buffer, 4, false);

src/procedures.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,22 @@ int getPlayerData (int client_fd, PlayerData **output) {
125125
return 1;
126126
}
127127

128+
// Returns the player with the given name, or NULL if not found
129+
PlayerData *getPlayerByName (int start_offset, int end_offset, uint8_t *buffer) {
130+
for (int i = 0; i < MAX_PLAYERS; i ++) {
131+
if (player_data[i].client_fd == -1) continue;
132+
int j;
133+
for (j = start_offset; j < end_offset && j < 256 && buffer[j] != ' '; j++) {
134+
if (player_data[i].name[j - start_offset] != buffer[j]) break;
135+
}
136+
if ((j == end_offset || buffer[j] == ' ') && j < 256) {
137+
return &player_data[i];
138+
}
139+
}
140+
return NULL;
141+
}
142+
143+
128144
// Marks a client as disconnected and cleans up player data
129145
void handlePlayerDisconnect (int client_fd) {
130146
// Search for a corresponding player in the player data array

0 commit comments

Comments
 (0)