1 // Copyright 2015-2017 the openage authors. See copying.md for legal info. 2 3 #pragma once 4 5 #include "../job/job.h" 6 #include "../gamedata/gamedata.gen.h" 7 #include "../gamedata/graphic.gen.h" 8 #include "../terrain/terrain.h" 9 #include "../unit/unit_texture.h" 10 #include "../util/csv.h" 11 12 #include <unordered_map> 13 #include <memory> 14 #include <QObject> 15 16 17 namespace openage { 18 19 class AssetManager; 20 class GameSpec; 21 class UnitType; 22 class UnitTypeMeta; 23 class Player; 24 25 26 /** 27 * the key type mapped to data objects 28 */ 29 using index_t = int; 30 31 32 /** 33 * could use unique ptr 34 */ 35 using unit_type_list = std::vector<std::shared_ptr<UnitType>>; 36 using unit_meta_list = std::vector<std::shared_ptr<UnitTypeMeta>>; 37 38 39 /** 40 * simple sound object 41 * TODO: move to assetmanager 42 */ 43 class Sound { 44 public: Sound(GameSpec * spec,std::vector<int> && sound_items)45 Sound(GameSpec *spec, std::vector<int> &&sound_items) 46 : 47 sound_items{sound_items}, 48 game_spec{spec} {} 49 50 void play() const; 51 52 std::vector<int> sound_items; 53 54 GameSpec *game_spec; 55 }; 56 57 58 /** 59 * GameSpec gives a collection of all game elements 60 * this currently includes unit types and terrain types 61 * This provides a system which can easily allow game modding 62 * 63 * uses the AssetManager to gather 64 * graphic data, composite textures and sounds. 65 * 66 * all types are sorted and stored by id values, 67 * each data object is referenced by a type and id pair 68 * 69 * dealing directly with files done by asset manager 70 * TODO: should the audio loading should be moved there? 71 */ 72 class GameSpec { 73 public: 74 GameSpec(AssetManager *am); 75 virtual ~GameSpec(); 76 77 /** 78 * perform the main loading job. 79 * this loads all the data into the storage. 80 */ 81 bool initialize(); 82 83 /** 84 * Check if loading has been completed, 85 * a load percent would be nice 86 */ 87 bool load_complete() const; 88 89 /** 90 * return data used for constructing terrain objects 91 */ 92 terrain_meta *get_terrain_meta(); 93 94 /** 95 * reverse lookup of slp 96 */ 97 index_t get_slp_graphic(index_t slp); 98 99 /** 100 * lookup using a texture id, this specifically avoids returning the missing placeholder texture 101 */ 102 Texture *get_texture(index_t graphic_id) const; 103 104 /** 105 * lookup using a texture file name 106 */ 107 Texture *get_texture(const std::string &file_name, bool use_metafile=true) const; 108 109 /** 110 * get unit texture by graphic id -- this is an directional texture 111 * which also includes graphic deltas 112 */ 113 std::shared_ptr<UnitTexture> get_unit_texture(index_t graphic_id) const; 114 115 /** 116 * get sound by sound id 117 */ 118 const Sound *get_sound(index_t sound_id) const; 119 120 /** 121 * gamedata for a graphic 122 * nyan will have to replace this somehow 123 */ 124 const gamedata::graphic *get_graphic_data(index_t grp_id) const; 125 126 /** 127 * get available commands for a unit id 128 * nyan will have to replace this somehow 129 */ 130 std::vector<const gamedata::unit_command *> get_command_data(index_t unit_id) const; 131 132 /** 133 * returns the name of a civ by index 134 */ 135 std::string get_civ_name(int civ_id) const; 136 137 /** 138 * makes initial unit types for a particular civ id 139 */ 140 void create_unit_types(unit_meta_list &objects, int civ_id) const; 141 142 /** 143 * Return the asset manager used for loading resources 144 * of this game specification. 145 */ 146 AssetManager *get_asset_manager() const; 147 148 private: 149 /** 150 * check graphic id is valid 151 */ 152 bool valid_graphic_id(index_t) const; 153 154 /** 155 * create unit abilities from game data 156 */ 157 void create_abilities(const gamedata::empiresdat &gamedata); 158 159 /** 160 * loads required assets to construct a buildings. 161 * adds to the type list if the object can be created safely. 162 */ 163 void load_building(const gamedata::building_unit &, unit_meta_list &) const; 164 165 /** 166 * loads assets for living things. 167 */ 168 void load_living(const gamedata::living_unit &, unit_meta_list &) const; 169 170 /** 171 * load assets for other game objects (not building and living). 172 */ 173 void load_object(const gamedata::unit_object &, unit_meta_list &) const; 174 175 /** 176 * load missile assets. 177 */ 178 void load_missile(const gamedata::missile_unit &, unit_meta_list &) const; 179 180 /** 181 * fill in the terrain_data attribute of this 182 */ 183 void load_terrain(const gamedata::empiresdat &gamedata); 184 185 /** 186 * Invoked when the gamedata has been loaded. 187 */ 188 void on_gamedata_loaded(const gamedata::empiresdat &gamedata); 189 190 /** 191 * Asset management entity that is responsible for textures, sounds, etc. 192 */ 193 AssetManager *assetmanager; 194 195 /** 196 * The full original gamedata tree. 197 */ 198 std::vector<gamedata::empiresdat> gamedata; 199 200 /** 201 * data used for constructing terrain objects 202 */ 203 terrain_meta terrain_data; 204 205 /** 206 * slp to graphic id reverse lookup 207 */ 208 std::unordered_map<index_t, index_t> slp_to_graphic; 209 210 /** 211 * map graphic id to gamedata graphic. 212 */ 213 std::unordered_map<index_t, const gamedata::graphic *> graphics; 214 215 /** 216 * commands available for each unit id 217 */ 218 std::unordered_map<index_t, std::vector<const gamedata::unit_command *>> commands; 219 220 /** 221 * graphic ids -> unit texture for that id 222 */ 223 std::unordered_map<index_t, std::shared_ptr<UnitTexture>> unit_textures; 224 225 /** 226 * sound ids mapped to playable sounds for all available sounds. 227 */ 228 std::unordered_map<index_t, Sound> available_sounds; 229 230 /** 231 * has game data been load yet 232 */ 233 bool gamedata_loaded; 234 }; 235 236 } // openage 237 238 namespace qtsdl { 239 class GuiItemLink; 240 } // qtsdl 241 242 namespace openage { 243 244 class GameSpecSignals; 245 246 /** 247 * Game specification instanciated in QML. 248 * Linked to the "GameSpec" QML type. 249 * 250 * Wraps the "GameSpec" C++ class from above. 251 */ 252 class GameSpecHandle { 253 public: 254 explicit GameSpecHandle(qtsdl::GuiItemLink *gui_link); 255 256 /** 257 * Control whether this specification can be loaded (=true) 258 * or will not be loaded (=false). 259 */ 260 void set_active(bool active); 261 262 /** 263 * invoked from qml when the asset_manager member is set. 264 */ 265 void set_asset_manager(AssetManager *asset_manager); 266 267 /** 268 * Return if the specification was fully loaded. 269 */ 270 bool is_ready() const; 271 272 /** 273 * forget everything about the specification and 274 * reload it with `start_loading_if_needed`. 275 */ 276 void invalidate(); 277 278 /** 279 * signal about a loaded spec if any 280 */ 281 void announce_spec(); 282 283 /** 284 * Return the contained game specification. 285 */ 286 std::shared_ptr<GameSpec> get_spec(); 287 288 private: 289 /** 290 * load the game specification if not already present. 291 */ 292 void start_loading_if_needed(); 293 294 /** 295 * Actually dispatch the loading job to the job manager. 296 */ 297 void start_load_job(); 298 299 /** 300 * called from the job manager when the loading job finished. 301 */ 302 void on_loaded(job::result_function_t<bool> result); 303 304 /** 305 * The real game specification. 306 */ 307 std::shared_ptr<GameSpec> spec; 308 309 /** 310 * enables the loading of the game specification. 311 */ 312 bool active; 313 314 AssetManager *asset_manager; 315 316 public: 317 std::shared_ptr<GameSpecSignals> gui_signals; 318 qtsdl::GuiItemLink *gui_link; 319 }; 320 321 class GameSpecSignals : public QObject { 322 Q_OBJECT 323 324 public: 325 signals: 326 /* 327 * Some load job has finished. 328 * 329 * To be sure that the latest result is used, do the verification at the point of use. 330 */ 331 void load_job_finished(); 332 333 void game_spec_loaded(std::shared_ptr<GameSpec> loaded_game_spec); 334 }; 335 336 } 337