Merge pull request #7289 from Robyt3/Map-Version-Check

Ensure current map is not corrupted when loading another fails
This commit is contained in:
Dennis Felsing 2023-10-03 13:17:03 +00:00 committed by GitHub
commit dbd9da3c7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 517 additions and 499 deletions

View file

@ -30,6 +30,13 @@ public:
m_pDataFile(nullptr) {} m_pDataFile(nullptr) {}
~CDataFileReader() { Close(); } ~CDataFileReader() { Close(); }
CDataFileReader &operator=(CDataFileReader &&Other)
{
m_pDataFile = Other.m_pDataFile;
Other.m_pDataFile = nullptr;
return *this;
}
bool Open(class IStorage *pStorage, const char *pFilename, int StorageType); bool Open(class IStorage *pStorage, const char *pFilename, int StorageType);
bool Close(); bool Close();
bool IsOpen() const { return m_pDataFile != nullptr; } bool IsOpen() const { return m_pDataFile != nullptr; }

View file

@ -2,6 +2,8 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include "map.h" #include "map.h"
#include <base/log.h>
#include <engine/storage.h> #include <engine/storage.h>
#include <game/mapitems.h> #include <game/mapitems.h>
@ -63,23 +65,32 @@ bool CMap::Load(const char *pMapName)
IStorage *pStorage = Kernel()->RequestInterface<IStorage>(); IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
if(!pStorage) if(!pStorage)
return false; return false;
if(!m_DataFile.Open(pStorage, pMapName, IStorage::TYPE_ALL))
return false; // Ensure current datafile is not left in an inconsistent state if loading fails,
// check version // by loading the new datafile separately first.
const CMapItemVersion *pItem = (CMapItemVersion *)m_DataFile.FindItem(MAPITEMTYPE_VERSION, 0); CDataFileReader NewDataFile;
if(!pItem || pItem->m_Version != CMapItemVersion::CURRENT_VERSION) if(!NewDataFile.Open(pStorage, pMapName, IStorage::TYPE_ALL))
return false; return false;
// replace compressed tile layers with uncompressed ones // Check version
const CMapItemVersion *pItem = (CMapItemVersion *)NewDataFile.FindItem(MAPITEMTYPE_VERSION, 0);
if(pItem == nullptr || pItem->m_Version != CMapItemVersion::CURRENT_VERSION)
{
log_error("map/load", "Error: map version not supported.");
NewDataFile.Close();
return false;
}
// Replace compressed tile layers with uncompressed ones
int GroupsStart, GroupsNum, LayersStart, LayersNum; int GroupsStart, GroupsNum, LayersStart, LayersNum;
m_DataFile.GetType(MAPITEMTYPE_GROUP, &GroupsStart, &GroupsNum); NewDataFile.GetType(MAPITEMTYPE_GROUP, &GroupsStart, &GroupsNum);
m_DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); NewDataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum);
for(int g = 0; g < GroupsNum; g++) for(int g = 0; g < GroupsNum; g++)
{ {
const CMapItemGroup *pGroup = static_cast<CMapItemGroup *>(m_DataFile.GetItem(GroupsStart + g)); const CMapItemGroup *pGroup = static_cast<CMapItemGroup *>(NewDataFile.GetItem(GroupsStart + g));
for(int l = 0; l < pGroup->m_NumLayers; l++) for(int l = 0; l < pGroup->m_NumLayers; l++)
{ {
CMapItemLayer *pLayer = static_cast<CMapItemLayer *>(m_DataFile.GetItem(LayersStart + pGroup->m_StartLayer + l)); CMapItemLayer *pLayer = static_cast<CMapItemLayer *>(NewDataFile.GetItem(LayersStart + pGroup->m_StartLayer + l));
if(pLayer->m_Type == LAYERTYPE_TILES) if(pLayer->m_Type == LAYERTYPE_TILES)
{ {
CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer); CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer);
@ -87,13 +98,16 @@ bool CMap::Load(const char *pMapName)
{ {
const size_t TilemapSize = (size_t)pTilemap->m_Width * pTilemap->m_Height * sizeof(CTile); const size_t TilemapSize = (size_t)pTilemap->m_Width * pTilemap->m_Height * sizeof(CTile);
CTile *pTiles = static_cast<CTile *>(malloc(TilemapSize)); CTile *pTiles = static_cast<CTile *>(malloc(TilemapSize));
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)); ExtractTiles(pTiles, (size_t)pTilemap->m_Width * pTilemap->m_Height, static_cast<CTile *>(NewDataFile.GetData(pTilemap->m_Data)), NewDataFile.GetDataSize(pTilemap->m_Data) / sizeof(CTile));
m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles), TilemapSize); NewDataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles), TilemapSize);
} }
} }
} }
} }
// Replace existing datafile with new datafile
m_DataFile.Close();
m_DataFile = std::move(NewDataFile);
return true; return true;
} }

View file

@ -7907,7 +7907,6 @@ bool CEditor::Load(const char *pFileName, int StorageType)
else else
{ {
m_aFileName[0] = 0; m_aFileName[0] = 0;
Reset();
} }
return Result; return Result;
} }

File diff suppressed because it is too large Load diff