mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Propagate unknown UUID-based map items in map tools
Adapt the `CDataFileReader::GetItem` function so it optionally also returns a `CUuid` for UUID-based map items, including for items with unknown UUIDs where the item type will be `-1`. Adapt the `CDataFileWriter::AddItem` function so it optionally also accepts a `CUuid` which will be used if the item type is `-1`. The additional checks for invalid map item types in the map tools are removed again and instead the new UUID parameters are used so map items with unknown UUIDs are written back to maps correctly. Closes #7701.
This commit is contained in:
parent
fe87fe6a3f
commit
999119c60f
|
@ -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);
|
||||
}
|
||||
|
||||
int CDataFileReader::GetExternalItemType(int InternalType)
|
||||
int CDataFileReader::GetExternalItemType(int InternalType, CUuid *pUuid)
|
||||
{
|
||||
if(InternalType <= OFFSET_UUID_TYPE || InternalType == ITEMTYPE_EX)
|
||||
{
|
||||
if(pUuid)
|
||||
*pUuid = UUID_ZEROED;
|
||||
return InternalType;
|
||||
}
|
||||
int TypeIndex = FindItemIndex(ITEMTYPE_EX, InternalType);
|
||||
if(TypeIndex < 0 || GetItemSize(TypeIndex) < (int)sizeof(CItemEx))
|
||||
{
|
||||
if(pUuid)
|
||||
*pUuid = UUID_ZEROED;
|
||||
return InternalType;
|
||||
}
|
||||
const CItemEx *pItemEx = (const CItemEx *)GetItem(TypeIndex);
|
||||
CUuid Uuid = pItemEx->ToUuid();
|
||||
if(pUuid)
|
||||
*pUuid = Uuid;
|
||||
// Propagate UUID_UNKNOWN, it doesn't hurt.
|
||||
return g_UuidManager.LookupUuid(pItemEx->ToUuid());
|
||||
return g_UuidManager.LookupUuid(Uuid);
|
||||
}
|
||||
|
||||
int CDataFileReader::GetInternalItemType(int ExternalType)
|
||||
|
@ -490,7 +497,7 @@ int CDataFileReader::GetInternalItemType(int ExternalType)
|
|||
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)
|
||||
{
|
||||
|
@ -498,14 +505,18 @@ void *CDataFileReader::GetItem(int Index, int *pType, int *pID)
|
|||
*pType = 0;
|
||||
if(pID)
|
||||
*pID = 0;
|
||||
if(pUuid)
|
||||
*pUuid = UUID_ZEROED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// remove sign extension
|
||||
*pType = GetExternalItemType((pItem->m_TypeAndID >> 16) & 0xffff);
|
||||
*pType = Type;
|
||||
}
|
||||
if(pID)
|
||||
{
|
||||
|
@ -643,35 +654,51 @@ int CDataFileWriter::GetTypeFromIndex(int Index) const
|
|||
return ITEMTYPE_EX - Index - 1;
|
||||
}
|
||||
|
||||
int CDataFileWriter::GetExtendedItemTypeIndex(int Type)
|
||||
int CDataFileWriter::GetExtendedItemTypeIndex(int Type, const CUuid *pUuid)
|
||||
{
|
||||
int Index = 0;
|
||||
for(int ExtendedItemType : m_vExtendedItemTypes)
|
||||
if(Type == -1)
|
||||
{
|
||||
if(ExtendedItemType == Type)
|
||||
return Index;
|
||||
++Index;
|
||||
// Unknown type, search for UUID
|
||||
for(const auto &ExtendedItemType : m_vExtendedItemTypes)
|
||||
{
|
||||
if(ExtendedItemType.m_Uuid == *pUuid)
|
||||
return Index;
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const auto &ExtendedItemType : m_vExtendedItemTypes)
|
||||
{
|
||||
if(ExtendedItemType.m_Type == Type)
|
||||
return Index;
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
|
||||
// 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));
|
||||
AddItem(ITEMTYPE_EX, GetTypeFromIndex(Index), sizeof(ExtendedType), &ExtendedType);
|
||||
CItemEx ItemEx = CItemEx::FromUuid(ExtendedType.m_Uuid);
|
||||
AddItem(ITEMTYPE_EX, GetTypeFromIndex(Index), sizeof(ItemEx), &ItemEx);
|
||||
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(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 % 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();
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <base/hash.h>
|
||||
#include <base/types.h>
|
||||
|
||||
#include "uuid_manager.h"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
|
@ -25,7 +27,7 @@ class CDataFileReader
|
|||
void *GetDataImpl(int Index, bool Swap);
|
||||
int GetFileDataSize(int Index) const;
|
||||
|
||||
int GetExternalItemType(int InternalType);
|
||||
int GetExternalItemType(int InternalType, CUuid *pUuid);
|
||||
int GetInternalItemType(int ExternalType);
|
||||
|
||||
public:
|
||||
|
@ -54,7 +56,7 @@ public:
|
|||
int NumData() 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);
|
||||
int FindItemIndex(int Type, int ID);
|
||||
void *FindItem(int Type, int ID);
|
||||
|
@ -94,6 +96,12 @@ class CDataFileWriter
|
|||
int m_Last;
|
||||
};
|
||||
|
||||
struct CExtendedItemType
|
||||
{
|
||||
int m_Type;
|
||||
CUuid m_Uuid;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_ITEM_TYPES = 0x10000,
|
||||
|
@ -103,10 +111,10 @@ class CDataFileWriter
|
|||
std::array<CItemTypeInfo, MAX_ITEM_TYPES> m_aItemTypes;
|
||||
std::vector<CItemInfo> m_vItems;
|
||||
std::vector<CDataInfo> m_vDatas;
|
||||
std::vector<int> m_vExtendedItemTypes;
|
||||
std::vector<CExtendedItemType> m_vExtendedItemTypes;
|
||||
|
||||
int GetTypeFromIndex(int Index) const;
|
||||
int GetExtendedItemTypeIndex(int Type);
|
||||
int GetExtendedItemTypeIndex(int Type, const CUuid *pUuid);
|
||||
|
||||
public:
|
||||
CDataFileWriter();
|
||||
|
@ -122,7 +130,7 @@ public:
|
|||
~CDataFileWriter();
|
||||
|
||||
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 AddDataSwapped(size_t Size, const void *pData);
|
||||
int AddDataString(const char *pStr);
|
||||
|
|
|
@ -218,11 +218,11 @@ int main(int argc, const char **argv)
|
|||
for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
|
||||
{
|
||||
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.
|
||||
if(Type < 0 || Type == ITEMTYPE_EX)
|
||||
if(Type == ITEMTYPE_EX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ int main(int argc, const char **argv)
|
|||
Size = sizeof(CMapItemImage);
|
||||
NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION;
|
||||
}
|
||||
g_DataWriter.AddItem(Type, ID, Size, pItem);
|
||||
g_DataWriter.AddItem(Type, ID, Size, pItem, &Uuid);
|
||||
}
|
||||
|
||||
// add all data
|
||||
|
|
|
@ -375,11 +375,11 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap, CMapIt
|
|||
for(int i = 0; i < InputMap.NumItems(); i++)
|
||||
{
|
||||
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.
|
||||
if(Type < 0 || Type == ITEMTYPE_EX)
|
||||
if(Type == ITEMTYPE_EX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap, CMapIt
|
|||
pItem = pNewItem;
|
||||
|
||||
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++)
|
||||
|
|
|
@ -139,11 +139,11 @@ int main(int argc, const char **argv)
|
|||
for(int Index = 0, i = 0; Index < Reader.NumItems(); Index++)
|
||||
{
|
||||
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.
|
||||
if(Type < 0 || Type == ITEMTYPE_EX)
|
||||
if(Type == ITEMTYPE_EX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ int main(int argc, const char **argv)
|
|||
}
|
||||
|
||||
int Size = Reader.GetItemSize(Index);
|
||||
Writer.AddItem(Type, ID, Size, pPtr);
|
||||
Writer.AddItem(Type, ID, Size, pPtr, &Uuid);
|
||||
}
|
||||
|
||||
// add all data
|
||||
|
|
|
@ -166,11 +166,11 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap)
|
|||
for(int i = 0; i < InputMap.NumItems(); i++)
|
||||
{
|
||||
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.
|
||||
if(Type < 0 || Type == ITEMTYPE_EX)
|
||||
if(Type == ITEMTYPE_EX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap)
|
|||
pItem = g_apNewItem[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++)
|
||||
|
|
|
@ -148,11 +148,11 @@ int main(int argc, const char **argv)
|
|||
for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
|
||||
{
|
||||
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.
|
||||
if(Type < 0 || Type == ITEMTYPE_EX)
|
||||
if(Type == ITEMTYPE_EX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ int main(int argc, const char **argv)
|
|||
NewImageItem.m_Version = CMapItemImage::CURRENT_VERSION;
|
||||
}
|
||||
|
||||
Writer.AddItem(Type, ID, Size, pItem);
|
||||
Writer.AddItem(Type, ID, Size, pItem, &Uuid);
|
||||
}
|
||||
|
||||
if(g_NewDataID == -1)
|
||||
|
|
|
@ -30,17 +30,17 @@ static int ResaveMap(const char *pSourceMap, const char *pDestinationMap, IStora
|
|||
for(int Index = 0; Index < Reader.NumItems(); Index++)
|
||||
{
|
||||
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.
|
||||
if(Type < 0 || Type == ITEMTYPE_EX)
|
||||
if(Type == ITEMTYPE_EX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int Size = Reader.GetItemSize(Index);
|
||||
Writer.AddItem(Type, ID, Size, pPtr);
|
||||
Writer.AddItem(Type, ID, Size, pPtr, &Uuid);
|
||||
}
|
||||
|
||||
// add all data
|
||||
|
|
Loading…
Reference in a new issue