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