Extract CMap::ExtractTiles with more validation

To reduce duplicate code and to add validation for tile skip everywhere.

Add separate `CMapItemLayerTilemap::TILE_SKIP_MIN_VERSION` constant and change `CMapItemVersion::CURRENT_VERSION` back to the previous version, as maps with tile skip can be loaded but skip is not used when saving.
This commit is contained in:
Robert Müller 2022-08-14 16:02:15 +02:00
parent a92ab45c3c
commit 32f2fe936a
6 changed files with 34 additions and 41 deletions

View file

@ -83,24 +83,10 @@ bool CMap::Load(const char *pMapName)
if(pLayer->m_Type == LAYERTYPE_TILES)
{
CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer);
if(pTilemap->m_Version > 3)
if(pTilemap->m_Version >= CMapItemLayerTilemap::TILE_SKIP_MIN_VERSION)
{
CTile *pTiles = static_cast<CTile *>(malloc(pTilemap->m_Width * pTilemap->m_Height * sizeof(CTile)));
// extract original tile data
int i = 0;
CTile *pSavedTiles = static_cast<CTile *>(m_DataFile.GetData(pTilemap->m_Data));
while(i < pTilemap->m_Width * pTilemap->m_Height)
{
for(unsigned Counter = 0; Counter <= pSavedTiles->m_Skip && i < pTilemap->m_Width * pTilemap->m_Height; Counter++)
{
pTiles[i] = *pSavedTiles;
pTiles[i++].m_Skip = 0;
}
pSavedTiles++;
}
CTile *pTiles = static_cast<CTile *>(malloc((size_t)pTilemap->m_Width * pTilemap->m_Height * sizeof(CTile)));
ExtractTiles(pTiles, (size_t)pTilemap->m_Width * pTilemap->m_Height, static_cast<CTile *>(m_DataFile.GetData(pTilemap->m_Data)), m_DataFile.GetDataSize(pTilemap->m_Data) / sizeof(CTile));
m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles));
}
}
@ -140,4 +126,20 @@ int CMap::MapSize() const
return m_DataFile.MapSize();
}
void CMap::ExtractTiles(CTile *pDest, size_t DestSize, const CTile *pSrc, size_t SrcSize)
{
size_t DestIndex = 0;
size_t SrcIndex = 0;
while(DestIndex < DestSize && SrcIndex < SrcSize)
{
for(unsigned Counter = 0; Counter <= pSrc[SrcIndex].m_Skip && DestIndex < DestSize; Counter++)
{
pDest[DestIndex] = pSrc[SrcIndex];
pDest[DestIndex].m_Skip = 0;
DestIndex++;
}
SrcIndex++;
}
}
extern IEngineMap *CreateEngineMap() { return new CMap; }

View file

@ -35,6 +35,8 @@ public:
SHA256_DIGEST Sha256() const override;
unsigned Crc() const override;
int MapSize() const override;
static void ExtractTiles(class CTile *pDest, size_t DestSize, const class CTile *pSrc, size_t SrcSize);
};
#endif

View file

@ -624,7 +624,7 @@ public:
void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override;
void PrepareForSave();
void ExtractTiles(CTile *pSavedTiles);
void ExtractTiles(int TilemapItemVersion, const CTile *pSavedTiles, size_t SavedTilesSize);
void GetSize(float *pWidth, float *pHeight) override
{

View file

@ -201,7 +201,7 @@ bool CEditorMap::Save(const char *pFileName)
pLayerTiles->PrepareForSave();
CMapItemLayerTilemap Item;
Item.m_Version = 3;
Item.m_Version = CMapItemLayerTilemap::CURRENT_VERSION;
Item.m_Layer.m_Version = 0; // was previously uninitialized, do not rely on it being 0
Item.m_Layer.m_Flags = pLayerTiles->m_Flags;
@ -736,11 +736,7 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
{
void *pFrontData = DataFile.GetData(pTilemapItem->m_Front);
unsigned int Size = DataFile.GetDataSize(pTilemapItem->m_Front);
if(pTilemapItem->m_Version > 3)
pTiles->ExtractTiles((CTile *)pFrontData);
else if(Size >= (size_t)pTiles->m_Width * pTiles->m_Height * sizeof(CTile))
mem_copy(pTiles->m_pTiles, pFrontData, (size_t)pTiles->m_Width * pTiles->m_Height * sizeof(CTile));
pTiles->ExtractTiles(pTilemapItem->m_Version, (CTile *)pFrontData, Size);
DataFile.UnloadData(pTilemapItem->m_Front);
}
else if(pTiles->m_Switch)
@ -795,10 +791,7 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
{
void *pData = DataFile.GetData(pTilemapItem->m_Data);
unsigned int Size = DataFile.GetDataSize(pTilemapItem->m_Data);
if(pTilemapItem->m_Version > 3)
pTiles->ExtractTiles((CTile *)pData);
else if(Size >= (size_t)pTiles->m_Width * pTiles->m_Height * sizeof(CTile))
mem_copy(pTiles->m_pTiles, pData, (size_t)pTiles->m_Width * pTiles->m_Height * sizeof(CTile));
pTiles->ExtractTiles(pTilemapItem->m_Version, (CTile *)pData, Size);
if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem))
{

View file

@ -4,6 +4,7 @@
#include <engine/client.h>
#include <engine/graphics.h>
#include <engine/shared/map.h>
#include <engine/textrender.h>
#include "editor.h"
@ -97,19 +98,13 @@ void CLayerTiles::PrepareForSave()
}
}
void CLayerTiles::ExtractTiles(CTile *pSavedTiles)
void CLayerTiles::ExtractTiles(int TilemapItemVersion, const CTile *pSavedTiles, size_t SavedTilesSize)
{
int i = 0;
while(i < m_Width * m_Height)
{
for(unsigned Counter = 0; Counter <= pSavedTiles->m_Skip && i < m_Width * m_Height; Counter++)
{
m_pTiles[i] = *pSavedTiles;
m_pTiles[i++].m_Skip = 0;
}
pSavedTiles++;
}
const size_t DestSize = (size_t)m_Width * m_Height;
if(TilemapItemVersion >= CMapItemLayerTilemap::TILE_SKIP_MIN_VERSION)
CMap::ExtractTiles(m_pTiles, DestSize, pSavedTiles, SavedTilesSize);
else if(SavedTilesSize >= DestSize)
mem_copy(m_pTiles, pSavedTiles, DestSize * sizeof(CTile));
}
void CLayerTiles::MakePalette()

View file

@ -300,7 +300,8 @@ struct CMapItemLayerTilemap
{
enum
{
CURRENT_VERSION = 4
CURRENT_VERSION = 3,
TILE_SKIP_MIN_VERSION = 4, // supported for loading but not saving
};
CMapItemLayer m_Layer;