1 // Copyright (C) 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2005 Andrea Paternesi
4 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Library General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include <sigc++/functors/mem_fun.h>
28 #include "rectangle.h"
29 #include "armysetlist.h"
33 #include "ucompose.hpp"
35 #include "tarhelper.h"
40 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
43 Armysetlist* Armysetlist::s_instance = 0;
45 Armysetlist* Armysetlist::getInstance()
48 s_instance = new Armysetlist();
53 void Armysetlist::deleteInstance()
61 void Armysetlist::add(Armyset *armyset)
63 std::string subdir = File::get_basename(armyset->getDirectory());
65 for (Armyset::iterator ait = armyset->begin(); ait != armyset->end(); ait++)
66 d_armies[armyset->getId()].push_back(*ait);
67 d_names[armyset->getId()] = armyset->getName();
68 d_ids[String::ucompose("%1 %2", armyset->getName(), armyset->getTileSize())] = armyset->getId();
69 armyset->setSubDir(subdir);
70 d_armysets[subdir] = armyset;
71 d_armysetids[armyset->getId()] = armyset;
74 void Armysetlist::loadArmysets(std::list<std::string> armysets)
76 for (std::list<std::string>::const_iterator i = armysets.begin();
77 i != armysets.end(); i++)
79 Armyset *armyset = loadArmyset(*i);
87 Armysetlist::Armysetlist()
90 std::list<std::string> armysets = Armyset::scanSystemCollection();
91 loadArmysets(armysets);
92 armysets = Armyset::scanUserCollection();
93 loadArmysets(armysets);
97 Armysetlist::~Armysetlist()
99 for (iterator it = begin(); it != end(); it++)
102 // remove all army entries
103 for (ArmyPrototypeMap::iterator it = d_armies.begin();
104 it != d_armies.end(); it++)
105 while (!(*it).second.empty())
106 delete ((*it).second)[0];
109 ArmyProto* Armysetlist::getArmy(guint32 id, guint32 index) const
111 // always use ArmyProtoMap::find for searching, else a default entry is
112 // created, which can produce really bad results!!
113 ArmyPrototypeMap::const_iterator it = d_armies.find(id);
115 // armyset does not exist
116 if (it == d_armies.end())
120 if (index >= (*it).second.size())
123 return ((*it).second)[index];
126 ArmyProto* Armysetlist::getScout(guint32 id) const
128 // always use ArmyProtoMap::find for searching, else a default entry is
129 // created, which can produce really bad results!!
130 ArmyPrototypeMap::const_iterator it = d_armies.find(id);
132 // armyset does not exist
133 if (it == d_armies.end())
136 return ((*it).second)[0];
139 guint32 Armysetlist::getSize(guint32 id) const
141 ArmyPrototypeMap::const_iterator it = d_armies.find(id);
143 // armyset does not exist
144 if (it == d_armies.end())
147 return (*it).second.size();
150 std::list<std::string> Armysetlist::getNames()
152 std::list<std::string> names;
153 for (iterator it = begin(); it != end(); it++)
154 names.push_back((*it)->getName());
158 std::list<std::string> Armysetlist::getNames(guint32 tilesize)
160 std::list<std::string> names;
161 for (iterator it = begin(); it != end(); it++)
162 if ((*it)->getTileSize() == tilesize)
163 names.push_back((*it)->getName());
167 std::string Armysetlist::getName(guint32 id) const
169 NameMap::const_iterator it = d_names.find(id);
171 // armyset does not exist
172 if (it == d_names.end())
178 Armyset *Armysetlist::loadArmyset(std::string name)
180 debug("Loading armyset " <<name);
181 Armyset *armyset = Armyset::create(name);
184 if (armyset->validate() == false)
186 cerr << "Error! armyset: `" << armyset->getName() <<
187 "' is invalid. Skipping." << endl;
191 if (d_armysetids.find(armyset->getId()) != d_armysetids.end())
193 Armyset *a = (*d_armysetids.find(armyset->getId())).second;
194 cerr << "Error! armyset: `" << armyset->getName() <<
195 "' shares a duplicate armyset id with `" <<
196 a->getConfigurationFile() << "'. Skipping." << endl;
204 PixMask* Armysetlist::getShipPic (guint32 id)
206 for (iterator it = begin(); it != end(); it++)
208 if ((*it)->getId() == id)
209 return (*it)->getShipPic();
214 PixMask* Armysetlist::getShipMask (guint32 id)
216 for (iterator it = begin(); it != end(); it++)
218 if ((*it)->getId() == id)
219 return (*it)->getShipMask();
224 guint32 Armysetlist::getTileSize(guint32 id)
226 for (iterator it = begin(); it != end(); it++)
228 if ((*it)->getId() == id)
229 return (*it)->getTileSize();
234 PixMask* Armysetlist::getBagPic (guint32 id)
236 for (iterator it = begin(); it != end(); it++)
238 if ((*it)->getId() == id)
239 return (*it)->getBagPic();
244 PixMask* Armysetlist::getStandardPic (guint32 id)
246 for (iterator it = begin(); it != end(); it++)
248 if ((*it)->getId() == id)
249 return (*it)->getStandardPic();
254 PixMask* Armysetlist::getStandardMask (guint32 id)
256 for (iterator it = begin(); it != end(); it++)
258 if ((*it)->getId() == id)
259 return (*it)->getStandardMask();
264 void Armysetlist::getSizes(std::list<guint32> &sizes)
266 for (iterator i = begin(); i != end(); i++)
268 if (find (sizes.begin(), sizes.end(), (*i)->getTileSize()) == sizes.end())
269 sizes.push_back((*i)->getTileSize());
273 guint32 Armysetlist::getArmysetId(std::string armyset, guint32 tilesize)
275 return d_ids[String::ucompose("%1 %2", armyset, tilesize)];
278 std::string Armysetlist::getArmysetDir(std::string name, guint32 tilesize)
280 return getArmyset(getArmysetId(name, tilesize))->getSubDir();
283 int Armysetlist::getNextAvailableId(int after)
285 std::list<guint32> ids;
286 std::list<std::string> armysets = Armyset::scanSystemCollection();
287 //there might be IDs in invalid armysets.
288 for (std::list<std::string>::const_iterator i = armysets.begin();
289 i != armysets.end(); i++)
291 Armyset *armyset = Armyset::create(*i);
294 ids.push_back(armyset->getId());
298 armysets = Armyset::scanUserCollection();
299 for (std::list<std::string>::const_iterator i = armysets.begin();
300 i != armysets.end(); i++)
302 Armyset *armyset = Armyset::create(*i);
305 ids.push_back(armyset->getId());
309 for (guint32 i = after + 1; i < 1000000; i++)
311 if (find(ids.begin(), ids.end(), i) == ids.end())
317 void Armysetlist::instantiateImages()
319 for (iterator it = begin(); it != end(); it++)
320 (*it)->instantiateImages();
323 void Armysetlist::uninstantiateImages()
325 for (iterator it = begin(); it != end(); it++)
326 (*it)->uninstantiateImages();
329 Armyset *Armysetlist::getArmyset(guint32 id)
331 if (d_armysetids.find(id) == d_armysetids.end())
333 return d_armysetids[id];
336 Armyset *Armysetlist::getArmyset(std::string dir)
338 if (d_armysets.find(dir) == d_armysets.end())
340 return d_armysets[dir];
342 bool Armysetlist::addToPersonalCollection(Armyset *armyset, std::string &new_subdir, guint32 &new_id)
344 //do we already have this one?
346 if (getArmyset(armyset->getSubDir()) == getArmyset(armyset->getId()) &&
347 getArmyset(armyset->getSubDir()) != NULL)
349 armyset->setDirectory(getArmyset(armyset->getId())->getDirectory());
353 //if the subdir conflicts with any other subdir, then change it.
354 if (getArmyset(armyset->getSubDir()) != NULL)
357 for (int count = 0; count < 100; count++)
359 new_subdir = String::ucompose("%1%2", armyset->getSubDir(), count);
360 if (getArmyset(new_subdir) == NULL)
368 armyset->setSubDir(new_subdir);
371 new_subdir = armyset->getSubDir();
373 //if the id conflicts with any other id, then change it
374 if (getArmyset(armyset->getId()) != NULL)
376 new_id = Armysetlist::getNextAvailableId(armyset->getId());
377 armyset->setId(new_id);
380 new_id = armyset->getId();
382 //make the directory where the armyset is going to live.
383 std::string directory =
384 File::getUserArmysetDir() + armyset->getSubDir() + "/";
386 if (File::create_dir(directory) == false)
389 //okay now we copy the image files into the new directory
390 std::list<std::string> files;
391 armyset->getFilenames(files);
392 for (std::list<std::string>::iterator it = files.begin(); it != files.end();
394 File::copy(armyset->getFile(*it), directory + *it);
396 //save out the armyset file
397 armyset->setDirectory(directory);
398 XML_Helper helper(armyset->getConfigurationFile(), std::ios::out, false);
399 armyset->save(&helper);
406 Armyset *Armysetlist::import(Tar_Helper *t, std::string f, bool &broken)
408 std::string filename = t->getFile(f, broken);
409 Armyset *armyset = Armyset::create(filename);
410 assert (armyset != NULL);
411 armyset->setSubDir(File::get_basename(f));
413 //extract all the files and remember where we extracted them
414 std::list<std::string> delfiles;
415 delfiles.push_back(filename);
416 std::list<std::string> files;
417 armyset->getFilenames(files);
418 for (std::list<std::string>::iterator i = files.begin(); i != files.end(); i++)
420 std::string b = *i + ".png";
421 std::string file = t->getFile(*i + ".png", broken);
422 delfiles.push_back (file);
425 std::string subdir = "";
427 addToPersonalCollection(armyset, subdir, id);
429 for (std::list<std::string>::iterator it = delfiles.begin(); it != delfiles.end(); it++)