Skip to content

Commit

Permalink
fix: Dismantling basically being O(n!) (#1295)
Browse files Browse the repository at this point in the history
  • Loading branch information
EmosewaMC authored Nov 16, 2023
1 parent 59303a2 commit 8b270ca
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 36 deletions.
8 changes: 3 additions & 5 deletions dGame/dGameMessages/GameMessages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2708,7 +2708,7 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent
PropertyManagementComponent::Instance()->AddModel(newEntity->GetObjectID(), newIDL);
}

});
});
}

void GameMessages::HandlePropertyEntranceSync(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
Expand Down Expand Up @@ -5441,10 +5441,8 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En
iStackCount = std::min<uint32_t>(item->GetCount(), iStackCount);

if (bConfirmed) {
for (auto i = 0; i < iStackCount; ++i) {
if (eInvType == eInventoryType::MODELS) {
item->DisassembleModel();
}
if (eInvType == eInventoryType::MODELS) {
item->DisassembleModel(iStackCount);
}

item->SetCount(item->GetCount() - iStackCount, true);
Expand Down
67 changes: 37 additions & 30 deletions dGame/dInventory/Item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,14 +395,13 @@ void Item::Disassemble(const eInventoryType inventoryType) {
}
}

void Item::DisassembleModel() {
void Item::DisassembleModel(uint32_t numToDismantle) {
auto* table = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();

const auto componentId = table->GetByIDAndType(GetLot(), eReplicaComponentType::RENDER);

auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT render_asset, LXFMLFolder FROM RenderComponent WHERE id = ?;");
query.bind(1, (int)componentId);
auto query = CDClientDatabase::CreatePreppedStmt("SELECT render_asset, LXFMLFolder FROM RenderComponent WHERE id = ?;");
query.bind(1, static_cast<int>(componentId));

auto result = query.execQuery();

Expand All @@ -426,8 +425,6 @@ void Item::DisassembleModel() {

std::istream file(&buffer);

result.finalize();

if (!file.good()) {
buffer.close();
return;
Expand All @@ -438,56 +435,66 @@ void Item::DisassembleModel() {

buffer.close();

if (data.str().empty()) {
return;
}
uint32_t fileSize;
file.seekg(0, std::ios::end);
fileSize = static_cast<uint32_t>(file.tellg());
file.seekg(0, std::ios::beg);

std::unique_ptr<tinyxml2::XMLDocument> doc(new tinyxml2::XMLDocument());
if (fileSize == 0) return;

if (!doc) {
return;
}
tinyxml2::XMLDocument doc;

if (doc->Parse(data.str().c_str(), data.str().size()) != 0) {
if (doc.Parse(data.str().c_str(), data.str().size()) != tinyxml2::XML_SUCCESS) {
return;
}

std::vector<int> parts;

auto* lxfml = doc->FirstChildElement("LXFML");
auto* lxfml = doc.FirstChildElement("LXFML");
if (!lxfml) return;
auto* bricks = lxfml->FirstChildElement("Bricks");
std::string searchTerm = "Brick";

if (!bricks) {
searchTerm = "Part";
bricks = lxfml->FirstChildElement("Scene")->FirstChildElement("Model")->FirstChildElement("Group");
auto* scene = lxfml->FirstChildElement("Scene");
if (!scene) return;

if (!bricks) {
return;
}
auto* model = scene->FirstChildElement("Model");
if (!model) return;

auto* group = model->FirstChildElement("Group");
if (!group) return;
}

auto* currentBrick = bricks->FirstChildElement(searchTerm.c_str());

// First iteration gets the count
std::map<int32_t, int32_t> parts;
while (currentBrick) {
if (currentBrick->Attribute("designID") != nullptr) {
parts.push_back(std::stoi(currentBrick->Attribute("designID")));
auto* designID = currentBrick->Attribute("designID");
if (designID) {
uint32_t designId;
if (!GeneralUtils::TryParse(designID, designId)) {
LOG("Failed to parse designID %s", designID);
continue;
}
parts[designId]++;
}

currentBrick = currentBrick->NextSiblingElement(searchTerm.c_str());
}

auto* brickIDTable = CDClientManager::Instance().GetTable<CDBrickIDTableTable>();

for (unsigned int part : parts) {
const auto brickID = brickIDTable->Query([=](const CDBrickIDTable& entry) {
return entry.LEGOBrickID == part;
// Second iteration actually distributes the bricks
for (const auto&[part, count] : parts) {
const auto partLocal = part;
const auto brickID = brickIDTable->Query([&](const CDBrickIDTable& entry) {
return entry.LEGOBrickID == partLocal;
});

if (brickID.empty()) {
continue;
}
if (brickID.empty()) continue;

GetInventory()->GetComponent()->AddItem(brickID[0].NDObjectID, 1, eLootSourceType::DELETION);
GetInventory()->GetComponent()->AddItem(brickID[0].NDObjectID, count * numToDismantle, eLootSourceType::DELETION);
}
}

Expand Down
2 changes: 1 addition & 1 deletion dGame/dInventory/Item.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class Item final
/**
* Disassembles this item into bricks
*/
void DisassembleModel();
void DisassembleModel(uint32_t numToDismantle);

/**
* Removes the item from the linked inventory
Expand Down

0 comments on commit 8b270ca

Please sign in to comment.