int main(int argc, const char **argv) { if(argc != 2) { printf("wrong arguments, there has to be one and only one and this is the mapfile to extract the images from.\n"); return -1; } IStorage *pStorage = CreateStorage("Teeworlds", argc, argv); CDataFileReader DataFile; if(!pStorage) { printf("Cannot get storage\n"); return -1; } if(!DataFile.Open(pStorage, argv[1], IStorage::TYPE_ALL)) { printf("Cannot read %s\n", argv[1]); return -1; } printf("Loading %s\n", argv[1]); png_init(0, 0); // load images int start, num; DataFile.GetType(MAPITEMTYPE_IMAGE, &start, &num); for(int i = 0; i < num; i++) { CMapItemImage *pImg = (CMapItemImage *)DataFile.GetItem(start+i, 0, 0); char *pName = (char *)DataFile.GetData(pImg->m_ImageName); if(pImg->m_External) { printf("skipping external %s\n", pName); } else { printf("writing %s.png\n", pName); void *pData = DataFile.GetData(pImg->m_ImageData); char buf[255]; #if defined(CONF_FAMILY_WINDOWS) _snprintf(buf, sizeof(buf), "%s.png", pName); #else snprintf(buf, sizeof(buf), "%s.png", pName); #endif png_t png; png_open_file_write(&png, buf); png_set_data(&png, pImg->m_Width, pImg->m_Height, 8, PNG_TRUECOLOR_ALPHA, (unsigned char*) pData); png_close_file(&png); DataFile.UnloadData(pImg->m_ImageData); } } DataFile.Close(); return 0; }
void *ReplaceImageItem(void *pItem, int Type, const char *pImgName, const char *pImgFile, CMapItemImage *pNewImgItem) { if(Type != MAPITEMTYPE_IMAGE) return pItem; CMapItemImage *pImgItem = (CMapItemImage *)pItem; char *pName = (char *)g_DataReader.GetData(pImgItem->m_ImageName); if(str_comp(pImgName, pName) != 0) return pItem; dbg_msg("map_replace_image", "found image '%s'", pImgName); CImageInfo ImgInfo; if(!LoadPNG(&ImgInfo, pImgFile)) return 0; *pNewImgItem = *pImgItem; pNewImgItem->m_Width = ImgInfo.m_Width; pNewImgItem->m_Height = ImgInfo.m_Height; int PixelSize = ImgInfo.m_Format == CImageInfo::FORMAT_RGB ? 3 : 4; g_NewNameID = pImgItem->m_ImageName; IStorage::StripPathAndExtension(pImgFile, g_aNewName, sizeof(g_aNewName)); g_NewDataID = pImgItem->m_ImageData; g_pNewData = ImgInfo.m_pData; g_NewDataSize = ImgInfo.m_Width * ImgInfo.m_Height * PixelSize; return (void *)pNewImgItem; }
virtual bool Load(const char *pMapName) { IStorageTW *pStorage = Kernel()->RequestInterface<IStorageTW>(); if(!pStorage) return false; return m_DataFile.Open(pStorage, pMapName, IStorageTW::TYPE_ALL); }
void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) { CDataFileReader Map; if(!Map.Open(pStorage, pMapName, IStorage::TYPE_ALL)) { dbg_msg("config_retrieve", "error opening map '%s'", pMapName); return; } bool ConfigFound = false; int Start, Num; Map.GetType(MAPITEMTYPE_INFO, &Start, &Num); for(int i = Start; i < Start + Num; i++) { int ItemID; CMapItemInfoSettings *pItem = (CMapItemInfoSettings *)Map.GetItem(i, 0, &ItemID); int ItemSize = Map.GetItemSize(i) - 8; if(!pItem || ItemID != 0) continue; if(ItemSize < (int)sizeof(CMapItemInfoSettings)) break; if(!(pItem->m_Settings > -1)) break; ConfigFound = true; IOHANDLE Config = pStorage->OpenFile(pConfigName, IOFLAG_WRITE, IStorage::TYPE_ALL); if(!Config) { dbg_msg("config_retrieve", "error opening config for writing '%s'", pConfigName); return; } int Size = Map.GetUncompressedDataSize(pItem->m_Settings); char *pSettings = (char *)Map.GetData(pItem->m_Settings); char *pNext = pSettings; while(pNext < pSettings + Size) { int StrSize = str_length(pNext) + 1; io_write(Config, pNext, StrSize - 1); io_write_newline(Config); pNext += StrSize; } Map.UnloadData(pItem->m_Settings); io_close(Config); break; } Map.Close(); if(!ConfigFound) { fs_remove(pConfigName); } }
int main(int argc, const char **argv) { IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); int Index, ID = 0, Type = 0, Size; void *pPtr; char aFileName[1024]; CDataFileReader DataFile; CDataFileWriter df; if(!pStorage || argc != 3) return -1; str_format(aFileName, sizeof(aFileName), "%s", argv[2]); if(!DataFile.Open(pStorage, argv[1], IStorage::TYPE_ALL)) return -1; if(!df.Open(pStorage, aFileName)) return -1; // add all items for(Index = 0; Index < DataFile.NumItems(); Index++) { pPtr = DataFile.GetItem(Index, &Type, &ID); Size = DataFile.GetItemSize(Index); df.AddItem(Type, ID, Size, pPtr); } // add all data for(Index = 0; Index < DataFile.NumData(); Index++) { pPtr = DataFile.GetData(Index); Size = DataFile.GetDataSize(Index); df.AddData(Size, pPtr); } DataFile.Close(); df.Finish(); return 0; }
virtual void Unload() { m_DataFile.Close(); }
virtual int NumItems() { return m_DataFile.NumItems(); }
virtual void *FindItem(int Type, int ID) { return m_DataFile.FindItem(Type, ID); }
virtual void GetType(int Type, int *pStart, int *pNum) { m_DataFile.GetType(Type, pStart, pNum); }
virtual void *GetItem(int Index, int *pType, int *pID) { return m_DataFile.GetItem(Index, pType, pID); }
virtual void UnloadData(int Index) { m_DataFile.UnloadData(Index); }
virtual int GetItemSize(int Index) { return m_DataFile.GetItemSize(Index); }
virtual unsigned Crc() { return m_DataFile.Crc(); }
int main(int argc, const char **argv) { dbg_logger_stdout(); IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv); if(argc != 5) { dbg_msg("map_replace_image", "Invalid arguments"); dbg_msg("map_replace_image", "Usage: map_replace_image <source map filepath> <dest map filepath> <current image name> <new image filepath>"); dbg_msg("map_replace_image", "Notes: map filepath must be relative to user default teeworlds folder"); dbg_msg("map_replace_image", " new image filepath must be absolute or relative to the current position"); return -1; } if (!pStorage) { dbg_msg("map_replace_image", "error loading storage"); return -1; } const char *pSourceFileName = argv[1]; const char *pDestFileName = argv[2]; const char *pImageName = argv[3]; const char *pImageFile = argv[4]; int ID = 0; int Type = 0; int Size = 0; void *pItem = 0; void *pData = 0; if(!g_DataReader.Open(pStorage, pSourceFileName, IStorage::TYPE_ALL)) { dbg_msg("map_replace_image", "failed to open source map. filename='%s'", pSourceFileName); return -1; } if(!g_DataWriter.Open(pStorage, pDestFileName)) { dbg_msg("map_replace_image", "failed to open destination map. filename='%s'", pDestFileName); return -1; } png_init(0,0); // add all items for(int Index = 0; Index < g_DataReader.NumItems(); Index++) { CMapItemImage NewImageItem; pItem = g_DataReader.GetItem(Index, &Type, &ID); Size = g_DataReader.GetItemSize(Index); pItem = ReplaceImageItem(pItem, Type, pImageName, pImageFile, &NewImageItem); if(!pItem) return -1; g_DataWriter.AddItem(Type, ID, Size, pItem); } if(g_NewDataID == -1) { dbg_msg("map_replace_image", "image '%s' not found on source map '%s'.", pImageName, pSourceFileName); return -1; } // add all data for(int Index = 0; Index < g_DataReader.NumItems(); Index++) { if(Index == g_NewDataID) { pData = g_pNewData; Size = g_NewDataSize; } else if (Index == g_NewNameID) { pData = (void *)g_aNewName; Size = str_length(g_aNewName) + 1; } else { pData = g_DataReader.GetData(Index); Size = g_DataReader.GetDataSize(Index); } g_DataWriter.AddData(Size, pData); } g_DataReader.Close(); g_DataWriter.Finish(); dbg_msg("map_replace_image", "image '%s' replaced", pImageName); return 0; }
void Process(IStorageTW *pStorage, const char *pMapName, const char *pConfigName) { IOHANDLE File = pStorage->OpenFile(pConfigName, IOFLAG_READ, IStorageTW::TYPE_ALL); array<char *> aLines; char *pSettings = NULL; if(!File) { dbg_msg("config_store", "config '%s' not found", pConfigName); return; } CLineReader LineReader; LineReader.Init(File); char *pLine; int TotalLength = 0; while((pLine = LineReader.Get())) { int Length = str_length(pLine) + 1; char *pCopy = (char *)mem_alloc(Length, 1); mem_copy(pCopy, pLine, Length); aLines.add(pCopy); TotalLength += Length; } pSettings = (char *)mem_alloc(TotalLength, 1); int Offset = 0; for(int i = 0; i < aLines.size(); i++) { int Length = str_length(aLines[i]) + 1; mem_copy(pSettings + Offset, aLines[i], Length); Offset += Length; mem_free(aLines[i]); } CDataFileReader Reader; Reader.Open(pStorage, pMapName, IStorageTW::TYPE_ALL); CDataFileWriter Writer; Writer.Init(); int SettingsIndex = Reader.NumData(); bool FoundInfo = false; for(int i = 0; i < Reader.NumItems(); i++) { int TypeID; int ItemID; int *pData = (int *)Reader.GetItem(i, &TypeID, &ItemID); // GetItemSize returns item size including header, remove that. int Size = Reader.GetItemSize(i) - sizeof(int) * 2; CMapItemInfoSettings MapInfo; if(TypeID == MAPITEMTYPE_INFO && ItemID == 0) { FoundInfo = true; CMapItemInfoSettings *pInfo = (CMapItemInfoSettings *)pData; if(Size >= (int)sizeof(CMapItemInfoSettings)) { MapInfo = *pInfo; pData = (int *)&MapInfo; Size = sizeof(MapInfo); if(pInfo->m_Settings > -1) { SettingsIndex = pInfo->m_Settings; char *pMapSettings = (char *)Reader.GetData(SettingsIndex); int DataSize = Reader.GetUncompressedDataSize(SettingsIndex); if(DataSize == TotalLength && mem_comp(pSettings, pMapSettings, DataSize) == 0) { dbg_msg("config_store", "configs coincide, not updating map"); return; } Reader.UnloadData(pInfo->m_Settings); } else { MapInfo = *pInfo; MapInfo.m_Settings = SettingsIndex; pData = (int *)&MapInfo; Size = sizeof(MapInfo); } } else { *(CMapItemInfo *)&MapInfo = *(CMapItemInfo *)pInfo; MapInfo.m_Settings = SettingsIndex; pData = (int *)&MapInfo; Size = sizeof(MapInfo); } } Writer.AddItem(TypeID, ItemID, Size, pData); } if(!FoundInfo) { CMapItemInfoSettings Info; Info.m_Version = 1; Info.m_Author = -1; Info.m_MapVersion = -1; Info.m_Credits = -1; Info.m_License = -1; Info.m_Settings = SettingsIndex; Writer.AddItem(MAPITEMTYPE_INFO, 0, sizeof(Info), &Info); } for(int i = 0; i < Reader.NumData() || i == SettingsIndex; i++) { if(i == SettingsIndex) { Writer.AddData(TotalLength, pSettings); continue; } unsigned char *pData = (unsigned char *)Reader.GetData(i); int Size = Reader.GetUncompressedDataSize(i); Writer.AddData(Size, pData); Reader.UnloadData(i); } Reader.Close(); if(!Writer.OpenFile(pStorage, pMapName)) { dbg_msg("config_store", "couldn't open map file '%s' for writing", pMapName); return; } Writer.Finish(); dbg_msg("config_store", "imported settings"); }
int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int StorageType) { CDataFileReader DataFile; //DATAFILE *df = datafile_load(filename); if(!DataFile.Open(pStorage, pFileName, StorageType)) return 0; Clean(); // check version CMapItemVersion *pItem = (CMapItemVersion *)DataFile.FindItem(MAPITEMTYPE_VERSION, 0); if(!pItem) { // import old map /*MAP old_mapstuff; editor->reset(); editor_load_old(df, this); */ } else if(pItem->m_Version == 1) { //editor.reset(false); // load images { int Start, Num; DataFile.GetType( MAPITEMTYPE_IMAGE, &Start, &Num); for(int i = 0; i < Num; i++) { CMapItemImage *pItem = (CMapItemImage *)DataFile.GetItem(Start+i, 0, 0); char *pName = (char *)DataFile.GetData(pItem->m_ImageName); // copy base info CEditorImage *pImg = new CEditorImage(m_pEditor); pImg->m_External = pItem->m_External; if(pItem->m_External) { char aBuf[256]; str_format(aBuf, sizeof(aBuf),"mapres/%s.png", pName); // load external CEditorImage ImgInfo(m_pEditor); if(m_pEditor->Graphics()->LoadPNG(&ImgInfo, aBuf, IStorage::TYPE_ALL)) { *pImg = ImgInfo; pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0); pImg->m_External = 1; } } else { pImg->m_Width = pItem->m_Width; pImg->m_Height = pItem->m_Height; pImg->m_Format = CImageInfo::FORMAT_RGBA; // copy image data void *pData = DataFile.GetData(pItem->m_ImageData); pImg->m_pData = mem_alloc(pImg->m_Width*pImg->m_Height*4, 1); mem_copy(pImg->m_pData, pData, pImg->m_Width*pImg->m_Height*4); pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, pImg->m_Format, pImg->m_pData, CImageInfo::FORMAT_AUTO, 0); } // copy image name if(pName) str_copy(pImg->m_aName, pName, 128); m_lImages.add(pImg); // unload image DataFile.UnloadData(pItem->m_ImageData); DataFile.UnloadData(pItem->m_ImageName); } } // load groups { int LayersStart, LayersNum; DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); int Start, Num; DataFile.GetType(MAPITEMTYPE_GROUP, &Start, &Num); for(int g = 0; g < Num; g++) { CMapItemGroup *pGItem = (CMapItemGroup *)DataFile.GetItem(Start+g, 0, 0); if(pGItem->m_Version < 1 || pGItem->m_Version > CMapItemGroup::CURRENT_VERSION) continue; CLayerGroup *pGroup = NewGroup(); pGroup->m_ParallaxX = pGItem->m_ParallaxX; pGroup->m_ParallaxY = pGItem->m_ParallaxY; pGroup->m_OffsetX = pGItem->m_OffsetX; pGroup->m_OffsetY = pGItem->m_OffsetY; if(pGItem->m_Version >= 2) { pGroup->m_UseClipping = pGItem->m_UseClipping; pGroup->m_ClipX = pGItem->m_ClipX; pGroup->m_ClipY = pGItem->m_ClipY; pGroup->m_ClipW = pGItem->m_ClipW; pGroup->m_ClipH = pGItem->m_ClipH; } for(int l = 0; l < pGItem->m_NumLayers; l++) { CLayer *pLayer = 0; CMapItemLayer *pLayerItem = (CMapItemLayer *)DataFile.GetItem(LayersStart+pGItem->m_StartLayer+l, 0, 0); if(!pLayerItem) continue; if(pLayerItem->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTilemapItem = (CMapItemLayerTilemap *)pLayerItem; CLayerTiles *pTiles = 0; if(pTilemapItem->m_Flags&1) { pTiles = new CLayerGame(pTilemapItem->m_Width, pTilemapItem->m_Height); MakeGameLayer(pTiles); MakeGameGroup(pGroup); } else { pTiles = new CLayerTiles(pTilemapItem->m_Width, pTilemapItem->m_Height); pTiles->m_pEditor = m_pEditor; pTiles->m_Color.r = pTilemapItem->m_Color.r; pTiles->m_Color.g = pTilemapItem->m_Color.g; pTiles->m_Color.b = pTilemapItem->m_Color.b; pTiles->m_Color.a = pTilemapItem->m_Color.a; } pLayer = pTiles; pGroup->AddLayer(pTiles); void *pData = DataFile.GetData(pTilemapItem->m_Data); pTiles->m_Image = pTilemapItem->m_Image; pTiles->m_Game = pTilemapItem->m_Flags&1; mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem)) { for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) { if(pTiles->m_pTiles[i].m_Index) pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET; } } DataFile.UnloadData(pTilemapItem->m_Data); } else if(pLayerItem->m_Type == LAYERTYPE_QUADS) { CMapItemLayerQuads *pQuadsItem = (CMapItemLayerQuads *)pLayerItem; CLayerQuads *pQuads = new CLayerQuads; pQuads->m_pEditor = m_pEditor; pLayer = pQuads; pQuads->m_Image = pQuadsItem->m_Image; if(pQuads->m_Image < -1 || pQuads->m_Image >= m_lImages.size()) pQuads->m_Image = -1; void *pData = DataFile.GetDataSwapped(pQuadsItem->m_Data); pGroup->AddLayer(pQuads); pQuads->m_lQuads.set_size(pQuadsItem->m_NumQuads); mem_copy(pQuads->m_lQuads.base_ptr(), pData, sizeof(CQuad)*pQuadsItem->m_NumQuads); DataFile.UnloadData(pQuadsItem->m_Data); } if(pLayer) pLayer->m_Flags = pLayerItem->m_Flags; } } } // load envelopes { CEnvPoint *pPoints = 0; { int Start, Num; DataFile.GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num); if(Num) pPoints = (CEnvPoint *)DataFile.GetItem(Start, 0, 0); } int Start, Num; DataFile.GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num); for(int e = 0; e < Num; e++) { CMapItemEnvelope *pItem = (CMapItemEnvelope *)DataFile.GetItem(Start+e, 0, 0); CEnvelope *pEnv = new CEnvelope(pItem->m_Channels); pEnv->m_lPoints.set_size(pItem->m_NumPoints); mem_copy(pEnv->m_lPoints.base_ptr(), &pPoints[pItem->m_StartPoint], sizeof(CEnvPoint)*pItem->m_NumPoints); if(pItem->m_aName[0] != -1) // compatibility with old maps IntsToStr(pItem->m_aName, sizeof(pItem->m_aName)/sizeof(int), pEnv->m_aName); m_lEnvelopes.add(pEnv); } } } return 1; }
virtual SHA256_DIGEST Sha256() { return m_DataFile.Sha256(); }
virtual bool Load(const char *pMapName, IStorage *pStorage) { if(!pStorage) pStorage = Kernel()->RequestInterface<IStorage>(); if(!pStorage) return false; if(!m_DataFile.Open(pStorage, pMapName, IStorage::TYPE_ALL)) return false; // check version CMapItemVersion *pItem = (CMapItemVersion *)m_DataFile.FindItem(MAPITEMTYPE_VERSION, 0); if(!pItem || pItem->m_Version != CMapItemVersion::CURRENT_VERSION) return false; // replace compressed tile layers with uncompressed ones int GroupsStart, GroupsNum, LayersStart, LayersNum; m_DataFile.GetType(MAPITEMTYPE_GROUP, &GroupsStart, &GroupsNum); m_DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); for(int g = 0; g < GroupsNum; g++) { CMapItemGroup *pGroup = static_cast<CMapItemGroup *>(m_DataFile.GetItem(GroupsStart + g, 0, 0)); for(int l = 0; l < pGroup->m_NumLayers; l++) { CMapItemLayer *pLayer = static_cast<CMapItemLayer *>(m_DataFile.GetItem(LayersStart + pGroup->m_StartLayer + l, 0, 0)); if(pLayer->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer); if(pTilemap->m_Version > 3) { const int TilemapCount = pTilemap->m_Width * pTilemap->m_Height; const int TilemapSize = TilemapCount * sizeof(CTile); if((TilemapCount / pTilemap->m_Width != pTilemap->m_Height) || (TilemapSize / (int)sizeof(CTile) != TilemapCount)) { dbg_msg("engine", "map layer too big (%d * %d * %u causes an integer overflow)", pTilemap->m_Width, pTilemap->m_Height, unsigned(sizeof(CTile))); return false; } CTile *pTiles = static_cast<CTile *>(mem_alloc(TilemapSize, 1)); if(!pTiles) return false; // extract original tile data int i = 0; CTile *pSavedTiles = static_cast<CTile *>(m_DataFile.GetData(pTilemap->m_Data)); while(i < TilemapCount) { for(unsigned Counter = 0; Counter <= pSavedTiles->m_Skip && i < TilemapCount; Counter++) { pTiles[i] = *pSavedTiles; pTiles[i++].m_Skip = 0; } pSavedTiles++; } m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles)); } } } } return true; }
virtual bool IsLoaded() { return m_DataFile.IsOpen(); }
virtual void *GetData(int Index) { return m_DataFile.GetData(Index); }
virtual void *GetDataSwapped(int Index) { return m_DataFile.GetDataSwapped(Index); }
virtual int GetUncompressedDataSize(int Index) { return m_DataFile.GetUncompressedDataSize(Index); }