Merge pull request #7747 from Robyt3/Map-UUID-Unknown-Handling

Propagate unknown UUID-based map items in map tools
This commit is contained in:
heinrich5991 2024-01-06 22:18:30 +00:00 committed by GitHub
commit 7aba25d3f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 46 deletions

View file

@ -450,20 +450,27 @@ int CDataFileReader::GetItemSize(int Index) const
return m_pDataFile->m_Info.m_pItemOffsets[Index + 1] - m_pDataFile->m_Info.m_pItemOffsets[Index] - sizeof(CDatafileItem); return m_pDataFile->m_Info.m_pItemOffsets[Index + 1] - m_pDataFile->m_Info.m_pItemOffsets[Index] - sizeof(CDatafileItem);
} }
int CDataFileReader::GetExternalItemType(int InternalType) int CDataFileReader::GetExternalItemType(int InternalType, CUuid *pUuid)
{ {
if(InternalType <= OFFSET_UUID_TYPE || InternalType == ITEMTYPE_EX) if(InternalType <= OFFSET_UUID_TYPE || InternalType == ITEMTYPE_EX)
{ {
if(pUuid)
*pUuid = UUID_ZEROED;
return InternalType; return InternalType;
} }
int TypeIndex = FindItemIndex(ITEMTYPE_EX, InternalType); int TypeIndex = FindItemIndex(ITEMTYPE_EX, InternalType);
if(TypeIndex < 0 || GetItemSize(TypeIndex) < (int)sizeof(CItemEx)) if(TypeIndex < 0 || GetItemSize(TypeIndex) < (int)sizeof(CItemEx))
{ {
if(pUuid)
*pUuid = UUID_ZEROED;
return InternalType; return InternalType;
} }
const CItemEx *pItemEx = (const CItemEx *)GetItem(TypeIndex); const CItemEx *pItemEx = (const CItemEx *)GetItem(TypeIndex);
CUuid Uuid = pItemEx->ToUuid();
if(pUuid)
*pUuid = Uuid;
// Propagate UUID_UNKNOWN, it doesn't hurt. // Propagate UUID_UNKNOWN, it doesn't hurt.
return g_UuidManager.LookupUuid(pItemEx->ToUuid()); return g_UuidManager.LookupUuid(Uuid);
} }
int CDataFileReader::GetInternalItemType(int ExternalType) int CDataFileReader::GetInternalItemType(int ExternalType)
@ -490,7 +497,7 @@ int CDataFileReader::GetInternalItemType(int ExternalType)
return -1; return -1;
} }
void *CDataFileReader::GetItem(int Index, int *pType, int *pID) void *CDataFileReader::GetItem(int Index, int *pType, int *pID, CUuid *pUuid)
{ {
if(!m_pDataFile) if(!m_pDataFile)
{ {
@ -498,14 +505,18 @@ void *CDataFileReader::GetItem(int Index, int *pType, int *pID)
*pType = 0; *pType = 0;
if(pID) if(pID)
*pID = 0; *pID = 0;
if(pUuid)
*pUuid = UUID_ZEROED;
return nullptr; return nullptr;
} }
CDatafileItem *pItem = (CDatafileItem *)(m_pDataFile->m_Info.m_pItemStart + m_pDataFile->m_Info.m_pItemOffsets[Index]); CDatafileItem *pItem = (CDatafileItem *)(m_pDataFile->m_Info.m_pItemStart + m_pDataFile->m_Info.m_pItemOffsets[Index]);
// remove sign extension
const int Type = GetExternalItemType((pItem->m_TypeAndID >> 16) & 0xffff, pUuid);
if(pType) if(pType)
{ {
// remove sign extension *pType = Type;
*pType = GetExternalItemType((pItem->m_TypeAndID >> 16) & 0xffff);
} }
if(pID) if(pID)
{ {
@ -643,35 +654,51 @@ int CDataFileWriter::GetTypeFromIndex(int Index) const
return ITEMTYPE_EX - Index - 1; return ITEMTYPE_EX - Index - 1;
} }
int CDataFileWriter::GetExtendedItemTypeIndex(int Type) int CDataFileWriter::GetExtendedItemTypeIndex(int Type, const CUuid *pUuid)
{ {
int Index = 0; int Index = 0;
for(int ExtendedItemType : m_vExtendedItemTypes) if(Type == -1)
{ {
if(ExtendedItemType == Type) // Unknown type, search for UUID
for(const auto &ExtendedItemType : m_vExtendedItemTypes)
{
if(ExtendedItemType.m_Uuid == *pUuid)
return Index; return Index;
++Index; ++Index;
} }
}
else
{
for(const auto &ExtendedItemType : m_vExtendedItemTypes)
{
if(ExtendedItemType.m_Type == Type)
return Index;
++Index;
}
}
// Type not found, add it. // Type not found, add it.
m_vExtendedItemTypes.push_back(Type); CExtendedItemType ExtendedType;
ExtendedType.m_Type = Type;
ExtendedType.m_Uuid = Type == -1 ? *pUuid : g_UuidManager.GetUuid(Type);
m_vExtendedItemTypes.push_back(ExtendedType);
CItemEx ExtendedType = CItemEx::FromUuid(g_UuidManager.GetUuid(Type)); CItemEx ItemEx = CItemEx::FromUuid(ExtendedType.m_Uuid);
AddItem(ITEMTYPE_EX, GetTypeFromIndex(Index), sizeof(ExtendedType), &ExtendedType); AddItem(ITEMTYPE_EX, GetTypeFromIndex(Index), sizeof(ItemEx), &ItemEx);
return Index; return Index;
} }
int CDataFileWriter::AddItem(int Type, int ID, size_t Size, const void *pData) int CDataFileWriter::AddItem(int Type, int ID, size_t Size, const void *pData, const CUuid *pUuid)
{ {
dbg_assert((Type >= 0 && Type < MAX_ITEM_TYPES) || Type >= OFFSET_UUID, "Invalid type"); dbg_assert((Type >= 0 && Type < MAX_ITEM_TYPES) || Type >= OFFSET_UUID || (Type == -1 && pUuid != nullptr), "Invalid type");
dbg_assert(ID >= 0 && ID <= ITEMTYPE_EX, "Invalid ID"); dbg_assert(ID >= 0 && ID <= ITEMTYPE_EX, "Invalid ID");
dbg_assert(Size == 0 || pData != nullptr, "Data missing"); // Items without data are allowed dbg_assert(Size == 0 || pData != nullptr, "Data missing"); // Items without data are allowed
dbg_assert(Size <= (size_t)std::numeric_limits<int>::max(), "Data too large"); dbg_assert(Size <= (size_t)std::numeric_limits<int>::max(), "Data too large");
dbg_assert(Size % sizeof(int) == 0, "Invalid data boundary"); dbg_assert(Size % sizeof(int) == 0, "Invalid data boundary");
if(Type >= OFFSET_UUID) if(Type == -1 || Type >= OFFSET_UUID)
{ {
Type = GetTypeFromIndex(GetExtendedItemTypeIndex(Type)); Type = GetTypeFromIndex(GetExtendedItemTypeIndex(Type, pUuid));
} }
const int NumItems = m_vItems.size(); const int NumItems = m_vItems.size();

View file

@ -8,6 +8,8 @@
#include <base/hash.h> #include <base/hash.h>
#include <base/types.h> #include <base/types.h>
#include "uuid_manager.h"
#include <array> #include <array>
#include <vector> #include <vector>
@ -25,7 +27,7 @@ class CDataFileReader
void *GetDataImpl(int Index, bool Swap); void *GetDataImpl(int Index, bool Swap);
int GetFileDataSize(int Index) const; int GetFileDataSize(int Index) const;
int GetExternalItemType(int InternalType); int GetExternalItemType(int InternalType, CUuid *pUuid);
int GetInternalItemType(int ExternalType); int GetInternalItemType(int ExternalType);
public: public:
@ -54,7 +56,7 @@ public:
int NumData() const; int NumData() const;
int GetItemSize(int Index) const; int GetItemSize(int Index) const;
void *GetItem(int Index, int *pType = nullptr, int *pID = nullptr); void *GetItem(int Index, int *pType = nullptr, int *pID = nullptr, CUuid *pUuid = nullptr);
void GetType(int Type, int *pStart, int *pNum); void GetType(int Type, int *pStart, int *pNum);
int FindItemIndex(int Type, int ID); int FindItemIndex(int Type, int ID);
void *FindItem(int Type, int ID); void *FindItem(int Type, int ID);
@ -94,6 +96,12 @@ class CDataFileWriter
int m_Last; int m_Last;
}; };
struct CExtendedItemType
{
int m_Type;
CUuid m_Uuid;
};
enum enum
{ {
MAX_ITEM_TYPES = 0x10000, MAX_ITEM_TYPES = 0x10000,
@ -103,10 +111,10 @@ class CDataFileWriter
std::array<CItemTypeInfo, MAX_ITEM_TYPES> m_aItemTypes; std::array<CItemTypeInfo, MAX_ITEM_TYPES> m_aItemTypes;
std::vector<CItemInfo> m_vItems; std::vector<CItemInfo> m_vItems;
std::vector<CDataInfo> m_vDatas; std::vector<CDataInfo> m_vDatas;
std::vector<int> m_vExtendedItemTypes; std::vector<CExtendedItemType> m_vExtendedItemTypes;
int GetTypeFromIndex(int Index) const; int GetTypeFromIndex(int Index) const;
int GetExtendedItemTypeIndex(int Type); int GetExtendedItemTypeIndex(int Type, const CUuid *pUuid);
public: public:
CDataFileWriter(); CDataFileWriter();
@ -122,7 +130,7 @@ public:
~CDataFileWriter(); ~CDataFileWriter();
bool Open(class IStorage *pStorage, const char *pFilename, int StorageType = IStorage::TYPE_SAVE); bool Open(class IStorage *pStorage, const char *pFilename, int StorageType = IStorage::TYPE_SAVE);
int AddItem(int Type, int ID, size_t Size, const void *pData); int AddItem(int Type, int ID, size_t Size, const void *pData, const CUuid *pUuid = nullptr);
int AddData(size_t Size, const void *pData, int CompressionLevel = Z_DEFAULT_COMPRESSION); int AddData(size_t Size, const void *pData, int CompressionLevel = Z_DEFAULT_COMPRESSION);
int AddDataSwapped(size_t Size, const void *pData); int AddDataSwapped(size_t Size, const void *pData);
int AddDataString(const char *pStr); int AddDataString(const char *pStr);

View file

@ -218,11 +218,11 @@ int main(int argc, const char **argv)
for(int Index = 0; Index < g_DataReader.NumItems(); Index++) for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
{ {
int Type, ID; int Type, ID;
void *pItem = g_DataReader.GetItem(Index, &Type, &ID); CUuid Uuid;
void *pItem = g_DataReader.GetItem(Index, &Type, &ID, &Uuid);
// Filter items with unknown type, as we can't write them back.
// Filter ITEMTYPE_EX items, they will be automatically added again. // Filter ITEMTYPE_EX items, they will be automatically added again.
if(Type < 0 || Type == ITEMTYPE_EX) if(Type == ITEMTYPE_EX)
{ {
continue; continue;
} }
@ -239,7 +239,7 @@ int main(int argc, const char **argv)
Size = sizeof(CMapItemImage); Size = sizeof(CMapItemImage);
NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION; NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION;
} }
g_DataWriter.AddItem(Type, ID, Size, pItem); g_DataWriter.AddItem(Type, ID, Size, pItem, &Uuid);
} }
// add all data // add all data

View file

@ -375,11 +375,11 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap, CMapIt
for(int i = 0; i < InputMap.NumItems(); i++) for(int i = 0; i < InputMap.NumItems(); i++)
{ {
int ID, Type; int ID, Type;
void *pItem = InputMap.GetItem(i, &Type, &ID); CUuid Uuid;
void *pItem = InputMap.GetItem(i, &Type, &ID, &Uuid);
// Filter items with unknown type, as we can't write them back.
// Filter ITEMTYPE_EX items, they will be automatically added again. // Filter ITEMTYPE_EX items, they will be automatically added again.
if(Type < 0 || Type == ITEMTYPE_EX) if(Type == ITEMTYPE_EX)
{ {
continue; continue;
} }
@ -388,7 +388,7 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap, CMapIt
pItem = pNewItem; pItem = pNewItem;
int Size = InputMap.GetItemSize(i); int Size = InputMap.GetItemSize(i);
OutputMap.AddItem(Type, ID, Size, pItem); OutputMap.AddItem(Type, ID, Size, pItem, &Uuid);
} }
for(int i = 0; i < InputMap.NumData(); i++) for(int i = 0; i < InputMap.NumData(); i++)

View file

@ -139,11 +139,11 @@ int main(int argc, const char **argv)
for(int Index = 0, i = 0; Index < Reader.NumItems(); Index++) for(int Index = 0, i = 0; Index < Reader.NumItems(); Index++)
{ {
int Type, ID; int Type, ID;
void *pPtr = Reader.GetItem(Index, &Type, &ID); CUuid Uuid;
void *pPtr = Reader.GetItem(Index, &Type, &ID, &Uuid);
// Filter items with unknown type, as we can't write them back.
// Filter ITEMTYPE_EX items, they will be automatically added again. // Filter ITEMTYPE_EX items, they will be automatically added again.
if(Type < 0 || Type == ITEMTYPE_EX) if(Type == ITEMTYPE_EX)
{ {
continue; continue;
} }
@ -205,7 +205,7 @@ int main(int argc, const char **argv)
} }
int Size = Reader.GetItemSize(Index); int Size = Reader.GetItemSize(Index);
Writer.AddItem(Type, ID, Size, pPtr); Writer.AddItem(Type, ID, Size, pPtr, &Uuid);
} }
// add all data // add all data

