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