GunChleoc has proposed merging lp:~widelands-dev/widelands/map_object_info into lp:widelands.
Commit message: Created a new executable that will generate JSON files for updating the encyclopedia on the website. Requested reviews: GunChleoc (gunchleoc) kaputtnik (franku): testing Related bugs: Bug #350465 in widelands: "online_help returns false information" https://bugs.launchpad.net/widelands/+bug/350465 Bug #1324015 in widelands: "Rework wares encyclopedia" https://bugs.launchpad.net/widelands/+bug/1324015 For more details, see: https://code.launchpad.net/~widelands-dev/widelands/map_object_info/+merge/287409 Created a new executable that will generate JSON files for updating the encyclopedia on the website. I recommend that we wait with merging this when we get close to the release candidate, because we now have extra linking time with each compile. Related website branch: https://code.launchpad.net/~widelands-dev/widelands-website/encyclopedia -- Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/map_object_info.
=== added directory 'data/tribes/scripting/mapobject_info' === added file 'data/tribes/scripting/mapobject_info/building_helptext.lua' --- data/tribes/scripting/mapobject_info/building_helptext.lua 1970-01-01 00:00:00 +0000 +++ data/tribes/scripting/mapobject_info/building_helptext.lua 2016-05-14 07:36:19 +0000 @@ -0,0 +1,9 @@ +-- This is used by the mapinfo standalone executable to get buildings' helptexts. +-- Note that this can't handle localization properly. + +return { + func = function(helptext_script) + include(helptext_script) + return building_helptext_purpose() + end +} === added file 'data/tribes/scripting/mapobject_info/ware_helptext.lua' --- data/tribes/scripting/mapobject_info/ware_helptext.lua 1970-01-01 00:00:00 +0000 +++ data/tribes/scripting/mapobject_info/ware_helptext.lua 2016-05-14 07:36:19 +0000 @@ -0,0 +1,9 @@ +-- This is used by the mapinfo standalone executable to get wares' helptexts. +-- Note that this can't handle localization properly. + +return { + func = function(tribename, helptext_script) + include(helptext_script) + return ware_helptext(tribename) + end +} === added file 'data/tribes/scripting/mapobject_info/worker_helptext.lua' --- data/tribes/scripting/mapobject_info/worker_helptext.lua 1970-01-01 00:00:00 +0000 +++ data/tribes/scripting/mapobject_info/worker_helptext.lua 2016-05-14 07:36:19 +0000 @@ -0,0 +1,9 @@ +-- This is used by the mapinfo standalone executable to get workers' helptexts. +-- Note that this can't handle localization properly. + +return { + func = function(helptext_script) + include(helptext_script) + return worker_helptext() + end +} === modified file 'debian/widelands.install' --- debian/widelands.install 2016-01-22 07:20:01 +0000 +++ debian/widelands.install 2016-05-14 07:36:19 +0000 @@ -1,5 +1,6 @@ usr/widelands usr/games usr/wl_map_info usr/games +usr/wl_mapobject_info usr/games usr/wl_render_richtext usr/games usr/share/applications usr/share/icons === modified file 'src/CMakeLists.txt' --- src/CMakeLists.txt 2016-02-06 11:11:24 +0000 +++ src/CMakeLists.txt 2016-05-14 07:36:19 +0000 @@ -82,6 +82,7 @@ add_subdirectory(third_party) add_subdirectory(ui_basic) add_subdirectory(ui_fsmenu) +add_subdirectory(website) add_subdirectory(wui) # TODO(unknown): Ideally widelands_ball_of_mud shouldn't exist, everything should be in a === modified file 'src/logic/CMakeLists.txt' --- src/logic/CMakeLists.txt 2016-03-19 15:49:51 +0000 +++ src/logic/CMakeLists.txt 2016-05-14 07:36:19 +0000 @@ -1,19 +1,3 @@ -wl_binary(wl_map_info - SRCS - map_info.cc - USES_SDL2 - DEPENDS - base_log - graphic - graphic_image_io - graphic_minimap_renderer - graphic_surface - io_fileread - io_filesystem - logic - map_io_map_loader -) - wl_library(logic_widelands_geometry SRCS widelands_geometry.cc === modified file 'src/logic/map_objects/immovable.cc' --- src/logic/map_objects/immovable.cc 2016-03-21 05:45:29 +0000 +++ src/logic/map_objects/immovable.cc 2016-05-14 07:36:19 +0000 @@ -58,9 +58,11 @@ namespace Widelands { -namespace { +BaseImmovable::BaseImmovable(const MapObjectDescr & mo_descr) : +MapObject(&mo_descr) +{} -BaseImmovable::Size string_to_size(const std::string& size) { +int32_t BaseImmovable::string_to_size(const std::string& size) { if (size == "none") return BaseImmovable::NONE; if (size == "small") @@ -72,13 +74,20 @@ throw GameDataError("Unknown size %s.", size.c_str()); } -} // namespace - - -BaseImmovable::BaseImmovable(const MapObjectDescr & mo_descr) : -MapObject(&mo_descr) -{} - +std::string BaseImmovable::size_to_string(int32_t size) { + switch (size) { + case BaseImmovable::NONE: + return "none"; + case BaseImmovable::SMALL: + return "small"; + case BaseImmovable::MEDIUM: + return "medium"; + case BaseImmovable::BIG: + return "big"; + default: + NEVER_HERE(); + } +} static std::string const base_immovable_name = "unknown"; @@ -203,7 +212,7 @@ } if (table.has_key("size")) { - size_ = string_to_size(table.get_string("size")); + size_ = BaseImmovable::string_to_size(table.get_string("size")); } if (table.has_key("terrain_affinity")) { === modified file 'src/logic/map_objects/immovable.h' --- src/logic/map_objects/immovable.h 2016-03-19 09:58:41 +0000 +++ src/logic/map_objects/immovable.h 2016-05-14 07:36:19 +0000 @@ -96,6 +96,9 @@ (const EditorGameBase &, RenderTarget &, const FCoords&, const Point&) = 0; + static int32_t string_to_size(const std::string& size); + static std::string size_to_string(int32_t size); + protected: void set_position(EditorGameBase &, Coords); void unset_position(EditorGameBase &, Coords); === modified file 'src/scripting/lua_map.cc' --- src/scripting/lua_map.cc 2016-04-23 09:31:28 +0000 +++ src/scripting/lua_map.cc 2016-05-14 07:36:19 +0000 @@ -1562,20 +1562,9 @@ * :const:`big` -- Example: Big sized buildings or rocks */ int LuaImmovableDescription::get_size(lua_State * L) { - switch (get()->get_size()) { - case BaseImmovable::NONE: - lua_pushstring(L, "none"); - break; - case BaseImmovable::SMALL: - lua_pushstring(L, "small"); - break; - case BaseImmovable::MEDIUM: - lua_pushstring(L, "medium"); - break; - case BaseImmovable::BIG: - lua_pushstring(L, "big"); - break; - default: + try { + lua_pushstring(L, BaseImmovable::size_to_string(get()->get_size())); + } catch (std::exception&) { report_error(L, "Unknown size %i in LuaImmovableDescription::get_size: %s", get()->get_size(), get()->name().c_str()); } @@ -1821,17 +1810,9 @@ * :const:`big` -- Big sized buildings */ int LuaBuildingDescription::get_size(lua_State * L) { - switch (get()->get_size()) { - case BaseImmovable::SMALL: - lua_pushstring(L, "small"); - break; - case BaseImmovable::MEDIUM: - lua_pushstring(L, "medium"); - break; - case BaseImmovable::BIG: - lua_pushstring(L, "big"); - break; - default: + try { + lua_pushstring(L, BaseImmovable::size_to_string(get()->get_size())); + } catch (std::exception&) { report_error(L, "Unknown size %i in LuaBuildingDescription::get_size: %s", get()->get_size(), get()->name().c_str()); } === added directory 'src/website' === added file 'src/website/CMakeLists.txt' --- src/website/CMakeLists.txt 1970-01-01 00:00:00 +0000 +++ src/website/CMakeLists.txt 2016-05-14 07:36:19 +0000 @@ -0,0 +1,30 @@ +wl_binary(wl_map_info + SRCS + map_info.cc + USES_SDL2 + DEPENDS + base_log + graphic + graphic_image_io + graphic_minimap_renderer + graphic_surface + io_fileread + io_filesystem + logic + map_io_map_loader +) + +wl_binary(wl_map_object_info + SRCS + map_object_info.cc + USES_SDL2 + DEPENDS + base_i18n + base_log + base_macros + graphic + io_fileread + io_filesystem + logic + sound +) === renamed file 'src/logic/map_info.cc' => 'src/website/map_info.cc' === added file 'src/website/map_object_info.cc' --- src/website/map_object_info.cc 1970-01-01 00:00:00 +0000 +++ src/website/map_object_info.cc 2016-05-14 07:36:19 +0000 @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2016 by the Widelands Development Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <memory> + +#include <SDL.h> +#include <boost/algorithm/string.hpp> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> + +#include "base/i18n.h" +#include "base/log.h" +#include "base/macros.h" +#include "config.h" +#include "graphic/graphic.h" +#include "io/filesystem/filesystem.h" +#include "io/filesystem/layered_filesystem.h" +#include "io/filewrite.h" +#include "logic/editor_game_base.h" +#include "logic/map_objects/tribes/tribes.h" +#include "logic/map_objects/world/world.h" +#include "sound/sound_handler.h" + +using namespace Widelands; + +namespace { + +/* + ========================================================== + SETUP + ========================================================== + */ + + +// Setup the static objects Widelands needs to operate and initializes systems. +void initialize(const std::string& output_path) { + i18n::set_locale("en"); + + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + throw wexception("Unable to initialize SDL: %s", SDL_GetError()); + } + + g_fs = new LayeredFileSystem(); + g_fs->add_file_system(&FileSystem::create(INSTALL_DATADIR)); + + FileSystem* out_filesystem = &FileSystem::create(output_path); + g_fs->add_file_system(out_filesystem); + + // We don't really need graphics or sound here, but we will get error messages + // when they aren't initialized + g_gr = new Graphic(); + g_gr->initialize(Graphic::TraceGl::kNo, 1, 1, false); + + g_sound_handler.init(); + g_sound_handler.nosound_ = true; +} + +/* + ========================================================== + SPECIALIZED FILEWRITE + ========================================================== + */ + +// Defines some convenience writing functions for the JSON format +class JSONFileWrite : public FileWrite { +public: + JSONFileWrite() : FileWrite(), level_(0) {} + + void write_string(const std::string& s, bool use_indent = false) { + std::string writeme = s; + if (use_indent) { + for (int i = 0; i < level_; ++i) { + writeme = (boost::format(" %s") % writeme).str(); + } + } + data(writeme.c_str(), writeme.size()); + } + void write_key(const std::string& key) { + write_string((boost::format("\"%s\":\n") % key).str(), true); + } + void write_value_string(const std::string& quoted_value) { + write_string((boost::format("\"%s\"") % quoted_value).str(), true); + } + void write_key_value(const std::string& key, const std::string& quoted_value) { + write_string((boost::format("\"%s\": %s") % key % quoted_value).str(), true); + } + void write_key_value_string(const std::string& key, const std::string& value) { + std::string quoted_value = value; + boost::replace_all(quoted_value, "\"", "\\\""); + write_key_value(key, "\"" + value + "\""); + } + void write_key_value_int(const std::string& key, const int value) { + write_key_value(key, boost::lexical_cast<std::string>(value)); + } + void open_brace() { + write_string("{\n", true); + ++level_; + } + // JSON hates a final comma. This defaults to having NO comma. + void close_brace(bool precede_newline = false, int current = 0, int total = 0) { + --level_; + if (precede_newline) { + write_string("\n"); + } + if (current < total - 1) { + write_string("},\n", true); + } else { + write_string("}", true); + } + } + void open_array(const std::string& name) { + write_string((boost::format("\"%s\":[\n") % name).str(), true); + ++level_; + } + // JSON hates a final comma. This defaults to having NO comma. + void close_array(int current = 0, int total = 0) { + --level_; + write_string("\n"); + if (current < total - 1) { + write_string("],\n", true); + } else { + write_string("]\n", true); + } + } + // JSON hates a final comma. This defaults to having a comma. + void close_element(int current = -2, int total = 0) { + if (current < total - 1) { + write_string(",\n"); + } + } +private: + int level_; +}; + +/* + ========================================================== + BUILDINGS + ========================================================== + */ + +void write_buildings(const TribeDescr& tribe, EditorGameBase& egbase, const std::string& output_path) { + + log("\n==================\nWriting buildings:\n==================\n"); + JSONFileWrite fw; + fw.open_brace(); // Main + fw.open_array("buildings"); // Buildings + + // We don't want any partially finished buildings + std::vector<const BuildingDescr*> buildings; + for (const DescriptionIndex& index : tribe.buildings()) { + const BuildingDescr* building = tribe.get_building_descr(index); + if (building->type() != MapObjectType::CONSTRUCTIONSITE && + building->type() != MapObjectType::DISMANTLESITE) { + buildings.push_back(building); + } + } + + // Now write + for (size_t i = 0; i < buildings.size(); ++i) { + const BuildingDescr& building = *buildings[i]; + log(" %s", building.name().c_str()); + fw.open_brace(); // Building + + fw.write_key_value_string("name", building.name()); + fw.close_element(); + fw.write_key_value_string("descname", building.descname()); + fw.close_element(); + fw.write_key_value_string("icon", building.representative_image_filename()); + fw.close_element(); + + // Conditional stuff in between, so we won't run into trouble with the commas. + + // Buildcost + if (building.is_buildable()) { + fw.open_array("buildcost"); // Buildcost + size_t buildcost_counter = 0; + for (WareAmount buildcost : building.buildcost()) { + const WareDescr& ware = *tribe.get_ware_descr(buildcost.first); + fw.open_brace(); // Buildcost + fw.write_key_value_string("name", ware.name()); + fw.close_element(); + fw.write_key_value_int("amount", buildcost.second); + fw.close_brace(true, buildcost_counter, building.buildcost().size()); // Buildcost + ++buildcost_counter; + } + fw.close_array(1, 5); // Buildcost - we need a comma + } + + if (building.is_enhanced()) { + fw.write_key_value_string("enhanced", tribe.get_building_descr(building.enhanced_from())->name()); + fw.close_element(); + } + + if (building.enhancement() != INVALID_INDEX) { + fw.write_key_value_string("enhancement", tribe.get_building_descr(building.enhancement())->name()); + fw.close_element(); + } + + if (upcast(ProductionSiteDescr const, productionsite, &building)) { + // Produces + if (productionsite->output_ware_types().size() > 0) { + fw.open_array("produced_wares"); // Produces + size_t produces_counter = 0; + for (DescriptionIndex ware_index : productionsite->output_ware_types()) { + fw.write_value_string(tribe.get_ware_descr(ware_index)->name()); + fw.close_element(produces_counter, productionsite->output_ware_types().size()); + ++produces_counter; + } + fw.close_array(1, 5); // Produces - we need a comma + } + if (productionsite->output_worker_types().size() > 0) { + fw.open_array("produced_workers"); // Produces + size_t produces_counter = 0; + for (DescriptionIndex worker_index : productionsite->output_worker_types()) { + fw.write_value_string(tribe.get_worker_descr(worker_index)->name()); + fw.close_element(produces_counter, productionsite->output_worker_types().size()); + ++produces_counter; + } + fw.close_array(1, 5); // Produces - we need a comma + } + + // Consumes + if (productionsite->inputs().size() > 0) { + fw.open_array("stored_wares"); // Consumes + size_t consumes_counter = 0; + for (WareAmount input : productionsite->inputs()) { + const WareDescr& ware = *tribe.get_ware_descr(input.first); + fw.open_brace(); // Input + fw.write_key_value_string("name", ware.name()); + fw.close_element(); + fw.write_key_value_int("amount", input.second); + fw.close_brace(true, consumes_counter, productionsite->inputs().size()); // Input + ++consumes_counter; + } + fw.close_array(1, 5); // Consumes - we need a comma + } + + fw.open_array("workers"); // Workers + size_t worker_counter = 0; + for (WareAmount input : productionsite->working_positions()) { + const WorkerDescr& worker = *tribe.get_worker_descr(input.first); + fw.open_brace(); // Worker + fw.write_key_value_string("name", worker.name()); + fw.close_element(); + fw.write_key_value_int("amount", input.second); + fw.close_brace(true, worker_counter, productionsite->working_positions().size()); // Worker + ++worker_counter; + } + fw.close_array(1, 5); // Workers - we need a comma + } else if (upcast(MilitarySiteDescr const, militarysite, &building)) { + fw.write_key_value_int("conquers", militarysite->get_conquers()); + fw.close_element(); + fw.write_key_value_int("max_soldiers", militarysite->get_max_number_of_soldiers()); + fw.close_element(); + fw.write_key_value_int("heal_per_second", militarysite->get_heal_per_second()); + fw.close_element(); + } + + switch (building.type()) { + case MapObjectType::PRODUCTIONSITE: + fw.write_key_value_string("type", "productionsite"); + break; + case MapObjectType::WAREHOUSE: + fw.write_key_value_string("type", "warehouse"); + break; + case MapObjectType::MILITARYSITE: + fw.write_key_value_string("type", "militarysite"); + break; + case MapObjectType::TRAININGSITE: + fw.write_key_value_string("type", "trainingsite"); + break; + default: + NEVER_HERE(); + } + fw.close_element(); + + // Size + if (building.type() == MapObjectType::WAREHOUSE && + !building.is_buildable() && !building.is_enhanced()) { + fw.write_key_value_string("size", "headquarters"); + } else if (building.get_ismine()) { + fw.write_key_value_string("size", "mine"); + } else if (building.get_isport()) { + fw.write_key_value_string("size", "port"); + } else { + fw.write_key_value_string("size", BaseImmovable::size_to_string(building.get_size())); + } + fw.close_element(); + + // Helptext + try { + std::unique_ptr<LuaTable> table( + egbase.lua().run_script("tribes/scripting/mapobject_info/building_helptext.lua")); + std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func")); + cr->push_arg(building.helptext_script()); + cr->resume(); + const std::string help_text = cr->pop_string(); + fw.write_key_value_string("helptext", help_text); + } catch (LuaError& err) { + fw.write_key_value_string("helptext", err.what()); + } + + fw.close_brace(true, i, buildings.size()); // Building + } + fw.close_array(); // Buildings + fw.close_brace(); // Main + fw.write(*g_fs, (boost::format("%s/%s_buildings.json") % output_path % tribe.name()).str().c_str()); + log("\n"); +} + +/* + ========================================================== + WARES + ========================================================== + */ + +void write_wares(const TribeDescr& tribe, EditorGameBase& egbase, const std::string& output_path) { + log("\n===============\nWriting wares:\n===============\n"); + JSONFileWrite fw; + fw.open_brace(); // Main + + fw.open_array("wares"); // Wares + size_t counter = 0; + const size_t no_of_wares = tribe.wares().size(); + for (DescriptionIndex ware_index : tribe.wares()) { + const WareDescr& ware = *tribe.get_ware_descr(ware_index); + log(" %s", ware.name().c_str()); + fw.open_brace(); + fw.write_key_value_string("name", ware.name()); + fw.close_element(); + fw.write_key_value_string("descname", ware.descname()); + fw.close_element(); + fw.write_key_value_string("icon", ware.icon_filename()); + fw.close_element(); + + // Helptext + try { + std::unique_ptr<LuaTable> table( + egbase.lua().run_script("tribes/scripting/mapobject_info/ware_helptext.lua")); + std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func")); + cr->push_arg(tribe.name()); + cr->push_arg(ware.helptext_script()); + cr->resume(); + const std::string help_text = cr->pop_string(); + fw.write_key_value_string("helptext", help_text); + } catch (LuaError& err) { + fw.write_key_value_string("helptext", err.what()); + } + fw.close_brace(true, counter, no_of_wares); // Ware + ++counter; + } + fw.close_array(); // Wares + + fw.close_brace(); // Main + fw.write(*g_fs, (boost::format("%s/%s_wares.json") % output_path % tribe.name()).str().c_str()); + log("\n"); +} + +/* + ========================================================== + WORKERS + ========================================================== + */ + +void write_workers(const TribeDescr& tribe, EditorGameBase& egbase, const std::string& output_path) { + log("\n================\nWriting workers:\n================\n"); + JSONFileWrite fw; + fw.open_brace(); // Main + + fw.open_array("workers"); // Workers + size_t counter = 0; + const size_t no_of_workers = tribe.workers().size(); + for (DescriptionIndex worker_index : tribe.workers()) { + const WorkerDescr& worker = *tribe.get_worker_descr(worker_index); + log(" %s", worker.name().c_str()); + fw.open_brace(); + fw.write_key_value_string("name", worker.name()); + fw.close_element(); + fw.write_key_value_string("descname", worker.descname()); + fw.close_element(); + fw.write_key_value_string("icon", worker.icon_filename()); + fw.close_element(); + + // Helptext + try { + std::unique_ptr<LuaTable> table( + egbase.lua().run_script("tribes/scripting/mapobject_info/worker_helptext.lua")); + std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func")); + cr->push_arg(worker.helptext_script()); + cr->resume(); + const std::string help_text = cr->pop_string(); + fw.write_key_value_string("helptext", help_text); + } catch (LuaError& err) { + fw.write_key_value_string("helptext", err.what()); + } + + if (worker.becomes() != INVALID_INDEX) { + fw.close_element(); + const WorkerDescr& becomes = *tribe.get_worker_descr(worker.becomes()); + fw.write_key("becomes"); + fw.open_brace(); + fw.write_key_value_string("name", becomes.name()); + fw.close_element(); + fw.write_key_value_int("experience", worker.get_needed_experience()); + fw.close_brace(true); + } + fw.close_brace(true, counter, no_of_workers); // Worker + ++counter; + } + fw.close_array(); // Workers + + fw.close_brace(); // Main + fw.write(*g_fs, (boost::format("%s/%s_workers.json") % output_path % tribe.name()).str().c_str()); + log("\n"); +} + +/* + ========================================================== + TRIBES + ========================================================== + */ + +void add_tribe_info(const TribeBasicInfo& tribe_info, JSONFileWrite* fw) { + fw->write_key_value_string("name", tribe_info.name); + fw->close_element(); + fw->write_key_value_string("descname", tribe_info.descname); + fw->close_element(); + fw->write_key_value_string("author", tribe_info.author); + fw->close_element(); + fw->write_key_value_string("tooltip", tribe_info.tooltip); + fw->close_element(); + fw->write_key_value_string("icon", tribe_info.icon); +} + +void write_tribes(EditorGameBase& egbase, const std::string& output_path) { + JSONFileWrite fw; + fw.open_brace(); // Main + fw.open_array("tribes"); // Tribes + + /// Tribes + egbase.mutable_tribes()->postload(); // Make sure that all values have been set. + const Tribes& tribes = egbase.tribes(); + + std::vector<TribeBasicInfo> tribeinfos = tribes.get_all_tribeinfos(); + for (size_t tribe_index = 0; tribe_index < tribeinfos.size(); ++tribe_index) { + const TribeBasicInfo& tribe_info = tribeinfos[tribe_index]; + log("\n\n=========================\nWriting tribe: %s\n=========================\n", + tribe_info.name.c_str()); + + fw.open_brace(); // TribeDescr + add_tribe_info(tribe_info, &fw); + fw.close_brace(true, tribe_index, tribeinfos.size()); // TribeDescr + + // These go in separate files + + JSONFileWrite fw_tribe; + fw_tribe.open_brace(); // TribeDescr + add_tribe_info(tribe_info, &fw_tribe); + fw_tribe.close_brace(true); // TribeDescr + fw_tribe.write(*g_fs, + (boost::format("%s/tribe_%s.json") % output_path % tribe_info.name).str().c_str()); + + const TribeDescr& tribe = + *tribes.get_tribe_descr(tribes.tribe_index(tribe_info.name)); + + write_buildings(tribe, egbase, output_path); + write_wares(tribe, egbase, output_path); + write_workers(tribe, egbase, output_path); + } + fw.close_array(); // Tribes + fw.close_brace(); // Main + fw.write(*g_fs, (boost::format("%s/tribes.json") % output_path).str().c_str()); +} + +} // namespace + +/* + ========================================================== + MAIN + ========================================================== + */ + +int main(int argc, char ** argv) +{ + if (!(2 <= argc && argc <= 3)) { + log("Usage: %s <existing-absolute-output-path>\n", argv[0]); + return 1; + } + + const std::string output_path = argv[argc - 1]; + + try { + initialize(output_path); + EditorGameBase egbase(nullptr); + write_tribes(egbase, output_path); + } + catch (std::exception& e) { + log("Exception: %s.\n", e.what()); + g_sound_handler.shutdown(); + return 1; + } + g_sound_handler.shutdown(); + return 0; +} === added file 'utils/validate_json.py' --- utils/validate_json.py 1970-01-01 00:00:00 +0000 +++ utils/validate_json.py 2016-05-14 07:36:19 +0000 @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import codecs +import json +import os.path +import sys + +# Tests if the .json files in the directories on the bottom are valid JSON files + +def validate_files_in_path(source_path): + + if (not os.path.isdir(source_path)): + print("Error: Path " + source_path + " not found.") + sys.exit(1) + + source_files = sorted(os.listdir(source_path), key=str.lower) + + print("Reading JSON files in:\n " + source_path) + failed = 0 + for source_filename in source_files: + file_path = source_path + "/" + source_filename + if source_filename.endswith(".json"): + source_file = open(file_path, "r") + try: + dataset = json.load(source_file) + except ValueError as err: + failed = failed + 1 + print("\n Error reading " + source_filename + ":"); + print(" " + str(err)) + + if failed == 0: + print("\nAll JSON files are OK.") + else: + if failed == 1: + print("\n" + str(failed) + " file is not valid JSON!"); + else: + print("\n" + str(failed) + " files are not valid JSON!"); + return failed < 1 + +sucess = False + +if (len(sys.argv) == 2): + base_path = os.path.normpath(sys.argv[1]) + if (not os.path.exists(base_path) or os.path.isfile(base_path)): + base_path = os.path.abspath(os.path.join(os.path.dirname(__file__),os.path.pardir),base_path) + + if (os.path.exists(base_path) and not os.path.isfile(base_path)): + success = validate_files_in_path(os.path.normpath(base_path)) + +if success: + sys.exit(0) +else: + sys.exit(1)
_______________________________________________ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp