GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/db/colordb.cpp Lines: 11 84 13.1 %
Date: 2017-11-29 Branches: 3 146 2.1 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2008  Aethyra Development Team
4
 *  Copyright (C) 2011-2017  The ManaPlus Developers
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "resources/db/colordb.h"
23
24
#include "configuration.h"
25
26
#include "utils/cast.h"
27
#include "utils/checkutils.h"
28
29
#include "resources/beingcommon.h"
30
31
#include "debug.h"
32
33
namespace
34
{
35
    int mHairColorsSize = 0;
36
    bool mLoaded = false;
37
6
    std::string mFail("#ffffff");
38
2
    ColorDB::ColorLists mColorLists;
39
}  // namespace
40
41
void ColorDB::load()
42
{
43
    if (mLoaded)
44
        unload();
45
46
    logger->log1("Initializing color database...");
47
48
    std::map<ItemColor, ItemColorData> colors;
49
    ColorListsIterator it = mColorLists.find("hair");
50
    if (it != mColorLists.end())
51
        colors = it->second;
52
    loadHair(paths.getStringValue("hairColorFile"),
53
        colors,
54
        SkipError_true);
55
    loadHair(paths.getStringValue("hairColorPatchFile"),
56
        colors,
57
        SkipError_true);
58
    StringVect list;
59
    VirtFs::getFilesInDir(paths.getStringValue(
60
        "hairColorPatchDir"), list, ".xml");
61
    FOR_EACH (StringVectCIter, it2, list)
62
        loadHair(*it2, colors, SkipError_true);
63
64
    mColorLists["hair"] = colors;
65
66
    loadColorLists(paths.getStringValue("itemColorsFile"),
67
        SkipError_false);
68
    loadColorLists(paths.getStringValue("itemColorsPatchFile"),
69
        SkipError_true);
70
    loadXmlDir("itemColorsPatchDir", loadColorLists);
71
72
    it = mColorLists.find("hair");
73
    if (it != mColorLists.end())
74
        mHairColorsSize = CAST_S32((*it).second.size());
75
    else
76
        mHairColorsSize = 0;
77
    mLoaded = true;
78
}
79
80
void ColorDB::loadHair(const std::string &fileName,
81
                       std::map<ItemColor, ItemColorData> &colors,
82
                       const SkipError skipError)
83
{
84
    XML::Document *doc = new XML::Document(fileName,
85
        UseVirtFs_true,
86
        skipError);
87
    XmlNodeConstPtrConst root = doc->rootNode();
88
89
    if ((root == nullptr) || !xmlNameEqual(root, "colors"))
90
    {
91
        logger->log("ColorDB: Failed to find hair colors file.");
92
        if (colors.find(ItemColor_zero) == colors.end())
93
            colors[ItemColor_zero] = ItemColorData(ItemColor_zero, "", "");
94
        delete doc;
95
        return;
96
    }
97
98
    reportAlways("Found legacy hair.xml");
99
    for_each_xml_child_node(node, root)
100
    {
101
        if (xmlNameEqual(node, "include"))
102
        {
103
            const std::string name = XML::getProperty(node, "name", "");
104
            if (!name.empty())
105
                loadHair(name, colors, skipError);
106
            continue;
107
        }
108
        else if (xmlNameEqual(node, "color"))
109
        {
110
            const ItemColor id = fromInt(XML::getProperty(
111
                node, "id", 0), ItemColor);
112
113
            if (colors.find(id) != colors.end())
114
            {
115
                reportAlways("ColorDB: Redefinition of dye ID %d",
116
                    toInt(id, int));
117
            }
118
119
            colors[id] = ItemColorData(id, XML::langProperty(node, "name", ""),
120
                XML::getProperty(node, "value", "#FFFFFF"));
121
        }
122
    }
123
124
    delete doc;
125
}
126
127
void ColorDB::loadColorLists(const std::string &fileName,
128
                             const SkipError skipError)
129
{
130
    XML::Document *doc = new XML::Document(fileName,
131
        UseVirtFs_true,
132
        skipError);
133
    XmlNodeConstPtrConst root = doc->rootNode();
134
    if (root == nullptr)
135
    {
136
        delete doc;
137
        return;
138
    }
139
140
    for_each_xml_child_node(node, root)
141
    {
142
        if (xmlNameEqual(node, "include"))
143
        {
144
            const std::string name = XML::getProperty(node, "name", "");
145
            if (!name.empty())
146
                loadColorLists(name, skipError);
147
            continue;
148
        }
149
        else if (xmlNameEqual(node, "list"))
150
        {
151
            const std::string name = XML::getProperty(node, "name", "");
152
            if (name.empty())
153
                continue;
154
155
            std::map <ItemColor, ItemColorData> colors;
156
            const ColorListsIterator it = mColorLists.find(name);
157
158
            if (it != mColorLists.end())
159
                colors = it->second;
160
161
            for_each_xml_child_node(colorNode, node)
162
            {
163
                if (xmlNameEqual(colorNode, "color"))
164
                {
165
                    const int id = XML::getProperty(colorNode, "id", -1);
166
                    if (id > -1)
167
                    {
168
                        ItemColorData c(fromInt(id, ItemColor),
169
                            XML::langProperty(colorNode, "name", ""),
170
                            XML::getProperty(colorNode, "value", ""));
171
                            colors[c.id] = c;
172
                    }
173
                }
174
            }
175
            mColorLists[name] = colors;
176
        }
177
    }
178
    delete doc;
179
}
180
181
384
void ColorDB::unload()
182
{
183
384
    logger->log1("Unloading color database...");
184
185
384
    mColorLists.clear();
186
384
    mLoaded = false;
187
384
}
188
189
std::string &ColorDB::getHairColorName(const ItemColor id)
190
{
191
    if (!mLoaded)
192
        load();
193
194
    const ColorListsIterator it = mColorLists.find("hair");
195
    if (it == mColorLists.end())
196
    {
197
        reportAlways("ColorDB: Error, hair colors list empty");
198
        return mFail;
199
    }
200
201
    const ColorIterator i = (*it).second.find(id);
202
203
    if (i == (*it).second.end())
204
    {
205
        reportAlways("ColorDB: Error, unknown dye ID# %d",
206
            toInt(id, int));
207
        return mFail;
208
    }
209
    return i->second.name;
210
}
211
212
int ColorDB::getHairSize()
213
{
214
    return mHairColorsSize;
215
}
216
217
const std::map <ItemColor, ItemColorData>
218
336
     *ColorDB::getColorsList(const std::string &name)
219
{
220
336
    const ColorListsIterator it = mColorLists.find(name);
221
222
336
    if (it != mColorLists.end())
223
        return &it->second;
224
    return nullptr;
225

6
}