Compare commits

...

3 Commits

Author SHA1 Message Date
David Markowitz
1b9f7e44c7 remove dead loop (#1700) 2024-12-28 17:11:44 -06:00
David Markowitz
08a168de88 update cdclient.fdb file check (#1699) 2024-12-27 22:15:32 -06:00
David Markowitz
0c948a8df6 use simpler converter (#1695) 2024-12-24 22:23:14 -08:00
4 changed files with 122 additions and 132 deletions

View File

@@ -72,7 +72,7 @@ std::string FdbToSqlite::Convert::ReadString(std::istream& cdClientBuffer) {
const auto readString = BinaryIO::ReadU8String(cdClientBuffer); const auto readString = BinaryIO::ReadU8String(cdClientBuffer);
cdClientBuffer.seekg(prevPosition); cdClientBuffer.seekg(prevPosition);
return GeneralUtils::Latin1ToWTF8(readString); return GeneralUtils::Latin1ToUTF8(readString);
} }
int32_t FdbToSqlite::Convert::SeekPointer(std::istream& cdClientBuffer) { int32_t FdbToSqlite::Convert::SeekPointer(std::istream& cdClientBuffer) {

View File

@@ -167,11 +167,18 @@ std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view string, const s
return ret; return ret;
} }
std::string GeneralUtils::Latin1ToUTF8(const std::u8string_view string, const size_t size) {
std::string toReturn{};
//! Converts a (potentially-ill-formed) Latin1 string to UTF-8 for (const auto u : string) {
PushUTF8CodePoint(toReturn, u);
}
return toReturn;
}
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16> //! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
template<typename StringType> std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view string, const size_t size) {
std::string ToWTF8(const StringType string, const size_t size) {
const size_t newSize = MinSize(size, string); const size_t newSize = MinSize(size, string);
std::string ret; std::string ret;
ret.reserve(newSize); ret.reserve(newSize);
@@ -196,13 +203,6 @@ std::string ToWTF8(const StringType string, const size_t size) {
return ret; return ret;
} }
std::string GeneralUtils::Latin1ToWTF8(const std::u8string_view string, const size_t size) {
return ToWTF8(string, size);
}
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view string, const size_t size) {
return ToWTF8(string, size);
}
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b) { bool GeneralUtils::CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b) {
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); }); return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });

View File

