mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-22 21:43:35 +00:00
Merge remote-tracking branch 'upstream/main' into ub-fixes
This commit is contained in:
commit
4922e2edb1
@ -87,7 +87,7 @@ if(UNIX)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
add_compile_options("-rdynamic")
|
add_link_options("-export-dynamic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${GGDB})
|
if(${GGDB})
|
||||||
|
11
dCommon/dEnums/ePropertySortType.h
Normal file
11
dCommon/dEnums/ePropertySortType.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef EPROPERTYSORTTYPE_H
|
||||||
|
#define EPROPERTYSORTTYPE_H
|
||||||
|
|
||||||
|
enum ePropertySortType : int32_t {
|
||||||
|
SORT_TYPE_FRIENDS = 0,
|
||||||
|
SORT_TYPE_REPUTATION = 1,
|
||||||
|
SORT_TYPE_RECENT = 3,
|
||||||
|
SORT_TYPE_FEATURED = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!EPROPERTYSORTTYPE_H
|
@ -4,6 +4,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
enum ePropertySortType : int32_t;
|
||||||
|
|
||||||
class IProperty {
|
class IProperty {
|
||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
@ -18,11 +20,33 @@ public:
|
|||||||
uint32_t lastUpdatedTime{};
|
uint32_t lastUpdatedTime{};
|
||||||
uint32_t claimedTime{};
|
uint32_t claimedTime{};
|
||||||
uint32_t reputation{};
|
uint32_t reputation{};
|
||||||
|
float performanceCost{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PropertyLookup {
|
||||||
|
uint32_t mapId{};
|
||||||
|
std::string searchString;
|
||||||
|
ePropertySortType sortChoice{};
|
||||||
|
uint32_t playerId{};
|
||||||
|
uint32_t numResults{};
|
||||||
|
uint32_t startIndex{};
|
||||||
|
uint32_t playerSort{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PropertyEntranceResult {
|
||||||
|
int32_t totalEntriesMatchingQuery{};
|
||||||
|
// The entries that match the query. This should only contain up to 12 entries.
|
||||||
|
std::vector<IProperty::Info> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the property info for the given property id.
|
// Get the property info for the given property id.
|
||||||
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
||||||
|
|
||||||
|
// Get the properties for the given property lookup params.
|
||||||
|
// This is expected to return a result set of up to 12 properties
|
||||||
|
// so as not to transfer too much data at once.
|
||||||
|
virtual std::optional<IProperty::PropertyEntranceResult> GetProperties(const PropertyLookup& params) = 0;
|
||||||
|
|
||||||
// Update the property moderation info for the given property id.
|
// Update the property moderation info for the given property id.
|
||||||
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ public:
|
|||||||
std::string GetBehavior(const int32_t behaviorId) override;
|
std::string GetBehavior(const int32_t behaviorId) override;
|
||||||
void RemoveBehavior(const int32_t characterId) override;
|
void RemoveBehavior(const int32_t characterId) override;
|
||||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Generic query functions that can be used for any query.
|
// Generic query functions that can be used for any query.
|
||||||
|
@ -1,8 +1,140 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
#include "ePropertySortType.h"
|
||||||
|
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> result;
|
||||||
|
std::string query;
|
||||||
|
std::unique_ptr<sql::ResultSet> properties;
|
||||||
|
|
||||||
|
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
|
||||||
|
query = R"QUERY(
|
||||||
|
FROM properties as p
|
||||||
|
JOIN charinfo as ci
|
||||||
|
ON ci.prop_clone_id = p.clone_id
|
||||||
|
where p.zone_id = ?
|
||||||
|
AND (
|
||||||
|
p.description LIKE ?
|
||||||
|
OR p.name LIKE ?
|
||||||
|
OR ci.name LIKE ?
|
||||||
|
)
|
||||||
|
AND p.privacy_option >= ?
|
||||||
|
AND p.owner_id IN (
|
||||||
|
SELECT fr.requested_player AS player FROM (
|
||||||
|
SELECT CASE
|
||||||
|
WHEN player_id = ? THEN friend_id
|
||||||
|
WHEN friend_id = ? THEN player_id
|
||||||
|
END AS requested_player FROM friends
|
||||||
|
) AS fr
|
||||||
|
JOIN charinfo AS ci ON ci.id = fr.requested_player
|
||||||
|
WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?
|
||||||
|
) ORDER BY ci.name ASC
|
||||||
|
)QUERY";
|
||||||
|
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
|
||||||
|
properties = ExecuteSelect(
|
||||||
|
completeQuery,
|
||||||
|
params.mapId,
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
params.playerSort,
|
||||||
|
params.playerId,
|
||||||
|
params.playerId,
|
||||||
|
params.playerId,
|
||||||
|
params.numResults,
|
||||||
|
params.startIndex
|
||||||
|
);
|
||||||
|
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
|
||||||
|
auto count = ExecuteSelect(
|
||||||
|
countQuery,
|
||||||
|
params.mapId,
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
params.playerSort,
|
||||||
|
params.playerId,
|
||||||
|
params.playerId,
|
||||||
|
params.playerId
|
||||||
|
);
|
||||||
|
if (count->next()) {
|
||||||
|
result->totalEntriesMatchingQuery = count->getUInt("count");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (params.sortChoice == SORT_TYPE_REPUTATION) {
|
||||||
|
query = R"QUERY(
|
||||||
|
FROM properties as p
|
||||||
|
JOIN charinfo as ci
|
||||||
|
ON ci.prop_clone_id = p.clone_id
|
||||||
|
where p.zone_id = ?
|
||||||
|
AND (
|
||||||
|
p.description LIKE ?
|
||||||
|
OR p.name LIKE ?
|
||||||
|
OR ci.name LIKE ?
|
||||||
|
)
|
||||||
|
AND p.privacy_option >= ?
|
||||||
|
ORDER BY p.reputation DESC, p.last_updated DESC
|
||||||
|
)QUERY";
|
||||||
|
} else {
|
||||||
|
query = R"QUERY(
|
||||||
|
FROM properties as p
|
||||||
|
JOIN charinfo as ci
|
||||||
|
ON ci.prop_clone_id = p.clone_id
|
||||||
|
where p.zone_id = ?
|
||||||
|
AND (
|
||||||
|
p.description LIKE ?
|
||||||
|
OR p.name LIKE ?
|
||||||
|
OR ci.name LIKE ?
|
||||||
|
)
|
||||||
|
AND p.privacy_option >= ?
|
||||||
|
ORDER BY p.last_updated DESC
|
||||||
|
)QUERY";
|
||||||
|
}
|
||||||
|
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
|
||||||
|
properties = ExecuteSelect(
|
||||||
|
completeQuery,
|
||||||
|
params.mapId,
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
params.playerSort,
|
||||||
|
params.numResults,
|
||||||
|
params.startIndex
|
||||||
|
);
|
||||||
|
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
|
||||||
|
auto count = ExecuteSelect(
|
||||||
|
countQuery,
|
||||||
|
params.mapId,
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
"%" + params.searchString + "%",
|
||||||
|
params.playerSort
|
||||||
|
);
|
||||||
|
if (count->next()) {
|
||||||
|
result->totalEntriesMatchingQuery = count->getUInt("count");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (properties->next()) {
|
||||||
|
auto& entry = result->entries.emplace_back();
|
||||||
|
entry.id = properties->getUInt64("id");
|
||||||
|
entry.ownerId = properties->getUInt64("owner_id");
|
||||||
|
entry.cloneId = properties->getUInt64("clone_id");
|
||||||
|
entry.name = properties->getString("name").c_str();
|
||||||
|
entry.description = properties->getString("description").c_str();
|
||||||
|
entry.privacyOption = properties->getInt("privacy_option");
|
||||||
|
entry.rejectionReason = properties->getString("rejection_reason").c_str();
|
||||||
|
entry.lastUpdatedTime = properties->getUInt("last_updated");
|
||||||
|
entry.claimedTime = properties->getUInt("time_claimed");
|
||||||
|
entry.reputation = properties->getUInt("reputation");
|
||||||
|
entry.modApproved = properties->getUInt("mod_approved");
|
||||||
|
entry.performanceCost = properties->getFloat("performance_cost");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
||||||
auto propertyEntry = ExecuteSelect(
|
auto propertyEntry = ExecuteSelect(
|
||||||
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved "
|
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||||
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
||||||
|
|
||||||
if (!propertyEntry->next()) {
|
if (!propertyEntry->next()) {
|
||||||
@ -21,6 +153,7 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
|
|||||||
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
||||||
toReturn.reputation = propertyEntry->getUInt("reputation");
|
toReturn.reputation = propertyEntry->getUInt("reputation");
|
||||||
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
||||||
|
toReturn.performanceCost = propertyEntry->getFloat("performance_cost");
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ class TestSQLDatabase : public GameDatabase {
|
|||||||
std::string GetBehavior(const int32_t behaviorId) override;
|
std::string GetBehavior(const int32_t behaviorId) override;
|
||||||
void RemoveBehavior(const int32_t behaviorId) override;
|
void RemoveBehavior(const int32_t behaviorId) override;
|
||||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override { return {}; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!TESTSQLDATABASE_H
|
#endif //!TESTSQLDATABASE_H
|
||||||
|
@ -1351,11 +1351,6 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
|||||||
callback(other);
|
callback(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchComponent* switchComp = GetComponent<SwitchComponent>();
|
|
||||||
if (switchComp) {
|
|
||||||
switchComp->EntityEnter(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerEvent(eTriggerEventType::ENTER, other);
|
TriggerEvent(eTriggerEventType::ENTER, other);
|
||||||
|
|
||||||
// POI system
|
// POI system
|
||||||
|
@ -25,7 +25,7 @@ public:
|
|||||||
User& operator=(const User& other);
|
User& operator=(const User& other);
|
||||||
bool operator==(const User& other) const;
|
bool operator==(const User& other) const;
|
||||||
|
|
||||||
uint32_t GetAccountID() { return m_AccountID; }
|
uint32_t GetAccountID() const noexcept { return m_AccountID; }
|
||||||
std::string& GetUsername() { return m_Username; }
|
std::string& GetUsername() { return m_Username; }
|
||||||
std::string& GetSessionKey() { return m_SessionKey; }
|
std::string& GetSessionKey() { return m_SessionKey; }
|
||||||
SystemAddress& GetSystemAddress() { return m_SystemAddress; }
|
SystemAddress& GetSystemAddress() { return m_SystemAddress; }
|
||||||
|
@ -381,7 +381,7 @@ void PetComponent::Update(float deltaTime) {
|
|||||||
float distance = Vector3::DistanceSquared(position, switchPosition);
|
float distance = Vector3::DistanceSquared(position, switchPosition);
|
||||||
if (distance < 3 * 3) {
|
if (distance < 3 * 3) {
|
||||||
m_Interaction = closestSwitch->GetParentEntity()->GetObjectID();
|
m_Interaction = closestSwitch->GetParentEntity()->GetObjectID();
|
||||||
closestSwitch->EntityEnter(m_Parent);
|
closestSwitch->OnUse(m_Parent);
|
||||||
} else if (distance < 20 * 20) {
|
} else if (distance < 20 * 20) {
|
||||||
haltDistance = 1;
|
haltDistance = 1;
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "Amf3.h"
|
#include "Amf3.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
#include "ePropertySortType.h"
|
||||||
|
#include "User.h"
|
||||||
|
|
||||||
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
|
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
|
||||||
this->propertyQueries = {};
|
this->propertyQueries = {};
|
||||||
@ -74,261 +76,103 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index,
|
|||||||
launcher->Launch(entity, launcher->GetTargetZone(), cloneId);
|
launcher->Launch(entity, launcher->GetTargetZone(), cloneId);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) {
|
|
||||||
property.CloneId = cloneId;
|
|
||||||
property.OwnerName = ownerName;
|
|
||||||
property.Name = propertyName;
|
|
||||||
property.Description = propertyDescription;
|
|
||||||
property.Reputation = reputation;
|
|
||||||
property.IsBestFriend = isBFF;
|
|
||||||
property.IsFriend = isFriend;
|
|
||||||
property.IsModeratorApproved = isModeratorApproved;
|
|
||||||
property.IsAlt = isAlt;
|
|
||||||
property.IsOwned = isOwned;
|
|
||||||
property.AccessType = privacyOption;
|
|
||||||
property.DateLastPublished = timeLastUpdated;
|
|
||||||
property.PerformanceCost = performanceCost;
|
|
||||||
|
|
||||||
return property;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery, bool wantLimits) {
|
|
||||||
std::string base;
|
|
||||||
if (customQuery == "") {
|
|
||||||
base = baseQueryForProperties;
|
|
||||||
} else {
|
|
||||||
base = customQuery;
|
|
||||||
}
|
|
||||||
std::string orderBy = "";
|
|
||||||
if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) {
|
|
||||||
std::string friendsList = " AND p.owner_id IN (";
|
|
||||||
|
|
||||||
auto friendsListQuery = Database::Get()->CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
|
|
||||||
|
|
||||||
friendsListQuery->setUInt(1, character->GetID());
|
|
||||||
friendsListQuery->setUInt(2, character->GetID());
|
|
||||||
|
|
||||||
auto friendsListQueryResult = friendsListQuery->executeQuery();
|
|
||||||
|
|
||||||
while (friendsListQueryResult->next()) {
|
|
||||||
auto playerIDToConvert = friendsListQueryResult->getInt(1);
|
|
||||||
friendsList = friendsList + std::to_string(playerIDToConvert) + ",";
|
|
||||||
}
|
|
||||||
// Replace trailing comma with the closing parenthesis.
|
|
||||||
if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1);
|
|
||||||
friendsList += ") ";
|
|
||||||
|
|
||||||
// If we have no friends then use a -1 for the query.
|
|
||||||
if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) ";
|
|
||||||
|
|
||||||
orderBy += friendsList + "ORDER BY ci.name ASC ";
|
|
||||||
|
|
||||||
delete friendsListQueryResult;
|
|
||||||
friendsListQueryResult = nullptr;
|
|
||||||
|
|
||||||
delete friendsListQuery;
|
|
||||||
friendsListQuery = nullptr;
|
|
||||||
} else if (sortMethod == SORT_TYPE_RECENT) {
|
|
||||||
orderBy = "ORDER BY p.last_updated DESC ";
|
|
||||||
} else if (sortMethod == SORT_TYPE_REPUTATION) {
|
|
||||||
orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC ";
|
|
||||||
} else {
|
|
||||||
orderBy = "ORDER BY p.last_updated DESC ";
|
|
||||||
}
|
|
||||||
return base + orderBy + (wantLimits ? "LIMIT ? OFFSET ?;" : ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr) {
|
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr) {
|
||||||
|
const auto* const character = entity->GetCharacter();
|
||||||
std::vector<PropertySelectQueryProperty> entries{};
|
|
||||||
PropertySelectQueryProperty playerEntry{};
|
|
||||||
|
|
||||||
auto character = entity->GetCharacter();
|
|
||||||
if (!character) return;
|
if (!character) return;
|
||||||
|
const auto* const user = character->GetParentUser();
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
auto& entries = propertyQueries[entity->GetObjectID()];
|
||||||
|
entries.clear();
|
||||||
// Player property goes in index 1 of the vector. This is how the client expects it.
|
// Player property goes in index 1 of the vector. This is how the client expects it.
|
||||||
auto playerPropertyLookup = Database::Get()->CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?");
|
const auto playerProperty = Database::Get()->GetPropertyInfo(m_MapID, character->GetPropertyCloneID());
|
||||||
|
|
||||||
playerPropertyLookup->setInt(1, character->GetID());
|
|
||||||
playerPropertyLookup->setInt(2, this->m_MapID);
|
|
||||||
|
|
||||||
auto playerPropertyLookupResults = playerPropertyLookup->executeQuery();
|
|
||||||
|
|
||||||
// If the player has a property this query will have a single result.
|
// If the player has a property this query will have a single result.
|
||||||
if (playerPropertyLookupResults->next()) {
|
auto& playerEntry = entries.emplace_back();
|
||||||
const auto cloneId = playerPropertyLookupResults->getUInt64(4);
|
if (playerProperty.has_value()) {
|
||||||
const auto propertyName = std::string(playerPropertyLookupResults->getString(5).c_str());
|
playerEntry.OwnerName = character->GetName();
|
||||||
const auto propertyDescription = std::string(playerPropertyLookupResults->getString(6).c_str());
|
playerEntry.IsBestFriend = true;
|
||||||
const auto privacyOption = playerPropertyLookupResults->getInt(9);
|
playerEntry.IsFriend = true;
|
||||||
const auto modApproved = playerPropertyLookupResults->getBoolean(10);
|
playerEntry.IsAlt = true;
|
||||||
const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11);
|
playerEntry.IsOwned = true;
|
||||||
const auto reputation = playerPropertyLookupResults->getUInt(14);
|
playerEntry.CloneId = playerProperty->cloneId;
|
||||||
const auto performanceCost = playerPropertyLookupResults->getFloat(16);
|
playerEntry.Name = playerProperty->name;
|
||||||
|
playerEntry.Description = playerProperty->description;
|
||||||
playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), propertyName, propertyDescription, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost);
|
playerEntry.AccessType = playerProperty->privacyOption;
|
||||||
|
playerEntry.IsModeratorApproved = playerProperty->modApproved;
|
||||||
|
playerEntry.DateLastPublished = playerProperty->lastUpdatedTime;
|
||||||
|
playerEntry.Reputation = playerProperty->reputation;
|
||||||
|
playerEntry.PerformanceCost = playerProperty->performanceCost;
|
||||||
|
auto& entry = playerEntry;
|
||||||
} else {
|
} else {
|
||||||
playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true);
|
playerEntry.OwnerName = character->GetName();
|
||||||
|
playerEntry.IsBestFriend = true;
|
||||||
|
playerEntry.IsFriend = true;
|
||||||
|
playerEntry.IsAlt = false;
|
||||||
|
playerEntry.IsOwned = false;
|
||||||
|
playerEntry.CloneId = character->GetPropertyCloneID();
|
||||||
|
playerEntry.Name = "";
|
||||||
|
playerEntry.Description = "";
|
||||||
|
playerEntry.AccessType = 0;
|
||||||
|
playerEntry.IsModeratorApproved = false;
|
||||||
|
playerEntry.DateLastPublished = 0;
|
||||||
|
playerEntry.Reputation = 0;
|
||||||
|
playerEntry.PerformanceCost = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete playerPropertyLookupResults;
|
IProperty::PropertyLookup propertyLookup;
|
||||||
playerPropertyLookupResults = nullptr;
|
propertyLookup.mapId = m_MapID;
|
||||||
|
propertyLookup.searchString = filterText;
|
||||||
|
propertyLookup.sortChoice = static_cast<ePropertySortType>(sortMethod);
|
||||||
|
propertyLookup.playerSort = static_cast<uint32_t>(sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? PropertyPrivacyOption::Friends : PropertyPrivacyOption::Public);
|
||||||
|
propertyLookup.playerId = character->GetID();
|
||||||
|
propertyLookup.numResults = numResults;
|
||||||
|
propertyLookup.startIndex = startIndex;
|
||||||
|
|
||||||
delete playerPropertyLookup;
|
const auto lookupResult = Database::Get()->GetProperties(propertyLookup);
|
||||||
playerPropertyLookup = nullptr;
|
|
||||||
|
|
||||||
entries.push_back(playerEntry);
|
|
||||||
|
|
||||||
const auto query = BuildQuery(entity, sortMethod, character);
|
|
||||||
|
|
||||||
auto propertyLookup = Database::Get()->CreatePreppedStmt(query);
|
|
||||||
|
|
||||||
const auto searchString = "%" + filterText + "%";
|
|
||||||
propertyLookup->setUInt(1, this->m_MapID);
|
|
||||||
propertyLookup->setString(2, searchString.c_str());
|
|
||||||
propertyLookup->setString(3, searchString.c_str());
|
|
||||||
propertyLookup->setString(4, searchString.c_str());
|
|
||||||
propertyLookup->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? static_cast<uint32_t>(PropertyPrivacyOption::Friends) : static_cast<uint32_t>(PropertyPrivacyOption::Public));
|
|
||||||
propertyLookup->setInt(6, numResults);
|
|
||||||
propertyLookup->setInt(7, startIndex);
|
|
||||||
|
|
||||||
auto propertyEntry = propertyLookup->executeQuery();
|
|
||||||
|
|
||||||
while (propertyEntry->next()) {
|
|
||||||
const auto propertyId = propertyEntry->getUInt64(1);
|
|
||||||
const auto owner = propertyEntry->getInt(2);
|
|
||||||
const auto cloneId = propertyEntry->getUInt64(4);
|
|
||||||
const auto propertyNameFromDb = std::string(propertyEntry->getString(5).c_str());
|
|
||||||
const auto propertyDescriptionFromDb = std::string(propertyEntry->getString(6).c_str());
|
|
||||||
const auto privacyOption = propertyEntry->getInt(9);
|
|
||||||
const auto modApproved = propertyEntry->getBoolean(10);
|
|
||||||
const auto dateLastUpdated = propertyEntry->getInt(11);
|
|
||||||
const float reputation = propertyEntry->getInt(14);
|
|
||||||
const auto performanceCost = propertyEntry->getFloat(16);
|
|
||||||
|
|
||||||
PropertySelectQueryProperty entry{};
|
|
||||||
|
|
||||||
std::string ownerName = "";
|
|
||||||
bool isOwned = true;
|
|
||||||
auto nameLookup = Database::Get()->CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
|
|
||||||
|
|
||||||
nameLookup->setUInt64(1, cloneId);
|
|
||||||
|
|
||||||
auto nameResult = nameLookup->executeQuery();
|
|
||||||
|
|
||||||
if (!nameResult->next()) {
|
|
||||||
delete nameLookup;
|
|
||||||
nameLookup = nullptr;
|
|
||||||
|
|
||||||
LOG("Failed to find property owner name for %llu!", cloneId);
|
|
||||||
|
|
||||||
|
for (const auto& propertyEntry : lookupResult->entries) {
|
||||||
|
const auto owner = propertyEntry.ownerId;
|
||||||
|
const auto otherCharacter = Database::Get()->GetCharacterInfo(owner);
|
||||||
|
if (!otherCharacter.has_value()) {
|
||||||
|
LOG("Failed to find property owner name for %u!", owner);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
isOwned = cloneId == character->GetPropertyCloneID();
|
|
||||||
ownerName = std::string(nameResult->getString(1).c_str());
|
|
||||||
}
|
}
|
||||||
|
auto& entry = entries.emplace_back();
|
||||||
|
|
||||||
delete nameResult;
|
entry.IsOwned = entry.CloneId == otherCharacter->cloneId;
|
||||||
nameResult = nullptr;
|
entry.OwnerName = otherCharacter->name;
|
||||||
|
entry.CloneId = propertyEntry.cloneId;
|
||||||
delete nameLookup;
|
entry.Name = propertyEntry.name;
|
||||||
nameLookup = nullptr;
|
entry.Description = propertyEntry.description;
|
||||||
|
entry.AccessType = propertyEntry.privacyOption;
|
||||||
std::string propertyName = propertyNameFromDb;
|
entry.IsModeratorApproved = propertyEntry.modApproved;
|
||||||
std::string propertyDescription = propertyDescriptionFromDb;
|
entry.DateLastPublished = propertyEntry.lastUpdatedTime;
|
||||||
|
entry.Reputation = propertyEntry.reputation;
|
||||||
bool isBestFriend = false;
|
entry.PerformanceCost = propertyEntry.performanceCost;
|
||||||
bool isFriend = false;
|
entry.IsBestFriend = false;
|
||||||
|
entry.IsFriend = false;
|
||||||
// Convert owner char id to LWOOBJID
|
|
||||||
LWOOBJID ownerObjId = owner;
|
|
||||||
GeneralUtils::SetBit(ownerObjId, eObjectBits::CHARACTER);
|
|
||||||
GeneralUtils::SetBit(ownerObjId, eObjectBits::PERSISTENT);
|
|
||||||
|
|
||||||
// Query to get friend and best friend fields
|
// Query to get friend and best friend fields
|
||||||
auto friendCheck = Database::Get()->CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
|
const auto friendCheck = Database::Get()->GetBestFriendStatus(character->GetID(), owner);
|
||||||
|
|
||||||
friendCheck->setUInt(1, character->GetID());
|
|
||||||
friendCheck->setUInt(2, ownerObjId);
|
|
||||||
friendCheck->setUInt(3, ownerObjId);
|
|
||||||
friendCheck->setUInt(4, character->GetID());
|
|
||||||
|
|
||||||
auto friendResult = friendCheck->executeQuery();
|
|
||||||
|
|
||||||
// If we got a result than the two players are friends.
|
// If we got a result than the two players are friends.
|
||||||
if (friendResult->next()) {
|
if (friendCheck.has_value()) {
|
||||||
isFriend = true;
|
entry.IsFriend = true;
|
||||||
if (friendResult->getInt(1) == 3) {
|
entry.IsBestFriend = friendCheck->bestFriendStatus == 3;
|
||||||
isBestFriend = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete friendCheck;
|
if (!entry.IsModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
|
||||||
friendCheck = nullptr;
|
entry.Name = "[AWAITING APPROVAL]";
|
||||||
|
entry.Description = "[AWAITING APPROVAL]";
|
||||||
delete friendResult;
|
entry.IsModeratorApproved = true;
|
||||||
friendResult = nullptr;
|
|
||||||
|
|
||||||
bool isModeratorApproved = propertyEntry->getBoolean(10);
|
|
||||||
|
|
||||||
if (!isModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
|
|
||||||
propertyName = "[AWAITING APPROVAL]";
|
|
||||||
propertyDescription = "[AWAITING APPROVAL]";
|
|
||||||
isModeratorApproved = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAlt = false;
|
|
||||||
// Query to determine whether this property is an alt character of the entity.
|
// Query to determine whether this property is an alt character of the entity.
|
||||||
auto isAltQuery = Database::Get()->CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;");
|
for (const auto charid : Database::Get()->GetAccountCharacterIds(user->GetAccountID())) {
|
||||||
|
entry.IsAlt = charid == owner;
|
||||||
isAltQuery->setInt(1, character->GetID());
|
if (entry.IsAlt) break;
|
||||||
isAltQuery->setInt(2, owner);
|
|
||||||
|
|
||||||
auto isAltQueryResults = isAltQuery->executeQuery();
|
|
||||||
|
|
||||||
if (isAltQueryResults->next()) {
|
|
||||||
isAlt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete isAltQueryResults;
|
|
||||||
isAltQueryResults = nullptr;
|
|
||||||
|
|
||||||
delete isAltQuery;
|
|
||||||
isAltQuery = nullptr;
|
|
||||||
|
|
||||||
entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost);
|
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete propertyEntry;
|
|
||||||
propertyEntry = nullptr;
|
|
||||||
|
|
||||||
delete propertyLookup;
|
|
||||||
propertyLookup = nullptr;
|
|
||||||
|
|
||||||
propertyQueries[entity->GetObjectID()] = entries;
|
|
||||||
|
|
||||||
// Query here is to figure out whether or not to display the button to go to the next page or not.
|
// Query here is to figure out whether or not to display the button to go to the next page or not.
|
||||||
int32_t numberOfProperties = 0;
|
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, lookupResult->totalEntriesMatchingQuery - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
|
||||||
|
|
||||||
auto buttonQuery = BuildQuery(entity, sortMethod, character, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false);
|
|
||||||
auto propertiesLeft = Database::Get()->CreatePreppedStmt(buttonQuery);
|
|
||||||
|
|
||||||
propertiesLeft->setUInt(1, this->m_MapID);
|
|
||||||
propertiesLeft->setString(2, searchString.c_str());
|
|
||||||
propertiesLeft->setString(3, searchString.c_str());
|
|
||||||
propertiesLeft->setString(4, searchString.c_str());
|
|
||||||
propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2);
|
|
||||||
|
|
||||||
auto result = propertiesLeft->executeQuery();
|
|
||||||
result->next();
|
|
||||||
numberOfProperties = result->getInt(1);
|
|
||||||
|
|
||||||
delete result;
|
|
||||||
result = nullptr;
|
|
||||||
|
|
||||||
delete propertiesLeft;
|
|
||||||
propertiesLeft = nullptr;
|
|
||||||
|
|
||||||
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
|
|
||||||
}
|
}
|
||||||
|
@ -57,11 +57,7 @@ public:
|
|||||||
* Returns the map ID for this property
|
* Returns the map ID for this property
|
||||||
* @return the map ID for this property
|
* @return the map ID for this property
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; };
|
[[nodiscard]] LWOMAPID GetMapID() const noexcept { return m_MapID; };
|
||||||
|
|
||||||
PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f);
|
|
||||||
|
|
||||||
std::string BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery = "", bool wantLimits = true);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@ -78,13 +74,4 @@ private:
|
|||||||
* The base map ID for this property (Avant Grove, etc).
|
* The base map ID for this property (Avant Grove, etc).
|
||||||
*/
|
*/
|
||||||
LWOMAPID m_MapID;
|
LWOMAPID m_MapID;
|
||||||
|
|
||||||
enum ePropertySortType : int32_t {
|
|
||||||
SORT_TYPE_FRIENDS = 0,
|
|
||||||
SORT_TYPE_REPUTATION = 1,
|
|
||||||
SORT_TYPE_RECENT = 3,
|
|
||||||
SORT_TYPE_FEATURED = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ";
|
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
#include "eTriggerEventType.h"
|
#include "eTriggerEventType.h"
|
||||||
#include "RenderComponent.h"
|
#include "RenderComponent.h"
|
||||||
|
#include "DestroyableComponent.h"
|
||||||
|
|
||||||
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
|
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
|
||||||
|
|
||||||
@ -11,6 +12,13 @@ SwitchComponent::SwitchComponent(Entity* parent) : Component(parent) {
|
|||||||
m_ResetTime = m_Parent->GetVarAs<int32_t>(u"switch_reset_time");
|
m_ResetTime = m_Parent->GetVarAs<int32_t>(u"switch_reset_time");
|
||||||
|
|
||||||
m_QuickBuild = m_Parent->GetComponent<QuickBuildComponent>();
|
m_QuickBuild = m_Parent->GetComponent<QuickBuildComponent>();
|
||||||
|
|
||||||
|
const auto factions = GeneralUtils::SplitString(m_Parent->GetVar<std::u16string>(u"respond_to_faction"), u':');
|
||||||
|
for (const auto& faction : factions) {
|
||||||
|
auto factionID = GeneralUtils::TryParse<int32_t>(GeneralUtils::UTF16ToWTF8(faction));
|
||||||
|
if (!factionID) continue;
|
||||||
|
m_FactionsToRespondTo.push_back(factionID.value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchComponent::~SwitchComponent() {
|
SwitchComponent::~SwitchComponent() {
|
||||||
@ -25,6 +33,17 @@ void SwitchComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitial
|
|||||||
outBitStream.Write(m_Active);
|
outBitStream.Write(m_Active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwitchComponent::OnUse(Entity* originator) {
|
||||||
|
const auto* const destroyableComponent = originator->GetComponent<DestroyableComponent>();
|
||||||
|
if (!destroyableComponent) return;
|
||||||
|
for (const auto faction : m_FactionsToRespondTo) {
|
||||||
|
if (destroyableComponent->HasFaction(faction)) {
|
||||||
|
EntityEnter(originator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SwitchComponent::SetActive(bool active) {
|
void SwitchComponent::SetActive(bool active) {
|
||||||
m_Active = active;
|
m_Active = active;
|
||||||
|
|
||||||
@ -63,6 +82,7 @@ void SwitchComponent::EntityEnter(Entity* entity) {
|
|||||||
RenderComponent::PlayAnimation(m_Parent, u"engaged");
|
RenderComponent::PlayAnimation(m_Parent, u"engaged");
|
||||||
m_PetBouncer->SetPetBouncerEnabled(true);
|
m_PetBouncer->SetPetBouncerEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
|
GameMessages::SendKnockback(entity->GetObjectID(), m_Parent->GetObjectID(), m_Parent->GetObjectID(), 0.0f, NiPoint3(0.0f, 17.0f, 0.0f));
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
~SwitchComponent() override;
|
~SwitchComponent() override;
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
|
void OnUse(Entity* originator) override;
|
||||||
|
|
||||||
Entity* GetParentEntity() const;
|
Entity* GetParentEntity() const;
|
||||||
|
|
||||||
@ -101,6 +102,8 @@ private:
|
|||||||
* Attached pet bouncer
|
* Attached pet bouncer
|
||||||
*/
|
*/
|
||||||
BouncerComponent* m_PetBouncer = nullptr;
|
BouncerComponent* m_PetBouncer = nullptr;
|
||||||
|
|
||||||
|
std::vector<int32_t> m_FactionsToRespondTo{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SWITCHCOMPONENT_H
|
#endif // SWITCHCOMPONENT_H
|
||||||
|
@ -29,10 +29,10 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const {
|
|||||||
stream.Write(IsOwned);
|
stream.Write(IsOwned);
|
||||||
stream.Write(AccessType);
|
stream.Write(AccessType);
|
||||||
stream.Write(DateLastPublished);
|
stream.Write(DateLastPublished);
|
||||||
stream.Write(PerformanceIndex);
|
|
||||||
stream.Write(PerformanceCost);
|
stream.Write(PerformanceCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const {
|
void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const {
|
||||||
// Do we need this?
|
// Do we need this?
|
||||||
|
// no
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
|
||||||
class PropertySelectQueryProperty final
|
class PropertySelectQueryProperty final {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
void Serialize(RakNet::BitStream& stream) const;
|
void Serialize(RakNet::BitStream& stream) const;
|
||||||
|
|
||||||
@ -23,9 +22,8 @@ public:
|
|||||||
bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner
|
bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner
|
||||||
bool IsOwned = false; // Whether or not the property is owned
|
bool IsOwned = false; // Whether or not the property is owned
|
||||||
uint32_t AccessType = 0; // The privacy option of the property
|
uint32_t AccessType = 0; // The privacy option of the property
|
||||||
uint32_t DateLastPublished = 0; // The last day the property was published
|
uint64_t DateLastPublished = 0; // The last day the property was published
|
||||||
float PerformanceCost = 0; // The performance cost of the property
|
float PerformanceCost = 0; // The performance cost of the property
|
||||||
uint32_t PerformanceIndex = 0; // The performance index of the property? Always 0?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,7 +12,10 @@ void BaseFootRaceManager::OnFireEventServerSide(Entity* self, Entity* sender, st
|
|||||||
if (splitArguments.size() > 1) {
|
if (splitArguments.size() > 1) {
|
||||||
|
|
||||||
const auto eventName = splitArguments[0];
|
const auto eventName = splitArguments[0];
|
||||||
const auto player = Game::entityManager->GetEntity(std::stoull(splitArguments[1]));
|
auto playerId = GeneralUtils::TryParse<LWOOBJID>(splitArguments[1]);
|
||||||
|
if (!playerId) return;
|
||||||
|
|
||||||
|
const auto player = Game::entityManager->GetEntity(playerId.value());
|
||||||
|
|
||||||
if (player != nullptr) {
|
if (player != nullptr) {
|
||||||
if (eventName == "updatePlayer") {
|
if (eventName == "updatePlayer") {
|
||||||
|
@ -131,12 +131,16 @@ void Level::ReadChunks(std::istream& file) {
|
|||||||
if (initPos == std::streamoff(0)) { //Really old chunk version
|
if (initPos == std::streamoff(0)) { //Really old chunk version
|
||||||
file.seekg(0);
|
file.seekg(0);
|
||||||
Header header;
|
Header header;
|
||||||
header.id = ChunkTypeID::FileInfo; //I guess?
|
header.id = ChunkTypeID::FileInfo;
|
||||||
BinaryIO::BinaryRead(file, header.chunkVersion);
|
BinaryIO::BinaryRead(file, header.chunkVersion);
|
||||||
BinaryIO::BinaryRead(file, header.chunkType);
|
BinaryIO::BinaryRead(file, header.chunkType);
|
||||||
file.ignore(1);
|
uint8_t important = 0;
|
||||||
BinaryIO::BinaryRead(file, header.fileInfo.revision);
|
BinaryIO::BinaryRead(file, important);
|
||||||
|
// file.ignore(1); //probably used
|
||||||
|
if (header.chunkVersion > 36) {
|
||||||
|
BinaryIO::BinaryRead(file, header.fileInfo.revision);
|
||||||
|
}
|
||||||
|
// HARDCODED 3
|
||||||
if (header.chunkVersion >= 45) file.ignore(4);
|
if (header.chunkVersion >= 45) file.ignore(4);
|
||||||
file.ignore(4 * (4 * 3));
|
file.ignore(4 * (4 * 3));
|
||||||
|
|
||||||
@ -170,25 +174,32 @@ void Level::ReadChunks(std::istream& file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 6; ++i) {
|
// skydome info
|
||||||
uint32_t count = 0;
|
|
||||||
BinaryIO::BinaryRead(file, count);
|
|
||||||
file.ignore(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
file.ignore(4);
|
|
||||||
|
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
BinaryIO::BinaryRead(file, count);
|
BinaryIO::BinaryRead(file, count);
|
||||||
file.ignore(count * 12);
|
file.ignore(count);
|
||||||
|
|
||||||
|
if (header.chunkVersion >= 33) {
|
||||||
|
for (uint32_t i = 0; i < 5; ++i) {
|
||||||
|
uint32_t count = 0;
|
||||||
|
BinaryIO::BinaryRead(file, count);
|
||||||
|
file.ignore(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// editor settings
|
||||||
|
if (!important && header.chunkVersion >= 37){
|
||||||
|
file.ignore(4);
|
||||||
|
|
||||||
|
uint32_t count = 0;
|
||||||
|
BinaryIO::BinaryRead(file, count);
|
||||||
|
file.ignore(count * 12);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
header.id = ChunkTypeID::SceneObjectData;
|
||||||
|
header.fileInfo.version = header.chunkVersion;
|
||||||
|
ReadSceneObjectDataChunk(file, header);
|
||||||
m_ChunkHeaders.insert(std::make_pair(header.id, header));
|
m_ChunkHeaders.insert(std::make_pair(header.id, header));
|
||||||
|
|
||||||
//Now pretend to be a normal file and read Objects chunk:
|
|
||||||
Header hdr;
|
|
||||||
hdr.id = ChunkTypeID::SceneObjectData;
|
|
||||||
ReadSceneObjectDataChunk(file, hdr);
|
|
||||||
m_ChunkHeaders.insert(std::make_pair(hdr.id, hdr));
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,8 +235,14 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
|||||||
BinaryIO::BinaryRead(file, obj.id);
|
BinaryIO::BinaryRead(file, obj.id);
|
||||||
BinaryIO::BinaryRead(file, obj.lot);
|
BinaryIO::BinaryRead(file, obj.lot);
|
||||||
|
|
||||||
/*if (header.fileInfo->version >= 0x26)*/ BinaryIO::BinaryRead(file, obj.nodeType);
|
if (header.fileInfo.version >= 38) {
|
||||||
/*if (header.fileInfo->version >= 0x20)*/ BinaryIO::BinaryRead(file, obj.glomId);
|
uint32_t tmp = 1;
|
||||||
|
BinaryIO::BinaryRead(file, tmp);
|
||||||
|
if (tmp > -1 && tmp < 11) obj.nodeType = tmp;
|
||||||
|
}
|
||||||
|
if (header.fileInfo.version >= 32) {
|
||||||
|
BinaryIO::BinaryRead(file, obj.glomId);
|
||||||
|
}
|
||||||
|
|
||||||
BinaryIO::BinaryRead(file, obj.position);
|
BinaryIO::BinaryRead(file, obj.position);
|
||||||
BinaryIO::BinaryRead(file, obj.rotation);
|
BinaryIO::BinaryRead(file, obj.rotation);
|
||||||
|
@ -160,6 +160,7 @@ std::string Zone::GetFilePathForZoneID() {
|
|||||||
if (zone != nullptr) {
|
if (zone != nullptr) {
|
||||||
std::string toReturn = "maps/" + zone->zoneName;
|
std::string toReturn = "maps/" + zone->zoneName;
|
||||||
std::transform(toReturn.begin(), toReturn.end(), toReturn.begin(), ::tolower);
|
std::transform(toReturn.begin(), toReturn.end(), toReturn.begin(), ::tolower);
|
||||||
|
std::ranges::replace(toReturn, '\\', '/');
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user