mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 03:28:19 +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);
|
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
|
||||||
return Index;
|
for(const auto &ExtendedItemType : m_vExtendedItemTypes)
|
||||||
++Index;
|
{
|
||||||
|
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.
|
// 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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue