ManaPlus
horsedb.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2009 Aethyra Development Team
4  * Copyright (C) 2011-2019 The ManaPlus Developers
5  * Copyright (C) 2019-2021 Andrei Karas
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "resources/db/horsedb.h"
24 
25 #include "configuration.h"
26 
28 
29 #include "resources/beingcommon.h"
30 #include "resources/horseinfo.h"
31 
32 #include "utils/checkutils.h"
33 #include "utils/dtor.h"
34 
35 #include "debug.h"
36 
37 namespace
38 {
41  bool mLoaded = false;
42 } // namespace
43 
44 #define loadSprite(name) \
45  { \
46  SpriteReference *const currentSprite = new SpriteReference; \
47  currentSprite->sprite = pathJoin(paths.getStringValue("sprites"), \
48  XmlChildContent(spriteNode)); \
49  currentSprite->variant = XML::getProperty( \
50  spriteNode, "variant", 0); \
51  currentInfo->name.push_back(currentSprite); \
52  }
53 
54 static void loadDownSprites(XmlNodePtrConst parentNode,
55  HorseInfo *const currentInfo);
56 
57 static void loadUpSprites(XmlNodePtrConst parentNode,
58  HorseInfo *const currentInfo);
59 
61 {
62  if (mLoaded)
63  unload();
64 
65  logger->log1("Initializing horse database...");
66 
67  SpriteReference *currentSprite = new SpriteReference;
68  currentSprite->sprite = pathJoin(paths.getStringValue("sprites"),
69  paths.getStringValue("spriteErrorFile"));
70  currentSprite->variant = 0;
71  mUnknown.downSprites.push_back(currentSprite);
72 
73  currentSprite = new SpriteReference;
74  currentSprite->sprite = pathJoin(paths.getStringValue("sprites"),
75  paths.getStringValue("spriteErrorFile"));
76  currentSprite->variant = 0;
77  mUnknown.upSprites.push_back(currentSprite);
78 
80  loadXmlFile(paths.getStringValue("horsesPatchFile"), SkipError_true);
81  loadXmlDir("horsesPatchDir", loadXmlFile)
82 
83  mLoaded = true;
84 }
85 
86 static int parseDirectionName(const std::string &name)
87 {
88  int id = -1;
89  if (name == "down")
90  {
92  }
93  else if (name == "downleft" || name == "leftdown")
94  {
96  }
97  else if (name == "left")
98  {
100  }
101  else if (name == "upleft" || name == "leftup")
102  {
104  }
105  else if (name == "up")
106  {
107  id = SpriteDirection::UP;
108  }
109  else if (name == "upright" || name == "rightup")
110  {
112  }
113  else if (name == "right")
114  {
116  }
117  else if (name == "downright" || name == "rightdown")
118  {
120  }
121  // hack for died action.
122  else if (name == "died")
123  {
124  id = 9;
125  }
126 
127  return id;
128 }
129 
130 static void loadRiderOffset(XmlNodePtrConst node,
131  HorseInfo *const currentInfo)
132 {
133  const std::string dirName = XML::getProperty(node,
134  "direction", "");
135  const int dir = parseDirectionName(dirName);
136  if (dir == -1)
137  {
138  reportAlways("Wrong or missing horse rider direcion: %s",
139  dirName.c_str())
140  return;
141  }
142  HorseOffset &offset = currentInfo->offsets[dir];
143  offset.riderOffsetX = XML::getProperty(node,
144  "riderOffsetX", 0);
145  offset.riderOffsetY = XML::getProperty(node,
146  "riderOffsetY", 0);
147 }
148 
149 void HorseDB::loadXmlFile(const std::string &fileName,
150  const SkipError skipError)
151 {
154  skipError);
155  XmlNodePtrConst rootNode = doc.rootNode();
156 
157  if ((rootNode == nullptr) || !xmlNameEqual(rootNode, "horses"))
158  {
159  logger->log("Horse Database: Error while loading %s!",
160  fileName.c_str());
161  return;
162  }
163 
164  // iterate <emote>s
165  for_each_xml_child_node(horseNode, rootNode)
166  {
167  if (xmlNameEqual(horseNode, "include"))
168  {
169  const std::string name = XML::getProperty(horseNode, "name", "");
170  if (!name.empty())
171  loadXmlFile(name, skipError);
172  continue;
173  }
174  else if (!xmlNameEqual(horseNode, "horse"))
175  {
176  continue;
177  }
178 
179  const int id = XML::getProperty(horseNode, "id", -1);
180 
181  if (id == -1)
182  {
183  reportAlways("Horse Database: Horse with missing ID in %s!",
184  paths.getStringValue("horsesFile").c_str())
185  continue;
186  }
187  HorseInfo *currentInfo = nullptr;
188  if (mHorseInfos.find(id) != mHorseInfos.end())
189  currentInfo = mHorseInfos[id];
190  else
191  currentInfo = new HorseInfo;
192 
193  if (currentInfo == nullptr)
194  continue;
195  for_each_xml_child_node(spriteNode, horseNode)
196  {
197  if (xmlNameEqual(spriteNode, "down"))
198  loadDownSprites(spriteNode, currentInfo);
199  else if (xmlNameEqual(spriteNode, "up"))
200  loadUpSprites(spriteNode, currentInfo);
201  else if (xmlNameEqual(spriteNode, "offset"))
202  loadRiderOffset(spriteNode, currentInfo);
203  }
204  mHorseInfos[id] = currentInfo;
205  }
206 }
207 
208 static void loadOffset(XmlNodePtrConst node,
209  HorseInfo *const currentInfo,
210  const bool isUp)
211 {
212  const std::string dirName = XML::getProperty(node,
213  "direction", "");
214  const int dir = parseDirectionName(dirName);
215  if (dir == -1)
216  {
217  reportAlways("Wrong or missing horse direcion: %s",
218  dirName.c_str())
219  return;
220  }
221  HorseOffset &offset = currentInfo->offsets[dir];
222  if (isUp)
223  {
224  offset.upOffsetX = XML::getProperty(node,
225  "horseOffsetX", 0);
226  offset.upOffsetY = XML::getProperty(node,
227  "horseOffsetY", 0);
228  }
229  else
230  {
231  offset.downOffsetX = XML::getProperty(node,
232  "horseOffsetX", 0);
233  offset.downOffsetY = XML::getProperty(node,
234  "horseOffsetY", 0);
235  }
236 }
237 
238 static void loadDownSprites(XmlNodePtrConst parentNode,
239  HorseInfo *const currentInfo)
240 {
241  for_each_xml_child_node(spriteNode, parentNode)
242  {
243  if (xmlNameEqual(spriteNode, "offset"))
244  loadOffset(spriteNode, currentInfo, false);
245  if (!XmlHaveChildContent(spriteNode))
246  continue;
247  if (xmlNameEqual(spriteNode, "sprite"))
248  loadSprite(downSprites)
249  }
250 }
251 
252 static void loadUpSprites(XmlNodePtrConst parentNode,
253  HorseInfo *const currentInfo)
254 {
255  for_each_xml_child_node(spriteNode, parentNode)
256  {
257  if (xmlNameEqual(spriteNode, "offset"))
258  loadOffset(spriteNode, currentInfo, true);
259  if (!XmlHaveChildContent(spriteNode))
260  continue;
261  if (xmlNameEqual(spriteNode, "sprite"))
262  loadSprite(upSprites)
263  }
264 }
265 
267 {
268  logger->log1("Unloading horse database...");
269  FOR_EACH (HorseInfos::const_iterator, i, mHorseInfos)
270  {
271  delete_all(i->second->upSprites);
272  delete_all(i->second->downSprites);
273  delete i->second;
274  }
275  mHorseInfos.clear();
276 
279  mUnknown.upSprites.clear();
280  mUnknown.downSprites.clear();
281 
282  mLoaded = false;
283 }
284 
285 HorseInfo *HorseDB::get(const int id, const bool allowNull)
286 {
287  const HorseInfos::const_iterator i = mHorseInfos.find(id);
288 
289  if (i == mHorseInfos.end())
290  {
291  if (allowNull)
292  return nullptr;
293  reportAlways("HorseDB: Warning, unknown horse ID %d requested",
294  id)
295  return &mUnknown;
296  }
297  return i->second;
298 }
299 
301 {
302  return static_cast<signed int>(mHorseInfos.size());
303 }
static void loadXmlFile(const std::string &file, const std::string &name, BadgesInfos &arr, const SkipError skipError)
Definition: badgesdb.cpp:43
#define loadXmlDir(name, function)
Definition: beingcommon.h:39
#define reportAlways(...)
Definition: checkutils.h:253
std::string getStringValue(const std::string &key) const
void log(const char *const log_text,...)
Definition: logger.cpp:269
void log1(const char *const log_text)
Definition: logger.cpp:238
xmlNodePtr rootNode()
Definition: libxml.cpp:169
Configuration paths
void delete_all(Container &c)
Definition: dtor.h:56
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
static void loadRiderOffset(xmlNode *const node, HorseInfo *const currentInfo)
Definition: horsedb.cpp:130
static void loadOffset(xmlNode *const node, HorseInfo *const currentInfo, const bool isUp)
Definition: horsedb.cpp:208
static void loadDownSprites(xmlNode *const parentNode, HorseInfo *const currentInfo)
Definition: horsedb.cpp:238
static void loadUpSprites(xmlNode *const parentNode, HorseInfo *const currentInfo)
Definition: horsedb.cpp:252
static int parseDirectionName(const std::string &name)
Definition: horsedb.cpp:86
#define loadSprite(name)
Definition: horsedb.cpp:44
std::map< int, HorseInfo * > HorseInfos
Definition: horsedb.h:33
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:161
Logger * logger
Definition: logger.cpp:89
void unload()
Definition: horsedb.cpp:266
void load()
Definition: horsedb.cpp:60
void loadXmlFile(const std::string &fileName, const SkipError skipError)
Definition: horsedb.cpp:149
HorseInfo * get(const int id, const bool allowNull)
Definition: horsedb.cpp:285
int size()
Definition: horsedb.cpp:300
void unload()
Definition: net.cpp:180
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:174
const bool SkipError_false
Definition: skiperror.h:30
const bool SkipError_true
Definition: skiperror.h:30
bool SkipError
Definition: skiperror.h:30
std::string pathJoin(std::string str1, const std::string &str2)
std::vector< SpriteReference * > upSprites
Definition: horseinfo.h:53
std::vector< SpriteReference * > downSprites
Definition: horseinfo.h:52
HorseOffset offsets[10]
Definition: horseinfo.h:54
int downOffsetY
Definition: horseoffset.h:43
int riderOffsetY
Definition: horseoffset.h:45
int downOffsetX
Definition: horseoffset.h:42
int riderOffsetX
Definition: horseoffset.h:44
std::string sprite
std::string fileName
Definition: testmain.cpp:39
const bool UseVirtFs_true
Definition: usevirtfs.h:30