mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-16 20:24:39 -06:00
Compare commits
24 Commits
config-log
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
| e66f82ff07 | |||
|
|
889ee5bd14 | ||
|
|
c5c3ef23b9 | ||
|
|
b8d5e63c0c | ||
|
|
316e0bc47e | ||
|
|
d3b5941458 | ||
|
|
9274494023 | ||
|
|
0a06698514 | ||
|
|
856186636f | ||
|
|
f4a9cd21be | ||
|
|
c29f0d151e | ||
|
|
da801c61ab | ||
|
|
94acddc3e9 | ||
|
|
dac47cc240 | ||
|
|
6bb8040221 | ||
|
|
6d96eb208c | ||
|
|
a18a3f5b25 | ||
|
|
14915000ab | ||
|
|
3e838c11ef | ||
|
|
841e55c389 | ||
|
|
863e6d625c | ||
|
|
621f85f0af | ||
|
|
f86024e06d | ||
|
|
d19ba5ed59 |
@@ -237,6 +237,8 @@ include_directories(
|
||||
|
||||
"dWeb"
|
||||
|
||||
"dScripts"
|
||||
|
||||
"tests"
|
||||
"tests/dCommonTests"
|
||||
"tests/dGameTests"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CDAnimationsTable.h"
|
||||
#include "CDBehaviorParameterTable.h"
|
||||
#include "CDBehaviorTemplateTable.h"
|
||||
#include "CDBaseCombatAIComponentTable.h"
|
||||
#include "CDClientDatabase.h"
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDCurrencyTableTable.h"
|
||||
@@ -65,6 +66,7 @@
|
||||
DEFINE_TABLE_STORAGE(CDActivityRewardsTable);
|
||||
DEFINE_TABLE_STORAGE(CDActivitiesTable);
|
||||
DEFINE_TABLE_STORAGE(CDAnimationsTable);
|
||||
DEFINE_TABLE_STORAGE(CDBaseCombatAIComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDBehaviorParameterTable);
|
||||
DEFINE_TABLE_STORAGE(CDBehaviorTemplateTable);
|
||||
DEFINE_TABLE_STORAGE(CDBrickIDTableTable);
|
||||
@@ -154,5 +156,16 @@ void CDClientManager::LoadValuesFromDatabase() {
|
||||
void CDClientManager::LoadValuesFromDefaults() {
|
||||
LOG("Loading default CDClient tables!");
|
||||
|
||||
CDBaseCombatAIComponentTable::Instance().LoadValuesFromDefaults();
|
||||
CDPetComponentTable::Instance().LoadValuesFromDefaults();
|
||||
CDActivitiesTable::Instance().LoadValuesFromDefaults();
|
||||
CDActivityRewardsTable::Instance().LoadValuesFromDefaults();
|
||||
CDCurrencyTableTable::Instance().LoadValuesFromDefaults();
|
||||
CDMissionsTable::Instance().LoadValuesFromDefaults();
|
||||
CDComponentsRegistryTable::Instance().LoadValuesFromDefaults();
|
||||
CDItemComponentTable::Instance().LoadValuesFromDefaults();
|
||||
CDSkillBehaviorTable::Instance().LoadValuesFromDefaults();
|
||||
CDVendorComponentTable::Instance().LoadValuesFromDefaults();
|
||||
CDLootMatrixTable::Instance().LoadValuesFromDefaults();
|
||||
CDLootTableTable::Instance().LoadValuesFromDefaults();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
#include "CDActivitiesTable.h"
|
||||
|
||||
namespace {
|
||||
// Default entries for fallback
|
||||
CDActivities defaultEntry{
|
||||
.ActivityID = 1,
|
||||
.locStatus = 0,
|
||||
.instanceMapID = 0,
|
||||
.minTeams = 1,
|
||||
.maxTeams = 1,
|
||||
.minTeamSize = 1,
|
||||
.maxTeamSize = 1,
|
||||
.waitTime = 0,
|
||||
.startDelay = 0,
|
||||
.requiresUniqueData = false,
|
||||
.leaderboardType = 0,
|
||||
.localize = false,
|
||||
.optionalCostLOT = -1,
|
||||
.optionalCostCount = -1,
|
||||
.showUIRewards = false,
|
||||
.CommunityActivityFlagID = 0,
|
||||
.gate_version = "",
|
||||
.noTeamLootOnDeath = false,
|
||||
.optionalPercentage = 0.0f,
|
||||
};
|
||||
}
|
||||
|
||||
void CDActivitiesTable::LoadValuesFromDatabase() {
|
||||
// First, get the size of the table
|
||||
@@ -48,6 +72,12 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDActivitiesTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
entries.push_back(defaultEntry);
|
||||
}
|
||||
|
||||
std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActivities)> predicate) {
|
||||
|
||||
std::vector<CDActivities> data = cpplinq::from(GetEntries())
|
||||
|
||||
@@ -28,6 +28,7 @@ struct CDActivities {
|
||||
class CDActivitiesTable : public CDTable<CDActivitiesTable, std::vector<CDActivities>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
|
||||
// Queries the table with a custom "where" clause
|
||||
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
#include "CDActivityRewardsTable.h"
|
||||
|
||||
namespace {
|
||||
// Default entries for fallback
|
||||
CDActivityRewards defaultEntry{
|
||||
.objectTemplate = 1,
|
||||
.ActivityRewardIndex = 1,
|
||||
.activityRating = 1,
|
||||
.LootMatrixIndex = 0,
|
||||
.CurrencyIndex = 1,
|
||||
.ChallengeRating = 1,
|
||||
.description = "Default test activity reward",
|
||||
};
|
||||
}
|
||||
|
||||
void CDActivityRewardsTable::LoadValuesFromDatabase() {
|
||||
|
||||
@@ -37,6 +49,12 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDActivityRewardsTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
entries.push_back(defaultEntry);
|
||||
}
|
||||
|
||||
std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(CDActivityRewards)> predicate) {
|
||||
|
||||
std::vector<CDActivityRewards> data = cpplinq::from(GetEntries())
|
||||
|
||||
@@ -16,6 +16,7 @@ struct CDActivityRewards {
|
||||
class CDActivityRewardsTable : public CDTable<CDActivityRewardsTable, std::vector<CDActivityRewards>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
// Queries the table with a custom "where" clause
|
||||
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "CDBaseCombatAIComponentTable.h"
|
||||
|
||||
namespace {
|
||||
// Default entries for fallback
|
||||
CDBaseCombatAIComponent defaultEntry{
|
||||
.id = 1,
|
||||
.behaviorType = 0,
|
||||
.combatRoundLength = 5.0f,
|
||||
.combatRole = 0,
|
||||
.minRoundLength = 3.0f,
|
||||
.maxRoundLength = 8.0f,
|
||||
.tetherSpeed = 4.0f,
|
||||
.pursuitSpeed = 2.0f,
|
||||
.combatStartDelay = 0.5f,
|
||||
.softTetherRadius = 25.0f,
|
||||
.hardTetherRadius = 100.0f,
|
||||
.spawnTimer = 0.0f,
|
||||
.tetherEffectID = 0,
|
||||
.ignoreMediator = false,
|
||||
.aggroRadius = 25.0f,
|
||||
.ignoreStatReset = false,
|
||||
.ignoreParent = false,
|
||||
};
|
||||
}
|
||||
|
||||
void CDBaseCombatAIComponentTable::LoadValuesFromDatabase() {
|
||||
// First, get the size of the table
|
||||
uint32_t size = 0;
|
||||
auto tableSize = CDClientDatabase::CreatePreppedStmt("SELECT COUNT(*) FROM BaseCombatAIComponent");
|
||||
auto tableSizeResult = tableSize.execQuery();
|
||||
while (!tableSizeResult.eof()) {
|
||||
size = tableSizeResult.getIntField(0, 0);
|
||||
tableSizeResult.nextRow();
|
||||
}
|
||||
tableSizeResult.finalize();
|
||||
|
||||
// Reserve the size
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.reserve(size);
|
||||
|
||||
// Now get the data
|
||||
auto tableData = CDClientDatabase::CreatePreppedStmt("SELECT * FROM BaseCombatAIComponent");
|
||||
auto tableDataResult = tableData.execQuery();
|
||||
|
||||
while (!tableDataResult.eof()) {
|
||||
CDBaseCombatAIComponent entry;
|
||||
|
||||
entry.id = tableDataResult.getIntField("id", -1);
|
||||
entry.behaviorType = tableDataResult.getIntField("behaviorType", 0);
|
||||
entry.combatRoundLength = tableDataResult.getFloatField("combatRoundLength", 5.0f);
|
||||
entry.combatRole = tableDataResult.getIntField("combatRole", 0);
|
||||
entry.minRoundLength = tableDataResult.getFloatField("minRoundLength", 3.0f);
|
||||
entry.maxRoundLength = tableDataResult.getFloatField("maxRoundLength", 8.0f);
|
||||
entry.tetherSpeed = tableDataResult.getFloatField("tetherSpeed", 4.0f);
|
||||
entry.pursuitSpeed = tableDataResult.getFloatField("pursuitSpeed", 2.0f);
|
||||
entry.combatStartDelay = tableDataResult.getFloatField("combatStartDelay", 0.5f);
|
||||
entry.softTetherRadius = tableDataResult.getFloatField("softTetherRadius", 25.0f);
|
||||
entry.hardTetherRadius = tableDataResult.getFloatField("hardTetherRadius", 100.0f);
|
||||
entry.spawnTimer = tableDataResult.getFloatField("spawnTimer", 0.0f);
|
||||
entry.tetherEffectID = tableDataResult.getIntField("tetherEffectID", 0);
|
||||
entry.ignoreMediator = tableDataResult.getIntField("ignoreMediator", 0) != 0;
|
||||
entry.aggroRadius = tableDataResult.getFloatField("aggroRadius", 25.0f);
|
||||
entry.ignoreStatReset = tableDataResult.getIntField("ignoreStatReset", 0) != 0;
|
||||
entry.ignoreParent = tableDataResult.getIntField("ignoreParent", 0) != 0;
|
||||
|
||||
entries.push_back(entry);
|
||||
tableDataResult.nextRow();
|
||||
}
|
||||
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDBaseCombatAIComponentTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
entries.push_back(defaultEntry);
|
||||
}
|
||||
|
||||
std::vector<CDBaseCombatAIComponent> CDBaseCombatAIComponentTable::Query(std::function<bool(CDBaseCombatAIComponent)> predicate) {
|
||||
std::vector<CDBaseCombatAIComponent> data = cpplinq::from(GetEntries())
|
||||
>> cpplinq::where(predicate)
|
||||
>> cpplinq::to_vector();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
const std::vector<CDBaseCombatAIComponent>& CDBaseCombatAIComponentTable::GetEntries() const {
|
||||
return CDTable::GetEntries();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef CDBASECOMBATAICOMPONENTTABLE_H
|
||||
#define CDBASECOMBATAICOMPONENTTABLE_H
|
||||
|
||||
#include "CDTable.h"
|
||||
|
||||
struct CDBaseCombatAIComponent {
|
||||
int32_t id;
|
||||
int32_t behaviorType;
|
||||
float combatRoundLength;
|
||||
int32_t combatRole;
|
||||
float minRoundLength;
|
||||
float maxRoundLength;
|
||||
float tetherSpeed;
|
||||
float pursuitSpeed;
|
||||
float combatStartDelay;
|
||||
float softTetherRadius;
|
||||
float hardTetherRadius;
|
||||
float spawnTimer;
|
||||
int32_t tetherEffectID;
|
||||
bool ignoreMediator;
|
||||
float aggroRadius;
|
||||
bool ignoreStatReset;
|
||||
bool ignoreParent;
|
||||
};
|
||||
|
||||
class CDBaseCombatAIComponentTable : public CDTable<CDBaseCombatAIComponentTable, std::vector<CDBaseCombatAIComponent>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
|
||||
std::vector<CDBaseCombatAIComponent> Query(std::function<bool(CDBaseCombatAIComponent)> predicate);
|
||||
const std::vector<CDBaseCombatAIComponent>& GetEntries() const;
|
||||
};
|
||||
|
||||
#endif //CDBASECOMBATAICOMPONENTTABLE_H
|
||||
@@ -20,6 +20,20 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDComponentsRegistryTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add some default component registrations for common LOTs
|
||||
// Component type ITEM (LOT 1000)
|
||||
entries.insert_or_assign(static_cast<uint64_t>(eReplicaComponentType::ITEM) << 32 | static_cast<uint64_t>(1000), 1);
|
||||
entries.insert_or_assign(1000, 0);
|
||||
|
||||
// Component type VENDOR (LOT 2000)
|
||||
entries.insert_or_assign(static_cast<uint64_t>(eReplicaComponentType::VENDOR) << 32 | static_cast<uint64_t>(2000), 1);
|
||||
entries.insert_or_assign(2000, 0);
|
||||
}
|
||||
|
||||
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
||||
auto& entries = GetEntriesMutable();
|
||||
auto exists = entries.find(id);
|
||||
@@ -28,6 +42,12 @@ int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponent
|
||||
return iter == entries.end() ? defaultValue : iter->second;
|
||||
}
|
||||
|
||||
// If database is not connected (e.g., in tests), return default value
|
||||
if (!CDClientDatabase::isConnected) {
|
||||
entries.insert_or_assign(id, 0);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Now get the data. Get all components of this entity so we dont do a query for each component
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;");
|
||||
query.bind(1, static_cast<int32_t>(id));
|
||||
|
||||
@@ -16,5 +16,6 @@ struct CDComponentsRegistry {
|
||||
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable, std::unordered_map<uint64_t, uint32_t>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
#include "CDCurrencyTableTable.h"
|
||||
|
||||
namespace {
|
||||
// Default entries for fallback
|
||||
CDCurrencyTable defaultEntry{
|
||||
.currencyIndex = 1,
|
||||
.npcminlevel = 1,
|
||||
.minvalue = 1,
|
||||
.maxvalue = 10,
|
||||
.id = 1,
|
||||
};
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
void CDCurrencyTableTable::LoadValuesFromDatabase() {
|
||||
|
||||
@@ -35,6 +46,12 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDCurrencyTableTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
entries.push_back(defaultEntry);
|
||||
}
|
||||
|
||||
std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCurrencyTable)> predicate) {
|
||||
std::vector<CDCurrencyTable> data = cpplinq::from(GetEntries())
|
||||
>> cpplinq::where(predicate)
|
||||
|
||||
@@ -21,6 +21,7 @@ struct CDCurrencyTable {
|
||||
class CDCurrencyTableTable : public CDTable<CDCurrencyTableTable, std::vector<CDCurrencyTable>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
// Queries the table with a custom "where" clause
|
||||
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
||||
};
|
||||
|
||||
@@ -70,6 +70,56 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDItemComponentTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add default item component entry
|
||||
CDItemComponent defaultEntry{
|
||||
.id = 1,
|
||||
.equipLocation = "",
|
||||
.baseValue = 0,
|
||||
.isKitPiece = false,
|
||||
.rarity = 0,
|
||||
.itemType = 0,
|
||||
.itemInfo = 0,
|
||||
.inLootTable = false,
|
||||
.inVendor = false,
|
||||
.isUnique = false,
|
||||
.isBOP = false,
|
||||
.isBOE = false,
|
||||
.reqFlagID = 0,
|
||||
.reqSpecialtyID = 0,
|
||||
.reqSpecRank = 0,
|
||||
.reqAchievementID = 0,
|
||||
.stackSize = 1,
|
||||
.color1 = 0,
|
||||
.decal = 0,
|
||||
.offsetGroupID = 0,
|
||||
.buildTypes = 0,
|
||||
.reqPrecondition = "",
|
||||
.animationFlag = 0,
|
||||
.equipEffects = 0,
|
||||
.readyForQA = false,
|
||||
.itemRating = 0,
|
||||
.isTwoHanded = false,
|
||||
.minNumRequired = 0,
|
||||
.delResIndex = 0,
|
||||
.currencyLOT = 0,
|
||||
.altCurrencyCost = 0,
|
||||
.subItems = "",
|
||||
.noEquipAnimation = false,
|
||||
.commendationLOT = 0,
|
||||
.commendationCost = 0,
|
||||
.currencyCosts = "",
|
||||
.locStatus = 0,
|
||||
.forgeType = 0,
|
||||
.SellMultiplier = 1.0f,
|
||||
};
|
||||
|
||||
entries.insert(std::make_pair(defaultEntry.id, defaultEntry));
|
||||
}
|
||||
|
||||
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skillID) {
|
||||
auto& entries = GetEntriesMutable();
|
||||
const auto& it = entries.find(skillID);
|
||||
@@ -77,6 +127,12 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skill
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// If database is not connected (e.g., in tests), return the default entry
|
||||
if (!CDClientDatabase::isConnected) {
|
||||
entries.insert(std::make_pair(skillID, Default));
|
||||
return Default;
|
||||
}
|
||||
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ItemComponent WHERE id = ?;");
|
||||
query.bind(1, static_cast<int32_t>(skillID));
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ struct CDItemComponent {
|
||||
class CDItemComponentTable : public CDTable<CDItemComponentTable, std::map<uint32_t, CDItemComponent>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
|
||||
|
||||
// Gets an entry by ID
|
||||
|
||||
@@ -39,6 +39,23 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
void CDLootMatrixTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add default loot matrix entry
|
||||
CDLootMatrix defaultEntry{
|
||||
.LootTableIndex = 1,
|
||||
.RarityTableIndex = 1,
|
||||
.percent = 1.0f,
|
||||
.minToDrop = 1,
|
||||
.maxToDrop = 1,
|
||||
.flagID = 0,
|
||||
};
|
||||
|
||||
entries[0].push_back(defaultEntry);
|
||||
}
|
||||
|
||||
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
|
||||
auto& entries = GetEntriesMutable();
|
||||
auto itr = entries.find(matrixId);
|
||||
@@ -46,6 +63,11 @@ const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// If database is not connected (e.g., in tests), return empty vector
|
||||
if (!CDClientDatabase::isConnected) {
|
||||
return entries[matrixId]; // Creates empty vector
|
||||
}
|
||||
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootMatrix where LootMatrixIndex = ?;");
|
||||
query.bind(1, static_cast<int32_t>(matrixId));
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ typedef std::vector<CDLootMatrix> LootMatrixEntries;
|
||||
class CDLootMatrixTable : public CDTable<CDLootMatrixTable, std::unordered_map<LootMatrixIndex, LootMatrixEntries>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
|
||||
// Gets a matrix by ID or inserts a blank one if none existed.
|
||||
const LootMatrixEntries& GetMatrix(uint32_t matrixId);
|
||||
|
||||
@@ -66,6 +66,21 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
void CDLootTableTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add default loot table entry
|
||||
CDLootTable defaultEntry{
|
||||
.itemid = 1000,
|
||||
.LootTableIndex = 1,
|
||||
.MissionDrop = false,
|
||||
.sortPriority = 1,
|
||||
};
|
||||
|
||||
entries[1].push_back(defaultEntry);
|
||||
}
|
||||
|
||||
const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) {
|
||||
auto& entries = GetEntriesMutable();
|
||||
auto itr = entries.find(tableId);
|
||||
@@ -73,6 +88,11 @@ const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) {
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// If database is not connected (e.g., in tests), return empty vector
|
||||
if (!CDClientDatabase::isConnected) {
|
||||
return entries[tableId]; // Creates empty vector
|
||||
}
|
||||
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootTable WHERE LootTableIndex = ?;");
|
||||
query.bind(1, static_cast<int32_t>(tableId));
|
||||
auto tableData = query.execQuery();
|
||||
|
||||
@@ -21,6 +21,7 @@ private:
|
||||
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
// Queries the table with a custom "where" clause
|
||||
const LootTableEntries& GetTable(const uint32_t tableId);
|
||||
};
|
||||
|
||||
@@ -83,6 +83,67 @@ void CDMissionsTable::LoadValuesFromDatabase() {
|
||||
Default.id = -1;
|
||||
}
|
||||
|
||||
void CDMissionsTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add default mission entry
|
||||
CDMissions defaultEntry{
|
||||
.id = 1,
|
||||
.defined_type = "Mission",
|
||||
.defined_subtype = "",
|
||||
.UISortOrder = 0,
|
||||
.offer_objectID = -1,
|
||||
.target_objectID = -1,
|
||||
.reward_currency = 0,
|
||||
.LegoScore = 0,
|
||||
.reward_reputation = 0,
|
||||
.isChoiceReward = false,
|
||||
.reward_item1 = 0,
|
||||
.reward_item1_count = 0,
|
||||
.reward_item2 = 0,
|
||||
.reward_item2_count = 0,
|
||||
.reward_item3 = 0,
|
||||
.reward_item3_count = 0,
|
||||
.reward_item4 = 0,
|
||||
.reward_item4_count = 0,
|
||||
.reward_emote = -1,
|
||||
.reward_emote2 = -1,
|
||||
.reward_emote3 = -1,
|
||||
.reward_emote4 = -1,
|
||||
.reward_maximagination = -1,
|
||||
.reward_maxhealth = -1,
|
||||
.reward_maxinventory = -1,
|
||||
.reward_maxmodel = -1,
|
||||
.reward_maxwidget = -1,
|
||||
.reward_maxwallet = -1,
|
||||
.repeatable = false,
|
||||
.reward_currency_repeatable = 0,
|
||||
.reward_item1_repeatable = 0,
|
||||
.reward_item1_repeat_count = 0,
|
||||
.reward_item2_repeatable = 0,
|
||||
.reward_item2_repeat_count = 0,
|
||||
.reward_item3_repeatable = 0,
|
||||
.reward_item3_repeat_count = 0,
|
||||
.reward_item4_repeatable = 0,
|
||||
.reward_item4_repeat_count = 0,
|
||||
.time_limit = -1,
|
||||
.isMission = true,
|
||||
.missionIconID = -1,
|
||||
.prereqMissionID = "",
|
||||
.localize = false,
|
||||
.inMOTD = false,
|
||||
.cooldownTime = -1,
|
||||
.isRandom = false,
|
||||
.randomPool = "",
|
||||
.UIPrereqID = -1,
|
||||
.reward_bankinventory = -1,
|
||||
};
|
||||
|
||||
entries.push_back(defaultEntry);
|
||||
Default.id = -1;
|
||||
}
|
||||
|
||||
std::vector<CDMissions> CDMissionsTable::Query(std::function<bool(CDMissions)> predicate) {
|
||||
|
||||
std::vector<CDMissions> data = cpplinq::from(GetEntries())
|
||||
|
||||
@@ -63,6 +63,7 @@ struct CDMissions {
|
||||
class CDMissionsTable : public CDTable<CDMissionsTable, std::vector<CDMissions>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
// Queries the table with a custom "where" clause
|
||||
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
||||
|
||||
|
||||
@@ -50,6 +50,22 @@ void CDSkillBehaviorTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDSkillBehaviorTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add default skill behavior entry
|
||||
CDSkillBehavior defaultEntry{
|
||||
.skillID = 1,
|
||||
.behaviorID = 1,
|
||||
.imaginationcost = 0,
|
||||
.cooldowngroup = 0,
|
||||
.cooldown = 0.0f,
|
||||
};
|
||||
|
||||
entries.insert(std::make_pair(defaultEntry.skillID, defaultEntry));
|
||||
}
|
||||
|
||||
const CDSkillBehavior& CDSkillBehaviorTable::GetSkillByID(uint32_t skillID) {
|
||||
auto& entries = GetEntries();
|
||||
auto it = entries.find(skillID);
|
||||
|
||||
@@ -28,6 +28,7 @@ struct CDSkillBehavior {
|
||||
class CDSkillBehaviorTable : public CDTable<CDSkillBehaviorTable, std::map<uint32_t, CDSkillBehavior>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
|
||||
// Gets an entry by skillID
|
||||
const CDSkillBehavior& GetSkillByID(uint32_t skillID);
|
||||
|
||||
@@ -34,6 +34,22 @@ void CDVendorComponentTable::LoadValuesFromDatabase() {
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
void CDVendorComponentTable::LoadValuesFromDefaults() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
entries.clear();
|
||||
|
||||
// Add default vendor component entry
|
||||
CDVendorComponent defaultEntry{
|
||||
.id = 1,
|
||||
.buyScalar = 1.0f,
|
||||
.sellScalar = 1.0f,
|
||||
.refreshTimeSeconds = 0.0f,
|
||||
.LootMatrixIndex = 0,
|
||||
};
|
||||
|
||||
entries.push_back(defaultEntry);
|
||||
}
|
||||
|
||||
//! Queries the table with a custom "where" clause
|
||||
std::vector<CDVendorComponent> CDVendorComponentTable::Query(std::function<bool(CDVendorComponent)> predicate) {
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ struct CDVendorComponent {
|
||||
class CDVendorComponentTable : public CDTable<CDVendorComponentTable, std::vector<CDVendorComponent>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
void LoadValuesFromDefaults();
|
||||
// Queries the table with a custom "where" clause
|
||||
std::vector<CDVendorComponent> Query(std::function<bool(CDVendorComponent)> predicate);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
||||
"CDActivityRewardsTable.cpp"
|
||||
"CDAnimationsTable.cpp"
|
||||
"CDBaseCombatAIComponentTable.cpp"
|
||||
"CDBehaviorParameterTable.cpp"
|
||||
"CDBehaviorTemplateTable.cpp"
|
||||
"CDBrickIDTableTable.cpp"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "CDClientDatabase.h"
|
||||
#include "CDClientManager.h"
|
||||
#include "CDBaseCombatAIComponentTable.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -41,31 +42,20 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
|
||||
m_ForcedTetherTime = 0.0f;
|
||||
|
||||
//Grab the aggro information from BaseCombatAI:
|
||||
auto componentQuery = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = ?;");
|
||||
componentQuery.bind(1, static_cast<int>(id));
|
||||
auto* componentTable = CDClientManager::GetTable<CDBaseCombatAIComponentTable>();
|
||||
auto componentEntries = componentTable->Query([id](CDBaseCombatAIComponent entry) {
|
||||
return entry.id == static_cast<int32_t>(id);
|
||||
});
|
||||
|
||||
auto componentResult = componentQuery.execQuery();
|
||||
|
||||
if (!componentResult.eof()) {
|
||||
if (!componentResult.fieldIsNull("aggroRadius"))
|
||||
m_AggroRadius = componentResult.getFloatField("aggroRadius");
|
||||
|
||||
if (!componentResult.fieldIsNull("tetherSpeed"))
|
||||
m_TetherSpeed = componentResult.getFloatField("tetherSpeed");
|
||||
|
||||
if (!componentResult.fieldIsNull("pursuitSpeed"))
|
||||
m_PursuitSpeed = componentResult.getFloatField("pursuitSpeed");
|
||||
|
||||
if (!componentResult.fieldIsNull("softTetherRadius"))
|
||||
m_SoftTetherRadius = componentResult.getFloatField("softTetherRadius");
|
||||
|
||||
if (!componentResult.fieldIsNull("hardTetherRadius"))
|
||||
m_HardTetherRadius = componentResult.getFloatField("hardTetherRadius");
|
||||
if (!componentEntries.empty()) {
|
||||
const auto& component = componentEntries[0];
|
||||
m_AggroRadius = component.aggroRadius;
|
||||
m_TetherSpeed = component.tetherSpeed;
|
||||
m_PursuitSpeed = component.pursuitSpeed;
|
||||
m_SoftTetherRadius = component.softTetherRadius;
|
||||
m_HardTetherRadius = component.hardTetherRadius;
|
||||
}
|
||||
|
||||
componentResult.finalize();
|
||||
|
||||
// Get aggro and tether radius from settings and use this if it is present. Only overwrite the
|
||||
// radii if it is greater than the one in the database.
|
||||
if (m_Parent) {
|
||||
@@ -78,28 +68,31 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
|
||||
/*
|
||||
* Find skills
|
||||
*/
|
||||
auto skillQuery = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);");
|
||||
skillQuery.bind(1, static_cast<int>(parent->GetLOT()));
|
||||
// Only execute skill query if database is connected
|
||||
if (CDClientDatabase::isConnected) {
|
||||
auto skillQuery = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);");
|
||||
skillQuery.bind(1, static_cast<int>(parent->GetLOT()));
|
||||
|
||||
auto result = skillQuery.execQuery();
|
||||
auto result = skillQuery.execQuery();
|
||||
|
||||
while (!result.eof()) {
|
||||
const auto skillId = static_cast<uint32_t>(result.getIntField("skillID"));
|
||||
while (!result.eof()) {
|
||||
const auto skillId = static_cast<uint32_t>(result.getIntField("skillID"));
|
||||
|
||||
const auto abilityCooldown = static_cast<float>(result.getFloatField("cooldown"));
|
||||
const auto abilityCooldown = static_cast<float>(result.getFloatField("cooldown"));
|
||||
|
||||
const auto behaviorId = static_cast<uint32_t>(result.getIntField("behaviorID"));
|
||||
const auto behaviorId = static_cast<uint32_t>(result.getIntField("behaviorID"));
|
||||
|
||||
auto* behavior = Behavior::CreateBehavior(behaviorId);
|
||||
auto* behavior = Behavior::CreateBehavior(behaviorId);
|
||||
|
||||
std::stringstream behaviorQuery;
|
||||
std::stringstream behaviorQuery;
|
||||
|
||||
AiSkillEntry entry = { skillId, 0, abilityCooldown, behavior };
|
||||
AiSkillEntry entry = { skillId, 0, abilityCooldown, behavior };
|
||||
|
||||
m_SkillEntries.push_back(entry);
|
||||
m_SkillEntries.push_back(entry);
|
||||
|
||||
result.nextRow();
|
||||
result.nextRow();
|
||||
}
|
||||
}
|
||||
|
||||
Stun(1.0f);
|
||||
|
||||
@@ -435,6 +435,12 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
|
||||
return pair->second;
|
||||
}
|
||||
|
||||
// If database is not connected (e.g., in tests), return empty parameters
|
||||
if (!CDClientDatabase::isConnected) {
|
||||
m_Cache.insert_or_assign(buffId, std::vector<BuffParameter>{});
|
||||
return m_Cache.find(buffId)->second;
|
||||
}
|
||||
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM BuffParameters WHERE BuffID = ?;");
|
||||
query.bind(1, static_cast<int>(buffId));
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLDocument;
|
||||
}
|
||||
@@ -12,7 +14,9 @@ namespace GameMessages {
|
||||
struct GameMsg;
|
||||
}
|
||||
|
||||
class Entity;
|
||||
namespace MessageType {
|
||||
enum class Game : uint16_t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component base class, provides methods for game loop updates, usage events and loading and saving to XML.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "EntityManager.h"
|
||||
#include "dConfig.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "../../dChatFilter/dChatFilter.h"
|
||||
#include "GameDatabase/TestSQL/TestSQLDatabase.h"
|
||||
#include "Database.h"
|
||||
#include <gtest/gtest.h>
|
||||
@@ -40,6 +41,9 @@ protected:
|
||||
Game::entityManager = new EntityManager();
|
||||
Game::zoneManager = new dZoneManager();
|
||||
Game::zoneManager->LoadZone(LWOZONEID(1, 0, 0));
|
||||
// Initialize a chat filter for tests. Use dontGenerateDCF=true to avoid
|
||||
// attempting to generate DCF files during unit tests.
|
||||
Game::chatFilter = new dChatFilter("", true);
|
||||
Database::_setDatabase(new TestSQLDatabase()); // this new is managed by the Database
|
||||
|
||||
// Create a CDClientManager instance and load from defaults
|
||||
@@ -50,6 +54,8 @@ protected:
|
||||
if (Game::server) delete Game::server;
|
||||
if (Game::entityManager) delete Game::entityManager;
|
||||
if (Game::zoneManager) delete Game::zoneManager;
|
||||
if (Game::chatFilter) delete Game::chatFilter;
|
||||
Game::chatFilter = nullptr;
|
||||
if (Game::logger) {
|
||||
Game::logger->Flush();
|
||||
delete Game::logger;
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "AchievementVendorComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
#include "MessageType/Game.h"
|
||||
|
||||
class AchievementVendorComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(AchievementVendorComponentTest, Serialize) {
|
||||
Entity testEntity(15, info);
|
||||
// Test initial update
|
||||
AchievementVendorComponent achievementVendorComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
achievementVendorComponent.Serialize(bitStream, true);
|
||||
|
||||
// Read the data manually to validate serialization format
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_TRUE(hasVendorInfo); // Should always be true for initial update
|
||||
|
||||
bool hasStandardCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasStandardCostItems));
|
||||
EXPECT_TRUE(hasStandardCostItems); // Set by RefreshInventory
|
||||
|
||||
bool hasMultiCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasMultiCostItems));
|
||||
EXPECT_FALSE(hasMultiCostItems); // Default state
|
||||
}
|
||||
|
||||
TEST_F(AchievementVendorComponentTest, SerializeRegularUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
AchievementVendorComponent achievementVendorComponent(&testEntity);
|
||||
|
||||
// Reset dirty flag by doing initial serialization
|
||||
RakNet::BitStream initStream;
|
||||
achievementVendorComponent.Serialize(initStream, true);
|
||||
|
||||
// Do a second regular serialization to clear the dirty flag
|
||||
RakNet::BitStream clearStream;
|
||||
achievementVendorComponent.Serialize(clearStream, false);
|
||||
|
||||
// Test regular update with no changes
|
||||
RakNet::BitStream bitStream;
|
||||
achievementVendorComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_FALSE(hasVendorInfo); // No dirty flags, so no data
|
||||
}
|
||||
|
||||
TEST_F(AchievementVendorComponentTest, SerializeWithDirtyVendor) {
|
||||
Entity testEntity(15, info);
|
||||
AchievementVendorComponent achievementVendorComponent(&testEntity);
|
||||
|
||||
// Reset dirty flag
|
||||
RakNet::BitStream initStream;
|
||||
achievementVendorComponent.Serialize(initStream, true);
|
||||
|
||||
// Make vendor dirty by changing state
|
||||
achievementVendorComponent.SetHasMultiCostItems(true);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
achievementVendorComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_TRUE(hasVendorInfo); // Should be true due to dirty flag
|
||||
|
||||
bool hasStandardCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasStandardCostItems));
|
||||
EXPECT_TRUE(hasStandardCostItems);
|
||||
|
||||
bool hasMultiCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasMultiCostItems));
|
||||
EXPECT_TRUE(hasMultiCostItems); // Changed to true
|
||||
}
|
||||
|
||||
TEST_F(AchievementVendorComponentTest, SerializeAfterDirtyCleared) {
|
||||
Entity testEntity(15, info);
|
||||
AchievementVendorComponent achievementVendorComponent(&testEntity);
|
||||
|
||||
// Make dirty
|
||||
achievementVendorComponent.SetHasMultiCostItems(true);
|
||||
|
||||
// Serialize once to clear dirty flag
|
||||
RakNet::BitStream firstStream;
|
||||
achievementVendorComponent.Serialize(firstStream, false);
|
||||
|
||||
// Serialize again - should show no vendor info
|
||||
RakNet::BitStream secondStream;
|
||||
achievementVendorComponent.Serialize(secondStream, false);
|
||||
|
||||
secondStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(secondStream.Read(hasVendorInfo));
|
||||
EXPECT_FALSE(hasVendorInfo); // Dirty flag should be cleared
|
||||
}
|
||||
126
tests/dGameTests/dComponentsTests/BaseCombatAIComponentTests.cpp
Normal file
126
tests/dGameTests/dComponentsTests/BaseCombatAIComponentTests.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class BaseCombatAIComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
BaseCombatAIComponent* combatAIComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
combatAIComponent = baseEntity->AddComponent<BaseCombatAIComponent>(1);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test serialization of BaseCombatAIComponent in initial update with default spawn state
|
||||
*/
|
||||
TEST_F(BaseCombatAIComponentTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Component should be dirty by default and in spawn state
|
||||
combatAIComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true); // Should always be true for initial update
|
||||
|
||||
uint32_t state;
|
||||
bitStream.Read(state);
|
||||
EXPECT_EQ(state, static_cast<uint32_t>(AiState::spawn)); // Default state is spawn
|
||||
|
||||
LWOOBJID target;
|
||||
bitStream.Read(target);
|
||||
EXPECT_EQ(target, LWOOBJID_EMPTY); // No target by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of BaseCombatAIComponent in regular update with clean state
|
||||
*/
|
||||
TEST_F(BaseCombatAIComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// First serialize to clear dirty flag
|
||||
combatAIComponent->Serialize(bitStream, false); // This clears the dirty flag
|
||||
bitStream.Reset();
|
||||
|
||||
// Now serialize again - should not be dirty
|
||||
combatAIComponent->Serialize(bitStream, false);
|
||||
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, false); // Should not be dirty after previous serialization
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization when target changes during regular updates
|
||||
*/
|
||||
TEST_F(BaseCombatAIComponentTest, SerializeTargetChangeTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Initial state is spawn, serialize once to clear dirty flag
|
||||
combatAIComponent->Serialize(bitStream, false);
|
||||
bitStream.Reset();
|
||||
|
||||
// Change target - this should set dirty flag
|
||||
LWOOBJID testTarget = 12345;
|
||||
combatAIComponent->SetTarget(testTarget);
|
||||
combatAIComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true); // Should be dirty due to target change
|
||||
|
||||
uint32_t state;
|
||||
bitStream.Read(state);
|
||||
EXPECT_EQ(state, static_cast<uint32_t>(AiState::spawn)); // Still in spawn state
|
||||
|
||||
LWOOBJID target;
|
||||
bitStream.Read(target);
|
||||
EXPECT_EQ(target, testTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization with target management and getters/setters
|
||||
*/
|
||||
TEST_F(BaseCombatAIComponentTest, SerializeWithTargetTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Set a target and change state manually
|
||||
LWOOBJID testTarget = 12345;
|
||||
combatAIComponent->SetTarget(testTarget);
|
||||
combatAIComponent->SetState(AiState::tether);
|
||||
|
||||
combatAIComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true); // Should be dirty due to target change
|
||||
|
||||
uint32_t state;
|
||||
bitStream.Read(state);
|
||||
EXPECT_EQ(state, static_cast<uint32_t>(AiState::tether));
|
||||
|
||||
LWOOBJID target;
|
||||
bitStream.Read(target);
|
||||
EXPECT_EQ(target, testTarget);
|
||||
|
||||
// Verify component state
|
||||
EXPECT_EQ(combatAIComponent->GetTarget(), testTarget);
|
||||
EXPECT_EQ(combatAIComponent->GetState(), AiState::tether);
|
||||
}
|
||||
116
tests/dGameTests/dComponentsTests/BouncerComponentTests.cpp
Normal file
116
tests/dGameTests/dComponentsTests/BouncerComponentTests.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "BouncerComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class BouncerTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
BouncerComponent* bouncerComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
// BouncerComponent constructor doesn't require parameters
|
||||
bouncerComponent = baseEntity->AddComponent<BouncerComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test serialization of a BouncerComponent with pet enabled false
|
||||
*/
|
||||
TEST_F(BouncerTest, SerializePetDisabledTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Default state should have pet disabled
|
||||
bouncerComponent->SetPetEnabled(false);
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
bouncerComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool petEnabled;
|
||||
bitStream.Read(petEnabled);
|
||||
EXPECT_EQ(petEnabled, false);
|
||||
|
||||
// When pet is disabled, there should be no additional data
|
||||
EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of a BouncerComponent with pet enabled true
|
||||
*/
|
||||
TEST_F(BouncerTest, SerializePetEnabledTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Enable pet and set bouncer state
|
||||
bouncerComponent->SetPetEnabled(true);
|
||||
bouncerComponent->SetPetBouncerEnabled(true);
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
bouncerComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool petEnabled;
|
||||
bitStream.Read(petEnabled);
|
||||
EXPECT_EQ(petEnabled, true);
|
||||
|
||||
bool petBouncerEnabled;
|
||||
bitStream.Read(petBouncerEnabled);
|
||||
EXPECT_EQ(petBouncerEnabled, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of a BouncerComponent with pet enabled but bouncer disabled
|
||||
*/
|
||||
TEST_F(BouncerTest, SerializePetEnabledBouncerDisabledTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Enable pet but disable bouncer
|
||||
bouncerComponent->SetPetEnabled(true);
|
||||
bouncerComponent->SetPetBouncerEnabled(false);
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
bouncerComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool petEnabled;
|
||||
bitStream.Read(petEnabled);
|
||||
EXPECT_EQ(petEnabled, true);
|
||||
|
||||
bool petBouncerEnabled;
|
||||
bitStream.Read(petBouncerEnabled);
|
||||
EXPECT_EQ(petBouncerEnabled, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization during initial update
|
||||
*/
|
||||
TEST_F(BouncerTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Enable pet and set bouncer state
|
||||
bouncerComponent->SetPetEnabled(true);
|
||||
bouncerComponent->SetPetBouncerEnabled(true);
|
||||
|
||||
// Now we test a serialization for correctness with initial update.
|
||||
bouncerComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data - behavior should be same as regular update
|
||||
bool petEnabled;
|
||||
bitStream.Read(petEnabled);
|
||||
EXPECT_EQ(petEnabled, true);
|
||||
|
||||
bool petBouncerEnabled;
|
||||
bitStream.Read(petBouncerEnabled);
|
||||
EXPECT_EQ(petBouncerEnabled, true);
|
||||
}
|
||||
232
tests/dGameTests/dComponentsTests/BuffComponentTests.cpp
Normal file
232
tests/dGameTests/dComponentsTests/BuffComponentTests.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "BuffComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class BuffComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
BuffComponent* buffComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
buffComponent = baseEntity->AddComponent<BuffComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test BuffComponent serialization with no buffs applied
|
||||
*/
|
||||
TEST_F(BuffComponentTest, SerializeNoBuffsTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// With no buffs, should serialize empty state
|
||||
buffComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool hasBuffs;
|
||||
bitStream.Read(hasBuffs);
|
||||
EXPECT_EQ(hasBuffs, false); // No buffs applied
|
||||
|
||||
bool immunityData;
|
||||
bitStream.Read(immunityData);
|
||||
EXPECT_EQ(immunityData, false); // Immunity data bit should be false
|
||||
}
|
||||
|
||||
/**
|
||||
* Test BuffComponent serialization with single buff applied
|
||||
*/
|
||||
TEST_F(BuffComponentTest, SerializeSingleBuffTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Apply a buff with specific properties
|
||||
int32_t buffId = 123;
|
||||
float duration = 5.0f;
|
||||
LWOOBJID source = 9876;
|
||||
|
||||
buffComponent->ApplyBuff(buffId, duration, source, false, false, false, false, false, true, true, false, false);
|
||||
buffComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool hasBuffs;
|
||||
bitStream.Read(hasBuffs);
|
||||
EXPECT_EQ(hasBuffs, true); // Has buffs
|
||||
|
||||
uint32_t buffCount;
|
||||
bitStream.Read(buffCount);
|
||||
EXPECT_EQ(buffCount, 1); // Should have 1 buff
|
||||
|
||||
// Read buff data
|
||||
uint32_t serializedBuffId;
|
||||
bitStream.Read(serializedBuffId);
|
||||
EXPECT_EQ(serializedBuffId, buffId);
|
||||
|
||||
bool hasTime;
|
||||
bitStream.Read(hasTime);
|
||||
EXPECT_EQ(hasTime, true); // Buff has time
|
||||
|
||||
uint32_t timeMs;
|
||||
bitStream.Read(timeMs);
|
||||
EXPECT_GT(timeMs, 0); // Should have positive time (approx 5000ms but could be slightly less due to timing)
|
||||
EXPECT_LE(timeMs, 5000); // Should not exceed initial duration
|
||||
|
||||
// Read cancel flags in order they're written
|
||||
bool cancelOnDeath;
|
||||
bitStream.Read(cancelOnDeath);
|
||||
EXPECT_EQ(cancelOnDeath, false); // Set to false in ApplyBuff call
|
||||
|
||||
bool cancelOnZone;
|
||||
bitStream.Read(cancelOnZone);
|
||||
EXPECT_EQ(cancelOnZone, false); // Set to false in ApplyBuff call
|
||||
|
||||
bool cancelOnDamaged;
|
||||
bitStream.Read(cancelOnDamaged);
|
||||
EXPECT_EQ(cancelOnDamaged, false); // Set to false in ApplyBuff call
|
||||
|
||||
bool cancelOnRemoveBuff;
|
||||
bitStream.Read(cancelOnRemoveBuff);
|
||||
EXPECT_EQ(cancelOnRemoveBuff, false); // Set to false in ApplyBuff call
|
||||
|
||||
bool cancelOnUi;
|
||||
bitStream.Read(cancelOnUi);
|
||||
EXPECT_EQ(cancelOnUi, true); // Set to true in ApplyBuff call
|
||||
|
||||
bool cancelOnLogout;
|
||||
bitStream.Read(cancelOnLogout);
|
||||
EXPECT_EQ(cancelOnLogout, false); // Set to false in ApplyBuff call
|
||||
|
||||
bool cancelOnUnequip;
|
||||
bitStream.Read(cancelOnUnequip);
|
||||
EXPECT_EQ(cancelOnUnequip, true); // Set to true in ApplyBuff call
|
||||
|
||||
bool cancelOnDamageAbsorbRanOut;
|
||||
bitStream.Read(cancelOnDamageAbsorbRanOut);
|
||||
EXPECT_EQ(cancelOnDamageAbsorbRanOut, false); // Always false
|
||||
|
||||
bool addedByTeammate;
|
||||
bitStream.Read(addedByTeammate);
|
||||
EXPECT_EQ(addedByTeammate, false); // No team setup in test
|
||||
|
||||
bool applyOnTeammates;
|
||||
bitStream.Read(applyOnTeammates);
|
||||
EXPECT_EQ(applyOnTeammates, false); // Set to false in ApplyBuff call
|
||||
|
||||
uint32_t refCount;
|
||||
bitStream.Read(refCount);
|
||||
EXPECT_EQ(refCount, 1); // Should have ref count of 1
|
||||
|
||||
bool immunityData;
|
||||
bitStream.Read(immunityData);
|
||||
EXPECT_EQ(immunityData, false); // Immunity data bit should be false
|
||||
}
|
||||
|
||||
/**
|
||||
* Test BuffComponent serialization with multiple buffs
|
||||
*/
|
||||
TEST_F(BuffComponentTest, SerializeMultipleBuffsTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Apply multiple buffs
|
||||
buffComponent->ApplyBuff(100, 3.0f, 1000);
|
||||
buffComponent->ApplyBuff(200, 0.0f, 2000); // Permanent buff (time = 0)
|
||||
buffComponent->ApplyBuff(300, 10.0f, 3000);
|
||||
|
||||
buffComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool hasBuffs;
|
||||
bitStream.Read(hasBuffs);
|
||||
EXPECT_EQ(hasBuffs, true);
|
||||
|
||||
uint32_t buffCount;
|
||||
bitStream.Read(buffCount);
|
||||
EXPECT_EQ(buffCount, 3); // Should have 3 buffs
|
||||
|
||||
// Read first buff (ID 100)
|
||||
uint32_t buffId1;
|
||||
bitStream.Read(buffId1);
|
||||
EXPECT_EQ(buffId1, 100);
|
||||
|
||||
bool hasTime1;
|
||||
bitStream.Read(hasTime1);
|
||||
EXPECT_EQ(hasTime1, true);
|
||||
|
||||
uint32_t timeMs1;
|
||||
bitStream.Read(timeMs1);
|
||||
EXPECT_GT(timeMs1, 0);
|
||||
EXPECT_LE(timeMs1, 3000);
|
||||
|
||||
// Skip the rest of first buff's flags (8 bools + team stuff + refcount)
|
||||
bool dummy;
|
||||
for (int i = 0; i < 8; i++) bitStream.Read(dummy); // cancel flags
|
||||
bitStream.Read(dummy); // addedByTeammate
|
||||
bitStream.Read(dummy); // applyOnTeammates
|
||||
uint32_t dummyInt;
|
||||
bitStream.Read(dummyInt); // refCount
|
||||
|
||||
// Read second buff (ID 200) - permanent buff
|
||||
uint32_t buffId2;
|
||||
bitStream.Read(buffId2);
|
||||
EXPECT_EQ(buffId2, 200);
|
||||
|
||||
bool hasTime2;
|
||||
bitStream.Read(hasTime2);
|
||||
EXPECT_EQ(hasTime2, false); // Permanent buff has no time
|
||||
|
||||
// Skip the rest of second buff's flags
|
||||
for (int i = 0; i < 8; i++) bitStream.Read(dummy);
|
||||
bitStream.Read(dummy);
|
||||
bitStream.Read(dummy);
|
||||
bitStream.Read(dummyInt);
|
||||
|
||||
// Read third buff (ID 300)
|
||||
uint32_t buffId3;
|
||||
bitStream.Read(buffId3);
|
||||
EXPECT_EQ(buffId3, 300);
|
||||
|
||||
bool hasTime3;
|
||||
bitStream.Read(hasTime3);
|
||||
EXPECT_EQ(hasTime3, true);
|
||||
|
||||
uint32_t timeMs3;
|
||||
bitStream.Read(timeMs3);
|
||||
EXPECT_GT(timeMs3, 0);
|
||||
EXPECT_LE(timeMs3, 10000);
|
||||
|
||||
// Skip the rest of third buff's flags
|
||||
for (int i = 0; i < 8; i++) bitStream.Read(dummy);
|
||||
bitStream.Read(dummy);
|
||||
bitStream.Read(dummy);
|
||||
bitStream.Read(dummyInt);
|
||||
|
||||
bool immunityData;
|
||||
bitStream.Read(immunityData);
|
||||
EXPECT_EQ(immunityData, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test BuffComponent regular update serialization (should not serialize)
|
||||
*/
|
||||
TEST_F(BuffComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Apply a buff first
|
||||
buffComponent->ApplyBuff(123, 5.0f, 9876);
|
||||
|
||||
// Regular update should not serialize anything
|
||||
buffComponent->Serialize(bitStream, false);
|
||||
|
||||
// BitStream should be empty for regular updates
|
||||
EXPECT_EQ(bitStream.GetNumberOfBitsUsed(), 0);
|
||||
}
|
||||
@@ -1,8 +1,30 @@
|
||||
set(DCOMPONENTS_TESTS
|
||||
"AchievementVendorComponentTests.cpp"
|
||||
"BaseCombatAIComponentTests.cpp"
|
||||
"BouncerComponentTests.cpp"
|
||||
"BuffComponentTests.cpp"
|
||||
"CollectibleComponentTests.cpp"
|
||||
"ControllablePhysicsComponentTests.cpp"
|
||||
"DestroyableComponentTests.cpp"
|
||||
"DonationVendorComponentTests.cpp"
|
||||
"HavokVehiclePhysicsComponentTests.cpp"
|
||||
"ItemComponentTests.cpp"
|
||||
"LevelProgressionComponentTests.cpp"
|
||||
"LUPExhibitComponentTests.cpp"
|
||||
"ModelComponentTests.cpp"
|
||||
"MovingPlatformComponentTests.cpp"
|
||||
"PetComponentTests.cpp"
|
||||
"SimplePhysicsComponentTests.cpp"
|
||||
"PhantomPhysicsComponentTests.cpp"
|
||||
"QuickBuildComponentTests.cpp"
|
||||
"RenderComponentTests.cpp"
|
||||
"SavingTests.cpp"
|
||||
"ScriptedActivityComponentTests.cpp"
|
||||
"ScriptComponentTests.cpp"
|
||||
"SimplePhysicsComponentTests.cpp"
|
||||
"SkillComponentTests.cpp"
|
||||
"SoundTriggerComponentTests.cpp"
|
||||
"SwitchComponentTests.cpp"
|
||||
"VendorComponentTests.cpp"
|
||||
)
|
||||
|
||||
# Get the folder name and prepend it to the files above
|
||||
|
||||
106
tests/dGameTests/dComponentsTests/CollectibleComponentTests.cpp
Normal file
106
tests/dGameTests/dComponentsTests/CollectibleComponentTests.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "CollectibleComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class CollectibleComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
CollectibleComponent* collectibleComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
collectibleComponent = baseEntity->AddComponent<CollectibleComponent>(123); // Test with collectibleId = 123
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test basic CollectibleComponent serialization
|
||||
*/
|
||||
TEST_F(CollectibleComponentTest, SerializeBasicTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Serialize the collectible component
|
||||
collectibleComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
int16_t collectibleId;
|
||||
bitStream.Read(collectibleId);
|
||||
EXPECT_EQ(collectibleId, 123); // Should match the ID we set
|
||||
|
||||
// Verify getter
|
||||
EXPECT_EQ(collectibleComponent->GetCollectibleId(), 123);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CollectibleComponent serialization with construction flag true
|
||||
*/
|
||||
TEST_F(CollectibleComponentTest, SerializeConstructionTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Serialize with construction = true
|
||||
collectibleComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
int16_t collectibleId;
|
||||
bitStream.Read(collectibleId);
|
||||
EXPECT_EQ(collectibleId, 123);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CollectibleComponent serialization with construction flag false
|
||||
*/
|
||||
TEST_F(CollectibleComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Serialize with construction = false
|
||||
collectibleComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
int16_t collectibleId;
|
||||
bitStream.Read(collectibleId);
|
||||
EXPECT_EQ(collectibleId, 123); // Should still serialize the same way
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CollectibleComponent with different collectible IDs
|
||||
*/
|
||||
TEST_F(CollectibleComponentTest, DifferentIDsTest) {
|
||||
// Create another entity with a different collectible ID
|
||||
Entity* anotherEntity = new Entity(16, GameDependenciesTest::info);
|
||||
CollectibleComponent* anotherCollectible = anotherEntity->AddComponent<CollectibleComponent>(456);
|
||||
|
||||
bitStream.Reset();
|
||||
|
||||
// Serialize the first collectible
|
||||
collectibleComponent->Serialize(bitStream, true);
|
||||
|
||||
int16_t firstId;
|
||||
bitStream.Read(firstId);
|
||||
EXPECT_EQ(firstId, 123);
|
||||
|
||||
bitStream.Reset();
|
||||
|
||||
// Serialize the second collectible
|
||||
anotherCollectible->Serialize(bitStream, true);
|
||||
|
||||
int16_t secondId;
|
||||
bitStream.Read(secondId);
|
||||
EXPECT_EQ(secondId, 456);
|
||||
|
||||
// Verify getters
|
||||
EXPECT_EQ(collectibleComponent->GetCollectibleId(), 123);
|
||||
EXPECT_EQ(anotherCollectible->GetCollectibleId(), 456);
|
||||
|
||||
delete anotherEntity;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class ControllablePhysicsComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
ControllablePhysicsComponent* controllablePhysicsComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
controllablePhysicsComponent = baseEntity->AddComponent<ControllablePhysicsComponent>(1);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test ControllablePhysicsComponent initial update serialization
|
||||
*/
|
||||
TEST_F(ControllablePhysicsComponentTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Test initial update serialization
|
||||
controllablePhysicsComponent->Serialize(bitStream, true);
|
||||
|
||||
// ControllablePhysicsComponent inherits from PhysicsComponent, so it serializes
|
||||
// position data first, then its own data. Just verify it produces output.
|
||||
EXPECT_GT(bitStream.GetNumberOfBitsUsed(), 0);
|
||||
|
||||
// Verify the component exists and has reasonable default values
|
||||
EXPECT_FALSE(controllablePhysicsComponent->GetIsOnRail());
|
||||
EXPECT_EQ(controllablePhysicsComponent->GetSpeedMultiplier(), 1.0f);
|
||||
EXPECT_EQ(controllablePhysicsComponent->GetGravityScale(), 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ControllablePhysicsComponent jetpack mode serialization
|
||||
*/
|
||||
TEST_F(ControllablePhysicsComponentTest, SerializeJetpackTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Set jetpack mode
|
||||
controllablePhysicsComponent->SetInJetpackMode(true);
|
||||
|
||||
// Test serialization with jetpack mode
|
||||
controllablePhysicsComponent->Serialize(bitStream, true);
|
||||
|
||||
// Verify it produces output and jetpack mode is set
|
||||
EXPECT_GT(bitStream.GetNumberOfBitsUsed(), 0);
|
||||
EXPECT_TRUE(controllablePhysicsComponent->GetInJetpackMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ControllablePhysicsComponent regular update serialization
|
||||
*/
|
||||
TEST_F(ControllablePhysicsComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Do an initial update to clear dirty flags
|
||||
controllablePhysicsComponent->Serialize(bitStream, true);
|
||||
|
||||
bitStream.Reset();
|
||||
|
||||
// Test regular update serialization
|
||||
controllablePhysicsComponent->Serialize(bitStream, false);
|
||||
|
||||
// Should produce some output (at least physics position data)
|
||||
EXPECT_GT(bitStream.GetNumberOfBitsUsed(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ControllablePhysicsComponent position change serialization
|
||||
*/
|
||||
TEST_F(ControllablePhysicsComponentTest, SerializePositionChangeTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Change position to trigger dirty position flag
|
||||
NiPoint3 newPos(100.0f, 200.0f, 300.0f);
|
||||
controllablePhysicsComponent->SetPosition(newPos);
|
||||
|
||||
// Test serialization with position change
|
||||
controllablePhysicsComponent->Serialize(bitStream, false);
|
||||
|
||||
// Should produce output due to position change
|
||||
EXPECT_GT(bitStream.GetNumberOfBitsUsed(), 0);
|
||||
|
||||
// Verify the position was set
|
||||
auto pos = controllablePhysicsComponent->GetPosition();
|
||||
EXPECT_EQ(pos.x, 100.0f);
|
||||
EXPECT_EQ(pos.y, 200.0f);
|
||||
EXPECT_EQ(pos.z, 300.0f);
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eStateChangeType.h"
|
||||
|
||||
class DestroyableTest : public GameDependenciesTest {
|
||||
class DestroyableComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
DestroyableComponent* destroyableComponent;
|
||||
@@ -36,7 +36,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DestroyableTest, PlacementNewAddComponentTest) {
|
||||
TEST_F(DestroyableComponentTest, PlacementNewAddComponentTest) {
|
||||
ASSERT_NE(destroyableComponent, nullptr);
|
||||
ASSERT_EQ(destroyableComponent->GetArmor(), 7);
|
||||
baseEntity->AddComponent<DestroyableComponent>();
|
||||
@@ -47,7 +47,7 @@ TEST_F(DestroyableTest, PlacementNewAddComponentTest) {
|
||||
/**
|
||||
* Test Construction of a DestroyableComponent
|
||||
*/
|
||||
TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) {
|
||||
TEST_F(DestroyableComponentTest, SerializeConstructionTest) {
|
||||
destroyableComponent->Serialize(bitStream, true);
|
||||
// Assert that the full number of bits are present
|
||||
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 748);
|
||||
@@ -172,7 +172,7 @@ TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) {
|
||||
/**
|
||||
* Test serialization of a DestroyableComponent
|
||||
*/
|
||||
TEST_F(DestroyableTest, DestroyableComponentSerializeTest) {
|
||||
TEST_F(DestroyableComponentTest, SerializeTest) {
|
||||
bitStream.Reset();
|
||||
// Initialize some values to be not default so we can test a full serialization
|
||||
destroyableComponent->SetMaxHealth(1233.0f);
|
||||
@@ -250,7 +250,7 @@ TEST_F(DestroyableTest, DestroyableComponentSerializeTest) {
|
||||
/**
|
||||
* Test the Damage method of DestroyableComponent
|
||||
*/
|
||||
TEST_F(DestroyableTest, DestroyableComponentDamageTest) {
|
||||
TEST_F(DestroyableComponentTest, DamageTest) {
|
||||
// Do some actions
|
||||
destroyableComponent->SetMaxHealth(100.0f);
|
||||
destroyableComponent->SetHealth(100);
|
||||
@@ -318,12 +318,12 @@ TEST_F(DestroyableTest, DestroyableComponentDamageTest) {
|
||||
ASSERT_EQ(destroyableComponent->GetImagination(), 100);
|
||||
}
|
||||
|
||||
TEST_F(DestroyableTest, DestroyableComponentFactionTest) {
|
||||
TEST_F(DestroyableComponentTest, FactionTest) {
|
||||
ASSERT_TRUE(destroyableComponent->HasFaction(-1));
|
||||
ASSERT_TRUE(destroyableComponent->HasFaction(6));
|
||||
}
|
||||
|
||||
TEST_F(DestroyableTest, DestroyableComponentValiditiyTest) {
|
||||
TEST_F(DestroyableComponentTest, ValiditiyTest) {
|
||||
auto* enemyEntity = new Entity(19, info);
|
||||
enemyEntity->AddComponent<DestroyableComponent>()->AddFactionNoLookup(16);
|
||||
destroyableComponent->AddEnemyFaction(16);
|
||||
@@ -332,7 +332,7 @@ TEST_F(DestroyableTest, DestroyableComponentValiditiyTest) {
|
||||
delete enemyEntity;
|
||||
}
|
||||
|
||||
TEST_F(DestroyableTest, DestroyableComponentImmunityTest) {
|
||||
TEST_F(DestroyableComponentTest, ImmunityTest) {
|
||||
// assert to show that they are empty
|
||||
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
|
||||
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
|
||||
@@ -539,7 +539,7 @@ TEST_F(DestroyableTest, DestroyableComponentImmunityTest) {
|
||||
/**
|
||||
* Test the Damage cooldown timer of DestroyableComponent
|
||||
*/
|
||||
TEST_F(DestroyableTest, DestroyableComponentDamageCooldownTest) {
|
||||
TEST_F(DestroyableComponentTest, DamageCooldownTest) {
|
||||
// Test the damage immune timer state (anything above 0.0f)
|
||||
destroyableComponent->SetDamageCooldownTimer(1.0f);
|
||||
EXPECT_FLOAT_EQ(destroyableComponent->GetDamageCooldownTimer(), 1.0f);
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "DonationVendorComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class DonationVendorComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
DonationVendorComponent* donationVendorComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
// Set a custom goal for testing
|
||||
baseEntity->SetVar<int32_t>(u"donationGoal", 1000);
|
||||
baseEntity->SetVar<uint32_t>(u"activityID", 123);
|
||||
donationVendorComponent = baseEntity->AddComponent<DonationVendorComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
// Test initial serialization with no donations
|
||||
TEST_F(DonationVendorComponentTest, InitialSerialization) {
|
||||
donationVendorComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read VendorComponent serialization first
|
||||
bool vendorDirtyFlag;
|
||||
bitStream.Read(vendorDirtyFlag);
|
||||
EXPECT_TRUE(vendorDirtyFlag); // Should be true for initial update
|
||||
|
||||
if (vendorDirtyFlag) {
|
||||
bool hasStandardCostItems;
|
||||
bool hasMultiCostItems;
|
||||
bitStream.Read(hasStandardCostItems);
|
||||
bitStream.Read(hasMultiCostItems);
|
||||
// These may be true if vendor has items during construction
|
||||
// Just verify we can read them without asserting specific values
|
||||
}
|
||||
|
||||
// Read DonationVendorComponent serialization
|
||||
bool donationDirtyFlag;
|
||||
bitStream.Read(donationDirtyFlag);
|
||||
EXPECT_TRUE(donationDirtyFlag); // Should be true for initial update
|
||||
|
||||
if (donationDirtyFlag) {
|
||||
float percentComplete;
|
||||
int32_t totalDonated;
|
||||
int32_t totalRemaining;
|
||||
|
||||
bitStream.Read(percentComplete);
|
||||
bitStream.Read(totalDonated);
|
||||
bitStream.Read(totalRemaining);
|
||||
|
||||
EXPECT_EQ(percentComplete, 0.0f);
|
||||
EXPECT_EQ(totalDonated, 0);
|
||||
EXPECT_EQ(totalRemaining, 1000);
|
||||
}
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test serialization after donations
|
||||
TEST_F(DonationVendorComponentTest, SerializationAfterDonations) {
|
||||
// Do initial serialization to populate and clear dirty flags
|
||||
RakNet::BitStream initStream;
|
||||
donationVendorComponent->Serialize(initStream, true);
|
||||
|
||||
// Submit some donations (this will set the donation dirty flag)
|
||||
donationVendorComponent->SubmitDonation(250);
|
||||
|
||||
donationVendorComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read VendorComponent serialization first
|
||||
bool vendorDirtyFlag;
|
||||
bitStream.Read(vendorDirtyFlag);
|
||||
EXPECT_TRUE(vendorDirtyFlag); // Should be true for regular update with no vendor changes
|
||||
|
||||
if (vendorDirtyFlag) {
|
||||
bool hasStandardCostItems;
|
||||
bool hasMultiCostItems;
|
||||
bitStream.Read(hasStandardCostItems);
|
||||
bitStream.Read(hasMultiCostItems);
|
||||
// These may be true if vendor has items during construction
|
||||
// Just verify we can read them without asserting specific values
|
||||
}
|
||||
// Read DonationVendorComponent serialization
|
||||
bool donationDirtyFlag;
|
||||
bitStream.Read(donationDirtyFlag);
|
||||
EXPECT_TRUE(donationDirtyFlag); // Should be true because we submitted donations
|
||||
|
||||
if (donationDirtyFlag) {
|
||||
float percentComplete;
|
||||
int32_t totalDonated;
|
||||
int32_t totalRemaining;
|
||||
|
||||
bitStream.Read(percentComplete);
|
||||
bitStream.Read(totalDonated);
|
||||
bitStream.Read(totalRemaining);
|
||||
|
||||
EXPECT_EQ(percentComplete, 0.25f); // 250/1000 = 0.25
|
||||
EXPECT_EQ(totalDonated, 250);
|
||||
EXPECT_EQ(totalRemaining, 750);
|
||||
}
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test default jawbox activity (ID 117)
|
||||
TEST_F(DonationVendorComponentTest, JawboxActivitySerialization) {
|
||||
delete baseEntity;
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
baseEntity->SetVar<uint32_t>(u"activityID", 117); // Jawbox activity
|
||||
donationVendorComponent = baseEntity->AddComponent<DonationVendorComponent>();
|
||||
|
||||
donationVendorComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read VendorComponent serialization first
|
||||
bool vendorDirtyFlag;
|
||||
bitStream.Read(vendorDirtyFlag);
|
||||
EXPECT_TRUE(vendorDirtyFlag);
|
||||
|
||||
if (vendorDirtyFlag) {
|
||||
bool hasStandardCostItems;
|
||||
bool hasMultiCostItems;
|
||||
bitStream.Read(hasStandardCostItems);
|
||||
bitStream.Read(hasMultiCostItems);
|
||||
}
|
||||
|
||||
// Read DonationVendorComponent serialization
|
||||
bool donationDirtyFlag;
|
||||
bitStream.Read(donationDirtyFlag);
|
||||
EXPECT_TRUE(donationDirtyFlag);
|
||||
|
||||
if (donationDirtyFlag) {
|
||||
float percentComplete;
|
||||
int32_t totalDonated;
|
||||
int32_t totalRemaining;
|
||||
|
||||
bitStream.Read(percentComplete);
|
||||
bitStream.Read(totalDonated);
|
||||
bitStream.Read(totalRemaining);
|
||||
|
||||
// Jawbox activity should show as complete
|
||||
EXPECT_EQ(percentComplete, 1.0f);
|
||||
EXPECT_EQ(totalDonated, INT32_MAX);
|
||||
EXPECT_EQ(totalRemaining, 0);
|
||||
}
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test regular update without changes (dirty flag should be false)
|
||||
TEST_F(DonationVendorComponentTest, RegularUpdateWithoutChanges) {
|
||||
// Do initial update to populate data
|
||||
donationVendorComponent->Serialize(bitStream, true);
|
||||
bitStream.Reset();
|
||||
|
||||
// Do a regular update to clear vendor dirty flag
|
||||
donationVendorComponent->Serialize(bitStream, false);
|
||||
bitStream.Reset();
|
||||
|
||||
// Now do another regular update without any changes
|
||||
donationVendorComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read VendorComponent serialization first
|
||||
bool vendorDirtyFlag;
|
||||
bitStream.Read(vendorDirtyFlag);
|
||||
EXPECT_FALSE(vendorDirtyFlag);
|
||||
|
||||
// Read DonationVendorComponent serialization
|
||||
bool donationDirtyFlag;
|
||||
bitStream.Read(donationDirtyFlag);
|
||||
EXPECT_FALSE(donationDirtyFlag); // Should be false since nothing changed
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "HavokVehiclePhysicsComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "PositionUpdate.h"
|
||||
|
||||
class HavokVehiclePhysicsComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
HavokVehiclePhysicsComponent* havokVehiclePhysicsComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
havokVehiclePhysicsComponent = baseEntity->AddComponent<HavokVehiclePhysicsComponent>(1);
|
||||
// Initialize some values to be not default
|
||||
havokVehiclePhysicsComponent->SetPosition(NiPoint3(10.0f, 20.0f, 30.0f));
|
||||
havokVehiclePhysicsComponent->SetRotation(NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f));
|
||||
havokVehiclePhysicsComponent->SetVelocity(NiPoint3(5.0f, 6.0f, 7.0f));
|
||||
havokVehiclePhysicsComponent->SetAngularVelocity(NiPoint3(8.0f, 9.0f, 10.0f));
|
||||
havokVehiclePhysicsComponent->SetIsOnGround(true);
|
||||
havokVehiclePhysicsComponent->SetIsOnRail(false);
|
||||
|
||||
// Set remote input info
|
||||
RemoteInputInfo remoteInput;
|
||||
remoteInput.m_RemoteInputX = 0.5f;
|
||||
remoteInput.m_RemoteInputY = -0.3f;
|
||||
remoteInput.m_IsPowersliding = true;
|
||||
remoteInput.m_IsModified = false;
|
||||
havokVehiclePhysicsComponent->SetRemoteInputInfo(remoteInput);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test serialization of HavokVehiclePhysicsComponent during initial update
|
||||
*/
|
||||
TEST_F(HavokVehiclePhysicsComponentTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Now we test a serialization for correctness with initial update.
|
||||
havokVehiclePhysicsComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
|
||||
// First, check if position data is written
|
||||
bool hasPositionData;
|
||||
bitStream.Read(hasPositionData);
|
||||
EXPECT_EQ(hasPositionData, true);
|
||||
|
||||
if (hasPositionData) {
|
||||
// Position
|
||||
float posX, posY, posZ;
|
||||
bitStream.Read(posX);
|
||||
bitStream.Read(posY);
|
||||
bitStream.Read(posZ);
|
||||
EXPECT_EQ(posX, 10.0f);
|
||||
EXPECT_EQ(posY, 20.0f);
|
||||
EXPECT_EQ(posZ, 30.0f);
|
||||
|
||||
// Rotation (x, y, z, w order)
|
||||
float rotX, rotY, rotZ, rotW;
|
||||
bitStream.Read(rotX);
|
||||
bitStream.Read(rotY);
|
||||
bitStream.Read(rotZ);
|
||||
bitStream.Read(rotW);
|
||||
EXPECT_EQ(rotX, 1.0f);
|
||||
EXPECT_EQ(rotY, 2.0f);
|
||||
EXPECT_EQ(rotZ, 3.0f);
|
||||
EXPECT_EQ(rotW, 4.0f);
|
||||
|
||||
// Ground and rail status
|
||||
bool isOnGround, isOnRail;
|
||||
bitStream.Read(isOnGround);
|
||||
bitStream.Read(isOnRail);
|
||||
EXPECT_EQ(isOnGround, true);
|
||||
EXPECT_EQ(isOnRail, false);
|
||||
|
||||
// Velocity (conditional)
|
||||
bool hasVelocity;
|
||||
bitStream.Read(hasVelocity);
|
||||
EXPECT_EQ(hasVelocity, true);
|
||||
|
||||
if (hasVelocity) {
|
||||
float velX, velY, velZ;
|
||||
bitStream.Read(velX);
|
||||
bitStream.Read(velY);
|
||||
bitStream.Read(velZ);
|
||||
EXPECT_EQ(velX, 5.0f);
|
||||
EXPECT_EQ(velY, 6.0f);
|
||||
EXPECT_EQ(velZ, 7.0f);
|
||||
}
|
||||
|
||||
// Angular velocity (conditional)
|
||||
bool hasAngularVelocity;
|
||||
bitStream.Read(hasAngularVelocity);
|
||||
EXPECT_EQ(hasAngularVelocity, true);
|
||||
|
||||
if (hasAngularVelocity) {
|
||||
float angVelX, angVelY, angVelZ;
|
||||
bitStream.Read(angVelX);
|
||||
bitStream.Read(angVelY);
|
||||
bitStream.Read(angVelZ);
|
||||
EXPECT_EQ(angVelX, 8.0f);
|
||||
EXPECT_EQ(angVelY, 9.0f);
|
||||
EXPECT_EQ(angVelZ, 10.0f);
|
||||
}
|
||||
|
||||
// Local space info (always false for now)
|
||||
bool hasLocalSpaceInfo;
|
||||
bitStream.Read(hasLocalSpaceInfo);
|
||||
EXPECT_EQ(hasLocalSpaceInfo, false);
|
||||
|
||||
// Remote input info (always true)
|
||||
bool hasRemoteInputInfo;
|
||||
bitStream.Read(hasRemoteInputInfo);
|
||||
EXPECT_EQ(hasRemoteInputInfo, true);
|
||||
|
||||
if (hasRemoteInputInfo) {
|
||||
float remoteInputX, remoteInputY;
|
||||
bool isPowersliding, isModified;
|
||||
bitStream.Read(remoteInputX);
|
||||
bitStream.Read(remoteInputY);
|
||||
bitStream.Read(isPowersliding);
|
||||
bitStream.Read(isModified);
|
||||
|
||||
EXPECT_EQ(remoteInputX, 0.5f);
|
||||
EXPECT_EQ(remoteInputY, -0.3f);
|
||||
EXPECT_EQ(isPowersliding, true);
|
||||
EXPECT_EQ(isModified, false);
|
||||
}
|
||||
|
||||
// Remote input ping (always 125.0f)
|
||||
float remoteInputPing;
|
||||
bitStream.Read(remoteInputPing);
|
||||
EXPECT_EQ(remoteInputPing, 125.0f);
|
||||
}
|
||||
|
||||
// Initial update specific data
|
||||
uint8_t endBehavior;
|
||||
bitStream.Read(endBehavior);
|
||||
EXPECT_GE(endBehavior, 0); // Generated randomly between 0-7
|
||||
EXPECT_LE(endBehavior, 7);
|
||||
|
||||
bool isInputLocked;
|
||||
bitStream.Read(isInputLocked);
|
||||
EXPECT_EQ(isInputLocked, true); // Always true
|
||||
|
||||
// Final flag (always false)
|
||||
bool finalFlag;
|
||||
bitStream.Read(finalFlag);
|
||||
EXPECT_EQ(finalFlag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of HavokVehiclePhysicsComponent during regular update
|
||||
*/
|
||||
TEST_F(HavokVehiclePhysicsComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Now we test a serialization for correctness with regular update.
|
||||
havokVehiclePhysicsComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
|
||||
// First, check if position data is written
|
||||
bool hasPositionData;
|
||||
bitStream.Read(hasPositionData);
|
||||
EXPECT_EQ(hasPositionData, true);
|
||||
|
||||
if (hasPositionData) {
|
||||
// Position
|
||||
float posX, posY, posZ;
|
||||
bitStream.Read(posX);
|
||||
bitStream.Read(posY);
|
||||
bitStream.Read(posZ);
|
||||
EXPECT_EQ(posX, 10.0f);
|
||||
EXPECT_EQ(posY, 20.0f);
|
||||
EXPECT_EQ(posZ, 30.0f);
|
||||
|
||||
// Rotation (x, y, z, w order)
|
||||
float rotX, rotY, rotZ, rotW;
|
||||
bitStream.Read(rotX);
|
||||
bitStream.Read(rotY);
|
||||
bitStream.Read(rotZ);
|
||||
bitStream.Read(rotW);
|
||||
EXPECT_EQ(rotX, 1.0f);
|
||||
EXPECT_EQ(rotY, 2.0f);
|
||||
EXPECT_EQ(rotZ, 3.0f);
|
||||
EXPECT_EQ(rotW, 4.0f);
|
||||
|
||||
// Ground and rail status
|
||||
bool isOnGround, isOnRail;
|
||||
bitStream.Read(isOnGround);
|
||||
bitStream.Read(isOnRail);
|
||||
EXPECT_EQ(isOnGround, true);
|
||||
EXPECT_EQ(isOnRail, false);
|
||||
|
||||
// Velocity (conditional)
|
||||
bool hasVelocity;
|
||||
bitStream.Read(hasVelocity);
|
||||
EXPECT_EQ(hasVelocity, true);
|
||||
|
||||
if (hasVelocity) {
|
||||
float velX, velY, velZ;
|
||||
bitStream.Read(velX);
|
||||
bitStream.Read(velY);
|
||||
bitStream.Read(velZ);
|
||||
EXPECT_EQ(velX, 5.0f);
|
||||
EXPECT_EQ(velY, 6.0f);
|
||||
EXPECT_EQ(velZ, 7.0f);
|
||||
}
|
||||
|
||||
// Angular velocity (conditional)
|
||||
bool hasAngularVelocity;
|
||||
bitStream.Read(hasAngularVelocity);
|
||||
EXPECT_EQ(hasAngularVelocity, true);
|
||||
|
||||
if (hasAngularVelocity) {
|
||||
float angVelX, angVelY, angVelZ;
|
||||
bitStream.Read(angVelX);
|
||||
bitStream.Read(angVelY);
|
||||
bitStream.Read(angVelZ);
|
||||
EXPECT_EQ(angVelX, 8.0f);
|
||||
EXPECT_EQ(angVelY, 9.0f);
|
||||
EXPECT_EQ(angVelZ, 10.0f);
|
||||
}
|
||||
|
||||
// Local space info (always false for now)
|
||||
bool hasLocalSpaceInfo;
|
||||
bitStream.Read(hasLocalSpaceInfo);
|
||||
EXPECT_EQ(hasLocalSpaceInfo, false);
|
||||
|
||||
// Remote input info (always true)
|
||||
bool hasRemoteInputInfo;
|
||||
bitStream.Read(hasRemoteInputInfo);
|
||||
EXPECT_EQ(hasRemoteInputInfo, true);
|
||||
|
||||
if (hasRemoteInputInfo) {
|
||||
float remoteInputX, remoteInputY;
|
||||
bool isPowersliding, isModified;
|
||||
bitStream.Read(remoteInputX);
|
||||
bitStream.Read(remoteInputY);
|
||||
bitStream.Read(isPowersliding);
|
||||
bitStream.Read(isModified);
|
||||
|
||||
EXPECT_EQ(remoteInputX, 0.5f);
|
||||
EXPECT_EQ(remoteInputY, -0.3f);
|
||||
EXPECT_EQ(isPowersliding, true);
|
||||
EXPECT_EQ(isModified, false);
|
||||
}
|
||||
|
||||
// Remote input ping (always 125.0f)
|
||||
float remoteInputPing;
|
||||
bitStream.Read(remoteInputPing);
|
||||
EXPECT_EQ(remoteInputPing, 125.0f);
|
||||
|
||||
// Regular update has an additional flag
|
||||
bool extraFlag;
|
||||
bitStream.Read(extraFlag);
|
||||
EXPECT_EQ(extraFlag, false);
|
||||
}
|
||||
|
||||
// Final flag (always false)
|
||||
bool finalFlag;
|
||||
bitStream.Read(finalFlag);
|
||||
EXPECT_EQ(finalFlag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization with zero velocities
|
||||
*/
|
||||
TEST_F(HavokVehiclePhysicsComponentTest, SerializeZeroVelocitiesTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Set velocities to zero
|
||||
havokVehiclePhysicsComponent->SetVelocity(NiPoint3(0.0f, 0.0f, 0.0f));
|
||||
havokVehiclePhysicsComponent->SetAngularVelocity(NiPoint3(0.0f, 0.0f, 0.0f));
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
havokVehiclePhysicsComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
|
||||
// First, check if position data is written
|
||||
bool hasPositionData;
|
||||
bitStream.Read(hasPositionData);
|
||||
EXPECT_EQ(hasPositionData, true);
|
||||
|
||||
if (hasPositionData) {
|
||||
// Skip position and rotation data
|
||||
float posX, posY, posZ;
|
||||
bitStream.Read(posX);
|
||||
bitStream.Read(posY);
|
||||
bitStream.Read(posZ);
|
||||
|
||||
float rotX, rotY, rotZ, rotW;
|
||||
bitStream.Read(rotX);
|
||||
bitStream.Read(rotY);
|
||||
bitStream.Read(rotZ);
|
||||
bitStream.Read(rotW);
|
||||
|
||||
bool isOnGround, isOnRail;
|
||||
bitStream.Read(isOnGround);
|
||||
bitStream.Read(isOnRail);
|
||||
|
||||
// Velocity should be false since it's zero
|
||||
bool hasVelocity;
|
||||
bitStream.Read(hasVelocity);
|
||||
EXPECT_EQ(hasVelocity, false);
|
||||
|
||||
// Angular velocity should be false since it's zero
|
||||
bool hasAngularVelocity;
|
||||
bitStream.Read(hasAngularVelocity);
|
||||
EXPECT_EQ(hasAngularVelocity, false);
|
||||
|
||||
// Continue with rest of serialization...
|
||||
bool hasLocalSpaceInfo;
|
||||
bitStream.Read(hasLocalSpaceInfo);
|
||||
EXPECT_EQ(hasLocalSpaceInfo, false);
|
||||
|
||||
bool hasRemoteInputInfo;
|
||||
bitStream.Read(hasRemoteInputInfo);
|
||||
EXPECT_EQ(hasRemoteInputInfo, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test HavokVehiclePhysicsComponent getters and setters
|
||||
*/
|
||||
TEST_F(HavokVehiclePhysicsComponentTest, GettersSettersTest) {
|
||||
// Test velocity
|
||||
NiPoint3 testVelocity(100.0f, 200.0f, 300.0f);
|
||||
havokVehiclePhysicsComponent->SetVelocity(testVelocity);
|
||||
EXPECT_EQ(havokVehiclePhysicsComponent->GetVelocity(), testVelocity);
|
||||
|
||||
// Test angular velocity
|
||||
NiPoint3 testAngularVelocity(50.0f, 60.0f, 70.0f);
|
||||
havokVehiclePhysicsComponent->SetAngularVelocity(testAngularVelocity);
|
||||
EXPECT_EQ(havokVehiclePhysicsComponent->GetAngularVelocity(), testAngularVelocity);
|
||||
|
||||
// Test ground state
|
||||
havokVehiclePhysicsComponent->SetIsOnGround(false);
|
||||
EXPECT_EQ(havokVehiclePhysicsComponent->GetIsOnGround(), false);
|
||||
|
||||
havokVehiclePhysicsComponent->SetIsOnGround(true);
|
||||
EXPECT_EQ(havokVehiclePhysicsComponent->GetIsOnGround(), true);
|
||||
|
||||
// Test rail state
|
||||
havokVehiclePhysicsComponent->SetIsOnRail(true);
|
||||
EXPECT_EQ(havokVehiclePhysicsComponent->GetIsOnRail(), true);
|
||||
|
||||
havokVehiclePhysicsComponent->SetIsOnRail(false);
|
||||
EXPECT_EQ(havokVehiclePhysicsComponent->GetIsOnRail(), false);
|
||||
}
|
||||
83
tests/dGameTests/dComponentsTests/ItemComponentTests.cpp
Normal file
83
tests/dGameTests/dComponentsTests/ItemComponentTests.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "ItemComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class ItemComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
ItemComponent* itemComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
itemComponent = baseEntity->AddComponent<ItemComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
// Test serialization behavior (should just write a single 0 bit)
|
||||
TEST_F(ItemComponentTest, SerializationBehavior) {
|
||||
itemComponent->Serialize(bitStream, true);
|
||||
|
||||
// ItemComponent::Serialize just writes a single 0 bit
|
||||
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1);
|
||||
|
||||
bool value;
|
||||
bitStream.Read(value);
|
||||
EXPECT_FALSE(value); // Should be false (0 bit)
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test serialization with isConstruction = false
|
||||
TEST_F(ItemComponentTest, SerializationWithoutConstruction) {
|
||||
itemComponent->Serialize(bitStream, false);
|
||||
|
||||
// Should still just write a single 0 bit regardless of isConstruction parameter
|
||||
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1);
|
||||
|
||||
bool value;
|
||||
bitStream.Read(value);
|
||||
EXPECT_FALSE(value); // Should be false (0 bit)
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test multiple serializations produce consistent results
|
||||
TEST_F(ItemComponentTest, ConsistentSerialization) {
|
||||
// First serialization
|
||||
itemComponent->Serialize(bitStream, true);
|
||||
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1);
|
||||
bool value1;
|
||||
bitStream.Read(value1);
|
||||
bitStream.Reset();
|
||||
|
||||
// Second serialization
|
||||
itemComponent->Serialize(bitStream, false);
|
||||
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1);
|
||||
bool value2;
|
||||
bitStream.Read(value2);
|
||||
bitStream.Reset();
|
||||
|
||||
// Third serialization
|
||||
itemComponent->Serialize(bitStream, true);
|
||||
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1);
|
||||
bool value3;
|
||||
bitStream.Read(value3);
|
||||
|
||||
EXPECT_EQ(value1, value2);
|
||||
EXPECT_EQ(value2, value3);
|
||||
EXPECT_FALSE(value1); // All should be false
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
120
tests/dGameTests/dComponentsTests/LUPExhibitComponentTests.cpp
Normal file
120
tests/dGameTests/dComponentsTests/LUPExhibitComponentTests.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "LUPExhibitComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class LUPExhibitComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
LUPExhibitComponent* lupExhibitComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
lupExhibitComponent = baseEntity->AddComponent<LUPExhibitComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test LUPExhibitComponent initial serialization
|
||||
*/
|
||||
TEST_F(LUPExhibitComponentTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Component should be dirty by default
|
||||
lupExhibitComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true); // Should be dirty by default
|
||||
|
||||
LOT exhibitLOT;
|
||||
bitStream.Read(exhibitLOT);
|
||||
EXPECT_EQ(exhibitLOT, 11121); // First exhibit in the array
|
||||
}
|
||||
|
||||
/**
|
||||
* Test LUPExhibitComponent regular update when not dirty
|
||||
*/
|
||||
TEST_F(LUPExhibitComponentTest, SerializeNotDirtyTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// First serialize to clear dirty flag
|
||||
lupExhibitComponent->Serialize(bitStream, false); // This clears the dirty flag
|
||||
bitStream.Reset();
|
||||
|
||||
// Now serialize again - should not be dirty
|
||||
lupExhibitComponent->Serialize(bitStream, false);
|
||||
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, false); // Should not be dirty after previous serialization
|
||||
}
|
||||
|
||||
/**
|
||||
* Test LUPExhibitComponent cycling through exhibits
|
||||
*/
|
||||
TEST_F(LUPExhibitComponentTest, NextExhibitTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Get first exhibit
|
||||
lupExhibitComponent->Serialize(bitStream, true);
|
||||
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true);
|
||||
|
||||
LOT firstExhibit;
|
||||
bitStream.Read(firstExhibit);
|
||||
EXPECT_EQ(firstExhibit, 11121); // First exhibit
|
||||
|
||||
bitStream.Reset();
|
||||
|
||||
// Move to next exhibit
|
||||
lupExhibitComponent->NextLUPExhibit();
|
||||
lupExhibitComponent->Serialize(bitStream, false);
|
||||
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true); // Should be dirty after NextLUPExhibit
|
||||
|
||||
LOT secondExhibit;
|
||||
bitStream.Read(secondExhibit);
|
||||
EXPECT_EQ(secondExhibit, 11295); // Second exhibit
|
||||
}
|
||||
|
||||
/**
|
||||
* Test LUPExhibitComponent cycling through all exhibits and wrapping around
|
||||
*/
|
||||
TEST_F(LUPExhibitComponentTest, CycleAllExhibitsTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Expected exhibit sequence: 11121, 11295, 11423, 11979, then back to 11121
|
||||
std::array<LOT, 5> expectedLOTs = { 11121, 11295, 11423, 11979, 11121 };
|
||||
|
||||
for (size_t i = 0; i < expectedLOTs.size(); ++i) {
|
||||
if (i > 0) {
|
||||
lupExhibitComponent->NextLUPExhibit();
|
||||
}
|
||||
|
||||
bitStream.Reset();
|
||||
lupExhibitComponent->Serialize(bitStream, false);
|
||||
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true);
|
||||
|
||||
LOT exhibitLOT;
|
||||
bitStream.Read(exhibitLOT);
|
||||
EXPECT_EQ(exhibitLOT, expectedLOTs[i]) << "Exhibit " << i << " should be " << expectedLOTs[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "LevelProgressionComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class LevelProgressionComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
LevelProgressionComponent* levelProgressionComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
levelProgressionComponent = baseEntity->AddComponent<LevelProgressionComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
// Test initial serialization
|
||||
TEST_F(LevelProgressionComponentTest, InitialSerialization) {
|
||||
levelProgressionComponent->Serialize(bitStream, true);
|
||||
|
||||
// Should write dirty flag and level
|
||||
bool dirtyFlag;
|
||||
uint32_t level;
|
||||
|
||||
bitStream.Read(dirtyFlag);
|
||||
EXPECT_TRUE(dirtyFlag); // Should be true for initial update
|
||||
|
||||
bitStream.Read(level);
|
||||
EXPECT_EQ(level, 1); // Default level should be 1
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test regular update without level change
|
||||
TEST_F(LevelProgressionComponentTest, RegularUpdateWithoutChange) {
|
||||
// First do initial serialization to clear dirty flag
|
||||
levelProgressionComponent->Serialize(bitStream, true);
|
||||
bitStream.Reset();
|
||||
|
||||
// Now do regular update
|
||||
levelProgressionComponent->Serialize(bitStream, false);
|
||||
|
||||
bool dirtyFlag;
|
||||
bitStream.Read(dirtyFlag);
|
||||
EXPECT_FALSE(dirtyFlag); // Should be false since level didn't change
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test serialization after level change
|
||||
TEST_F(LevelProgressionComponentTest, SerializationAfterLevelChange) {
|
||||
// Set a different level
|
||||
levelProgressionComponent->SetLevel(5);
|
||||
|
||||
levelProgressionComponent->Serialize(bitStream, false);
|
||||
|
||||
bool dirtyFlag;
|
||||
uint32_t level;
|
||||
|
||||
bitStream.Read(dirtyFlag);
|
||||
EXPECT_TRUE(dirtyFlag); // Should be true since level changed
|
||||
|
||||
bitStream.Read(level);
|
||||
EXPECT_EQ(level, 5);
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test that dirty flag gets cleared after serialization
|
||||
TEST_F(LevelProgressionComponentTest, DirtyFlagClearedAfterSerialization) {
|
||||
// Change level to make it dirty
|
||||
levelProgressionComponent->SetLevel(3);
|
||||
|
||||
// First serialization
|
||||
levelProgressionComponent->Serialize(bitStream, false);
|
||||
bitStream.Reset();
|
||||
|
||||
// Second serialization should not be dirty
|
||||
levelProgressionComponent->Serialize(bitStream, false);
|
||||
|
||||
bool dirtyFlag;
|
||||
bitStream.Read(dirtyFlag);
|
||||
EXPECT_FALSE(dirtyFlag); // Should be false since dirty flag was cleared
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
265
tests/dGameTests/dComponentsTests/ModelComponentTests.cpp
Normal file
265
tests/dGameTests/dComponentsTests/ModelComponentTests.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "ModelComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "PetComponent.h"
|
||||
|
||||
class ModelComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
ModelComponent* modelComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
modelComponent = baseEntity->AddComponent<ModelComponent>();
|
||||
// Initialize some values to be not default
|
||||
modelComponent->SetPosition(NiPoint3(10.0f, 20.0f, 30.0f));
|
||||
modelComponent->SetRotation(NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // w=4, x=1, y=2, z=3
|
||||
modelComponent->AddInteract(); // Make it pickable
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test serialization of a ModelComponent for a non-pet entity
|
||||
*/
|
||||
TEST_F(ModelComponentTest, SerializeNonPetTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
modelComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
|
||||
// ItemComponent serialization (since this is not a pet)
|
||||
bool hasItemComponent;
|
||||
bitStream.Read(hasItemComponent);
|
||||
EXPECT_EQ(hasItemComponent, true);
|
||||
|
||||
LWOOBJID userModelID;
|
||||
bitStream.Read(userModelID);
|
||||
EXPECT_EQ(userModelID, baseEntity->GetObjectID()); // Should use entity ID when no user model ID
|
||||
|
||||
int extraInfo;
|
||||
bitStream.Read(extraInfo);
|
||||
EXPECT_EQ(extraInfo, 0);
|
||||
|
||||
bool hasExtraItemData;
|
||||
bitStream.Read(hasExtraItemData);
|
||||
EXPECT_EQ(hasExtraItemData, false);
|
||||
|
||||
// ModelComponent serialization
|
||||
bool hasModelInfo;
|
||||
bitStream.Read(hasModelInfo);
|
||||
EXPECT_EQ(hasModelInfo, true);
|
||||
|
||||
bool isPickable;
|
||||
bitStream.Read(isPickable);
|
||||
EXPECT_EQ(isPickable, true); // We added an interact
|
||||
|
||||
uint32_t physicsType;
|
||||
bitStream.Read(physicsType);
|
||||
EXPECT_EQ(physicsType, 2);
|
||||
|
||||
NiPoint3 originalPosition;
|
||||
bitStream.Read(originalPosition.x);
|
||||
bitStream.Read(originalPosition.y);
|
||||
bitStream.Read(originalPosition.z);
|
||||
EXPECT_EQ(originalPosition, NiPoint3(10.0f, 20.0f, 30.0f));
|
||||
|
||||
NiQuaternion originalRotation;
|
||||
bitStream.Read(originalRotation.w);
|
||||
bitStream.Read(originalRotation.x);
|
||||
bitStream.Read(originalRotation.y);
|
||||
bitStream.Read(originalRotation.z);
|
||||
EXPECT_EQ(originalRotation, NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // w=4, x=1, y=2, z=3
|
||||
|
||||
bool hasBehaviorInfo;
|
||||
bitStream.Read(hasBehaviorInfo);
|
||||
EXPECT_EQ(hasBehaviorInfo, true);
|
||||
|
||||
uint32_t numBehaviors;
|
||||
bitStream.Read(numBehaviors);
|
||||
EXPECT_EQ(numBehaviors, 0); // No behaviors added in test
|
||||
|
||||
bool isPaused;
|
||||
bitStream.Read(isPaused);
|
||||
EXPECT_EQ(isPaused, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of a ModelComponent for a pet entity
|
||||
*/
|
||||
TEST_F(ModelComponentTest, SerializePetTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add a PetComponent to make this entity a pet
|
||||
baseEntity->AddComponent<PetComponent>(1);
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
modelComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
// Should NOT have ItemComponent serialization for pets
|
||||
|
||||
// ModelComponent serialization (should start immediately)
|
||||
bool hasModelInfo;
|
||||
bitStream.Read(hasModelInfo);
|
||||
EXPECT_EQ(hasModelInfo, true);
|
||||
|
||||
bool isPickable;
|
||||
bitStream.Read(isPickable);
|
||||
EXPECT_EQ(isPickable, true); // We added an interact
|
||||
|
||||
uint32_t physicsType;
|
||||
bitStream.Read(physicsType);
|
||||
EXPECT_EQ(physicsType, 2);
|
||||
|
||||
NiPoint3 originalPosition;
|
||||
bitStream.Read(originalPosition.x);
|
||||
bitStream.Read(originalPosition.y);
|
||||
bitStream.Read(originalPosition.z);
|
||||
EXPECT_EQ(originalPosition, NiPoint3(10.0f, 20.0f, 30.0f));
|
||||
|
||||
NiQuaternion originalRotation;
|
||||
bitStream.Read(originalRotation.w);
|
||||
bitStream.Read(originalRotation.x);
|
||||
bitStream.Read(originalRotation.y);
|
||||
bitStream.Read(originalRotation.z);
|
||||
EXPECT_EQ(originalRotation, NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // w=4, x=1, y=2, z=3
|
||||
|
||||
bool hasBehaviorInfo;
|
||||
bitStream.Read(hasBehaviorInfo);
|
||||
EXPECT_EQ(hasBehaviorInfo, true);
|
||||
|
||||
uint32_t numBehaviors;
|
||||
bitStream.Read(numBehaviors);
|
||||
EXPECT_EQ(numBehaviors, 0); // No behaviors added in test
|
||||
|
||||
bool isPaused;
|
||||
bitStream.Read(isPaused);
|
||||
EXPECT_EQ(isPaused, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of a ModelComponent during initial update
|
||||
*/
|
||||
TEST_F(ModelComponentTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Now we test a serialization for correctness with initial update.
|
||||
modelComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
|
||||
// ItemComponent serialization (since this is not a pet)
|
||||
bool hasItemComponent;
|
||||
bitStream.Read(hasItemComponent);
|
||||
EXPECT_EQ(hasItemComponent, true);
|
||||
|
||||
LWOOBJID userModelID;
|
||||
bitStream.Read(userModelID);
|
||||
EXPECT_EQ(userModelID, baseEntity->GetObjectID());
|
||||
|
||||
int extraInfo;
|
||||
bitStream.Read(extraInfo);
|
||||
EXPECT_EQ(extraInfo, 0);
|
||||
|
||||
bool hasExtraItemData;
|
||||
bitStream.Read(hasExtraItemData);
|
||||
EXPECT_EQ(hasExtraItemData, false);
|
||||
|
||||
// ModelComponent serialization
|
||||
bool hasModelInfo;
|
||||
bitStream.Read(hasModelInfo);
|
||||
EXPECT_EQ(hasModelInfo, true);
|
||||
|
||||
bool isPickable;
|
||||
bitStream.Read(isPickable);
|
||||
EXPECT_EQ(isPickable, true);
|
||||
|
||||
uint32_t physicsType;
|
||||
bitStream.Read(physicsType);
|
||||
EXPECT_EQ(physicsType, 2);
|
||||
|
||||
NiPoint3 originalPosition;
|
||||
bitStream.Read(originalPosition.x);
|
||||
bitStream.Read(originalPosition.y);
|
||||
bitStream.Read(originalPosition.z);
|
||||
EXPECT_EQ(originalPosition, NiPoint3(10.0f, 20.0f, 30.0f));
|
||||
|
||||
NiQuaternion originalRotation;
|
||||
bitStream.Read(originalRotation.w);
|
||||
bitStream.Read(originalRotation.x);
|
||||
bitStream.Read(originalRotation.y);
|
||||
bitStream.Read(originalRotation.z);
|
||||
EXPECT_EQ(originalRotation, NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // w=4, x=1, y=2, z=3
|
||||
|
||||
bool hasBehaviorInfo;
|
||||
bitStream.Read(hasBehaviorInfo);
|
||||
EXPECT_EQ(hasBehaviorInfo, true);
|
||||
|
||||
uint32_t numBehaviors;
|
||||
bitStream.Read(numBehaviors);
|
||||
EXPECT_EQ(numBehaviors, 0);
|
||||
|
||||
bool isPaused;
|
||||
bitStream.Read(isPaused);
|
||||
EXPECT_EQ(isPaused, false);
|
||||
|
||||
// During initial update, should write an additional false for model editing info
|
||||
bool hasModelEditingInfo;
|
||||
bitStream.Read(hasModelEditingInfo);
|
||||
EXPECT_EQ(hasModelEditingInfo, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ModelComponent getters and setters
|
||||
*/
|
||||
TEST_F(ModelComponentTest, GettersSettersTest) {
|
||||
// Test position
|
||||
NiPoint3 testPosition(100.0f, 200.0f, 300.0f);
|
||||
modelComponent->SetPosition(testPosition);
|
||||
EXPECT_EQ(modelComponent->GetOriginalPosition(), testPosition);
|
||||
|
||||
// Test rotation
|
||||
NiQuaternion testRotation(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
modelComponent->SetRotation(testRotation);
|
||||
EXPECT_EQ(modelComponent->GetOriginalRotation(), testRotation);
|
||||
|
||||
// Test speed
|
||||
modelComponent->SetSpeed(5.5f);
|
||||
// Note: GetSpeed() method doesn't exist in the header, but we can verify the setter works
|
||||
|
||||
// Test interact
|
||||
modelComponent->RemoveInteract(); // Remove the one we added in SetUp
|
||||
// Test that isPickable becomes false when no interactions
|
||||
bitStream.Reset();
|
||||
modelComponent->Serialize(bitStream, false);
|
||||
|
||||
// Skip itemcomponent data
|
||||
bool hasItemComponent;
|
||||
bitStream.Read(hasItemComponent);
|
||||
LWOOBJID userModelID;
|
||||
bitStream.Read(userModelID);
|
||||
int extraInfo;
|
||||
bitStream.Read(extraInfo);
|
||||
bool hasExtraItemData;
|
||||
bitStream.Read(hasExtraItemData);
|
||||
|
||||
// Check model component
|
||||
bool hasModelInfo;
|
||||
bitStream.Read(hasModelInfo);
|
||||
bool isPickable;
|
||||
bitStream.Read(isPickable);
|
||||
EXPECT_EQ(isPickable, false); // Should be false now
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "MovingPlatformComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eMovementPlatformState.h"
|
||||
|
||||
class MovingPlatformCompoenetTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
MovingPlatformComponent* movingPlatformComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
movingPlatformComponent = baseEntity->AddComponent<MovingPlatformComponent>("testPath");
|
||||
// Initialize some values to be not default
|
||||
movingPlatformComponent->SetSerialized(true);
|
||||
|
||||
// Set up the MoverSubComponent with some test values
|
||||
auto* moverSubComponent = movingPlatformComponent->GetMoverSubComponent();
|
||||
if (moverSubComponent) {
|
||||
moverSubComponent->mState = eMovementPlatformState::Moving;
|
||||
moverSubComponent->mDesiredWaypointIndex = 5;
|
||||
moverSubComponent->mShouldStopAtDesiredWaypoint = true;
|
||||
moverSubComponent->mInReverse = false;
|
||||
moverSubComponent->mPercentBetweenPoints = 0.75f;
|
||||
moverSubComponent->mPosition = NiPoint3(10.0f, 20.0f, 30.0f);
|
||||
moverSubComponent->mCurrentWaypointIndex = 3;
|
||||
moverSubComponent->mNextWaypointIndex = 4;
|
||||
moverSubComponent->mIdleTimeElapsed = 2.5f;
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test serialization of a MovingPlatformComponent with m_Serialize = false
|
||||
*/
|
||||
TEST_F(MovingPlatformCompoenetTest, SerializeDisabledTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Set m_Serialize to false to test the early return path
|
||||
movingPlatformComponent->SetSerialized(false);
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
movingPlatformComponent->Serialize(bitStream, false);
|
||||
|
||||
// Should only write two false booleans
|
||||
ASSERT_EQ(bitStream.GetNumberOfBitsUsed(), 2);
|
||||
|
||||
bool firstFlag;
|
||||
bool secondFlag;
|
||||
bitStream.Read(firstFlag);
|
||||
bitStream.Read(secondFlag);
|
||||
|
||||
EXPECT_EQ(firstFlag, false);
|
||||
EXPECT_EQ(secondFlag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of a MovingPlatformComponent with enabled serialization but no path
|
||||
*/
|
||||
TEST_F(MovingPlatformCompoenetTest, SerializeNoPathTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Create a component with no path to test the path logic
|
||||
auto* entityNoPath = new Entity(16, GameDependenciesTest::info);
|
||||
auto* componentNoPath = entityNoPath->AddComponent<MovingPlatformComponent>("");
|
||||
componentNoPath->SetSerialized(true);
|
||||
|
||||
// Stop pathing to make hasPath false
|
||||
componentNoPath->StopPathing();
|
||||
|
||||
componentNoPath->Serialize(bitStream, false);
|
||||
|
||||
// Should write: true (m_Serialize), false (hasPath), true (hasPlatform), mover type, then mover data
|
||||
bool isEnabled;
|
||||
bool hasPath;
|
||||
bool hasPlatform;
|
||||
|
||||
bitStream.Read(isEnabled);
|
||||
bitStream.Read(hasPath);
|
||||
bitStream.Read(hasPlatform);
|
||||
|
||||
EXPECT_EQ(isEnabled, true);
|
||||
EXPECT_EQ(hasPath, false);
|
||||
EXPECT_EQ(hasPlatform, true);
|
||||
|
||||
// Should continue with platform serialization
|
||||
eMoverSubComponentType moverType;
|
||||
bitStream.Read(moverType);
|
||||
EXPECT_EQ(moverType, eMoverSubComponentType::mover);
|
||||
|
||||
// Clean up
|
||||
delete entityNoPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test complete serialization of a MovingPlatformComponent with path
|
||||
*/
|
||||
TEST_F(MovingPlatformCompoenetTest, SerializeFullTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
movingPlatformComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isEnabled;
|
||||
bool hasPath;
|
||||
|
||||
bitStream.Read(isEnabled);
|
||||
bitStream.Read(hasPath);
|
||||
|
||||
EXPECT_EQ(isEnabled, true);
|
||||
EXPECT_EQ(hasPath, true);
|
||||
|
||||
if (hasPath) {
|
||||
bool isOnRail;
|
||||
bitStream.Read(isOnRail);
|
||||
EXPECT_EQ(isOnRail, true);
|
||||
|
||||
uint16_t pathNameSize;
|
||||
bitStream.Read(pathNameSize);
|
||||
EXPECT_EQ(pathNameSize, 8); // "testPath" length
|
||||
|
||||
std::u16string pathName;
|
||||
for (uint16_t i = 0; i < pathNameSize; i++) {
|
||||
uint16_t character;
|
||||
bitStream.Read(character);
|
||||
pathName += character;
|
||||
}
|
||||
|
||||
uint32_t startingPoint;
|
||||
bitStream.Read(startingPoint);
|
||||
EXPECT_EQ(startingPoint, 0);
|
||||
|
||||
bool reverse;
|
||||
bitStream.Read(reverse);
|
||||
EXPECT_EQ(reverse, false);
|
||||
}
|
||||
|
||||
bool hasPlatform;
|
||||
bitStream.Read(hasPlatform);
|
||||
EXPECT_EQ(hasPlatform, true);
|
||||
|
||||
if (hasPlatform) {
|
||||
eMoverSubComponentType moverType;
|
||||
bitStream.Read(moverType);
|
||||
EXPECT_EQ(moverType, eMoverSubComponentType::mover);
|
||||
|
||||
// Test MoverSubComponent serialization
|
||||
bool moverHasData;
|
||||
bitStream.Read(moverHasData);
|
||||
EXPECT_EQ(moverHasData, true);
|
||||
|
||||
eMovementPlatformState state;
|
||||
bitStream.Read(state);
|
||||
EXPECT_EQ(state, eMovementPlatformState::Moving);
|
||||
|
||||
int32_t desiredWaypointIndex;
|
||||
bitStream.Read(desiredWaypointIndex);
|
||||
EXPECT_EQ(desiredWaypointIndex, 5);
|
||||
|
||||
bool shouldStopAtDesiredWaypoint;
|
||||
bitStream.Read(shouldStopAtDesiredWaypoint);
|
||||
EXPECT_EQ(shouldStopAtDesiredWaypoint, true);
|
||||
|
||||
bool inReverse;
|
||||
bitStream.Read(inReverse);
|
||||
EXPECT_EQ(inReverse, false);
|
||||
|
||||
float percentBetweenPoints;
|
||||
bitStream.Read(percentBetweenPoints);
|
||||
EXPECT_EQ(percentBetweenPoints, 0.75f);
|
||||
|
||||
float positionX, positionY, positionZ;
|
||||
bitStream.Read(positionX);
|
||||
bitStream.Read(positionY);
|
||||
bitStream.Read(positionZ);
|
||||
EXPECT_EQ(positionX, 10.0f);
|
||||
EXPECT_EQ(positionY, 20.0f);
|
||||
EXPECT_EQ(positionZ, 30.0f);
|
||||
|
||||
uint32_t currentWaypointIndex;
|
||||
bitStream.Read(currentWaypointIndex);
|
||||
EXPECT_EQ(currentWaypointIndex, 3);
|
||||
|
||||
uint32_t nextWaypointIndex;
|
||||
bitStream.Read(nextWaypointIndex);
|
||||
EXPECT_EQ(nextWaypointIndex, 4);
|
||||
|
||||
float idleTimeElapsed;
|
||||
bitStream.Read(idleTimeElapsed);
|
||||
EXPECT_EQ(idleTimeElapsed, 2.5f);
|
||||
|
||||
float moveTimeElapsed;
|
||||
bitStream.Read(moveTimeElapsed);
|
||||
EXPECT_EQ(moveTimeElapsed, 0.0f); // Always 0 in current implementation
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "ePetAbilityType.h"
|
||||
#include "eStateChangeType.h"
|
||||
|
||||
class PetTest : public GameDependenciesTest {
|
||||
class PetComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
PetComponent* petComponent;
|
||||
@@ -31,7 +31,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PetTest, PlacementNewAddComponentTest) {
|
||||
TEST_F(PetComponentTest, PlacementNewAddComponentTest) {
|
||||
// Test adding component
|
||||
ASSERT_NE(petComponent, nullptr);
|
||||
baseEntity->AddComponent<PetComponent>(1);
|
||||
@@ -41,3 +41,74 @@ TEST_F(PetTest, PlacementNewAddComponentTest) {
|
||||
ASSERT_EQ(petComponent->GetParent()->GetObjectID(), 15);
|
||||
ASSERT_EQ(petComponent->GetAbility(), ePetAbilityType::Invalid);
|
||||
}
|
||||
|
||||
// Test untamed pet serialization (initial update)
|
||||
TEST_F(PetComponentTest, UntamedPetInitialSerialization) {
|
||||
petComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read the serialized data manually
|
||||
bool alwaysDirty;
|
||||
uint32_t status;
|
||||
ePetAbilityType ability;
|
||||
bool interacting;
|
||||
bool tamed;
|
||||
bool tamedForInitial;
|
||||
|
||||
bitStream.Read(alwaysDirty);
|
||||
EXPECT_TRUE(alwaysDirty); // Always true
|
||||
|
||||
bitStream.Read(status);
|
||||
EXPECT_EQ(status, 67108866); // Default status should be 67108866 since that is the untamed state
|
||||
|
||||
bitStream.Read(ability);
|
||||
EXPECT_EQ(ability, ePetAbilityType::Invalid); // Should be Invalid for untamed pets
|
||||
|
||||
bitStream.Read(interacting);
|
||||
EXPECT_FALSE(interacting); // No interaction by default
|
||||
|
||||
bitStream.Read(tamed);
|
||||
EXPECT_FALSE(tamed); // Pet is not tamed by default
|
||||
|
||||
// For initial update, should write tamed flag again
|
||||
bitStream.Read(tamedForInitial);
|
||||
EXPECT_FALSE(tamedForInitial); // Should match tamed flag
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
// Test pet with interaction serialization
|
||||
TEST_F(PetComponentTest, PetWithInteractionSerialization) {
|
||||
// Set up a pet with interaction
|
||||
LWOOBJID interactionID = 67890;
|
||||
petComponent->SetInteraction(interactionID);
|
||||
|
||||
petComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read the serialized data manually
|
||||
bool alwaysDirty;
|
||||
uint32_t status;
|
||||
ePetAbilityType ability;
|
||||
bool interacting;
|
||||
LWOOBJID interaction;
|
||||
bool tamed;
|
||||
|
||||
bitStream.Read(alwaysDirty);
|
||||
EXPECT_TRUE(alwaysDirty); // Always true
|
||||
|
||||
bitStream.Read(status);
|
||||
bitStream.Read(ability);
|
||||
EXPECT_EQ(ability, ePetAbilityType::Invalid); // Should be Invalid for untamed pets
|
||||
|
||||
bitStream.Read(interacting);
|
||||
EXPECT_TRUE(interacting); // Should be true
|
||||
|
||||
if (interacting) {
|
||||
bitStream.Read(interaction);
|
||||
EXPECT_EQ(interaction, interactionID);
|
||||
}
|
||||
|
||||
bitStream.Read(tamed);
|
||||
EXPECT_FALSE(tamed); // Pet is not tamed by default
|
||||
|
||||
bitStream.Reset();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "PhantomPhysicsComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
|
||||
class PhantomPhysicsComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* Test PhantomPhysicsComponent serialization for initial update
|
||||
*/
|
||||
TEST_F(PhantomPhysicsComponentTest, SerializeInitialUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
PhantomPhysicsComponent phantomPhysicsComponent(&testEntity, 1); // Need componentId parameter
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
phantomPhysicsComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// PhantomPhysicsComponent writes physics data (from PhysicsComponent)
|
||||
bool hasPhysicsData;
|
||||
ASSERT_TRUE(bitStream.Read(hasPhysicsData));
|
||||
EXPECT_TRUE(hasPhysicsData); // Always true for initial update
|
||||
|
||||
if (hasPhysicsData) {
|
||||
// Position data (x, y, z)
|
||||
float x, y, z;
|
||||
ASSERT_TRUE(bitStream.Read(x));
|
||||
ASSERT_TRUE(bitStream.Read(y));
|
||||
ASSERT_TRUE(bitStream.Read(z));
|
||||
EXPECT_EQ(x, 0.0f); // Default position
|
||||
EXPECT_EQ(y, 0.0f);
|
||||
EXPECT_EQ(z, 0.0f);
|
||||
|
||||
// Rotation data (x, y, z, w) - note: not w first like NiQuaternion
|
||||
float rX, rY, rZ, rW;
|
||||
ASSERT_TRUE(bitStream.Read(rX));
|
||||
ASSERT_TRUE(bitStream.Read(rY));
|
||||
ASSERT_TRUE(bitStream.Read(rZ));
|
||||
ASSERT_TRUE(bitStream.Read(rW));
|
||||
EXPECT_EQ(rX, 0.0f); // Default rotation
|
||||
EXPECT_EQ(rY, 0.0f);
|
||||
EXPECT_EQ(rZ, 0.0f);
|
||||
EXPECT_EQ(rW, 0.0f); // Default quaternion (not identity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test PhantomPhysicsComponent serialization for regular update (no changes)
|
||||
*/
|
||||
TEST_F(PhantomPhysicsComponentTest, SerializeRegularUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
PhantomPhysicsComponent phantomPhysicsComponent(&testEntity, 1); // Need componentId parameter
|
||||
|
||||
// Reset dirty flags with initial serialization
|
||||
RakNet::BitStream initStream;
|
||||
phantomPhysicsComponent.Serialize(initStream, true);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
phantomPhysicsComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// For regular updates with no dirty flags, should write false
|
||||
bool hasPhysicsData;
|
||||
ASSERT_TRUE(bitStream.Read(hasPhysicsData));
|
||||
EXPECT_FALSE(hasPhysicsData); // No changes
|
||||
}
|
||||
158
tests/dGameTests/dComponentsTests/QuickBuildComponentTests.cpp
Normal file
158
tests/dGameTests/dComponentsTests/QuickBuildComponentTests.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "QuickBuildComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
class QuickBuildComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(QuickBuildComponentTest, SerializeInitialUpdateNoDestroyable) {
|
||||
Entity testEntity(15, info);
|
||||
// Create QuickBuild without Destroyable component
|
||||
QuickBuildComponent quickBuildComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
quickBuildComponent.Serialize(bitStream, true);
|
||||
|
||||
// Read the data manually to validate serialization format
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// When no destroyable component, writes specific pattern for initial update
|
||||
bool flag1;
|
||||
ASSERT_TRUE(bitStream.Read(flag1));
|
||||
EXPECT_FALSE(flag1); // First flag is false
|
||||
|
||||
bool flag2;
|
||||
ASSERT_TRUE(bitStream.Read(flag2));
|
||||
EXPECT_FALSE(flag2); // Second flag is false
|
||||
|
||||
bool flag3;
|
||||
ASSERT_TRUE(bitStream.Read(flag3));
|
||||
EXPECT_FALSE(flag3); // Third flag is false
|
||||
|
||||
// ScriptedActivity section
|
||||
bool hasScriptedActivity;
|
||||
ASSERT_TRUE(bitStream.Read(hasScriptedActivity));
|
||||
EXPECT_TRUE(hasScriptedActivity); // Always writes 1
|
||||
|
||||
uint32_t builderCount;
|
||||
ASSERT_TRUE(bitStream.Read(builderCount));
|
||||
EXPECT_EQ(builderCount, 0); // No builder initially
|
||||
}
|
||||
|
||||
TEST_F(QuickBuildComponentTest, SerializeRegularUpdateNoDestroyable) {
|
||||
Entity testEntity(15, info);
|
||||
QuickBuildComponent quickBuildComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
quickBuildComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// Regular update without destroyable should only write specific flags
|
||||
bool flag1;
|
||||
ASSERT_TRUE(bitStream.Read(flag1));
|
||||
EXPECT_FALSE(flag1);
|
||||
|
||||
bool flag2;
|
||||
ASSERT_TRUE(bitStream.Read(flag2));
|
||||
EXPECT_FALSE(flag2);
|
||||
|
||||
// ScriptedActivity section
|
||||
bool hasScriptedActivity;
|
||||
ASSERT_TRUE(bitStream.Read(hasScriptedActivity));
|
||||
EXPECT_TRUE(hasScriptedActivity);
|
||||
|
||||
uint32_t builderCount;
|
||||
ASSERT_TRUE(bitStream.Read(builderCount));
|
||||
EXPECT_EQ(builderCount, 0);
|
||||
}
|
||||
|
||||
TEST_F(QuickBuildComponentTest, SerializeWithDestroyableComponent) {
|
||||
Entity testEntity(15, info);
|
||||
|
||||
// Add a destroyable component first
|
||||
DestroyableComponent* destroyableComponent = testEntity.AddComponent<DestroyableComponent>();
|
||||
|
||||
QuickBuildComponent quickBuildComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
quickBuildComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// With destroyable component, should skip the special flags and go directly to ScriptedActivity
|
||||
bool hasScriptedActivity;
|
||||
ASSERT_TRUE(bitStream.Read(hasScriptedActivity));
|
||||
EXPECT_TRUE(hasScriptedActivity);
|
||||
|
||||
uint32_t builderCount;
|
||||
ASSERT_TRUE(bitStream.Read(builderCount));
|
||||
EXPECT_EQ(builderCount, 0);
|
||||
}
|
||||
|
||||
TEST_F(QuickBuildComponentTest, SerializeWithBuilder) {
|
||||
Entity testEntity(15, info);
|
||||
Entity builderEntity(20, info);
|
||||
|
||||
QuickBuildComponent quickBuildComponent(&testEntity);
|
||||
|
||||
// Simulate having a builder (this would normally be set through the component's logic)
|
||||
// Since GetBuilder() is based on internal state, this test validates the serialization format
|
||||
// when there's no builder
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
quickBuildComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// Skip initial flags
|
||||
bool flag1, flag2, flag3;
|
||||
bitStream.Read(flag1);
|
||||
bitStream.Read(flag2);
|
||||
bitStream.Read(flag3);
|
||||
|
||||
bool hasScriptedActivity;
|
||||
ASSERT_TRUE(bitStream.Read(hasScriptedActivity));
|
||||
EXPECT_TRUE(hasScriptedActivity);
|
||||
|
||||
uint32_t builderCount;
|
||||
ASSERT_TRUE(bitStream.Read(builderCount));
|
||||
EXPECT_EQ(builderCount, 0); // No builder in default state
|
||||
}
|
||||
|
||||
TEST_F(QuickBuildComponentTest, SerializeConsistentFormat) {
|
||||
Entity testEntity(15, info);
|
||||
QuickBuildComponent quickBuildComponent(&testEntity);
|
||||
|
||||
// Test that serialization format is consistent between calls
|
||||
RakNet::BitStream firstStream, secondStream;
|
||||
|
||||
quickBuildComponent.Serialize(firstStream, true);
|
||||
quickBuildComponent.Serialize(secondStream, true);
|
||||
|
||||
// Compare the serialized data
|
||||
EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), secondStream.GetNumberOfBitsUsed());
|
||||
|
||||
// Reset and compare bit by bit
|
||||
firstStream.ResetReadPointer();
|
||||
secondStream.ResetReadPointer();
|
||||
|
||||
while (firstStream.GetNumberOfUnreadBits() > 0 && secondStream.GetNumberOfUnreadBits() > 0) {
|
||||
bool firstBit, secondBit;
|
||||
firstStream.Read(firstBit);
|
||||
secondStream.Read(secondBit);
|
||||
EXPECT_EQ(firstBit, secondBit);
|
||||
}
|
||||
}
|
||||
186
tests/dGameTests/dComponentsTests/RenderComponentTests.cpp
Normal file
186
tests/dGameTests/dComponentsTests/RenderComponentTests.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "RenderComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class RenderComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
RenderComponent* renderComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
renderComponent = baseEntity->AddComponent<RenderComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test RenderComponent serialization with no effects
|
||||
*/
|
||||
TEST_F(RenderComponentTest, SerializeNoEffectsTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Test initial update with no effects
|
||||
renderComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
uint32_t effectCount;
|
||||
bitStream.Read(effectCount);
|
||||
EXPECT_EQ(effectCount, 0); // No effects added
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RenderComponent serialization with single effect
|
||||
*/
|
||||
TEST_F(RenderComponentTest, SerializeSingleEffectTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add a single effect
|
||||
std::string effectName = "testEffect";
|
||||
std::u16string effectType = u"testType";
|
||||
int32_t effectId = 123;
|
||||
float priority = 1.5f;
|
||||
|
||||
renderComponent->AddEffect(effectId, effectName, effectType, priority);
|
||||
renderComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
uint32_t effectCount;
|
||||
bitStream.Read(effectCount);
|
||||
EXPECT_EQ(effectCount, 1); // One effect added
|
||||
|
||||
// Read effect name length
|
||||
uint8_t nameLength;
|
||||
bitStream.Read(nameLength);
|
||||
EXPECT_EQ(nameLength, effectName.size());
|
||||
|
||||
// Read effect name
|
||||
std::string readName;
|
||||
readName.resize(nameLength);
|
||||
for (uint8_t i = 0; i < nameLength; i++) {
|
||||
uint8_t ch;
|
||||
bitStream.Read(ch);
|
||||
readName[i] = static_cast<char>(ch);
|
||||
}
|
||||
EXPECT_EQ(readName, effectName);
|
||||
|
||||
// Read effect ID
|
||||
int32_t readEffectId;
|
||||
bitStream.Read(readEffectId);
|
||||
EXPECT_EQ(readEffectId, effectId);
|
||||
|
||||
// Read effect type length
|
||||
uint8_t typeLength;
|
||||
bitStream.Read(typeLength);
|
||||
EXPECT_EQ(typeLength, effectType.size());
|
||||
|
||||
// Read effect type
|
||||
std::u16string readType;
|
||||
readType.resize(typeLength);
|
||||
for (uint8_t i = 0; i < typeLength; i++) {
|
||||
uint16_t ch;
|
||||
bitStream.Read(ch);
|
||||
readType[i] = static_cast<char16_t>(ch);
|
||||
}
|
||||
EXPECT_EQ(readType, effectType);
|
||||
|
||||
// Read priority
|
||||
float readPriority;
|
||||
bitStream.Read(readPriority);
|
||||
EXPECT_EQ(readPriority, priority);
|
||||
|
||||
// Read secondary (should be 0 by default)
|
||||
int64_t secondary;
|
||||
bitStream.Read(secondary);
|
||||
EXPECT_EQ(secondary, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RenderComponent serialization with multiple effects
|
||||
*/
|
||||
TEST_F(RenderComponentTest, SerializeMultipleEffectsTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add multiple effects
|
||||
renderComponent->AddEffect(100, "effect1", u"type1", 1.0f);
|
||||
renderComponent->AddEffect(200, "effect2", u"type2", 2.0f);
|
||||
renderComponent->AddEffect(300, "effect3", u"type3", 3.0f);
|
||||
|
||||
renderComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
uint32_t effectCount;
|
||||
bitStream.Read(effectCount);
|
||||
EXPECT_EQ(effectCount, 3); // Three effects added
|
||||
|
||||
// Read first effect
|
||||
uint8_t nameLength1;
|
||||
bitStream.Read(nameLength1);
|
||||
EXPECT_EQ(nameLength1, 7); // "effect1"
|
||||
|
||||
// Skip reading the detailed content of all effects for brevity
|
||||
// Just verify that the count is correct and we can read some basic data
|
||||
|
||||
for (uint8_t i = 0; i < nameLength1; i++) {
|
||||
uint8_t dummy;
|
||||
bitStream.Read(dummy);
|
||||
}
|
||||
|
||||
int32_t effectId1;
|
||||
bitStream.Read(effectId1);
|
||||
EXPECT_EQ(effectId1, 100);
|
||||
|
||||
// Skip the rest of the first effect and the other effects
|
||||
// The important part is that the count was correct
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RenderComponent serialization with empty effect name
|
||||
*/
|
||||
TEST_F(RenderComponentTest, SerializeEmptyEffectNameTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add an effect with empty name
|
||||
renderComponent->AddEffect(456, "", u"emptyNameType", 0.5f);
|
||||
renderComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
uint32_t effectCount;
|
||||
bitStream.Read(effectCount);
|
||||
EXPECT_EQ(effectCount, 1); // One effect added
|
||||
|
||||
// Read effect name length
|
||||
uint8_t nameLength;
|
||||
bitStream.Read(nameLength);
|
||||
EXPECT_EQ(nameLength, 0); // Empty name
|
||||
|
||||
// According to the code, if name is empty, nothing else is written
|
||||
// So the stream should end here for this effect
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RenderComponent regular update serialization (should not serialize)
|
||||
*/
|
||||
TEST_F(RenderComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add an effect first
|
||||
renderComponent->AddEffect(789, "regularUpdate", u"regularType", 1.0f);
|
||||
|
||||
// Regular update should not serialize anything
|
||||
renderComponent->Serialize(bitStream, false);
|
||||
|
||||
// BitStream should be empty for regular updates
|
||||
EXPECT_EQ(bitStream.GetNumberOfBitsUsed(), 0);
|
||||
}
|
||||
147
tests/dGameTests/dComponentsTests/ScriptComponentTests.cpp
Normal file
147
tests/dGameTests/dComponentsTests/ScriptComponentTests.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
#include "GameMessages.h"
|
||||
#include "CppScripts.h"
|
||||
#include "ScriptComponent.h"
|
||||
|
||||
class ScriptComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ScriptComponentTest, SerializeInitialUpdateNoNetworkSettings) {
|
||||
Entity testEntity(15, info);
|
||||
ScriptComponent scriptComponent(&testEntity, "", false);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
scriptComponent.Serialize(bitStream, true);
|
||||
|
||||
// Read the data manually to validate serialization format
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasNetworkSettings;
|
||||
ASSERT_TRUE(bitStream.Read(hasNetworkSettings));
|
||||
EXPECT_FALSE(hasNetworkSettings); // No network settings by default
|
||||
}
|
||||
|
||||
TEST_F(ScriptComponentTest, SerializeRegularUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
ScriptComponent scriptComponent(&testEntity, "", false);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
scriptComponent.Serialize(bitStream, false);
|
||||
|
||||
// Regular updates should not write anything for ScriptComponent
|
||||
bitStream.ResetReadPointer();
|
||||
EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ScriptComponentTest, SerializeWithNetworkSettings) {
|
||||
Entity testEntity(15, info);
|
||||
|
||||
// Add some network settings to the entity
|
||||
testEntity.SetNetworkVar<float>(u"test_float", 123.45f);
|
||||
testEntity.SetNetworkVar<int32_t>(u"test_int", 42);
|
||||
|
||||
ScriptComponent scriptComponent(&testEntity, "", false);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
scriptComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasNetworkSettings;
|
||||
ASSERT_TRUE(bitStream.Read(hasNetworkSettings));
|
||||
EXPECT_TRUE(hasNetworkSettings); // Should have network settings
|
||||
|
||||
uint32_t ldfDataSize;
|
||||
ASSERT_TRUE(bitStream.Read(ldfDataSize));
|
||||
EXPECT_GT(ldfDataSize, 0); // Should have some data
|
||||
|
||||
// Verify the LDF data is present
|
||||
RakNet::BitStream ldfStream;
|
||||
ASSERT_TRUE(bitStream.Read(ldfStream, ldfDataSize));
|
||||
|
||||
ldfStream.ResetReadPointer();
|
||||
|
||||
uint8_t ldfType;
|
||||
ASSERT_TRUE(ldfStream.Read(ldfType));
|
||||
EXPECT_EQ(ldfType, 0); // Always writes 0 first
|
||||
|
||||
uint32_t settingsCount;
|
||||
ASSERT_TRUE(ldfStream.Read(settingsCount));
|
||||
EXPECT_EQ(settingsCount, 2); // We added 2 settings
|
||||
}
|
||||
|
||||
TEST_F(ScriptComponentTest, SerializeConsistentBehavior) {
|
||||
Entity testEntity(15, info);
|
||||
ScriptComponent scriptComponent(&testEntity, "", false);
|
||||
|
||||
// Test that multiple serializations are consistent
|
||||
RakNet::BitStream firstStream, secondStream;
|
||||
|
||||
scriptComponent.Serialize(firstStream, true);
|
||||
scriptComponent.Serialize(secondStream, true);
|
||||
|
||||
EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), secondStream.GetNumberOfBitsUsed());
|
||||
|
||||
firstStream.ResetReadPointer();
|
||||
secondStream.ResetReadPointer();
|
||||
|
||||
bool firstHasSettings, secondHasSettings;
|
||||
ASSERT_TRUE(firstStream.Read(firstHasSettings));
|
||||
ASSERT_TRUE(secondStream.Read(secondHasSettings));
|
||||
EXPECT_EQ(firstHasSettings, secondHasSettings);
|
||||
}
|
||||
|
||||
TEST_F(ScriptComponentTest, SerializeScriptNameHandling) {
|
||||
Entity testEntity(15, info);
|
||||
|
||||
// Test with different script names - serialization shouldn't change based on script name
|
||||
ScriptComponent scriptComponent1(&testEntity, "TestScript", false);
|
||||
ScriptComponent scriptComponent2(&testEntity, "AnotherScript", false);
|
||||
|
||||
RakNet::BitStream stream1, stream2;
|
||||
|
||||
scriptComponent1.Serialize(stream1, true);
|
||||
scriptComponent2.Serialize(stream2, true);
|
||||
|
||||
// Serialization should be the same regardless of script name since
|
||||
// script names are not serialized, only network settings
|
||||
stream1.ResetReadPointer();
|
||||
stream2.ResetReadPointer();
|
||||
|
||||
bool hasSettings1, hasSettings2;
|
||||
ASSERT_TRUE(stream1.Read(hasSettings1));
|
||||
ASSERT_TRUE(stream2.Read(hasSettings2));
|
||||
EXPECT_EQ(hasSettings1, hasSettings2);
|
||||
EXPECT_FALSE(hasSettings1); // Both should be false without network settings
|
||||
}
|
||||
|
||||
TEST_F(ScriptComponentTest, SerializeSerializedFlag) {
|
||||
Entity testEntity(15, info);
|
||||
ScriptComponent scriptComponent(&testEntity, "", false);
|
||||
|
||||
// Test the serialized flag functionality
|
||||
scriptComponent.SetSerialized(true); // Should accept this call
|
||||
|
||||
// The serialized flag itself doesn't affect the Serialize method output,
|
||||
// but it's tracked by the component
|
||||
RakNet::BitStream bitStream;
|
||||
scriptComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasNetworkSettings;
|
||||
ASSERT_TRUE(bitStream.Read(hasNetworkSettings));
|
||||
EXPECT_FALSE(hasNetworkSettings); // Still no network settings
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "ScriptedActivityComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class ScriptedActivityComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
ScriptedActivityComponent* scriptedActivityComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
// ScriptedActivityComponent is the concrete implementation of ActivityComponent
|
||||
// that provides the ComponentType required for the Entity template system
|
||||
scriptedActivityComponent = baseEntity->AddComponent<ScriptedActivityComponent>(1);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test serialization of an ActivityComponent with no players
|
||||
*/
|
||||
TEST_F(ScriptedActivityComponentTest, SerializeNoPlayersTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Component should be dirty by default
|
||||
// Now we test a serialization for correctness.
|
||||
scriptedActivityComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true);
|
||||
|
||||
uint32_t playerCount;
|
||||
bitStream.Read(playerCount);
|
||||
EXPECT_EQ(playerCount, 0); // No players added
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of an ActivityComponent with players
|
||||
*/
|
||||
TEST_F(ScriptedActivityComponentTest, SerializeWithPlayersTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add some test players
|
||||
LWOOBJID player1 = 100;
|
||||
LWOOBJID player2 = 200;
|
||||
|
||||
// Force dirty state for testing by adding and setting values
|
||||
scriptedActivityComponent->SetActivityValue(player1, 0, 10.5f); // Score
|
||||
scriptedActivityComponent->SetActivityValue(player1, 1, 25.0f); // Time
|
||||
scriptedActivityComponent->SetActivityValue(player1, 2, 3.0f); // Some other metric
|
||||
|
||||
scriptedActivityComponent->SetActivityValue(player2, 0, 15.5f); // Score
|
||||
scriptedActivityComponent->SetActivityValue(player2, 1, 20.0f); // Time
|
||||
scriptedActivityComponent->SetActivityValue(player2, 2, 5.0f); // Some other metric
|
||||
|
||||
// Now we test a serialization for correctness.
|
||||
scriptedActivityComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true);
|
||||
|
||||
uint32_t playerCount;
|
||||
bitStream.Read(playerCount);
|
||||
EXPECT_EQ(playerCount, 2);
|
||||
|
||||
// Read first player's data
|
||||
LWOOBJID readPlayer1;
|
||||
bitStream.Read(readPlayer1);
|
||||
EXPECT_EQ(readPlayer1, player1);
|
||||
|
||||
// Read all 10 values for first player
|
||||
for (int i = 0; i < 10; i++) {
|
||||
float value;
|
||||
bitStream.Read(value);
|
||||
float expectedValue = 0.0f; // Default value for most indices
|
||||
if (i == 0) expectedValue = 10.5f;
|
||||
else if (i == 1) expectedValue = 25.0f;
|
||||
else if (i == 2) expectedValue = 3.0f;
|
||||
EXPECT_EQ(value, expectedValue);
|
||||
}
|
||||
|
||||
// Read second player's data
|
||||
LWOOBJID readPlayer2;
|
||||
bitStream.Read(readPlayer2);
|
||||
EXPECT_EQ(readPlayer2, player2);
|
||||
|
||||
// Read all 10 values for second player
|
||||
for (int i = 0; i < 10; i++) {
|
||||
float value;
|
||||
bitStream.Read(value);
|
||||
float expectedValue = 0.0f; // Default value for most indices
|
||||
if (i == 0) expectedValue = 15.5f;
|
||||
else if (i == 1) expectedValue = 20.0f;
|
||||
else if (i == 2) expectedValue = 5.0f;
|
||||
EXPECT_EQ(value, expectedValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of an ActivityComponent during initial update
|
||||
*/
|
||||
TEST_F(ScriptedActivityComponentTest, SerializeInitialUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add a test player and set a value
|
||||
LWOOBJID player1 = 100;
|
||||
scriptedActivityComponent->SetActivityValue(player1, 0, 10.5f);
|
||||
|
||||
// Now we test a serialization for correctness with initial update.
|
||||
scriptedActivityComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, true);
|
||||
|
||||
uint32_t playerCount;
|
||||
bitStream.Read(playerCount);
|
||||
EXPECT_EQ(playerCount, 1);
|
||||
|
||||
// Read player's data
|
||||
LWOOBJID readPlayer1;
|
||||
bitStream.Read(readPlayer1);
|
||||
EXPECT_EQ(readPlayer1, player1);
|
||||
|
||||
// Read all 10 values
|
||||
for (int i = 0; i < 10; i++) {
|
||||
float value;
|
||||
bitStream.Read(value);
|
||||
float expectedValue = (i == 0) ? 10.5f : 0.0f; // Only first value should be set
|
||||
EXPECT_EQ(value, expectedValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of an ActivityComponent when not dirty
|
||||
*/
|
||||
TEST_F(ScriptedActivityComponentTest, SerializeNotDirtyTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Add a test player
|
||||
LWOOBJID player1 = 100;
|
||||
scriptedActivityComponent->AddActivityPlayerData(player1);
|
||||
|
||||
// Do a serialization to reset the dirty flag
|
||||
scriptedActivityComponent->Serialize(bitStream, false);
|
||||
bitStream.Reset(); // Reset bitstream for the actual test
|
||||
|
||||
// Now serialize again - should not be dirty this time
|
||||
scriptedActivityComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isDirty;
|
||||
bitStream.Read(isDirty);
|
||||
EXPECT_EQ(isDirty, false);
|
||||
|
||||
// No additional data should be written when not dirty
|
||||
EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0);
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eStateChangeType.h"
|
||||
|
||||
class SimplePhysicsTest : public GameDependenciesTest {
|
||||
class SimplePhysicsComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
std::unique_ptr<Entity> baseEntity;
|
||||
SimplePhysicsComponent* simplePhysicsComponent;
|
||||
@@ -29,7 +29,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(SimplePhysicsTest, SimplePhysicsSerializeTest) {
|
||||
TEST_F(SimplePhysicsComponentTest, SerializeTest) {
|
||||
simplePhysicsComponent->Serialize(bitStream, false);
|
||||
constexpr uint32_t sizeOfStream = 3 + BYTES_TO_BITS(3 * sizeof(NiPoint3)) + BYTES_TO_BITS(1 * sizeof(NiQuaternion)) + 1 * BYTES_TO_BITS(sizeof(uint32_t));
|
||||
ASSERT_EQ(bitStream.GetNumberOfBitsUsed(), sizeOfStream);
|
||||
@@ -76,7 +76,7 @@ TEST_F(SimplePhysicsTest, SimplePhysicsSerializeTest) {
|
||||
ASSERT_EQ(rotation, NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
|
||||
}
|
||||
|
||||
TEST_F(SimplePhysicsTest, SimplePhysicsConstructionTest) {
|
||||
TEST_F(SimplePhysicsComponentTest, ConstructionTest) {
|
||||
simplePhysicsComponent->Serialize(bitStream, true);
|
||||
constexpr uint32_t sizeOfStream = 4 + BYTES_TO_BITS(1 * sizeof(int32_t)) + BYTES_TO_BITS(3 * sizeof(NiPoint3)) + BYTES_TO_BITS(1 * sizeof(NiQuaternion)) + 1 * BYTES_TO_BITS(sizeof(uint32_t));
|
||||
ASSERT_EQ(bitStream.GetNumberOfBitsUsed(), sizeOfStream);
|
||||
@@ -131,7 +131,7 @@ TEST_F(SimplePhysicsTest, SimplePhysicsConstructionTest) {
|
||||
ASSERT_EQ(rotation, NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
|
||||
}
|
||||
|
||||
TEST_F(SimplePhysicsTest, SimplePhysicsGettersAndSettersTest) {
|
||||
TEST_F(SimplePhysicsComponentTest, GettersAndSettersTest) {
|
||||
ASSERT_EQ(simplePhysicsComponent->GetClimabbleType(), eClimbableType::CLIMBABLE_TYPE_WALL);
|
||||
ASSERT_EQ(simplePhysicsComponent->GetPosition(), NiPoint3(1.0f, 2.0f, 3.0f));
|
||||
ASSERT_EQ(simplePhysicsComponent->GetRotation(), NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
|
||||
|
||||
102
tests/dGameTests/dComponentsTests/SkillComponentTests.cpp
Normal file
102
tests/dGameTests/dComponentsTests/SkillComponentTests.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "SkillComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
|
||||
class SkillComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(SkillComponentTest, SerializeInitialUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
SkillComponent skillComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
skillComponent.Serialize(bitStream, true);
|
||||
|
||||
// Read the data manually to validate serialization format
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool skillFlag;
|
||||
ASSERT_TRUE(bitStream.Read(skillFlag));
|
||||
EXPECT_FALSE(skillFlag); // Always writes 0 for initial update
|
||||
}
|
||||
|
||||
TEST_F(SkillComponentTest, SerializeRegularUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
SkillComponent skillComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
skillComponent.Serialize(bitStream, false);
|
||||
|
||||
// Regular updates should not write anything for SkillComponent
|
||||
bitStream.ResetReadPointer();
|
||||
EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0);
|
||||
}
|
||||
|
||||
TEST_F(SkillComponentTest, SerializeConsistentBehavior) {
|
||||
Entity testEntity(15, info);
|
||||
SkillComponent skillComponent(&testEntity);
|
||||
|
||||
// Test that multiple initial serializations are consistent
|
||||
RakNet::BitStream firstStream, secondStream;
|
||||
|
||||
skillComponent.Serialize(firstStream, true);
|
||||
skillComponent.Serialize(secondStream, true);
|
||||
|
||||
EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), secondStream.GetNumberOfBitsUsed());
|
||||
EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), 1); // Should always be 1 bit (false)
|
||||
|
||||
firstStream.ResetReadPointer();
|
||||
secondStream.ResetReadPointer();
|
||||
|
||||
bool firstFlag, secondFlag;
|
||||
ASSERT_TRUE(firstStream.Read(firstFlag));
|
||||
ASSERT_TRUE(secondStream.Read(secondFlag));
|
||||
EXPECT_FALSE(firstFlag);
|
||||
EXPECT_FALSE(secondFlag);
|
||||
EXPECT_EQ(firstFlag, secondFlag);
|
||||
}
|
||||
|
||||
TEST_F(SkillComponentTest, GetUniqueSkillId) {
|
||||
Entity testEntity(15, info);
|
||||
SkillComponent skillComponent(&testEntity);
|
||||
|
||||
// Test that unique skill IDs increment
|
||||
uint32_t firstId = skillComponent.GetUniqueSkillId();
|
||||
uint32_t secondId = skillComponent.GetUniqueSkillId();
|
||||
uint32_t thirdId = skillComponent.GetUniqueSkillId();
|
||||
|
||||
EXPECT_EQ(secondId, firstId + 1);
|
||||
EXPECT_EQ(thirdId, firstId + 2);
|
||||
EXPECT_GT(firstId, 0); // Should start from at least 1
|
||||
}
|
||||
|
||||
TEST_F(SkillComponentTest, SerializeAfterSkillUse) {
|
||||
Entity testEntity(15, info);
|
||||
SkillComponent skillComponent(&testEntity);
|
||||
|
||||
// Generate some skill IDs to simulate skill usage
|
||||
skillComponent.GetUniqueSkillId();
|
||||
skillComponent.GetUniqueSkillId();
|
||||
skillComponent.GetUniqueSkillId();
|
||||
|
||||
// Serialization behavior should still be the same
|
||||
RakNet::BitStream bitStream;
|
||||
skillComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool skillFlag;
|
||||
ASSERT_TRUE(bitStream.Read(skillFlag));
|
||||
EXPECT_FALSE(skillFlag); // Still writes 0 regardless of internal state
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "SoundTriggerComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
|
||||
class SoundTriggerComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* Test SoundTriggerComponent serialization for initial update
|
||||
*/
|
||||
TEST_F(SoundTriggerComponentTest, SerializeInitialUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
SoundTriggerComponent soundTriggerComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
soundTriggerComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// SoundTriggerComponent always writes a dirty flag first
|
||||
bool hasSoundData;
|
||||
ASSERT_TRUE(bitStream.Read(hasSoundData));
|
||||
EXPECT_TRUE(hasSoundData); // Should be true for initial update
|
||||
|
||||
// Then it writes 5 collection sizes (all 0 for empty component)
|
||||
uint8_t musicCuesCount, musicParamsCount, ambientSounds2DCount, ambientSounds3DCount, mixerProgramsCount;
|
||||
ASSERT_TRUE(bitStream.Read(musicCuesCount));
|
||||
ASSERT_TRUE(bitStream.Read(musicParamsCount));
|
||||
ASSERT_TRUE(bitStream.Read(ambientSounds2DCount));
|
||||
ASSERT_TRUE(bitStream.Read(ambientSounds3DCount));
|
||||
ASSERT_TRUE(bitStream.Read(mixerProgramsCount));
|
||||
|
||||
EXPECT_EQ(musicCuesCount, 0);
|
||||
EXPECT_EQ(musicParamsCount, 0);
|
||||
EXPECT_EQ(ambientSounds2DCount, 0);
|
||||
EXPECT_EQ(ambientSounds3DCount, 0);
|
||||
EXPECT_EQ(mixerProgramsCount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test SoundTriggerComponent serialization for regular update
|
||||
*/
|
||||
TEST_F(SoundTriggerComponentTest, SerializeRegularUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
SoundTriggerComponent soundTriggerComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
soundTriggerComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
// For regular updates, component writes dirty flag only (should be false)
|
||||
bool hasSoundData;
|
||||
ASSERT_TRUE(bitStream.Read(hasSoundData));
|
||||
EXPECT_FALSE(hasSoundData); // Should be false for regular update with no changes
|
||||
}
|
||||
110
tests/dGameTests/dComponentsTests/SwitchComponentTests.cpp
Normal file
110
tests/dGameTests/dComponentsTests/SwitchComponentTests.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "GameDependencies.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "SwitchComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class SwitchComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
Entity* baseEntity;
|
||||
SwitchComponent* switchComponent;
|
||||
CBITSTREAM
|
||||
uint32_t flags = 0;
|
||||
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||
switchComponent = baseEntity->AddComponent<SwitchComponent>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete baseEntity;
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test SwitchComponent serialization with default inactive state
|
||||
*/
|
||||
TEST_F(SwitchComponentTest, SerializeInactiveTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Test initial update with default inactive state
|
||||
switchComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isActive;
|
||||
bitStream.Read(isActive);
|
||||
EXPECT_EQ(isActive, false); // Default state should be inactive
|
||||
}
|
||||
|
||||
/**
|
||||
* Test SwitchComponent serialization with active state
|
||||
*/
|
||||
TEST_F(SwitchComponentTest, SerializeActiveTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Set switch to active state
|
||||
switchComponent->SetActive(true);
|
||||
switchComponent->Serialize(bitStream, true);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isActive;
|
||||
bitStream.Read(isActive);
|
||||
EXPECT_EQ(isActive, true); // Should be active
|
||||
}
|
||||
|
||||
/**
|
||||
* Test SwitchComponent serialization state changes
|
||||
*/
|
||||
TEST_F(SwitchComponentTest, SerializeStateChangeTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Start inactive, then activate
|
||||
switchComponent->Serialize(bitStream, true);
|
||||
|
||||
bool isActive1;
|
||||
bitStream.Read(isActive1);
|
||||
EXPECT_EQ(isActive1, false);
|
||||
|
||||
// Reset and change to active
|
||||
bitStream.Reset();
|
||||
switchComponent->SetActive(true);
|
||||
switchComponent->Serialize(bitStream, false); // Regular update
|
||||
|
||||
bool isActive2;
|
||||
bitStream.Read(isActive2);
|
||||
EXPECT_EQ(isActive2, true);
|
||||
|
||||
// Reset and change back to inactive
|
||||
bitStream.Reset();
|
||||
switchComponent->SetActive(false);
|
||||
switchComponent->Serialize(bitStream, false); // Regular update
|
||||
|
||||
bool isActive3;
|
||||
bitStream.Read(isActive3);
|
||||
EXPECT_EQ(isActive3, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test SwitchComponent serialization regular update behavior
|
||||
*/
|
||||
TEST_F(SwitchComponentTest, SerializeRegularUpdateTest) {
|
||||
bitStream.Reset();
|
||||
|
||||
// Set to active state
|
||||
switchComponent->SetActive(true);
|
||||
|
||||
// Test regular update - should still serialize the boolean
|
||||
switchComponent->Serialize(bitStream, false);
|
||||
|
||||
// Read back the serialized data
|
||||
bool isActive;
|
||||
bitStream.Read(isActive);
|
||||
EXPECT_EQ(isActive, true);
|
||||
|
||||
// SwitchComponent always serializes the active state regardless of update type
|
||||
EXPECT_EQ(bitStream.GetNumberOfBitsUsed(), 1); // Should have exactly 1 bit used
|
||||
}
|
||||
174
tests/dGameTests/dComponentsTests/VendorComponentTests.cpp
Normal file
174
tests/dGameTests/dComponentsTests/VendorComponentTests.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "VendorComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "BitStream.h"
|
||||
#include "GameDependencies.h"
|
||||
|
||||
class VendorComponentTest : public GameDependenciesTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
SetUpDependencies();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
TearDownDependencies();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(VendorComponentTest, SerializeInitialUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
VendorComponent vendorComponent(&testEntity);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
vendorComponent.Serialize(bitStream, true);
|
||||
|
||||
// Read the data manually to validate serialization format
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_TRUE(hasVendorInfo); // Should always be true for initial update
|
||||
|
||||
bool hasStandardCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasStandardCostItems));
|
||||
// May be true if vendor has items during construction
|
||||
|
||||
bool hasMultiCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasMultiCostItems));
|
||||
// May be true if vendor has items during construction
|
||||
}
|
||||
|
||||
TEST_F(VendorComponentTest, SerializeRegularUpdate) {
|
||||
Entity testEntity(15, info);
|
||||
VendorComponent vendorComponent(&testEntity);
|
||||
|
||||
// Do initial serialization to populate data
|
||||
RakNet::BitStream initStream;
|
||||
vendorComponent.Serialize(initStream, true);
|
||||
|
||||
// Do a regular update to clear dirty flag
|
||||
RakNet::BitStream clearStream;
|
||||
vendorComponent.Serialize(clearStream, false);
|
||||
|
||||
// Now test regular update with no changes
|
||||
RakNet::BitStream bitStream;
|
||||
vendorComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_FALSE(hasVendorInfo); // No dirty flags after clearing, so no data
|
||||
}
|
||||
|
||||
TEST_F(VendorComponentTest, SerializeWithDirtyVendor) {
|
||||
Entity testEntity(15, info);
|
||||
VendorComponent vendorComponent(&testEntity);
|
||||
|
||||
// Reset dirty flag
|
||||
RakNet::BitStream initStream;
|
||||
vendorComponent.Serialize(initStream, true);
|
||||
|
||||
// Make vendor dirty by changing state
|
||||
vendorComponent.SetHasStandardCostItems(true);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
vendorComponent.Serialize(bitStream, false);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_TRUE(hasVendorInfo); // Should be true due to dirty flag
|
||||
|
||||
bool hasStandardCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasStandardCostItems));
|
||||
EXPECT_TRUE(hasStandardCostItems); // Changed to true
|
||||
|
||||
bool hasMultiCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasMultiCostItems));
|
||||
EXPECT_FALSE(hasMultiCostItems); // Still false
|
||||
}
|
||||
|
||||
TEST_F(VendorComponentTest, SerializeWithMultiCostItems) {
|
||||
Entity testEntity(15, info);
|
||||
VendorComponent vendorComponent(&testEntity);
|
||||
|
||||
// Set both flags
|
||||
vendorComponent.SetHasStandardCostItems(true);
|
||||
vendorComponent.SetHasMultiCostItems(true);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
vendorComponent.Serialize(bitStream, true);
|
||||
|
||||
bitStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(bitStream.Read(hasVendorInfo));
|
||||
EXPECT_TRUE(hasVendorInfo);
|
||||
|
||||
bool hasStandardCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasStandardCostItems));
|
||||
EXPECT_TRUE(hasStandardCostItems);
|
||||
|
||||
bool hasMultiCostItems;
|
||||
ASSERT_TRUE(bitStream.Read(hasMultiCostItems));
|
||||
EXPECT_TRUE(hasMultiCostItems);
|
||||
}
|
||||
|
||||
TEST_F(VendorComponentTest, SerializeDirtyFlagClearing) {
|
||||
Entity testEntity(15, info);
|
||||
VendorComponent vendorComponent(&testEntity);
|
||||
|
||||
// Make vendor dirty
|
||||
vendorComponent.SetHasStandardCostItems(true);
|
||||
|
||||
// First serialize should clear dirty flag
|
||||
RakNet::BitStream firstStream;
|
||||
vendorComponent.Serialize(firstStream, false);
|
||||
|
||||
// Second serialize should show no vendor info
|
||||
RakNet::BitStream secondStream;
|
||||
vendorComponent.Serialize(secondStream, false);
|
||||
|
||||
secondStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(secondStream.Read(hasVendorInfo));
|
||||
EXPECT_FALSE(hasVendorInfo); // Dirty flag should be cleared
|
||||
}
|
||||
|
||||
TEST_F(VendorComponentTest, SettersChangeDirtyFlag) {
|
||||
Entity testEntity(15, info);
|
||||
VendorComponent vendorComponent(&testEntity);
|
||||
|
||||
// Do initial update to populate data
|
||||
RakNet::BitStream initStream;
|
||||
vendorComponent.Serialize(initStream, true);
|
||||
|
||||
// Do regular update to clear dirty flag
|
||||
RakNet::BitStream clearStream;
|
||||
vendorComponent.Serialize(clearStream, false);
|
||||
|
||||
// Setting same value should not make dirty (assume it's true from construction)
|
||||
vendorComponent.SetHasStandardCostItems(true);
|
||||
|
||||
RakNet::BitStream noChangeStream;
|
||||
vendorComponent.Serialize(noChangeStream, false);
|
||||
noChangeStream.ResetReadPointer();
|
||||
|
||||
bool hasVendorInfo;
|
||||
ASSERT_TRUE(noChangeStream.Read(hasVendorInfo));
|
||||
EXPECT_FALSE(hasVendorInfo); // Should not be dirty
|
||||
|
||||
// Setting different value should make dirty
|
||||
vendorComponent.SetHasStandardCostItems(false);
|
||||
|
||||
RakNet::BitStream changeStream;
|
||||
vendorComponent.Serialize(changeStream, false);
|
||||
changeStream.ResetReadPointer();
|
||||
|
||||
ASSERT_TRUE(changeStream.Read(hasVendorInfo));
|
||||
EXPECT_TRUE(hasVendorInfo); // Should be dirty now
|
||||
}
|
||||
Reference in New Issue
Block a user