From f2444b0de7e878386aa68a9f35d472650a8ae540 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 12 Jul 2017 20:15:00 +0200 Subject: [PATCH] Add map_diff tool to compare tile layers of map versions --- src/engine/shared/storage.cpp | 8 ++- src/engine/storage.h | 1 + src/tools/config_retrieve.cpp | 4 +- src/tools/config_store.cpp | 4 +- src/tools/map_diff.cpp | 116 ++++++++++++++++++++++++++++++++++ src/tools/map_extract.cpp | 2 +- src/tools/map_resave.cpp | 2 +- 7 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/tools/map_diff.cpp diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 82d8adbb6..905e97aaa 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -280,7 +280,11 @@ public: BufferSize = sizeof(aBuffer); } - if(pFilename[0] == '/' || pFilename[0] == '\\' || str_find(pFilename, "../") != NULL || str_find(pFilename, "..\\") != NULL + if(Type == TYPE_ABSOLUTE) + { + return io_open(pFilename, Flags); + } + else if (pFilename[0] == '/' || pFilename[0] == '\\' || str_find(pFilename, "../") != NULL || str_find(pFilename, "..\\") != NULL #ifdef CONF_FAMILY_WINDOWS || (pFilename[0] && pFilename[1] == ':') #endif @@ -296,7 +300,7 @@ public: { IOHANDLE Handle = 0; - if(Type == TYPE_ALL) + if(Type <= TYPE_ALL) { // check all available directories for(int i = 0; i < m_NumPaths; ++i) diff --git a/src/engine/storage.h b/src/engine/storage.h index ed904d51b..20be34654 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -13,6 +13,7 @@ public: { TYPE_SAVE = 0, TYPE_ALL = -1, + TYPE_ABSOLUTE = -2, STORAGETYPE_BASIC = 0, STORAGETYPE_SERVER, diff --git a/src/tools/config_retrieve.cpp b/src/tools/config_retrieve.cpp index a5b4db93a..abdbe68aa 100644 --- a/src/tools/config_retrieve.cpp +++ b/src/tools/config_retrieve.cpp @@ -6,7 +6,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) { CDataFileReader Map; - if(!Map.Open(pStorage, pMapName, IStorage::TYPE_ALL)) + if(!Map.Open(pStorage, pMapName, IStorage::TYPE_ABSOLUTE)) { dbg_msg("config_retrieve", "error opening map '%s'", pMapName); return; @@ -28,7 +28,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) break; ConfigFound = true; - IOHANDLE Config = pStorage->OpenFile(pConfigName, IOFLAG_WRITE, IStorage::TYPE_ALL); + IOHANDLE Config = pStorage->OpenFile(pConfigName, IOFLAG_WRITE, IStorage::TYPE_ABSOLUTE); if(!Config) { dbg_msg("config_retrieve", "error opening config for writing '%s'", pConfigName); diff --git a/src/tools/config_store.cpp b/src/tools/config_store.cpp index 644c2496e..be88e7caa 100644 --- a/src/tools/config_store.cpp +++ b/src/tools/config_store.cpp @@ -7,7 +7,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) { - IOHANDLE File = pStorage->OpenFile(pConfigName, IOFLAG_READ, IStorage::TYPE_ALL); + IOHANDLE File = pStorage->OpenFile(pConfigName, IOFLAG_READ, IStorage::TYPE_ABSOLUTE); array aLines; char *pSettings = NULL; if(!File) @@ -42,7 +42,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) } CDataFileReader Reader; - Reader.Open(pStorage, pMapName, IStorage::TYPE_ALL); + Reader.Open(pStorage, pMapName, IStorage::TYPE_ABSOLUTE); CDataFileWriter Writer; Writer.Init(); diff --git a/src/tools/map_diff.cpp b/src/tools/map_diff.cpp new file mode 100644 index 000000000..17fe9ddc8 --- /dev/null +++ b/src/tools/map_diff.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include + +bool Process(IStorage *pStorage, char **pMapNames) +{ + CDataFileReader Maps[2]; + + for(int i = 0; i < 2; ++i) + { + if(!Maps[i].Open(pStorage, pMapNames[i], IStorage::TYPE_ABSOLUTE)) + { + dbg_msg("map_compare", "error opening map '%s'", pMapNames[i]); + return false; + } + + CDataFileReader *pMap = &Maps[i]; + // check version + CMapItemVersion *pVersion = (CMapItemVersion *)pMap->FindItem(MAPITEMTYPE_VERSION, 0); + if(pVersion && pVersion->m_Version != 1) + return false; + } + + int Start[2], Num[2]; + + Maps[0].GetType(MAPITEMTYPE_LAYER, &Start[0], &Num[0]); + Maps[1].GetType(MAPITEMTYPE_LAYER, &Start[1], &Num[1]); + + // ensure basic layout + if(Num[0] != Num[1]) + { + dbg_msg("map_compare", "different layer numbers:"); + for(int i = 0; i < 2; ++i) + dbg_msg("map_compare", " \"%s\": %d layers", pMapNames[i], Num[i]); + return false; + } + + // preload data + for(int j = 0; j < Num[0]; ++j) + { + CMapItemLayer *pItem[2]; + CMapItemLayerTilemap *pTilemap[2]; + for(int i = 0; i < 2; ++i) + { + pItem[i] = (CMapItemLayer *)Maps[i].GetItem(Start[i]+j, 0, 0); + pTilemap[i] = (CMapItemLayerTilemap *)pItem[i]; + (CTile *)Maps[i].GetData(pTilemap[i]->m_Data); + } + } + + // compare + for(int j = 0; j < Num[0]; ++j) + { + CMapItemLayer *pItem[2]; + for(int i = 0; i < 2; ++i) + pItem[i] = (CMapItemLayer *)Maps[i].GetItem(Start[i]+j, 0, 0); + + if(pItem[0]->m_Type != LAYERTYPE_TILES) + continue; + + CMapItemLayerTilemap *pTilemap[2]; + char aName[2][16]; + + for(int i = 0; i < 2; ++i) + { + pTilemap[i] = (CMapItemLayerTilemap *)pItem[i]; + IntsToStr(pTilemap[i]->m_aName, sizeof(pTilemap[i]->m_aName)/sizeof(int), aName[i]); + } + + if(str_comp_num(aName[0], aName[1], sizeof(aName[0])) != 0 || pTilemap[0]->m_Width != pTilemap[1]->m_Width || pTilemap[0]->m_Height != pTilemap[1]->m_Height) + { + dbg_msg("map_compare", "different tile layers:"); + for(int i = 0; i < 2; ++i) + dbg_msg("map_compare", " \"%s\" (%dx%d)", aName[i], pTilemap[i]->m_Width, pTilemap[i]->m_Height); + return false; + } + CTile *pTile[2]; + for(int i = 0; i < 2; ++i) + pTile[i] = (CTile *)Maps[i].GetData(pTilemap[i]->m_Data); + + for(int y = 0; y < pTilemap[0]->m_Height; y++) + { + for(int x = 0; x < pTilemap[0]->m_Width; x++) + { + int pos = y * pTilemap[0]->m_Width + x; + if(pTile[0][pos].m_Index != pTile[1][pos].m_Index || pTile[0][pos].m_Flags != pTile[1][pos].m_Flags) + { + dbg_msg("map_compare", "[%d:%s] %dx%d: (index: %d, flags: %d) != (index: %d, flags: %d)", Num[0], aName[0], x, y, pTile[0][pos].m_Index, pTile[0][pos].m_Flags, pTile[1][pos].m_Index, pTile[0][pos].m_Flags); + } + } + } + } + + return true; +} + +int main(int argc, char* argv[]) +{ + dbg_logger_stdout(); + dbg_logger_file("map_diff.txt"); + + IStorage *pStorage = CreateLocalStorage(); + + if(argc == 3) + { + return Process(pStorage, &argv[1]) ? 0 : 1; + } + else + { + dbg_msg("usage", "%s map1 map2", argv[0]); + return -1; + } +} diff --git a/src/tools/map_extract.cpp b/src/tools/map_extract.cpp index cd143f85b..0b1c800c2 100644 --- a/src/tools/map_extract.cpp +++ b/src/tools/map_extract.cpp @@ -9,7 +9,7 @@ bool Process(IStorage *pStorage, const char *pMapName, const char *pPathSave) { CDataFileReader Map; - if(!Map.Open(pStorage, pMapName, IStorage::TYPE_ALL)) + if(!Map.Open(pStorage, pMapName, IStorage::TYPE_ABSOLUTE)) { dbg_msg("map_extract", "error opening map '%s'", pMapName); return false; diff --git a/src/tools/map_resave.cpp b/src/tools/map_resave.cpp index 0a624b0f4..d4303506e 100644 --- a/src/tools/map_resave.cpp +++ b/src/tools/map_resave.cpp @@ -18,7 +18,7 @@ int main(int argc, const char **argv) str_format(aFileName, sizeof(aFileName), "%s", argv[2]); - if(!DataFile.Open(pStorage, argv[1], IStorage::TYPE_ALL)) + if(!DataFile.Open(pStorage, argv[1], IStorage::TYPE_ABSOLUTE)) return -1; if(!df.Open(pStorage, aFileName)) return -1;