Fix issues with OP_SpecialMesg handling

This should prevent any optimizations being done on the "1 char string"

This also fully documents the packet and expands the uses of
quest::say/QuestSay
This commit is contained in:
Michael Cook (mackal)
2019-07-18 00:56:46 -04:00
parent 16d6014a87
commit 9fe17f4d46
24 changed files with 343 additions and 291 deletions
+1
View File
@@ -75,6 +75,7 @@ public:
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
uint32 GetWritePosition() { return _wpos; }
+1
View File
@@ -87,6 +87,7 @@ typedef enum {
_eaMaxAppearance
} EmuAppearance;
#define MT_NPCQuestSay 10
// msg_type's for custom usercolors
#define MT_Say 256
#define MT_Tell 257
+14
View File
@@ -1188,6 +1188,20 @@ struct SpecialMesg_Struct
/*24*/ char message[1]; // What is being said?
};
struct SpecialMesgHeader_Struct
{
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
/*01*/ char JournalMode; // 1 and 2 go to journal
/*02*/ char language;
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
/*07*/ uint32 target_spawn_id; // Who is it being said to?
/*11*/ // speaker's name
/*xx*/ // unknown, location, client doesn't care
/*xx*/ // unknown
/*xx*/ // unknown
/*xx*/ // message
};
/*
** When somebody changes what they're wearing or give a pet a weapon (model changes)
** Length: 19 Bytes
+21 -29
View File
@@ -3199,43 +3199,35 @@ namespace RoF
EQApplicationPacket *in = *p;
*p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer;
// break strlen optimizations!
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string name;
in->ReadString(name); // NPC names max out at 63 chars
std::string old_message = message;
buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message;
in->ReadString(old_message);
ServerToRoFSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
buf.WriteString(new_message);
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
}
ENCODE(OP_Stun)
+21 -29
View File
@@ -3266,43 +3266,35 @@ namespace RoF2
EQApplicationPacket *in = *p;
*p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer;
// break strlen optimizations!
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string name;
in->ReadString(name); // NPC names max out at 63 chars
std::string old_message = message;
buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message;
in->ReadString(old_message);
ServerToRoF2SayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
buf.WriteString(new_message);
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
}
ENCODE(OP_Stun)
+21 -29
View File
@@ -2069,43 +2069,35 @@ namespace SoD
EQApplicationPacket *in = *p;
*p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer;
// break strlen optimizations!
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string name;
in->ReadString(name); // NPC names max out at 63 chars
std::string old_message = message;
buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message;
in->ReadString(old_message);
ServerToSoDSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
buf.WriteString(new_message);
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
}
ENCODE(OP_Stun)
+21 -29
View File
@@ -1720,43 +1720,35 @@ namespace SoF
EQApplicationPacket *in = *p;
*p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer;
// break strlen optimizations!
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string name;
in->ReadString(name);
std::string old_message = message;
buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message;
in->ReadString(old_message);
ServerToSoFSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
buf.WriteString(new_message);
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
}
ENCODE(OP_Stun)
+21 -29
View File
@@ -1420,43 +1420,35 @@ namespace Titanium
EQApplicationPacket *in = *p;
*p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer;
// break strlen optimizations!
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string name;
in->ReadString(name); // NPC names max out at 63 chars
std::string old_message = message;
buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message;
in->ReadString(old_message);
ServerToTitaniumSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
buf.WriteString(new_message);
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
}
ENCODE(OP_TaskDescription)
+21 -29
View File
@@ -2369,43 +2369,35 @@ namespace UF
EQApplicationPacket *in = *p;
*p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer;
// break strlen optimizations!
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string name;
in->ReadString(name); // NPC names max out at 63 chars
std::string old_message = message;
buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message;
in->ReadString(old_message);
ServerToUFSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
buf.WriteString(new_message);
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
}
ENCODE(OP_Stun)