1 /*
2  * Copyright (C) 2002-2020 by the Widelands Development Team
3  *
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.
8  *
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.
13  *
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  *
18  */
19 
20 #include "logic/map_objects/world/world.h"
21 
22 #include <memory>
23 
24 #include "base/i18n.h"
25 #include "graphic/graphic.h"
26 #include "graphic/image_io.h"
27 #include "logic/game_data_error.h"
28 #include "logic/map_objects/immovable.h"
29 #include "logic/map_objects/world/critter.h"
30 #include "logic/map_objects/world/editor_category.h"
31 #include "logic/map_objects/world/resource_description.h"
32 #include "logic/map_objects/world/terrain_description.h"
33 #include "scripting/lua_table.h"
34 
35 namespace Widelands {
36 
World()37 World::World()
38    : critters_(new DescriptionMaintainer<CritterDescr>()),
39      immovables_(new DescriptionMaintainer<ImmovableDescr>()),
40      terrains_(new DescriptionMaintainer<TerrainDescription>()),
41      resources_(new DescriptionMaintainer<ResourceDescription>()),
42      editor_terrain_categories_(new DescriptionMaintainer<EditorCategory>()),
43      editor_critter_categories_(new DescriptionMaintainer<EditorCategory>()),
44      editor_immovable_categories_(new DescriptionMaintainer<EditorCategory>()) {
45 }
46 
~World()47 World::~World() {
48 }
49 
load_graphics()50 void World::load_graphics() {
51 	for (size_t i = 0; i < terrains_->size(); ++i) {
52 		TerrainDescription* terrain = terrains_->get_mutable(i);
53 		for (size_t j = 0; j < terrain->texture_paths().size(); ++j) {
54 			// Set the minimap color on the first loaded image.
55 			if (j == 0) {
56 				SDL_Surface* sdl_surface = load_image_as_sdl_surface(terrain->texture_paths()[j]);
57 				uint8_t top_left_pixel = static_cast<uint8_t*>(sdl_surface->pixels)[0];
58 				const SDL_Color top_left_pixel_color =
59 				   sdl_surface->format->palette->colors[top_left_pixel];
60 				terrain->set_minimap_color(
61 				   RGBColor(top_left_pixel_color.r, top_left_pixel_color.g, top_left_pixel_color.b));
62 				SDL_FreeSurface(sdl_surface);
63 			}
64 			terrain->add_texture(g_gr->images().get(terrain->texture_paths()[j]));
65 		}
66 	}
67 }
68 
postload()69 void World::postload() {
70 	const DescriptionIndex nr_t = get_nr_terrains();
71 	for (size_t i = 0; i < nr_t; ++i) {
72 		const TerrainDescription& t = terrain_descr(i);
73 		if (!t.enhancement().empty()) {
74 			if (!terrain_descr(t.enhancement())) {
75 				throw GameDataError(
76 				   "Terrain %s: Unknown enhancement %s", t.name().c_str(), t.enhancement().c_str());
77 			}
78 		}
79 	}
80 }
81 
terrains() const82 const DescriptionMaintainer<TerrainDescription>& World::terrains() const {
83 	return *terrains_;
84 }
85 
add_resource_type(const LuaTable & table)86 void World::add_resource_type(const LuaTable& table) {
87 	resources_->add(new ResourceDescription(table));
88 }
89 
add_terrain_type(const LuaTable & table)90 void World::add_terrain_type(const LuaTable& table) {
91 	terrains_->add(new TerrainDescription(table, *this));
92 }
93 
add_critter_type(const LuaTable & table)94 void World::add_critter_type(const LuaTable& table) {
95 	i18n::Textdomain td("world");
96 	critters_->add(new CritterDescr(_(table.get_string("descname")), table, *this));
97 }
98 
immovables() const99 const DescriptionMaintainer<ImmovableDescr>& World::immovables() const {
100 	return *immovables_;
101 }
102 
add_immovable_type(const LuaTable & table)103 void World::add_immovable_type(const LuaTable& table) {
104 	i18n::Textdomain td("world");
105 	immovables_->add(new ImmovableDescr(_(table.get_string("descname")), table, *this));
106 }
107 
add_editor_terrain_category(const LuaTable & table)108 void World::add_editor_terrain_category(const LuaTable& table) {
109 	editor_terrain_categories_->add(new EditorCategory(table));
110 }
111 
editor_terrain_categories() const112 const DescriptionMaintainer<EditorCategory>& World::editor_terrain_categories() const {
113 	return *editor_terrain_categories_;
114 }
115 
add_editor_critter_category(const LuaTable & table)116 void World::add_editor_critter_category(const LuaTable& table) {
117 	editor_critter_categories_->add(new EditorCategory(table));
118 }
119 
editor_critter_categories() const120 const DescriptionMaintainer<EditorCategory>& World::editor_critter_categories() const {
121 	return *editor_critter_categories_;
122 }
123 
add_editor_immovable_category(const LuaTable & table)124 void World::add_editor_immovable_category(const LuaTable& table) {
125 	editor_immovable_categories_->add(new EditorCategory(table));
126 }
127 
editor_immovable_categories() const128 const DescriptionMaintainer<EditorCategory>& World::editor_immovable_categories() const {
129 	return *editor_immovable_categories_;
130 }
131 
safe_resource_index(const char * const resourcename) const132 DescriptionIndex World::safe_resource_index(const char* const resourcename) const {
133 	DescriptionIndex const result = resource_index(resourcename);
134 
135 	if (result == INVALID_INDEX)
136 		throw GameDataError("world does not define resource type \"%s\"", resourcename);
137 	return result;
138 }
139 
terrain_descr(DescriptionIndex const i) const140 TerrainDescription& World::terrain_descr(DescriptionIndex const i) const {
141 	return *terrains_->get_mutable(i);
142 }
143 
terrain_descr(const std::string & name) const144 const TerrainDescription* World::terrain_descr(const std::string& name) const {
145 	DescriptionIndex const i = terrains_->get_index(name);
146 	return i != INVALID_INDEX ? terrains_->get_mutable(i) : nullptr;
147 }
148 
get_terrain_index(const std::string & name) const149 DescriptionIndex World::get_terrain_index(const std::string& name) const {
150 	return terrains_->get_index(name);
151 }
152 
get_nr_terrains() const153 DescriptionIndex World::get_nr_terrains() const {
154 	return terrains_->size();
155 }
156 
get_critter(char const * const l) const157 DescriptionIndex World::get_critter(char const* const l) const {
158 	return critters_->get_index(l);
159 }
160 
critters() const161 const DescriptionMaintainer<CritterDescr>& World::critters() const {
162 	return *critters_;
163 }
164 
get_critter_descr(DescriptionIndex index) const165 CritterDescr const* World::get_critter_descr(DescriptionIndex index) const {
166 	return critters_->get_mutable(index);
167 }
168 
get_critter_descr(const std::string & name) const169 CritterDescr const* World::get_critter_descr(const std::string& name) const {
170 	return critters_->exists(name.c_str());
171 }
172 
get_immovable_index(const std::string & name) const173 DescriptionIndex World::get_immovable_index(const std::string& name) const {
174 	return immovables_->get_index(name);
175 }
176 
get_nr_immovables() const177 DescriptionIndex World::get_nr_immovables() const {
178 	return immovables_->size();
179 }
180 
get_immovable_descr(DescriptionIndex const index) const181 ImmovableDescr const* World::get_immovable_descr(DescriptionIndex const index) const {
182 	return immovables_->get_mutable(index);
183 }
184 
resource_index(const char * const name) const185 DescriptionIndex World::resource_index(const char* const name) const {
186 	return strcmp(name, "none") ? resources_->get_index(name) : Widelands::kNoResource;
187 }
188 
189 /***
190  * @return The ResourceDescription for the given index. Returns Nullptr for kNoResource.
191  */
get_resource(DescriptionIndex const res) const192 ResourceDescription const* World::get_resource(DescriptionIndex const res) const {
193 	assert(res < resources_->size() || res == Widelands::kNoResource);
194 	return resources_->get_mutable(res);
195 }
196 
get_nr_resources() const197 DescriptionIndex World::get_nr_resources() const {
198 	return resources_->size();
199 }
200 
201 }  // namespace Widelands
202