diff --git a/include/packets.h b/include/packets.h index 897c5ae..aa17f2f 100644 --- a/include/packets.h +++ b/include/packets.h @@ -14,6 +14,7 @@ int cs_setHeldItem (int client_fd); int cs_clickContainer (int client_fd); int cs_closeContainer (int client_fd); int cs_clientStatus (int client_fd); +int cs_chat(int client_fd); int sc_loginSuccess (int client_fd, uint8_t *uuid, char *name); int sc_knownPacks (int client_fd); diff --git a/src/main.c b/src/main.c index 7fe4df6..013b9a7 100644 --- a/src/main.c +++ b/src/main.c @@ -111,6 +111,13 @@ void handlePacket (int client_fd, int length, int packet_id) { } break; + case 0x08: + if (state == STATE_PLAY) { + cs_chat(client_fd); + return; + } + break; + case 0x0B: if (state == STATE_PLAY) { if (cs_clientStatus(client_fd)) break; diff --git a/src/packets.c b/src/packets.c index 6fb9de9..1e318fa 100644 --- a/src/packets.c +++ b/src/packets.c @@ -901,6 +901,7 @@ int cs_clientStatus (int client_fd) { return 0; } +// S->C System Chat int sc_systemChat (int client_fd, char* message, uint16_t len) { writeVarInt(client_fd, 5 + len); @@ -916,6 +917,52 @@ int sc_systemChat (int client_fd, char* message, uint16_t len) { } +// C->S Chat +int cs_chat (int client_fd) { + + readString(client_fd); + + PlayerData *player; + if (getPlayerData(client_fd, &player)) return 1; + + size_t message_len = strlen(recv_buffer); + uint8_t name_len = strlen(player->name); + + // To be safe, cap messages to 32 bytes before the buffer length + if (message_len > 224) { + recv_buffer[224] = '\0'; + 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] = ' '; + + // Forward message to all connected players + for (int i = 0; i < MAX_PLAYERS; i ++) { + if (player_data[i].client_fd == -1) continue; + sc_systemChat(client_fd, recv_buffer, message_len + name_len + 3); + } + + 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 + readUint32(client_fd); // Ignore acknowledgement bitmask + readByte(client_fd); // Ignore checksum + + return 0; +} + // S->C Registry Data (multiple packets) and Update Tags (configuration, multiple packets) int sc_registries (int client_fd) {