@@ -57,7 +57,7 @@ namespace GeneralUtils {
\param size A size to trim the string to. Default is SIZE_MAX (No trimming) \param size A size to trim the string to. Default is SIZE_MAX (No trimming)
\return An UTF-8 representation of the string \return An UTF-8 representation of the string
*/ */
std::string Latin1ToWTF8(const std::u8string_view string, const size_t size = SIZE_MAX); std::string Latin1ToUTF8(const std::u8string_view string, const size_t size = SIZE_MAX);
//! Converts a UTF-16 string to a UTF-8 string //! Converts a UTF-16 string to a UTF-8 string
/*! /*!

View File

@@ -267,41 +267,31 @@ int main(int argc, char** argv) {
// pre calculate the FDB checksum // pre calculate the FDB checksum
if (Game::config->GetValue("check_fdb") == "1") { if (Game::config->GetValue("check_fdb") == "1") {
std::ifstream fileStream; auto cdclient = Game::assetManager->GetFile("cdclient.fdb");
if (cdclient) {
static const std::vector<std::string> aliases = { const int32_t bufferSize = 1024;
"CDServers.fdb", MD5 md5;
"cdserver.fdb",
"CDClient.fdb",
"cdclient.fdb",
};
for (const auto& file : aliases) { char fileStreamBuffer[bufferSize] = {};
fileStream.open(Game::assetManager->GetResPath() / file, std::ios::binary | std::ios::in);
if (fileStream.is_open()) { while (!cdclient.eof()) {
break; memset(fileStreamBuffer, 0, bufferSize);
cdclient.read(fileStreamBuffer, bufferSize);
md5.update(fileStreamBuffer, cdclient.gcount());
} }
const char* nullTerminateBuffer = "\0";
md5.update(nullTerminateBuffer, 1); // null terminate the data
md5.finalize();
databaseChecksum = md5.hexdigest();
LOG("FDB Checksum calculated as: %s", databaseChecksum.c_str());
} }
if (databaseChecksum.empty()) {
const int32_t bufferSize = 1024; LOG("check_fdb is on but no fdb file found.");
MD5 md5; return EXIT_FAILURE;
char fileStreamBuffer[1024] = {};
while (!fileStream.eof()) {
memset(fileStreamBuffer, 0, bufferSize);
fileStream.read(fileStreamBuffer, bufferSize);
md5.update(fileStreamBuffer, fileStream.gcount());
} }
fileStream.close();
const char* nullTerminateBuffer = "\0";
md5.update(nullTerminateBuffer, 1); // null terminate the data
md5.finalize();
databaseChecksum = md5.hexdigest();
LOG("FDB Checksum calculated as: %s", databaseChecksum.c_str());
} }
uint32_t currentFrameDelta = highFrameDelta; uint32_t currentFrameDelta = highFrameDelta;
@@ -548,115 +538,115 @@ void HandlePacketChat(Packet* packet) {
if (packet->data[0] == ID_USER_PACKET_ENUM && packet->length >= 4) { if (packet->data[0] == ID_USER_PACKET_ENUM && packet->length >= 4) {
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) { if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
switch (static_cast<MessageType::Chat>(packet->data[3])) { switch (static_cast<MessageType::Chat>(packet->data[3])) {
case MessageType::Chat::WORLD_ROUTE_PACKET: { case MessageType::Chat::WORLD_ROUTE_PACKET: {
CINSTREAM_SKIP_HEADER; CINSTREAM_SKIP_HEADER;
LWOOBJID playerID; LWOOBJID playerID;
inStream.Read(playerID); inStream.Read(playerID);
auto player = Game::entityManager->GetEntity(playerID); auto player = Game::entityManager->GetEntity(playerID);
if (!player) return; if (!player) return;
auto sysAddr = player->GetSystemAddress(); auto sysAddr = player->GetSystemAddress();
//Write our stream outwards: //Write our stream outwards:
CBITSTREAM; CBITSTREAM;
unsigned char data; unsigned char data;
while (inStream.Read(data)) { while (inStream.Read(data)) {
bitStream.Write(data); bitStream.Write(data);
}
SEND_PACKET; //send routed packet to player
break;
} }
case MessageType::Chat::GM_ANNOUNCE: { SEND_PACKET; //send routed packet to player
CINSTREAM_SKIP_HEADER; break;
}
std::string title; case MessageType::Chat::GM_ANNOUNCE: {
std::string msg; CINSTREAM_SKIP_HEADER;
uint32_t len; std::string title;
inStream.Read<uint32_t>(len); std::string msg;
for (uint32_t i = 0; len > i; i++) {
char character;
inStream.Read<char>(character);
title += character;
}
len = 0; uint32_t len;
inStream.Read<uint32_t>(len); inStream.Read<uint32_t>(len);
for (uint32_t i = 0; len > i; i++) { for (uint32_t i = 0; len > i; i++) {
char character; char character;
inStream.Read<char>(character); inStream.Read<char>(character);
msg += character; title += character;
} }
//Send to our clients: len = 0;
AMFArrayValue args; inStream.Read<uint32_t>(len);
for (uint32_t i = 0; len > i; i++) {
char character;
inStream.Read<char>(character);
msg += character;
}
args.Insert("title", title); //Send to our clients:
args.Insert("message", msg); AMFArrayValue args;
GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args); args.Insert("title", title);
args.Insert("message", msg);
GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args);
break;
}
case MessageType::Chat::GM_MUTE: {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
time_t expire = 0;
inStream.Read(playerId);
inStream.Read(expire);
auto* entity = Game::entityManager->GetEntity(playerId);
auto* character = entity != nullptr ? entity->GetCharacter() : nullptr;
auto* user = character != nullptr ? character->GetParentUser() : nullptr;
if (user) {
user->SetMuteExpire(expire);
entity->GetCharacter()->SendMuteNotice();
}
break;
}
case MessageType::Chat::TEAM_GET_STATUS: {
CINSTREAM_SKIP_HEADER;
LWOOBJID teamID = 0;
char lootOption = 0;
char memberCount = 0;
std::vector<LWOOBJID> members;
inStream.Read(teamID);
bool deleteTeam = inStream.ReadBit();
if (deleteTeam) {
TeamManager::Instance()->DeleteTeam(teamID);
LOG("Deleting team (%llu)", teamID);
break; break;
} }
case MessageType::Chat::GM_MUTE: { inStream.Read(lootOption);
CINSTREAM_SKIP_HEADER; inStream.Read(memberCount);
LWOOBJID playerId; LOG("Updating team (%llu), (%i), (%i)", teamID, lootOption, memberCount);
time_t expire = 0; for (char i = 0; i < memberCount; i++) {
inStream.Read(playerId); LWOOBJID member = LWOOBJID_EMPTY;
inStream.Read(expire); inStream.Read(member);
members.push_back(member);
auto* entity = Game::entityManager->GetEntity(playerId); LOG("Updating team member (%llu)", member);
auto* character = entity != nullptr ? entity->GetCharacter() : nullptr;
auto* user = character != nullptr ? character->GetParentUser() : nullptr;
if (user) {
user->SetMuteExpire(expire);
entity->GetCharacter()->SendMuteNotice();
}
break;
} }
case MessageType::Chat::TEAM_GET_STATUS: { TeamManager::Instance()->UpdateTeam(teamID, lootOption, members);
CINSTREAM_SKIP_HEADER;
LWOOBJID teamID = 0; break;
char lootOption = 0; }
char memberCount = 0; default:
std::vector<LWOOBJID> members; LOG("Received an unknown chat: %i", int(packet->data[3]));
inStream.Read(teamID);
bool deleteTeam = inStream.ReadBit();
if (deleteTeam) {
TeamManager::Instance()->DeleteTeam(teamID);
LOG("Deleting team (%llu)", teamID);
break;
}
inStream.Read(lootOption);
inStream.Read(memberCount);
LOG("Updating team (%llu), (%i), (%i)", teamID, lootOption, memberCount);
for (char i = 0; i < memberCount; i++) {
LWOOBJID member = LWOOBJID_EMPTY;
inStream.Read(member);
members.push_back(member);
LOG("Updating team member (%llu)", member);
}
TeamManager::Instance()->UpdateTeam(teamID, lootOption, members);
break;
}
default:
LOG("Received an unknown chat: %i", int(packet->data[3]));
} }
} }
} }