1 // Copyright (C) 2008, 2010, 2011, 2014, 2015, 2020 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 //  02110-1301, USA.
17 
18 #include <sigc++/functors/mem_fun.h>
19 
20 #include "cityset.h"
21 #include "File.h"
22 #include "xmlhelper.h"
23 #include "gui/image-helpers.h"
24 #include "city.h"
25 #include "ruin.h"
26 #include "temple.h"
27 #include "tarhelper.h"
28 #include "Configuration.h"
29 #include "file-compat.h"
30 #include "ucompose.hpp"
31 
32 Glib::ustring Cityset::d_tag = "cityset";
33 Glib::ustring Cityset::file_extension = CITYSET_EXT;
34 
35 #include <iostream>
36 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
37 #define debug(x)
38 
39 #define DEFAULT_CITY_TILE_SIZE 40
Cityset(guint32 id,Glib::ustring name)40 Cityset::Cityset(guint32 id, Glib::ustring name)
41  : Set(CITYSET_EXT, id, name, DEFAULT_CITY_TILE_SIZE)
42 {
43 	d_cities_filename = "";
44 	d_razedcities_filename = "";
45 	d_port_filename = "";
46 	d_signpost_filename = "";
47 	d_ruins_filename = "";
48 	d_temples_filename = "";
49 	d_towers_filename = "";
50 	for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
51 	  citypics[i] = NULL;
52 	for (unsigned int i = 0; i < MAX_PLAYERS; i++)
53 	  razedcitypics[i] = NULL;
54 	port = NULL;
55 	signpost = NULL;
56 	for (unsigned int i = 0; i < RUIN_TYPES; i++)
57 	  ruinpics[i] = NULL;
58 	for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
59 	  templepics[i] = NULL;
60 	for (unsigned int i = 0; i < MAX_PLAYERS; i++)
61 	  towerpics[i] = NULL;
62 
63 	d_city_tile_width = 2;
64 	d_temple_tile_width = 1;
65 	d_ruin_tile_width = 1;
66 }
67 
Cityset(const Cityset & c)68 Cityset::Cityset(const Cityset& c)
69  : sigc::trackable(c), Set(c), d_cities_filename(c.d_cities_filename),
70     d_razedcities_filename(c.d_razedcities_filename),
71     d_port_filename(c.d_port_filename),
72     d_signpost_filename(c.d_signpost_filename),
73     d_ruins_filename(c.d_ruins_filename),
74     d_temples_filename(c.d_temples_filename),
75     d_towers_filename(c.d_towers_filename)
76 {
77   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
78     {
79       if (c.citypics[i] != NULL)
80         citypics[i] = c.citypics[i]->copy();
81       else
82         citypics[i] = NULL;
83     }
84   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
85     {
86       if (c.razedcitypics[i] != NULL)
87         razedcitypics[i] = c.razedcitypics[i]->copy();
88       else
89         razedcitypics[i] = NULL;
90     }
91   if (c.port != NULL)
92     port = c.port->copy();
93   else
94     port = NULL;
95   if (c.signpost != NULL)
96     signpost = c.signpost->copy();
97   else
98     signpost = NULL;
99 
100   for (unsigned int i = 0; i < RUIN_TYPES; i++)
101     {
102       if (c.ruinpics[i] != NULL)
103         ruinpics[i] = c.ruinpics[i]->copy();
104       else
105         ruinpics[i] = NULL;
106     }
107   for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
108     {
109       if (c.templepics[i] != NULL)
110         templepics[i] = c.templepics[i]->copy();
111       else
112         templepics[i] = NULL;
113     }
114   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
115     {
116       if (c.towerpics[i] != NULL)
117         towerpics[i] = c.towerpics[i]->copy();
118       else
119         towerpics[i] = NULL;
120     }
121 
122   d_city_tile_width = c.d_city_tile_width;
123   d_temple_tile_width = c.d_temple_tile_width;
124   d_ruin_tile_width = c.d_ruin_tile_width;
125 }
126 
Cityset(XML_Helper * helper,Glib::ustring directory)127 Cityset::Cityset(XML_Helper *helper, Glib::ustring directory)
128  : Set(CITYSET_EXT, helper)
129 {
130   setDirectory(directory);
131   guint32 ts;
132   helper->getData(ts, "tilesize");
133   setTileSize(ts);
134   helper->getData(d_cities_filename, "cities");
135   File::add_png_if_no_ext (d_cities_filename);
136   helper->getData(d_razedcities_filename, "razed_cities");
137   File::add_png_if_no_ext (d_razedcities_filename);
138   helper->getData(d_port_filename, "port");
139   File::add_png_if_no_ext (d_port_filename);
140   helper->getData(d_signpost_filename, "signpost");
141   File::add_png_if_no_ext (d_signpost_filename);
142   helper->getData(d_ruins_filename, "ruins");
143   File::add_png_if_no_ext (d_ruins_filename);
144   helper->getData(d_temples_filename, "temples");
145   File::add_png_if_no_ext (d_temples_filename);
146   helper->getData(d_towers_filename, "towers");
147   File::add_png_if_no_ext (d_towers_filename);
148   helper->getData(d_city_tile_width, "city_tile_width");
149   helper->getData(d_temple_tile_width, "temple_tile_width");
150   helper->getData(d_ruin_tile_width, "ruin_tile_width");
151   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
152     citypics[i] = NULL;
153   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
154     razedcitypics[i] = NULL;
155   for (unsigned int i = 0; i < RUIN_TYPES; i++)
156     ruinpics[i] = NULL;
157   for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
158     templepics[i] = NULL;
159   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
160     towerpics[i] = NULL;
161   port = NULL;
162   signpost = NULL;
163 }
164 
~Cityset()165 Cityset::~Cityset()
166 {
167   uninstantiateImages();
168   clean_tmp_dir();
169 }
170 
171 //! Helper class for making a new Cityset object from a cityset file.
172 class CitysetLoader
173 {
174 public:
CitysetLoader(Glib::ustring filename,bool & broken,bool & unsupported)175     CitysetLoader(Glib::ustring filename, bool &broken, bool &unsupported)
176       {
177         unsupported_version = false;
178 	cityset = NULL;
179 	dir = File::get_dirname(filename);
180         file = File::get_basename(filename);
181 	if (File::nameEndsWith(filename, Cityset::file_extension) == false)
182 	  filename += Cityset::file_extension;
183         Tar_Helper t(filename, std::ios::in, broken);
184         if (broken)
185           return;
186         Glib::ustring lwcfilename =
187           t.getFirstFile(Cityset::file_extension, broken);
188         if (broken)
189           return;
190 	XML_Helper helper(lwcfilename, std::ios::in);
191 	helper.registerTag(Cityset::d_tag, sigc::mem_fun((*this), &CitysetLoader::load));
192 	if (!helper.parseXML())
193 	  {
194             unsupported = unsupported_version;
195             std::cerr << String::ucompose(_("Error!  can't load cityset `%1'."), filename) << std::endl;
196 	    if (cityset != NULL)
197 	      delete cityset;
198 	    cityset = NULL;
199 	  }
200         helper.close();
201         File::erase(lwcfilename);
202         t.Close();
203       };
load(Glib::ustring tag,XML_Helper * helper)204     bool load(Glib::ustring tag, XML_Helper* helper)
205       {
206 	if (tag == Cityset::d_tag)
207 	  {
208             if (helper->getVersion() == LORDSAWAR_CITYSET_VERSION)
209               {
210                 cityset = new Cityset(helper, dir);
211                 cityset->setBaseName(file);
212                 return true;
213               }
214             else
215               {
216                 unsupported_version = true;
217                 return false;
218               }
219 	  }
220 	return false;
221       };
222     Glib::ustring dir;
223     Glib::ustring file;
224     Cityset *cityset;
225     bool unsupported_version;
226 };
227 
create(Glib::ustring file,bool & unsupported_version)228 Cityset *Cityset::create(Glib::ustring file, bool &unsupported_version)
229 {
230   bool broken = false;
231   CitysetLoader d(file, broken, unsupported_version);
232   if (broken)
233     return NULL;
234   return d.cityset;
235 }
236 
save(Glib::ustring filename,Glib::ustring ext) const237 bool Cityset::save(Glib::ustring filename, Glib::ustring ext) const
238 {
239   bool broken = false;
240   Glib::ustring goodfilename = File::add_ext_if_necessary(filename, ext);
241   Glib::ustring tmpfile = File::get_tmp_file();
242   XML_Helper helper(tmpfile, std::ios::out);
243   helper.begin(LORDSAWAR_CITYSET_VERSION);
244   broken = !save(&helper);
245   helper.close();
246   if (broken == true)
247     return false;
248   return saveTar(tmpfile, tmpfile + ".tar", goodfilename);
249 }
250 
save(XML_Helper * helper) const251 bool Cityset::save(XML_Helper *helper) const
252 {
253   bool retval = true;
254 
255   retval &= helper->openTag(d_tag);
256   retval &= Set::save(helper);
257   retval &= helper->saveData("tilesize", getUnscaledTileSize());
258   retval &= helper->saveData("cities", d_cities_filename);
259   retval &= helper->saveData("razed_cities", d_razedcities_filename);
260   retval &= helper->saveData("port", d_port_filename);
261   retval &= helper->saveData("signpost", d_signpost_filename);
262   retval &= helper->saveData("ruins", d_ruins_filename);
263   retval &= helper->saveData("temples", d_temples_filename);
264   retval &= helper->saveData("towers", d_towers_filename);
265   retval &= helper->saveData("city_tile_width", d_city_tile_width);
266   retval &= helper->saveData("temple_tile_width", d_temple_tile_width);
267   retval &= helper->saveData("ruin_tile_width", d_ruin_tile_width);
268   retval &= helper->closeTag();
269   return retval;
270 }
271 
uninstantiateImages()272 void Cityset::uninstantiateImages()
273 {
274   if (getPortImage() != NULL)
275     {
276       delete getPortImage();
277       setPortImage(NULL);
278     }
279   if (getSignpostImage() != NULL)
280     {
281       delete getSignpostImage();
282       setSignpostImage(NULL);
283     }
284   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
285     {
286       if (getCityImage(i) != NULL)
287 	{
288 	  delete getCityImage(i);
289 	  setCityImage(i, NULL);
290 	}
291     }
292   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
293     {
294       if (getRazedCityImage(i) != NULL)
295 	{
296 	  delete getRazedCityImage(i);
297 	  setRazedCityImage(i, NULL);
298 	}
299     }
300   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
301     {
302       if (getTowerImage(i) != NULL)
303 	{
304 	  delete getTowerImage(i);
305 	  setTowerImage(i, NULL);
306 	}
307     }
308   for (unsigned int i = 0; i < RUIN_TYPES; i++)
309     {
310       if (getRuinImage(i) != NULL)
311 	{
312 	  delete getRuinImage(i);
313 	  setRuinImage(i, NULL);
314 	}
315     }
316   for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
317     {
318       if (getTempleImage(i) != NULL)
319 	{
320 	  delete getTempleImage(i);
321 	  setTempleImage(i, NULL);
322 	}
323     }
324 }
325 
instantiateImages(Glib::ustring port_filename,Glib::ustring signpost_filename,Glib::ustring cities_filename,Glib::ustring razed_cities_filename,Glib::ustring towers_filename,Glib::ustring ruins_filename,Glib::ustring temples_filename,bool scale,bool & broken)326 void Cityset::instantiateImages(Glib::ustring port_filename,
327 				Glib::ustring signpost_filename,
328 				Glib::ustring cities_filename,
329 				Glib::ustring razed_cities_filename,
330 				Glib::ustring towers_filename,
331 				Glib::ustring ruins_filename,
332 				Glib::ustring temples_filename,
333                                 bool scale, bool &broken)
334 {
335   if (port_filename.empty() == false && !broken)
336     setPortImage (PixMask::create(port_filename, broken));
337   if (signpost_filename.empty() == false && !broken)
338     setSignpostImage (PixMask::create(signpost_filename, broken));
339 
340   int citysize = getUnscaledTileSize() * d_city_tile_width;
341   if (cities_filename.empty() == false && !broken)
342     {
343       std::vector<PixMask* > pics;
344       pics = disassemble_row(cities_filename, MAX_PLAYERS + 1, broken);
345       if (!broken)
346         {
347           for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
348             {
349               if (scale)
350                 {
351                   if (pics[i]->get_width() != citysize)
352                     PixMask::scale(pics[i], citysize, citysize);
353                 }
354               setCityImage(i, pics[i]);
355             }
356         }
357     }
358 
359   if (razed_cities_filename.empty() == false && !broken)
360     {
361       std::vector<PixMask* > pics;
362       pics = disassemble_row(razed_cities_filename, MAX_PLAYERS, broken);
363       if (!broken)
364         {
365           for (unsigned int i = 0; i < MAX_PLAYERS; i++)
366             {
367               if (scale)
368                 {
369                   if (pics[i]->get_width() != citysize)
370                     PixMask::scale(pics[i], citysize, citysize);
371                 }
372               setRazedCityImage(i, pics[i]);
373             }
374         }
375     }
376 
377   if (towers_filename.empty() == false && !broken)
378     {
379       std::vector<PixMask* > pics = disassemble_row(towers_filename,
380                                                     MAX_PLAYERS, broken);
381       if (!broken)
382         {
383           for (unsigned int i = 0; i < MAX_PLAYERS; i++)
384             {
385               if (scale)
386                 {
387                   if (pics[i]->get_width() != (int)getUnscaledTileSize())
388                     PixMask::scale(pics[i], getUnscaledTileSize(),
389                                    getUnscaledTileSize());
390                 }
391               setTowerImage(i, pics[i]);
392             }
393         }
394     }
395 
396   if (ruins_filename.empty() == false && !broken)
397     {
398       std::vector<PixMask* > pics = disassemble_row(ruins_filename,
399                                                         RUIN_TYPES, broken);
400       if (!broken)
401         {
402           int ruinsize = getUnscaledTileSize() * d_ruin_tile_width;
403           for (unsigned int i = 0; i < RUIN_TYPES ; i++)
404             {
405               if (scale)
406                 {
407                   if (pics[i]->get_width() != ruinsize)
408                     PixMask::scale(pics[i], ruinsize, ruinsize);
409                 }
410               setRuinImage(i, pics[i]);
411             }
412         }
413     }
414 
415   if (temples_filename.empty() == false && !broken)
416     {
417       std::vector<PixMask* > pics;
418       pics = disassemble_row(temples_filename, TEMPLE_TYPES, broken);
419       if (!broken)
420         {
421           int templesize = getUnscaledTileSize() * d_temple_tile_width;
422           for (unsigned int i = 0; i < TEMPLE_TYPES ; i++)
423             {
424               if (scale)
425                 {
426                   if (pics[i]->get_width() != templesize)
427                     PixMask::scale(pics[i], templesize, templesize);
428                 }
429               setTempleImage(i, pics[i]);
430             }
431         }
432     }
433 }
434 
instantiateImages(bool scale,bool & broken)435 void Cityset::instantiateImages(bool scale, bool &broken)
436 {
437   debug("Loading images for cityset " << getName());
438   uninstantiateImages();
439   broken = false;
440   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
441   if (broken)
442     return;
443   Glib::ustring port_filename = "";
444   Glib::ustring signpost_filename = "";
445   Glib::ustring cities_filename = "";
446   Glib::ustring razed_cities_filename = "";
447   Glib::ustring towers_filename = "";
448   Glib::ustring ruins_filename = "";
449   Glib::ustring temples_filename = "";
450 
451   if (getPortFilename().empty() == false && !broken)
452     port_filename = t.getFile(getPortFilename(), broken);
453   if (getSignpostFilename().empty() == false && !broken)
454     signpost_filename = t.getFile(getSignpostFilename(), broken);
455   if (getCitiesFilename().empty() == false && !broken)
456     cities_filename = t.getFile(getCitiesFilename(), broken);
457   if (getRazedCitiesFilename().empty() == false && !broken)
458     razed_cities_filename = t.getFile(getRazedCitiesFilename(), broken);
459   if (getTowersFilename().empty() == false && !broken)
460     towers_filename = t.getFile(getTowersFilename(), broken);
461   if (getRuinsFilename().empty() == false && !broken)
462     ruins_filename = t.getFile(getRuinsFilename(), broken);
463   if (getTemplesFilename().empty() == false && !broken)
464     temples_filename = t.getFile(getTemplesFilename(), broken);
465   if (!broken)
466     instantiateImages(port_filename, signpost_filename, cities_filename,
467                       razed_cities_filename, towers_filename, ruins_filename,
468                       temples_filename, scale, broken);
469   if (port_filename != "")
470     File::erase(port_filename);
471   if (signpost_filename != "")
472     File::erase(signpost_filename);
473   if (cities_filename != "")
474     File::erase(cities_filename);
475   if (razed_cities_filename != "")
476     File::erase(razed_cities_filename);
477   if (towers_filename != "")
478     File::erase(towers_filename);
479   if (ruins_filename != "")
480     File::erase(ruins_filename);
481   if (temples_filename != "")
482     File::erase(temples_filename);
483   t.Close();
484 }
485 
validate()486 bool Cityset::validate()
487 {
488   bool valid = true;
489   if (String::utrim (getName ()) == "")
490     return false;
491   if (validateCitiesFilename() == false)
492     return false;
493   if (validateRazedCitiesFilename() == false)
494     return false;
495   if (validatePortFilename() == false)
496     return false;
497   if (validateSignpostFilename() == false)
498     return false;
499   if (validateRuinsFilename() == false)
500     return false;
501   if (validateTemplesFilename() == false)
502     return false;
503   if (validateTowersFilename() == false)
504     return false;
505   if (validateCityTileWidth() == false)
506     return false;
507   if (validateRuinTileWidth() == false)
508     return false;
509   if (validateTempleTileWidth() == false)
510     return false;
511   return valid;
512 }
513 
validateCitiesFilename()514 bool Cityset::validateCitiesFilename()
515 {
516   if (getCitiesFilename().empty() == true)
517     return false;
518   return true;
519 }
520 
validateRazedCitiesFilename()521 bool Cityset::validateRazedCitiesFilename()
522 {
523   if (getRazedCitiesFilename().empty() == true)
524     return false;
525   return true;
526 }
527 
validateSignpostFilename()528 bool Cityset::validateSignpostFilename()
529 {
530   if (getSignpostFilename().empty() == true)
531     return false;
532   return true;
533 }
534 
validatePortFilename()535 bool Cityset::validatePortFilename()
536 {
537   if (getPortFilename().empty() == true)
538     return false;
539   return true;
540 }
541 
validateRuinsFilename()542 bool Cityset::validateRuinsFilename()
543 {
544   if (getRuinsFilename().empty() == true)
545     return false;
546   return true;
547 }
548 
validateTemplesFilename()549 bool Cityset::validateTemplesFilename()
550 {
551   if (getTemplesFilename().empty() == true)
552     return false;
553   return true;
554 }
555 
validateTowersFilename()556 bool Cityset::validateTowersFilename()
557 {
558   if (getTowersFilename().empty() == true)
559     return false;
560   return true;
561 }
562 
validateCityTileWidth()563 bool Cityset::validateCityTileWidth()
564 {
565   if (getCityTileWidth() <= 0)
566     return false;
567   return true;
568 }
569 
validateRuinTileWidth()570 bool Cityset::validateRuinTileWidth()
571 {
572   if (getRuinTileWidth() <= 0)
573     return false;
574   return true;
575 }
576 
validateTempleTileWidth()577 bool Cityset::validateTempleTileWidth()
578 {
579   if (getTempleTileWidth() <= 0)
580     return false;
581   return true;
582 }
583 
tileWidthsEqual(Cityset * cityset)584 bool Cityset::tileWidthsEqual(Cityset *cityset)
585 {
586   if (getCityTileWidth() == cityset->getCityTileWidth() &&
587       getRuinTileWidth() == cityset->getRuinTileWidth() &&
588       getTempleTileWidth() == cityset->getTempleTileWidth())
589     return true;
590   return false;
591 }
592 
reload(bool & broken)593 void Cityset::reload(bool &broken)
594 {
595   broken = false;
596   bool unsupported_version = false;
597   CitysetLoader d(getConfigurationFile(), broken, unsupported_version);
598   if (!broken && d.cityset && d.cityset->validate())
599     {
600       //steal the values from d.cityset and then don't delete it.
601       uninstantiateImages();
602       Glib::ustring basename = getBaseName();
603       *this = *d.cityset;
604       instantiateImages(true, broken);
605       setBaseName(basename);
606     }
607 }
608 
calculate_preferred_tile_size(guint32 & ts) const609 bool Cityset::calculate_preferred_tile_size(guint32 &ts) const
610 {
611   guint32 tilesize = 0;
612   std::map<guint32, guint32> sizecounts;
613 
614   if (citypics[0])
615     sizecounts[citypics[0]->get_unscaled_width() / d_city_tile_width]++;
616   if (razedcitypics[0])
617     sizecounts[razedcitypics[0]->get_unscaled_width() / d_city_tile_width]++;
618   if (port)
619     sizecounts[port->get_unscaled_width()]++;
620   if (signpost)
621     sizecounts[signpost->get_unscaled_width()]++;
622   if (ruinpics[0])
623     sizecounts[ruinpics[0]->get_unscaled_width() / d_ruin_tile_width]++;
624   if (templepics[0])
625     sizecounts[templepics[0]->get_unscaled_width() / d_temple_tile_width]++;
626   if (towerpics[0])
627     sizecounts[towerpics[0]->get_unscaled_width()]++;
628 
629   guint32 maxcount = 0;
630   for (std::map<guint32, guint32>::iterator it = sizecounts.begin();
631        it != sizecounts.end(); it++)
632     {
633       if ((*it).second > maxcount)
634         {
635           maxcount = (*it).second;
636           tilesize = (*it).first;
637         }
638     }
639   bool ret = true;
640   if (tilesize == 0)
641     {
642       ts = DEFAULT_CITY_TILE_SIZE;
643       ret = false;
644     }
645   else
646     ts = tilesize;
647   return ret;
648 }
649 
countEmptyImageNames() const650 guint32 Cityset::countEmptyImageNames() const
651 {
652   guint32 count = 0;
653   if (d_cities_filename.empty() == true)
654     count++;
655   if (d_razedcities_filename.empty() == true)
656     count++;
657   if (d_port_filename.empty() == true)
658     count++;
659   if (d_signpost_filename.empty() == true)
660     count++;
661   if (d_ruins_filename.empty() == true)
662     count++;
663   if (d_temples_filename.empty() == true)
664     count++;
665   if (d_towers_filename.empty() == true)
666     count++;
667   return count;
668 }
669 
upgrade(Glib::ustring filename,Glib::ustring old_version,Glib::ustring new_version)670 bool Cityset::upgrade(Glib::ustring filename, Glib::ustring old_version, Glib::ustring new_version)
671 {
672   return FileCompat::getInstance()->upgrade(filename, old_version, new_version,
673                                             FileCompat::CITYSET, d_tag);
674 }
675 
support_backward_compatibility()676 void Cityset::support_backward_compatibility()
677 {
678   FileCompat::getInstance()->support_type (FileCompat::CITYSET, file_extension,
679                                            d_tag, true);
680   FileCompat::getInstance()->support_version
681     (FileCompat::CITYSET, "0.2.0", LORDSAWAR_CITYSET_VERSION,
682      sigc::ptr_fun(&Cityset::upgrade));
683 }
684 
copy(const Cityset * cityset)685 Cityset* Cityset::copy(const Cityset *cityset)
686 {
687   if (!cityset)
688     return NULL;
689   return new Cityset(*cityset);
690 }
691 
clearCitiesImage(bool clear_name)692 void Cityset::clearCitiesImage (bool clear_name)
693 {
694   if (clear_name)
695     setCitiesFilename ("");
696 
697   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
698     {
699       PixMask *p = getCityImage (i);
700       delete p;
701       setCityImage (i, NULL);
702     }
703 }
704 
instantiateCityImages()705 bool Cityset::instantiateCityImages ()
706 {
707   clearCitiesImage (false);
708   bool broken = false;
709   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
710   if (broken)
711     return broken;
712   Glib::ustring imgname = getCitiesFilename();
713   if (imgname.empty() == false)
714     {
715       Glib::ustring filename = t.getFile(imgname, broken);
716       if (!broken)
717         {
718           std::vector<PixMask* > pics;
719           pics = disassemble_row(filename, MAX_PLAYERS + 1, broken);
720           if (!broken)
721             {
722               for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
723                 setCityImage(i, pics[i]);
724             }
725         }
726     }
727   return broken;
728 }
729 
clearRazedCitiesImage(bool clear_name)730 void Cityset::clearRazedCitiesImage (bool clear_name)
731 {
732   if (clear_name)
733     setRazedCitiesFilename ("");
734 
735   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
736     {
737       PixMask *p = getRazedCityImage (i);
738       delete p;
739       setRazedCityImage (i, NULL);
740     }
741 }
742 
instantiateRazedCityImages()743 bool Cityset::instantiateRazedCityImages ()
744 {
745   clearRazedCitiesImage (false);
746   bool broken = false;
747   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
748   if (broken)
749     return broken;
750   Glib::ustring imgname = getRazedCitiesFilename();
751   if (imgname.empty() == false)
752     {
753       Glib::ustring filename = t.getFile(imgname, broken);
754       if (!broken)
755         {
756           std::vector<PixMask* > pics;
757           pics = disassemble_row(filename, MAX_PLAYERS, broken);
758           if (!broken)
759             {
760               for (unsigned int i = 0; i < MAX_PLAYERS; i++)
761                 setRazedCityImage(i, pics[i]);
762             }
763         }
764     }
765   return broken;
766 }
767 
clearPortImage(bool clear_name)768 void Cityset::clearPortImage (bool clear_name)
769 {
770   if (clear_name)
771     setPortFilename ("");
772 
773   PixMask *p = getPortImage ();
774   if (p)
775     delete p;
776   setPortImage (NULL);
777 }
778 
instantiatePortImage()779 bool Cityset::instantiatePortImage ()
780 {
781   clearPortImage (false);
782   bool broken = false;
783   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
784   if (broken)
785     return broken;
786   Glib::ustring imgname = getPortFilename();
787   if (imgname.empty() == false)
788     {
789       Glib::ustring filename = t.getFile(imgname, broken);
790       if (!broken)
791         setPortImage (PixMask::create(filename, broken));
792     }
793   return broken;
794 }
795 
clearSignpostImage(bool clear_name)796 void Cityset::clearSignpostImage (bool clear_name)
797 {
798   if (clear_name)
799     setSignpostFilename ("");
800 
801   PixMask *p = getSignpostImage ();
802   if (p)
803     delete p;
804   setSignpostImage (NULL);
805 }
806 
instantiateSignpostImage()807 bool Cityset::instantiateSignpostImage ()
808 {
809   clearSignpostImage (false);
810   bool broken = false;
811   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
812   if (broken)
813     return broken;
814   Glib::ustring imgname = getSignpostFilename();
815   if (imgname.empty() == false)
816     {
817       Glib::ustring filename = t.getFile(imgname, broken);
818       if (!broken)
819         setSignpostImage (PixMask::create(filename, broken));
820     }
821   return broken;
822 }
823 
clearRuinsImage(bool clear_name)824 void Cityset::clearRuinsImage (bool clear_name)
825 {
826   if (clear_name)
827     setRuinsFilename ("");
828 
829   for (unsigned int i = 0; i < RUIN_TYPES; i++)
830     {
831       PixMask *p = getRuinImage (i);
832       delete p;
833       setRuinImage (i, NULL);
834     }
835 }
836 
instantiateRuinImages()837 bool Cityset::instantiateRuinImages ()
838 {
839   clearRuinsImage (false);
840   bool broken = false;
841   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
842   if (broken)
843     return broken;
844   Glib::ustring imgname = getRuinsFilename();
845   if (imgname.empty() == false)
846     {
847       Glib::ustring filename = t.getFile(imgname, broken);
848       if (!broken)
849         {
850           std::vector<PixMask* > pics =
851             disassemble_row(filename, RUIN_TYPES, broken);
852           if (!broken)
853             {
854               for (unsigned int i = 0; i < RUIN_TYPES ; i++)
855                 setRuinImage(i, pics[i]);
856             }
857         }
858     }
859   return broken;
860 }
861 
clearTemplesImage(bool clear_name)862 void Cityset::clearTemplesImage (bool clear_name)
863 {
864   if (clear_name)
865     setTemplesFilename ("");
866 
867   for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
868     {
869       PixMask *p = getTempleImage (i);
870       delete p;
871       setTempleImage (i, NULL);
872     }
873 }
874 
instantiateTempleImages()875 bool Cityset::instantiateTempleImages ()
876 {
877   clearTemplesImage (false);
878   bool broken = false;
879   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
880   if (broken)
881     return broken;
882   Glib::ustring imgname = getTemplesFilename();
883   if (imgname.empty() == false)
884     {
885       Glib::ustring filename = t.getFile(imgname, broken);
886       if (!broken)
887         {
888           std::vector<PixMask* > pics;
889           pics = disassemble_row(filename, TEMPLE_TYPES, broken);
890           if (!broken)
891             {
892               for (unsigned int i = 0; i < TEMPLE_TYPES ; i++)
893                 setTempleImage(i, pics[i]);
894             }
895         }
896     }
897   return broken;
898 }
899 
clearTowersImage(bool clear_name)900 void Cityset::clearTowersImage (bool clear_name)
901 {
902   if (clear_name)
903     setTowersFilename ("");
904 
905   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
906     {
907       PixMask *p = getTowerImage (i);
908       delete p;
909       setTowerImage (i, NULL);
910     }
911 }
912 
instantiateTowerImages()913 bool Cityset::instantiateTowerImages ()
914 {
915   clearTowersImage (false);
916   bool broken = false;
917   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
918   if (broken)
919     return broken;
920   Glib::ustring imgname = getTowersFilename();
921   if (imgname.empty() == false)
922     {
923       Glib::ustring filename = t.getFile(imgname, broken);
924       if (!broken)
925         {
926           std::vector<PixMask* > pics =
927             disassemble_row(filename, MAX_PLAYERS, broken);
928           if (!broken)
929             {
930               for (unsigned int i = 0; i < MAX_PLAYERS; i++)
931                 setTowerImage(i, pics[i]);
932             }
933         }
934     }
935   return broken;
936 }
937 
get_default_tile_size()938 guint32 Cityset::get_default_tile_size ()
939 {
940   Cityset *c = new Cityset (1, "");
941   guint32 ts = c->getUnscaledTileSize ();
942   delete c;
943   return ts;
944 }
945 
uninstantiateSameNamedImages(Glib::ustring name)946 void Cityset::uninstantiateSameNamedImages (Glib::ustring name)
947 {
948   if (getCitiesFilename() == name)
949     clearCitiesImage ();
950   if (getRazedCitiesFilename() == name)
951     clearRazedCitiesImage ();
952   if (getPortFilename() == name)
953     clearPortImage ();
954   if (getSignpostFilename() == name)
955     clearSignpostImage ();
956   if (getRuinsFilename() == name)
957     clearRuinsImage ();
958   if (getTemplesFilename() == name)
959     clearTemplesImage ();
960   if (getTowersFilename() == name)
961     clearTowersImage ();
962 }
963 // End of file
964