2
* Copyright (C) 2002, 2004 by the Widelands Development Team
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
#include "constants.h"
23
#include "filesystem.h"
26
#include "wexception.h"
28
#include "worlddata.h"
36
=============================================================================
40
=============================================================================
47
Parse a resource description section.
50
void Resource_Descr::parse(Section *s, std::string basedir)
56
m_descrname = s->get_string("name", s->get_name());
57
m_is_detectable=s->get_bool("detectable", true);
59
m_max_amount = s->get_safe_int("max_amount");
60
while(s->get_next_string("editor_pic", &string))
62
std::vector<std::string> args;
65
split_string(string, &args, " \t");
67
if (args.size() != 1 && args.size() != 2)
69
log("Resource '%s' has bad editor_pic=%s\n", m_name.c_str(), string);
73
i.picname = basedir + "/pics/";
81
i.upperlimit = strtol(args[1].c_str(), &endp, 0);
85
log("Resource '%s' has bad editor_pic=%s\n", m_name.c_str(), string);
90
m_editor_pics.push_back(i);
92
if(!m_editor_pics.size())
93
throw wexception("Resource '%s' has no editor_pic", m_name.c_str());
98
* Get the correct editor pic for this amount of this resource
100
std::string Resource_Descr::get_editor_pic(uint amount) {
103
assert(m_editor_pics.size());
105
for(uint i = 1; i < m_editor_pics.size(); ++i)
107
int diff1 = m_editor_pics[bestmatch].upperlimit - (int)amount;
108
int diff2 = m_editor_pics[i].upperlimit - (int)amount;
110
// This is a catch-all for high amounts
111
if (m_editor_pics[i].upperlimit < 0)
121
// This is lower than the actual amount
124
if (m_editor_pics[bestmatch].upperlimit < 0)
128
bestmatch = i; // still better than previous best match
135
// This is higher than the actual amount
136
if (m_editor_pics[bestmatch].upperlimit < 0 || diff1 > diff2 || diff1 < 0) {
142
// noLog("Resource(%s): Editor_Pic '%s' for amount = %u\n",
143
// m_name.c_str(), m_editor_pics[bestmatch].picname.c_str(), amount);
145
return m_editor_pics[bestmatch].picname;
150
=============================================================================
154
=============================================================================
157
World::World(const char* name)
163
snprintf(directory, sizeof(directory), "worlds/%s", name);
164
m_basedir = directory;
166
parse_root_conf(name);
171
catch(std::exception &e)
173
// tag with world name
174
throw wexception("Error loading world %s: %s", name, e.what());
188
Load all logic game data now
191
void World::postload(Editor_Game_Base* g)
193
// TODO: move more loads to postload
201
Load graphics data here
204
void World::load_graphics()
208
// Load terrain graphics
209
for(i = 0; i < ters.get_nitems(); i++)
210
ters.get(i)->load_graphics();
212
// TODO: load more graphics
217
// down here: Private functions for loading
221
// read the <world-directory>/conf
223
void World::parse_root_conf(const char *name)
227
snprintf(fname, sizeof(fname), "%s/conf", m_basedir.c_str());
234
s = prof.get_safe_section("world");
238
str = s->get_string("name", name);
239
snprintf(hd.name, sizeof(hd.name), "%s", str);
241
str = s->get_safe_string("author");
242
snprintf(hd.author, sizeof(hd.author), "%s", str);
244
str = s->get_safe_string("descr");
245
snprintf(hd.descr, sizeof(hd.descr), "%s", str);
249
catch(std::exception &e) {
250
throw wexception("%s: %s", fname, e.what());
254
void World::parse_resources()
258
snprintf(fname, sizeof(fname), "%s/resconf", m_basedir.c_str());
265
Resource_Descr* descr;
266
while((section=prof.get_next_section(0))) {
267
descr=new Resource_Descr();
268
descr->parse(section,m_basedir);
269
m_resources.add(descr);
272
catch(std::exception &e) {
273
throw wexception("%s: %s", fname, e.what());
277
void World::parse_terrains()
281
snprintf(fname, sizeof(fname), "%s/terrainconf", m_basedir.c_str());
288
while((s = prof.get_next_section(0)))
290
Terrain_Descr *ter = new Terrain_Descr(m_basedir.c_str(), s, &m_resources);
296
catch(std::exception &e) {
297
throw wexception("%s: %s", fname, e.what());
301
void World::parse_bobs()
306
snprintf(subdir, sizeof(subdir), "%s/bobs", m_basedir.c_str());
308
g_fs->FindFiles(subdir, "*", &dirs);
310
for(filenameset_t::iterator it = dirs.begin(); it != dirs.end(); it++) {
313
snprintf(fname, sizeof(fname), "%s/conf", it->c_str());
315
if (!g_fs->FileExists(fname))
319
const char *slash = strrchr(it->c_str(), '/');
320
const char *backslash = strrchr(it->c_str(), '\\');
322
if (backslash && (!slash || backslash > slash))
332
Profile prof(fname, "global"); // section-less file
333
Section *s = prof.get_safe_section("global");
334
const char *type = s->get_safe_string("type");
336
if (!strcasecmp(type, "critter")) {
338
descr = Bob_Descr::create_from_dir(name, it->c_str(), &prof, 0);
341
Immovable_Descr *descr = new Immovable_Descr(name, 0);
342
descr->parse(it->c_str(), &prof);
343
immovables.add(descr);
345
} catch(std::exception &e) {
346
cerr << it->c_str() << ": " << e.what() << " (garbage directory?)" << endl;
348
cerr << it->c_str() << ": unknown exception (garbage directory?)" << endl;
354
* World::exists_world()
356
bool World::exists_world(std::string worldname) {
358
buf="worlds/" + worldname + "/conf";;
361
return f.TryOpen(g_fs, buf.c_str());
365
* World::get_all_worlds()
367
void World::get_all_worlds(std::vector<std::string>* retval) {
371
filenameset_t m_worlds;
372
g_fs->FindFiles("worlds", "*", &m_worlds);
373
for(filenameset_t::iterator pname = m_worlds.begin(); pname != m_worlds.end(); pname++) {
374
std::string world=*pname;
375
world.erase(0,7); // remove worlds/
376
if(World::exists_world(world.c_str()))
377
retval->push_back(world);
383
==============================================================================
387
==============================================================================
390
Terrain_Descr::Terrain_Descr(const char* directory, Section* s, Descr_Maintainer<Resource_Descr>* resources)
396
m_frametime = FRAME_LENGTH;
398
m_valid_resources = 0;
399
m_nr_valid_resources = 0;
400
m_default_resources=-1;
403
// Read configuration
404
snprintf(m_name, sizeof(m_name), "%s", s->get_name());
406
// Parse the default resource
407
str = s->get_string("def_resources", 0);
409
std::istringstream str1(str);
410
std::string resource;
412
str1 >> resource >> amount;
413
int res=resources->get_index(resource.c_str());;
415
throw wexception("Terrain %s has valid resource %s which doesn't exist in world!\n", s->get_name(), resource.c_str());
416
m_default_resources=res;
417
m_default_amount=amount;
420
// Parse valid resources
421
std::string str1=s->get_string("resources", "");
425
while(i < str1.size()) { if(str1[i]==',') { nres++; } i++; }
427
m_nr_valid_resources=nres;
429
m_valid_resources=new uchar;
431
m_valid_resources=new uchar[nres];
435
while(i<=str1.size()) {
436
if(str1[i] == ' ' || str1[i] == ' ' || str1[i]=='\t') { ++i; continue; }
437
if(str1[i]==',' || i==str1.size()) {
438
int res=resources->get_index(curres.c_str());;
440
throw wexception("Terrain %s has valid resource %s which doesn't exist in world!\n", s->get_name(), curres.c_str());
441
m_valid_resources[cur_res++]=res;
444
curres.append(1, str1[i]);
450
int fps = s->get_int("fps");
452
m_frametime = 1000 / fps;
455
str = s->get_safe_string("is");
457
if(!strcasecmp(str, "dry")) {
459
} else if(!strcasecmp(str, "green")) {
461
} else if(!strcasecmp(str, "water")) {
462
m_is = TERRAIN_WATER|TERRAIN_DRY|TERRAIN_UNPASSABLE;
463
} else if(!strcasecmp(str, "acid")) {
464
m_is = TERRAIN_ACID|TERRAIN_DRY|TERRAIN_UNPASSABLE;
465
} else if(!strcasecmp(str, "mountain")) {
466
m_is = TERRAIN_DRY|TERRAIN_MOUNTAIN;
467
} else if(!strcasecmp(str, "dead")) {
468
m_is = TERRAIN_DRY|TERRAIN_UNPASSABLE|TERRAIN_ACID;
469
} else if(!strcasecmp(str, "unpassable")) {
470
m_is = TERRAIN_DRY|TERRAIN_UNPASSABLE;
472
throw wexception("%s: invalid type '%s'", m_name, str);
474
// Determine template of the texture animation pictures
477
str = s->get_string("texture", 0);
479
snprintf(fnametmpl, sizeof(fnametmpl), "%s/%s", directory, str);
481
snprintf(fnametmpl, sizeof(fnametmpl), "%s/pics/%s_??.png", directory, m_name);
483
m_picnametempl = strdup(fnametmpl);
486
Terrain_Descr::~Terrain_Descr()
489
free(m_picnametempl);
490
if(m_nr_valid_resources==1) {
491
delete m_valid_resources;
493
if(m_nr_valid_resources>1) {
494
delete[] m_valid_resources;
496
m_nr_valid_resources=0;
503
Terrain_Descr::load_graphics
505
Trigger load of the actual animation frames.
508
void Terrain_Descr::load_graphics()
511
m_texture = g_gr->get_maptexture(m_picnametempl, m_frametime);