DarkflameServer/dGame/dBehaviors/SwitchMultipleBehavior.cpp
David Markowitz a2ca273370
Cleanup behavior bitstream reads (#888)
* Add failArmor server side

Address out of bounds reading in behavior

Address the basicAttackBehavior reading out of bounds memory and reading bits that didnt exist, which occasionally caused crashes and also caused the behavior to do undefined behavior due to the bad reads.

Tested that attacking a wall anywhere with a projectile now does not crash the game.  Tested with logs that the behavior correctly returned when there were no allocated bits or returned when other states were met.

Add back logs and add fail handle

Remove comment block

Revert "Add back logs and add fail handle"

This reverts commit db19be0906fc8bf35bf89037e2bfba39f5ef9c0c.

Split out checks

* Cleanup Behavior streams
2022-12-16 15:23:02 -06:00

64 lines
1.7 KiB
C++

#include "SwitchMultipleBehavior.h"
#include <sstream>
#include "BehaviorBranchContext.h"
#include "CDActivitiesTable.h"
#include "Game.h"
#include "dLogger.h"
#include "EntityManager.h"
void SwitchMultipleBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
float value{};
if (!bitStream->Read(value)) {
Game::logger->Log("SwitchMultipleBehavior", "Unable to read value from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits());
};
uint32_t trigger = 0;
for (unsigned int i = 0; i < this->m_behaviors.size(); i++) {
const double data = this->m_behaviors.at(i).first;
if (value <= data) {
trigger = i;
break;
}
}
auto* behavior = this->m_behaviors.at(trigger).second;
behavior->Handle(context, bitStream, branch);
}
void SwitchMultipleBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
// TODO
}
void SwitchMultipleBehavior::Load() {
auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT replace(bP1.parameterID, 'behavior ', '') as key, bP1.value as behavior, "
"(select bP2.value FROM BehaviorParameter bP2 WHERE bP2.behaviorID = ?1 AND bP2.parameterID LIKE 'value %' "
"AND replace(bP1.parameterID, 'behavior ', '') = replace(bP2.parameterID, 'value ', '')) as value "
"FROM BehaviorParameter bP1 WHERE bP1.behaviorID = ?1 AND bP1.parameterID LIKE 'behavior %';");
query.bind(1, (int)this->m_behaviorId);
auto result = query.execQuery();
while (!result.eof()) {
const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1));
auto* behavior = CreateBehavior(behavior_id);
auto value = result.getFloatField(2);
this->m_behaviors.emplace_back(value, behavior);
result.nextRow();
}
}