Add /roll and friend management commands

Roll Command:
- Add /roll, /random, /rnd commands for random number generation
- Support multiple formats: /roll, /roll 100, /roll 1-100, /roll 10 50
- Broadcasts rolls to party/raid with "[Name] rolls X (min-max)" format
- Cap max roll at 10,000 to prevent abuse
- Use MSG_RANDOM_ROLL (0x1FB) bidirectional opcode

Friend Commands:
- Add /friend add <name>, /addfriend <name> to add friends
- Add /friend remove <name>, /removefriend <name> to remove friends
- Support aliases: /delfriend, /remfriend
- Maintain local friends cache mapping names to GUIDs for lookups
- Display status messages for all friend actions:
  - Friend added/removed confirmations
  - Friend online/offline notifications
  - Error messages (not found, already friends, list full, ignoring)

Social Opcodes:
- Add CMSG_ADD_FRIEND (0x69) and SMSG_FRIEND_STATUS (0x68)
- Add CMSG_DEL_FRIEND (0x6A) for friend removal
- Add CMSG_SET_CONTACT_NOTES (0x6B) for friend notes (future use)
- Add CMSG_ADD_IGNORE (0x6C) and CMSG_DEL_IGNORE (0x6D) (future use)

Implementation:
- Add RandomRollPacket builder and RandomRollParser for roll data
- Add AddFriendPacket and DelFriendPacket builders
- Add FriendStatusParser to handle server friend status updates
- Add friendsCache map to store friend name-to-GUID mappings
- Add handleRandomRoll() and handleFriendStatus() packet handlers
- Comprehensive slash command parsing with multiple formats and aliases
This commit is contained in:
kelsi davis 2026-02-07 12:51:30 -08:00
parent f9c4cbddee
commit 6f45c6ab69
6 changed files with 427 additions and 0 deletions

View file

@ -1230,6 +1230,67 @@ network::Packet WhoPacket::build(uint32_t minLevel, uint32_t maxLevel,
return packet;
}
// ============================================================
// Social Commands
// ============================================================
network::Packet AddFriendPacket::build(const std::string& playerName, const std::string& note) {
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_ADD_FRIEND));
packet.writeString(playerName);
packet.writeString(note);
LOG_DEBUG("Built CMSG_ADD_FRIEND: player=", playerName);
return packet;
}
network::Packet DelFriendPacket::build(uint64_t friendGuid) {
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_DEL_FRIEND));
packet.writeUInt64(friendGuid);
LOG_DEBUG("Built CMSG_DEL_FRIEND: guid=0x", std::hex, friendGuid, std::dec);
return packet;
}
network::Packet SetContactNotesPacket::build(uint64_t friendGuid, const std::string& note) {
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_SET_CONTACT_NOTES));
packet.writeUInt64(friendGuid);
packet.writeString(note);
LOG_DEBUG("Built CMSG_SET_CONTACT_NOTES: guid=0x", std::hex, friendGuid, std::dec);
return packet;
}
bool FriendStatusParser::parse(network::Packet& packet, FriendStatusData& data) {
data.status = packet.readUInt8();
data.guid = packet.readUInt64();
if (data.status == 1) { // Online
data.note = packet.readString();
data.chatFlag = packet.readUInt8();
}
LOG_DEBUG("Parsed SMSG_FRIEND_STATUS: status=", (int)data.status, " guid=0x", std::hex, data.guid, std::dec);
return true;
}
// ============================================================
// Random Roll
// ============================================================
network::Packet RandomRollPacket::build(uint32_t minRoll, uint32_t maxRoll) {
network::Packet packet(static_cast<uint16_t>(Opcode::MSG_RANDOM_ROLL));
packet.writeUInt32(minRoll);
packet.writeUInt32(maxRoll);
LOG_DEBUG("Built MSG_RANDOM_ROLL: ", minRoll, "-", maxRoll);
return packet;
}
bool RandomRollParser::parse(network::Packet& packet, RandomRollData& data) {
data.rollerGuid = packet.readUInt64();
data.targetGuid = packet.readUInt64();
data.minRoll = packet.readUInt32();
data.maxRoll = packet.readUInt32();
data.result = packet.readUInt32();
LOG_DEBUG("Parsed SMSG_RANDOM_ROLL: roller=0x", std::hex, data.rollerGuid, std::dec,
" result=", data.result, " (", data.minRoll, "-", data.maxRoll, ")");
return true;
}
network::Packet NameQueryPacket::build(uint64_t playerGuid) {
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_NAME_QUERY));
packet.writeUInt64(playerGuid);