View file

@ -166,11 +166,11 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap)
for(int i = 0; i < InputMap.NumItems(); i++) for(int i = 0; i < InputMap.NumItems(); i++)
{ {
int ID, Type; int ID, Type;
void *pItem = InputMap.GetItem(i, &Type, &ID); CUuid Uuid;
void *pItem = InputMap.GetItem(i, &Type, &ID, &Uuid);
// Filter items with unknown type, as we can't write them back.
// Filter ITEMTYPE_EX items, they will be automatically added again. // Filter ITEMTYPE_EX items, they will be automatically added again.
if(Type < 0 || Type == ITEMTYPE_EX) if(Type == ITEMTYPE_EX)
{ {
continue; continue;
} }
@ -179,7 +179,7 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap)
pItem = g_apNewItem[i]; pItem = g_apNewItem[i];
int Size = InputMap.GetItemSize(i); int Size = InputMap.GetItemSize(i);
OutputMap.AddItem(Type, ID, Size, pItem); OutputMap.AddItem(Type, ID, Size, pItem, &Uuid);
} }
for(int i = 0; i < InputMap.NumData(); i++) for(int i = 0; i < InputMap.NumData(); i++)

View file

@ -148,11 +148,11 @@ int main(int argc, const char **argv)
for(int Index = 0; Index < g_DataReader.NumItems(); Index++) for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
{ {
int Type, ID; int Type, ID;
void *pItem = g_DataReader.GetItem(Index, &Type, &ID); CUuid Uuid;
void *pItem = g_DataReader.GetItem(Index, &Type, &ID, &Uuid);
// Filter items with unknown type, as we can't write them back.
// Filter ITEMTYPE_EX items, they will be automatically added again. // Filter ITEMTYPE_EX items, they will be automatically added again.
if(Type < 0 || Type == ITEMTYPE_EX) if(Type == ITEMTYPE_EX)
{ {
continue; continue;
} }
@ -169,7 +169,7 @@ int main(int argc, const char **argv)
NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION; NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION;
} }
Writer.AddItem(Type, ID, Size, pItem); Writer.AddItem(Type, ID, Size, pItem, &Uuid);
} }
if(g_NewDataID == -1) if(g_NewDataID == -1)

View file

@ -30,17 +30,17 @@ static int ResaveMap(const char *pSourceMap, const char *pDestinationMap, IStora
for(int Index = 0; Index < Reader.NumItems(); Index++) for(int Index = 0; Index < Reader.NumItems(); Index++)
{ {
int Type, ID; int Type, ID;
const void *pPtr = Reader.GetItem(Index, &Type, &ID); CUuid Uuid;
const void *pPtr = Reader.GetItem(Index, &Type, &ID, &Uuid);
// Filter items with unknown type, as we can't write them back.
// Filter ITEMTYPE_EX items, they will be automatically added again. // Filter ITEMTYPE_EX items, they will be automatically added again.
if(Type < 0 || Type == ITEMTYPE_EX) if(Type == ITEMTYPE_EX)
{ {
continue; continue;
} }
int Size = Reader.GetItemSize(Index); int Size = Reader.GetItemSize(Index);
Writer.AddItem(Type, ID, Size, pPtr); Writer.AddItem(Type, ID, Size, pPtr, &Uuid);
} }
// add all data // add all data