| 1 | #include <base/log.h> |
| 2 | #include <base/math.h> |
| 3 | #include <base/system.h> |
| 4 | |
| 5 | #include <engine/shared/datafile.h> |
| 6 | #include <engine/shared/linereader.h> |
| 7 | #include <engine/storage.h> |
| 8 | |
| 9 | #include <game/mapitems.h> |
| 10 | |
| 11 | #include <vector> |
| 12 | |
| 13 | static void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) |
| 14 | { |
| 15 | CLineReader LineReader; |
| 16 | if(!LineReader.OpenFile(File: pStorage->OpenFile(pFilename: pConfigName, Flags: IOFLAG_READ, Type: IStorage::TYPE_ABSOLUTE))) |
| 17 | { |
| 18 | log_error("config_store" , "Failed to import settings from '%s': could not open config for reading" , pConfigName); |
| 19 | return; |
| 20 | } |
| 21 | |
| 22 | std::vector<const char *> vpLines; |
| 23 | int TotalLength = 0; |
| 24 | while(const char *pLine = LineReader.Get()) |
| 25 | { |
| 26 | vpLines.push_back(x: pLine); |
| 27 | TotalLength += str_length(str: pLine) + 1; |
| 28 | } |
| 29 | |
| 30 | CDataFileReader Reader; |
| 31 | if(!Reader.Open(pStorage, pFilename: pMapName, StorageType: IStorage::TYPE_ABSOLUTE)) |
| 32 | { |
| 33 | log_error("config_store" , "Failed to import settings from '%s': failed to open map '%s' for reading" , pConfigName, pMapName); |
| 34 | return; |
| 35 | } |
| 36 | |
| 37 | char *pSettings = (char *)malloc(size: maximum(a: 1, b: TotalLength)); |
| 38 | int Offset = 0; |
| 39 | for(const char *pLine : vpLines) |
| 40 | { |
| 41 | int Length = str_length(str: pLine) + 1; |
| 42 | mem_copy(dest: pSettings + Offset, source: pLine, size: Length); |
| 43 | Offset += Length; |
| 44 | } |
| 45 | |
| 46 | CDataFileWriter Writer; |
| 47 | |
| 48 | int SettingsIndex = Reader.NumData(); |
| 49 | bool FoundInfo = false; |
| 50 | for(int i = 0; i < Reader.NumItems(); i++) |
| 51 | { |
| 52 | int Type, Id; |
| 53 | int *pItem = (int *)Reader.GetItem(Index: i, pType: &Type, pId: &Id); |
| 54 | int Size = Reader.GetItemSize(Index: i); |
| 55 | CMapItemInfoSettings MapInfo; |
| 56 | if(Type == MAPITEMTYPE_INFO && Id == 0) |
| 57 | { |
| 58 | FoundInfo = true; |
| 59 | CMapItemInfoSettings *pInfo = (CMapItemInfoSettings *)pItem; |
| 60 | if(Size >= (int)sizeof(CMapItemInfoSettings)) |
| 61 | { |
| 62 | MapInfo = *pInfo; |
| 63 | pItem = (int *)&MapInfo; |
| 64 | Size = sizeof(MapInfo); |
| 65 | if(pInfo->m_Settings > -1) |
| 66 | { |
| 67 | SettingsIndex = pInfo->m_Settings; |
| 68 | char *pMapSettings = (char *)Reader.GetData(Index: SettingsIndex); |
| 69 | int DataSize = Reader.GetDataSize(Index: SettingsIndex); |
| 70 | if(DataSize == TotalLength && mem_comp(a: pSettings, b: pMapSettings, size: DataSize) == 0) |
| 71 | { |
| 72 | log_info("config_store" , "Configs coincide, not updating map" ); |
| 73 | free(ptr: pSettings); |
| 74 | return; |
| 75 | } |
| 76 | Reader.UnloadData(Index: pInfo->m_Settings); |
| 77 | } |
| 78 | else |
| 79 | { |
| 80 | MapInfo = *pInfo; |
| 81 | MapInfo.m_Settings = SettingsIndex; |
| 82 | pItem = (int *)&MapInfo; |
| 83 | Size = sizeof(MapInfo); |
| 84 | } |
| 85 | } |
| 86 | else |
| 87 | { |
| 88 | *(CMapItemInfo *)&MapInfo = *(CMapItemInfo *)pInfo; |
| 89 | MapInfo.m_Settings = SettingsIndex; |
| 90 | pItem = (int *)&MapInfo; |
| 91 | Size = sizeof(MapInfo); |
| 92 | } |
| 93 | } |
| 94 | Writer.AddItem(Type, Id, Size, pData: pItem); |
| 95 | } |
| 96 | |
| 97 | if(!FoundInfo) |
| 98 | { |
| 99 | CMapItemInfoSettings Info; |
| 100 | Info.m_Version = 1; |
| 101 | Info.m_Author = -1; |
| 102 | Info.m_MapVersion = -1; |
| 103 | Info.m_Credits = -1; |
| 104 | Info.m_License = -1; |
| 105 | Info.m_Settings = SettingsIndex; |
| 106 | Writer.AddItem(Type: MAPITEMTYPE_INFO, Id: 0, Size: sizeof(Info), pData: &Info); |
| 107 | } |
| 108 | |
| 109 | for(int i = 0; i < Reader.NumData() || i == SettingsIndex; i++) |
| 110 | { |
| 111 | if(i == SettingsIndex) |
| 112 | { |
| 113 | Writer.AddData(Size: TotalLength, pData: pSettings); |
| 114 | continue; |
| 115 | } |
| 116 | unsigned char *pData = (unsigned char *)Reader.GetData(Index: i); |
| 117 | int Size = Reader.GetDataSize(Index: i); |
| 118 | Writer.AddData(Size, pData); |
| 119 | Reader.UnloadData(Index: i); |
| 120 | } |
| 121 | |
| 122 | free(ptr: pSettings); |
| 123 | Reader.Close(); |
| 124 | if(!Writer.Open(pStorage, pFilename: pMapName)) |
| 125 | { |
| 126 | log_error("config_store" , "Failed to import settings from '%s': failed to open map '%s' for writing" , pConfigName, pMapName); |
| 127 | return; |
| 128 | } |
| 129 | Writer.Finish(); |
| 130 | log_info("config_store" , "Imported settings from '%s' into '%s'" , pConfigName, pMapName); |
| 131 | } |
| 132 | #include "config_common.h" |
| 133 | |