Compare commits

..

1 Commits

Author SHA1 Message Date
EmosewaMC
ae65ebc9df CDClient: Emote and Animations to std optional
Revert "CDClient: Emote and Animations to std optional"

This reverts commit 9d980cfde0dcce6aec0ac3a1b3a25269336c5acd.
2023-11-01 20:22:17 -07:00
8 changed files with 141 additions and 142 deletions

View File

@@ -144,7 +144,7 @@ std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::
listOfBadSegments.emplace_back(position, originalSegment.length()); listOfBadSegments.emplace_back(position, originalSegment.length());
} }
position += originalSegment.length() + 1; position += segment.length() + 1;
} }
return listOfBadSegments; return listOfBadSegments;

View File

@@ -145,8 +145,7 @@ void CatchUnhandled(int sig) {
std::string functionName = strings[i]; std::string functionName = strings[i];
std::string::size_type start = functionName.find('('); std::string::size_type start = functionName.find('(');
std::string::size_type end = functionName.find('+'); std::string::size_type end = functionName.find('+');
// strengthened check if (start != std::string::npos && end != std::string::npos) {
if (start != std::string::npos && start + 1 < functionName.size() && end != std::string::npos && start < end) {
std::string demangled = functionName.substr(start + 1, end - start - 1); std::string demangled = functionName.substr(start + 1, end - start - 1);
demangled = Demangler::Demangle(demangled.c_str()); demangled = Demangler::Demangle(demangled.c_str());

View File

@@ -2523,9 +2523,15 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent
inStream->Read(sd0Size); inStream->Read(sd0Size);
std::shared_ptr<char[]> sd0Data(new char[sd0Size]); std::shared_ptr<char[]> sd0Data(new char[sd0Size]);
if (sd0Data == nullptr) return; if (sd0Data == nullptr) {
return;
}
inStream->ReadAlignedBytes(reinterpret_cast<unsigned char*>(sd0Data.get()), sd0Size); for (uint32_t i = 0; i < sd0Size; ++i) {
uint8_t c;
inStream->Read(c);
sd0Data[i] = c;
}
uint32_t timeTaken; uint32_t timeTaken;
inStream->Read(timeTaken); inStream->Read(timeTaken);
@@ -2559,156 +2565,165 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent
//We runs this in async because the http library here is blocking, meaning it'll halt the thread. //We runs this in async because the http library here is blocking, meaning it'll halt the thread.
//But we don't want the server to go unresponsive, because then the client would disconnect. //But we don't want the server to go unresponsive, because then the client would disconnect.
auto returnVal = std::async(std::launch::async, [&]() {
//We need to get a new ID for our model first: //We need to get a new ID for our model first:
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t newID) { ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t newID) {
LWOOBJID newIDL = newID; LWOOBJID newIDL = newID;
GeneralUtils::SetBit(newIDL, eObjectBits::CHARACTER); GeneralUtils::SetBit(newIDL, eObjectBits::CHARACTER);
GeneralUtils::SetBit(newIDL, eObjectBits::PERSISTENT); GeneralUtils::SetBit(newIDL, eObjectBits::PERSISTENT);
uint32_t blueprintIDSmall = ObjectIDManager::Instance()->GenerateRandomObjectID(); ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t blueprintIDSmall) {
LWOOBJID blueprintID = blueprintIDSmall; blueprintIDSmall = ObjectIDManager::Instance()->GenerateRandomObjectID();
GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER); LWOOBJID blueprintID = blueprintIDSmall;
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT); GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER);
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT);
//We need to get the propertyID: (stolen from Wincent's propertyManagementComp) //We need to get the propertyID: (stolen from Wincent's propertyManagementComp)
const auto& worldId = Game::zoneManager->GetZone()->GetZoneID(); const auto& worldId = Game::zoneManager->GetZone()->GetZoneID();
const auto zoneId = worldId.GetMapID(); const auto zoneId = worldId.GetMapID();
const auto cloneId = worldId.GetCloneID(); const auto cloneId = worldId.GetCloneID();
auto query = CDClientDatabase::CreatePreppedStmt( auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT id FROM PropertyTemplate WHERE mapID = ?;"); "SELECT id FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, (int)zoneId); query.bind(1, (int)zoneId);
auto result = query.execQuery(); auto result = query.execQuery();
if (result.eof() || result.fieldIsNull(0)) return; if (result.eof() || result.fieldIsNull(0)) return;
int templateId = result.getIntField(0); int templateId = result.getIntField(0);
auto* propertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE template_id = ? AND clone_id = ?;"); result.finalize();
propertyLookup->setInt(1, templateId); auto* propertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE template_id = ? AND clone_id = ?;");
propertyLookup->setInt64(2, cloneId);
auto* propertyEntry = propertyLookup->executeQuery(); propertyLookup->setInt(1, templateId);
uint64_t propertyId = 0; propertyLookup->setInt64(2, cloneId);
if (propertyEntry->next()) { auto* propertyEntry = propertyLookup->executeQuery();
propertyId = propertyEntry->getUInt64(1); uint64_t propertyId = 0;
}
delete propertyEntry; if (propertyEntry->next()) {
delete propertyLookup; propertyId = propertyEntry->getUInt64(1);
}
//Insert into ugc: delete propertyEntry;
auto ugcs = Database::CreatePreppedStmt("INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)"); delete propertyLookup;
ugcs->setUInt(1, blueprintIDSmall);
ugcs->setInt(2, entity->GetParentUser()->GetAccountID());
ugcs->setInt(3, entity->GetCharacter()->GetID());
ugcs->setInt(4, 0);
//whacky stream biz //Insert into ugc:
std::string s(sd0Data.get(), sd0Size); auto ugcs = Database::CreatePreppedStmt("INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)");
std::istringstream iss(s); ugcs->setUInt(1, blueprintIDSmall);
ugcs->setInt(2, entity->GetParentUser()->GetAccountID());
ugcs->setInt(3, entity->GetCharacter()->GetID());
ugcs->setInt(4, 0);
ugcs->setBlob(5, &iss); //whacky stream biz
ugcs->setBoolean(6, false); std::string s(sd0Data.get(), sd0Size);
ugcs->setString(7, "weedeater.lxfml"); std::istringstream iss(s);
ugcs->execute(); std::istream& stream = iss;
delete ugcs;
//Insert into the db as a BBB model: ugcs->setBlob(5, &iss);
auto* stmt = Database::CreatePreppedStmt("INSERT INTO `properties_contents` VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); ugcs->setBoolean(6, false);
stmt->setUInt64(1, newIDL); ugcs->setString(7, "weedeater.lxfml");
stmt->setUInt64(2, propertyId); ugcs->execute();
stmt->setUInt(3, blueprintIDSmall); delete ugcs;
stmt->setUInt(4, 14); // 14 is the lot the BBB models use
stmt->setDouble(5, 0.0f); // x
stmt->setDouble(6, 0.0f); // y
stmt->setDouble(7, 0.0f); // z
stmt->setDouble(8, 0.0f); // rx
stmt->setDouble(9, 0.0f); // ry
stmt->setDouble(10, 0.0f); // rz
stmt->setDouble(11, 0.0f); // rw
stmt->setString(12, "Objects_14_name"); // Model name. TODO make this customizable
stmt->setString(13, ""); // Model description. TODO implement this.
stmt->setDouble(14, 0); // behavior 1. TODO implement this.
stmt->setDouble(15, 0); // behavior 2. TODO implement this.
stmt->setDouble(16, 0); // behavior 3. TODO implement this.
stmt->setDouble(17, 0); // behavior 4. TODO implement this.
stmt->setDouble(18, 0); // behavior 5. TODO implement this.
stmt->execute();
delete stmt;
/* //Insert into the db as a BBB model:
Commented out until UGC server would be updated to use a sd0 file instead of lxfml stream. auto* stmt = Database::CreatePreppedStmt("INSERT INTO `properties_contents` VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
(or you uncomment the lxfml decomp stuff above) stmt->setUInt64(1, newIDL);
*/ stmt->setUInt64(2, propertyId);
stmt->setUInt(3, blueprintIDSmall);
stmt->setUInt(4, 14); // 14 is the lot the BBB models use
stmt->setDouble(5, 0.0f); // x
stmt->setDouble(6, 0.0f); // y
stmt->setDouble(7, 0.0f); // z
stmt->setDouble(8, 0.0f); // rx
stmt->setDouble(9, 0.0f); // ry
stmt->setDouble(10, 0.0f); // rz
stmt->setDouble(11, 0.0f); // rw
stmt->setString(12, "Objects_14_name"); // Model name. TODO make this customizable
stmt->setString(13, ""); // Model description. TODO implement this.
stmt->setDouble(14, 0); // behavior 1. TODO implement this.
stmt->setDouble(15, 0); // behavior 2. TODO implement this.
stmt->setDouble(16, 0); // behavior 3. TODO implement this.
stmt->setDouble(17, 0); // behavior 4. TODO implement this.
stmt->setDouble(18, 0); // behavior 5. TODO implement this.
stmt->execute();
delete stmt;
////Send off to UGC for processing, if enabled: /*
//if (Game::config->GetValue("ugc_remote") == "1") { Commented out until UGC server would be updated to use a sd0 file instead of lxfml stream.
// std::string ugcIP = Game::config->GetValue("ugc_ip"); (or you uncomment the lxfml decomp stuff above)
// int ugcPort = std::stoi(Game::config->GetValue("ugc_port")); */
// httplib::Client cli(ugcIP, ugcPort); //connect to UGC HTTP server using our config above ^ ////Send off to UGC for processing, if enabled:
//if (Game::config->GetValue("ugc_remote") == "1") {
// std::string ugcIP = Game::config->GetValue("ugc_ip");
// int ugcPort = std::stoi(Game::config->GetValue("ugc_port"));
// //Send out a request: // httplib::Client cli(ugcIP, ugcPort); //connect to UGC HTTP server using our config above ^
// std::string request = "/3dservices/UGCC150/150" + std::to_string(blueprintID) + ".lxfml";
// cli.Put(request.c_str(), lxfml.c_str(), "text/lxfml");
// //When the "put" above returns, it means that the UGC HTTP server is done processing our model & // //Send out a request:
// //the nif, hkx and checksum files are ready to be downloaded from cache. // std::string request = "/3dservices/UGCC150/150" + std::to_string(blueprintID) + ".lxfml";
//} // cli.Put(request.c_str(), lxfml.c_str(), "text/lxfml");
//Tell the client their model is saved: (this causes us to actually pop out of our current state): // //When the "put" above returns, it means that the UGC HTTP server is done processing our model &
CBITSTREAM; // //the nif, hkx and checksum files are ready to be downloaded from cache.
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); //}
bitStream.Write(localId);
bitStream.Write(eBlueprintSaveResponseType::EverythingWorked);
bitStream.Write<uint32_t>(1);
bitStream.Write(blueprintID);
bitStream.Write<uint32_t>(sd0Size); //Tell the client their model is saved: (this causes us to actually pop out of our current state):
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE);
bitStream.Write(localId);
bitStream.Write(eBlueprintSaveResponseType::EverythingWorked);
bitStream.Write<uint32_t>(1);
bitStream.Write(blueprintID);
bitStream.WriteAlignedBytes(reinterpret_cast<unsigned char*>(sd0Data.get()), sd0Size); bitStream.Write<uint32_t>(sd0Size);
SEND_PACKET; for (size_t i = 0; i < sd0Size; ++i) {
bitStream.Write(sd0Data[i]);
}
//Now we have to construct this object: SEND_PACKET;
EntityInfo info; //Now we have to construct this object:
info.lot = 14;
info.pos = {};
info.rot = {};
info.spawner = nullptr;
info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0;
LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintid", blueprintID); EntityInfo info;
LDFBaseData* componentWhitelist = new LDFData<int>(u"componentWhitelist", 1); info.lot = 14;
LDFBaseData* modelType = new LDFData<int>(u"modelType", 2); info.pos = {};
LDFBaseData* propertyObjectID = new LDFData<bool>(u"propertyObjectID", true); info.rot = {};
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", newIDL); info.spawner = nullptr;
info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0;
info.settings.push_back(ldfBlueprintID); LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintid", blueprintID);
info.settings.push_back(componentWhitelist); LDFBaseData* componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
info.settings.push_back(modelType); LDFBaseData* modelType = new LDFData<int>(u"modelType", 2);
info.settings.push_back(propertyObjectID); LDFBaseData* propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
info.settings.push_back(userModelID); LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", newIDL);
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr); info.settings.push_back(ldfBlueprintID);
if (newEntity) { info.settings.push_back(componentWhitelist);
Game::entityManager->ConstructEntity(newEntity); info.settings.push_back(modelType);
info.settings.push_back(propertyObjectID);
info.settings.push_back(userModelID);
//Make sure the propMgmt doesn't delete our model after the server dies Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
//Trying to do this after the entity is constructed. Shouldn't really change anything but if (newEntity) {
//there was an issue with builds not appearing since it was placed above ConstructEntity. Game::entityManager->ConstructEntity(newEntity);
PropertyManagementComponent::Instance()->AddModel(newEntity->GetObjectID(), newIDL);
}
}); //Make sure the propMgmt doesn't delete our model after the server dies
//Trying to do this after the entity is constructed. Shouldn't really change anything but
//there was an issue with builds not appearing since it was placed above ConstructEntity.
PropertyManagementComponent::Instance()->AddModel(newEntity->GetObjectID(), newIDL);
}
});
});
});
} }
void GameMessages::HandlePropertyEntranceSync(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { void GameMessages::HandlePropertyEntranceSync(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {

View File

@@ -29,7 +29,7 @@ void ReportCheat(User* user, const SystemAddress& sysAddr, const char* messageIf
std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt( std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt(
"INSERT INTO player_cheat_detections (account_id, name, violation_msg, violation_system_address) VALUES (?, ?, ?, ?)") "INSERT INTO player_cheat_detections (account_id, name, violation_msg, violation_system_address) VALUES (?, ?, ?, ?)")
); );
user ? stmt->setInt(1, user->GetAccountID()) : stmt->setNull(1, sql::DataType::INTEGER); stmt->setInt(1, user ? user->GetAccountID() : 0);
stmt->setString(2, user ? user->GetUsername().c_str() : "User is null."); stmt->setString(2, user ? user->GetUsername().c_str() : "User is null.");
constexpr int32_t bufSize = 4096; constexpr int32_t bufSize = 4096;

View File

@@ -4,8 +4,6 @@
#include "MissionComponent.h" #include "MissionComponent.h"
#include "SkillComponent.h" #include "SkillComponent.h"
#include "eMissionTaskType.h" #include "eMissionTaskType.h"
#include "CDClientManager.h"
#include "CDObjectSkillsTable.h"
#include "RenderComponent.h" #include "RenderComponent.h"
//TODO: this has to be updated so that you only get killed if you're in a certain radius. //TODO: this has to be updated so that you only get killed if you're in a certain radius.
@@ -41,11 +39,9 @@ void ExplodingAsset::OnHit(Entity* self, Entity* attacker) {
self->SetOwnerOverride(attacker->GetObjectID()); self->SetOwnerOverride(attacker->GetObjectID());
GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake", self->GetObjectID(), 16); GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake", self->GetObjectID(), 16);
self->Smash(attacker->GetObjectID());
auto* skillComponent = self->GetComponent<SkillComponent>(); auto* skillComponent = self->GetComponent<SkillComponent>();
if (skillComponent != nullptr) { if (skillComponent != nullptr) {
// Technically supposed to get first skill in the skill component but only 1 object in the live game used this.
skillComponent->CalculateBehavior(147, 4721, LWOOBJID_EMPTY, true); skillComponent->CalculateBehavior(147, 4721, LWOOBJID_EMPTY, true);
} }
@@ -69,6 +65,8 @@ void ExplodingAsset::OnHit(Entity* self, Entity* attacker) {
} }
} }
} }
self->ScheduleKillAfterUpdate();
} }
void ExplodingAsset::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) { void ExplodingAsset::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {

View File

@@ -1,7 +1,6 @@
#include "NtCombatChallengeExplodingDummy.h" #include "NtCombatChallengeExplodingDummy.h"
#include "EntityManager.h" #include "EntityManager.h"
#include "SkillComponent.h" #include "SkillComponent.h"
#include "DestroyableComponent.h"
void NtCombatChallengeExplodingDummy::OnDie(Entity* self, Entity* killer) { void NtCombatChallengeExplodingDummy::OnDie(Entity* self, Entity* killer) {
const auto challengeObjectID = self->GetVar<LWOOBJID>(u"challengeObjectID"); const auto challengeObjectID = self->GetVar<LWOOBJID>(u"challengeObjectID");
@@ -16,17 +15,6 @@ void NtCombatChallengeExplodingDummy::OnDie(Entity* self, Entity* killer) {
} }
void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) { void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
auto numTimesHit = self->GetVar<int32_t>(u"numTimesHit");
if (destroyableComponent && numTimesHit == 0) {
self->SetVar<int32_t>(u"numTimesHit", 1);
destroyableComponent->SetHealth(destroyableComponent->GetHealth() / 2);
return;
} else if (numTimesHit == 2) {
return;
}
self->SetVar<int32_t>(u"numTimesHit", 2);
const auto challengeObjectID = self->GetVar<LWOOBJID>(u"challengeObjectID"); const auto challengeObjectID = self->GetVar<LWOOBJID>(u"challengeObjectID");
auto* challengeObject = Game::entityManager->GetEntity(challengeObjectID); auto* challengeObject = Game::entityManager->GetEntity(challengeObjectID);
@@ -40,6 +28,5 @@ void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* at
if (skillComponent != nullptr) { if (skillComponent != nullptr) {
skillComponent->CalculateBehavior(1338, 30875, attacker->GetObjectID()); skillComponent->CalculateBehavior(1338, 30875, attacker->GetObjectID());
} }
GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake", self->GetObjectID(), 16.0f); self->Kill(attacker);
self->Smash(attacker->GetObjectID());
} }

View File

@@ -925,7 +925,7 @@ void HandlePacket(Packet* packet) {
//We need to delete the entity first, otherwise the char list could delete it while it exists in the world! //We need to delete the entity first, otherwise the char list could delete it while it exists in the world!
if (Game::server->GetZoneID() != 0) { if (Game::server->GetZoneID() != 0) {
auto user = UserManager::Instance()->GetUser(packet->systemAddress); auto user = UserManager::Instance()->GetUser(packet->systemAddress);
if (!user || !user->GetLastUsedChar()) return; if (!user) return;
Game::entityManager->DestroyEntity(user->GetLastUsedChar()->GetEntity()); Game::entityManager->DestroyEntity(user->GetLastUsedChar()->GetEntity());
} }

Binary file not shown.