mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-14 00:24:09 +00:00
feat(inventory): enforce DeletionRestrictions when deleting items
Deleting an item now follows its ItemComponent delResIndex row in the DeletionRestrictions table, the way the client's shared inventory code decides it (LWOInventoryComponent_Common::CanRemoveFromInventory @ 0x00ce0d20, CheckDeletionRestrictionIndex @ 0x00c94c20): - missing, unrestricted, unknown-type or empty rows allow it; - LOTS_INCLUDED: another item of any listed LOT must remain; - LOTS_EXCLUDED: other items of every listed LOT must remain; - ANY_RESTRICTION / ALL_RESTRICTIONS: any / all listed rows allow it; - ZONE: only in the listed maps; ALWAYS_RESTRICTED: never. Operators (GM level 9) may delete anything, as in the client. A refused delete is logged and the item stays. ItemComponent.minNumRequired is not used: the client never reads it, so its meaning can't be verified. Issue 960: the rocket (6416, row 8) and the classic rocket parts (rows 1-3) have rows that keep at least one rocket or part, so the last rocket can no longer be deleted and strand the player. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include "CDMissionEmailTable.h"
|
||||
#include "CDRewardsTable.h"
|
||||
#include "CDPropertyEntranceComponentTable.h"
|
||||
#include "CDDeletionRestrictionsTable.h"
|
||||
#include "CDPropertyTemplateTable.h"
|
||||
#include "CDModularBuildComponentTable.h"
|
||||
#include "CDFeatureGatingTable.h"
|
||||
@@ -93,6 +94,7 @@ DEFINE_TABLE_STORAGE(CDPackageComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDPetComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDProximityMonitorComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDPropertyEntranceComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDDeletionRestrictionsTable);
|
||||
DEFINE_TABLE_STORAGE(CDPropertyTemplateTable);
|
||||
DEFINE_TABLE_STORAGE(CDModularBuildComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDRailActivatorComponentTable);
|
||||
@@ -118,6 +120,7 @@ void CDClientManager::LoadValuesFromDatabase() {
|
||||
CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
|
||||
CDCLIENT_DONT_CACHE_TABLE(CDComponentsRegistryTable::Instance().LoadValuesFromDatabase());
|
||||
CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
|
||||
CDDeletionRestrictionsTable::Instance().LoadValuesFromDatabase();
|
||||
CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
|
||||
CDEmoteTableTable::Instance().LoadValuesFromDatabase();
|
||||
CDFeatureGatingTable::Instance().LoadValuesFromDatabase();
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "CDDeletionRestrictionsTable.h"
|
||||
|
||||
void CDDeletionRestrictionsTable::LoadValuesFromDatabase() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT id, restricted, ids, checkType FROM DeletionRestrictions;");
|
||||
while (!tableData.eof()) {
|
||||
CDDeletionRestriction entry;
|
||||
entry.restricted = tableData.getIntField("restricted", 0) != 0;
|
||||
entry.ids = tableData.getStringField("ids", "");
|
||||
entry.checkType = tableData.getIntField("checkType", 0);
|
||||
entries.insert_or_assign(tableData.getIntField("id", -1), std::move(entry));
|
||||
tableData.nextRow();
|
||||
}
|
||||
|
||||
tableData.finalize();
|
||||
}
|
||||
|
||||
const CDDeletionRestriction* CDDeletionRestrictionsTable::Get(const int32_t id) const {
|
||||
const auto& entries = GetEntries();
|
||||
const auto it = entries.find(id);
|
||||
return it == entries.end() ? nullptr : &it->second;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "CDTable.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// How a DeletionRestrictions row decides whether an item may be deleted (eDeletionRestrictionCheckType in the client)
|
||||
enum class eDeletionRestrictionCheckType : int32_t {
|
||||
LOTS_INCLUDED = 0, // allowed if another item of one of the LOTs is owned
|
||||
LOTS_EXCLUDED = 1, // allowed if other items of every one of the LOTs are owned
|
||||
ANY_RESTRICTION = 2, // allowed if any of the listed rows allows it
|
||||
ALL_RESTRICTIONS = 3, // allowed if all of the listed rows allow it
|
||||
ZONE = 4, // allowed in the listed map IDs
|
||||
ALWAYS_RESTRICTED = 5, // never allowed
|
||||
};
|
||||
|
||||
struct CDDeletionRestriction {
|
||||
bool restricted{};
|
||||
std::string ids; // comma separated LOTs, row IDs or map IDs, depending on checkType
|
||||
int32_t checkType{};
|
||||
};
|
||||
|
||||
class CDDeletionRestrictionsTable : public CDTable<CDDeletionRestrictionsTable, std::map<int32_t, CDDeletionRestriction>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
// The row with this ID, or nullptr
|
||||
const CDDeletionRestriction* Get(int32_t id) const;
|
||||
};
|
||||
@@ -33,7 +33,7 @@ struct CDItemComponent {
|
||||
uint32_t itemRating; //!< ???
|
||||
bool isTwoHanded; //!< Whether or not the item is double handed
|
||||
uint32_t minNumRequired; //!< Maybe the minimum number required for a mission, or to own this object?
|
||||
uint32_t delResIndex; //!< ???
|
||||
uint32_t delResIndex; //!< Row of DeletionRestrictions, -1 (as unsigned) for none
|
||||
uint32_t currencyLOT; //!< ???
|
||||
uint32_t altCurrencyCost; //!< ???
|
||||
std::string subItems; //!< A comma seperate string of sub items (maybe for multi-itemed things like faction test gear set)
|
||||
|
||||
@@ -28,6 +28,7 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
||||
"CDPlayerFlagsTable.cpp"
|
||||
"CDPhysicsComponentTable.cpp"
|
||||
"CDPropertyEntranceComponentTable.cpp"
|
||||
"CDDeletionRestrictionsTable.cpp"
|
||||
"CDPropertyTemplateTable.cpp"
|
||||
"CDModularBuildComponentTable.cpp"
|
||||
"CDProximityMonitorComponentTable.cpp"
|
||||
|
||||
Reference in New Issue
Block a user