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
13static 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