← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/elk_moose into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/elk_moose into lp:widelands.

Commit message:
Rename "elk" to "moose" and add map compatibility code

- Add support for critter renamings depending on packet version to WorldLegacyLookupTable
- New map version property "needs_widelands_version_after" for the website

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1833662 in widelands: "Better handling of 'This map requires widelands Version >x'"
  https://bugs.launchpad.net/widelands/+bug/1833662

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/elk_moose/+merge/369201
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/elk_moose into lp:widelands.
=== renamed directory 'data/world/critters/elk' => 'data/world/critters/moose'
=== modified file 'data/world/critters/moose/init.lua'
--- data/world/critters/elk/init.lua	2019-04-21 14:57:55 +0000
+++ data/world/critters/moose/init.lua	2019-06-22 11:17:12 +0000
@@ -15,8 +15,8 @@
 add_directional_animation(animations, "walk", dirname, "walk", {21, 34}, 20)
 
 world:new_critter_type{
-   name = "elk",
-   descname = _ "Elk",
+   name = "moose",
+   descname = _ "Moose",
    editor_category = "critters_herbivores",
    attributes = { "eatable" },
    programs = {

=== modified file 'data/world/init.lua'
--- data/world/init.lua	2017-09-03 10:56:44 +0000
+++ data/world/init.lua	2019-06-22 11:17:12 +0000
@@ -288,7 +288,7 @@
       include "world/critters/deer/init.lua"
       include "world/critters/reindeer/init.lua"
       include "world/critters/stag/init.lua"
-      include "world/critters/elk/init.lua"
+      include "world/critters/moose/init.lua"
 
       -- Carnivores
       world:new_editor_critter_category {

=== modified file 'data/world/map_generation.lua'
--- data/world/map_generation.lua	2017-02-12 09:10:57 +0000
+++ data/world/map_generation.lua	2019-06-22 11:17:12 +0000
@@ -77,17 +77,17 @@
             "alder_summer_old", "birch_summer_old", "beech_summer_old",
             "larch_summer_old", "rowan_summer_old"
          },
-         critters = { "brownbear", "chamois", "elk", "lynx", "reindeer", "stag", "wildboar", "wolf" },
+         critters = { "brownbear", "chamois", "moose", "lynx", "reindeer", "stag", "wildboar", "wolf" },
       },
       {
          name = "bushes",
          immovables = { "bush1", "bush2", "bush3", "bush4", "bush5" },
-         critters = { "bunny", "elk", "fox", "lynx", "marten", "sheep", "sheep", "wildboar", "wisent", "wolf", "wolf" },
+         critters = { "bunny", "moose", "fox", "lynx", "marten", "sheep", "sheep", "wildboar", "wisent", "wolf", "wolf" },
       },
       {
          name = "grasses",
          immovables = { "grass1", "grass2", "grass3" },
-         critters = { "bunny", "elk", "fox", "lynx", "marten", "sheep", "sheep", "wolf" },
+         critters = { "bunny", "moose", "fox", "lynx", "marten", "sheep", "sheep", "wolf" },
       },
       {
          name = "standing_stones",
@@ -614,13 +614,13 @@
             "birch_summer_old", "beech_summer_old",
             "larch_summer_old", "rowan_summer_old",
          },
-         critters = { "deer", "elk", "lynx", "reindeer", "wolf" },
+         critters = { "deer", "moose", "lynx", "reindeer", "wolf" },
       },
       {
          name = "bushes",
          immovables = { "bush1", "bush2", "bush3", "bush4", "bush5" },
          critters = {
-            "wisent", "wolf", "bunny", "elk", "fox", "lynx",
+            "wisent", "wolf", "bunny", "moose", "fox", "lynx",
             "wolf", "marten", "sheep"
          },
       },
@@ -628,7 +628,7 @@
          name = "grasses",
          immovables = { "grass1", "grass2", "grass3" },
          critters = {
-            "wisent", "wolf", "bunny", "elk", "fox", "lynx",
+            "wisent", "wolf", "bunny", "moose", "fox", "lynx",
             "wolf", "marten", "sheep"
          },
       },

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2019-05-16 09:15:03 +0000
+++ src/logic/map.cc	2019-06-22 11:17:12 +0000
@@ -714,6 +714,22 @@
 	pathfieldmgr_->set_size(field_size);
 }
 
+int Map::needs_widelands_version_after() const {
+	return map_version_.needs_widelands_version_after;
+}
+
+void Map::calculate_needs_widelands_version_after(bool is_post_one_world) {
+	if (map_version_.needs_widelands_version_after == 0) {
+		if (nrplayers_ > 8) {
+			// We introduced support for 16 payers after Build 19
+			map_version_.needs_widelands_version_after = 19;
+		} else if (is_post_one_world) {
+			// We merged the worlds in the engine after Build 18
+			map_version_.needs_widelands_version_after = 18;
+		}
+	}
+}
+
 /*
  * The scenario get/set functions
  */

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2019-05-16 09:15:03 +0000
+++ src/logic/map.h	2019-06-22 11:17:12 +0000
@@ -289,6 +289,9 @@
 		return height_;
 	}
 
+	// Map compatibility information for the website
+	int needs_widelands_version_after() const;
+
 	//  The next few functions are only valid when the map is loaded as a
 	//  scenario.
 	const std::string& get_scenario_player_tribe(PlayerNumber) const;
@@ -518,6 +521,10 @@
 	std::map<Coords, FieldData>
 	resize(EditorGameBase& egbase, const Coords coords, int32_t w, int32_t h);
 
+protected:
+	// Calculate map compatibility information for the website if it wasn't defined in the map packet
+	void calculate_needs_widelands_version_after(bool is_post_one_world);
+
 private:
 	void recalc_border(const FCoords&);
 	void recalc_brightness(const FCoords&);

=== modified file 'src/logic/map_objects/world/critter.cc'
--- src/logic/map_objects/world/critter.cc	2019-05-25 08:51:42 +0000
+++ src/logic/map_objects/world/critter.cc	2019-06-22 11:17:12 +0000
@@ -268,7 +268,8 @@
 ==============================
 */
 
-constexpr uint8_t kCurrentPacketVersion = 1;
+// We need to bump this packet version every time we rename a critter, so that the world legacy lookup table will work.
+constexpr uint8_t kCurrentPacketVersion = 2;
 
 Critter::Loader::Loader() {
 }
@@ -303,7 +304,7 @@
 			const CritterDescr* descr = nullptr;
 
 			if (critter_owner == "world") {
-				critter_name = lookup_table.lookup_critter(critter_name);
+				critter_name = lookup_table.lookup_critter(critter_name, packet_version);
 				descr = egbase.world().get_critter_descr(critter_name);
 			} else {
 				throw GameDataError(

=== modified file 'src/logic/map_revision.h'
--- src/logic/map_revision.h	2019-02-23 11:00:49 +0000
+++ src/logic/map_revision.h	2019-06-22 11:17:12 +0000
@@ -37,6 +37,8 @@
 	int32_t map_version_major;
 	int32_t map_version_minor;
 	uint32_t map_version_timestamp;
+	// Map compatibility information for the website
+	int needs_widelands_version_after;
 
 	MapVersion();
 };

=== modified file 'src/map_io/map_bob_packet.cc'
--- src/map_io/map_bob_packet.cc	2019-02-23 11:00:49 +0000
+++ src/map_io/map_bob_packet.cc	2019-06-22 11:17:12 +0000
@@ -36,7 +36,7 @@
                             EditorGameBase& egbase,
                             MapObjectLoader&,
                             const Coords& coords,
-                            const WorldLegacyLookupTable& lookup_table) {
+                            const WorldLegacyLookupTable& lookup_table, uint16_t packet_version) {
 	const std::string owner = fr.c_string();
 	char const* const read_name = fr.c_string();
 	uint8_t subtype = fr.unsigned_8();
@@ -47,7 +47,7 @@
 		throw GameDataError("unknown legacy bob %s/%s", owner.c_str(), read_name);
 	}
 
-	const std::string name = lookup_table.lookup_critter(read_name);
+	const std::string name = lookup_table.lookup_critter(read_name, packet_version);
 	try {
 		const World& world = egbase.world();
 		DescriptionIndex const idx = world.get_critter(name.c_str());
@@ -84,7 +84,7 @@
 				for (uint16_t x = 0; x < map->get_width(); ++x) {
 					uint32_t const nr_bobs = fr.unsigned_32();
 					for (uint32_t i = 0; i < nr_bobs; ++i)
-						read_bob(fr, egbase, mol, Coords(x, y), lookup_table);
+						read_bob(fr, egbase, mol, Coords(x, y), lookup_table, packet_version);
 				}
 			}
 		else {

=== modified file 'src/map_io/map_bob_packet.h'
--- src/map_io/map_bob_packet.h	2019-02-23 11:00:49 +0000
+++ src/map_io/map_bob_packet.h	2019-06-22 11:17:12 +0000
@@ -42,7 +42,7 @@
 	              EditorGameBase&,
 	              MapObjectLoader&,
 	              const Coords&,
-	              const WorldLegacyLookupTable& lookup_table);
+	              const WorldLegacyLookupTable& lookup_table, uint16_t packet_version);
 };
 }  // namespace Widelands
 

=== modified file 'src/map_io/map_saver.cc'
--- src/map_io/map_saver.cc	2019-03-09 10:01:09 +0000
+++ src/map_io/map_saver.cc	2019-06-22 11:17:12 +0000
@@ -156,7 +156,7 @@
 	log("Writing Map Version ... ");
 	{
 		MapVersionPacket p;
-		p.write(fs_, egbase_, *mos_);
+		p.write(fs_, egbase_);
 	}
 	log("took %ums\n ", timer.ms_since_last_query());
 

=== modified file 'src/map_io/map_version_packet.cc'
--- src/map_io/map_version_packet.cc	2019-02-23 11:00:49 +0000
+++ src/map_io/map_version_packet.cc	2019-06-22 11:17:12 +0000
@@ -30,11 +30,17 @@
 namespace Widelands {
 
 constexpr uint16_t kCurrentPacketVersion = 1;
+// Map compatibility information for the website
+constexpr int kCurrentNeedsWidelandsVersionAfter = 20;
 
 void MapVersionPacket::read(FileSystem& fs,
                             EditorGameBase& egbase,
-                            bool const skip,
-                            MapObjectLoader&) {
+                            bool const skip, bool is_post_one_world) {
+
+	pre_read(fs, egbase.mutable_map(), skip, is_post_one_world);
+}
+
+void MapVersionPacket::pre_read(FileSystem& fs, Map* map, bool skip, bool is_post_one_world) {
 	if (skip)
 		return;
 
@@ -42,7 +48,6 @@
 	try {
 		prof.read("version", nullptr, fs);
 	} catch (...) {
-		Map* map = egbase.mutable_map();
 		map->map_version_.map_version_timestamp = 0;
 		map->map_version_.map_creator_version = "unknown";
 		return;
@@ -55,7 +60,6 @@
 		if ((packet_version == kCurrentPacketVersion) ||
 		    (packet_version > kCurrentPacketVersion &&
 		     forward_compatibility <= kCurrentPacketVersion)) {
-			Map* map = egbase.mutable_map();
 			map->map_version_.map_source_url = globv.get_safe_string("map_source_url");
 			map->map_version_.map_source_release = globv.get_safe_string("map_release");
 			map->map_version_.map_creator_version = globv.get_safe_string("map_creator_version");
@@ -63,6 +67,8 @@
 			map->map_version_.map_version_minor = globv.get_safe_int("map_version_minor");
 			uint32_t ts = static_cast<uint32_t>(globv.get_safe_int("map_version_timestamp"));
 			map->map_version_.map_version_timestamp = ts;
+			map->map_version_.needs_widelands_version_after = globv.get_int("needs_widelands_version_after", 0);
+			map->calculate_needs_widelands_version_after(is_post_one_world);
 		} else {
 			throw UnhandledVersionError("MapVersionPacket", packet_version, kCurrentPacketVersion);
 		}
@@ -71,7 +77,7 @@
 	}
 }
 
-void MapVersionPacket::write(FileSystem& fs, EditorGameBase& egbase, MapObjectSaver&) {
+void MapVersionPacket::write(FileSystem& fs, EditorGameBase& egbase) {
 	Profile prof;
 	Section& globs = prof.create_section("global");
 
@@ -117,6 +123,7 @@
 	globs.set_int("map_version_timestamp", static_cast<uint32_t>(time(nullptr)));
 	globs.set_int("packet_version", kCurrentPacketVersion);
 	globs.set_int("packet_compatibility", kCurrentPacketVersion);
+	globs.set_int("needs_widelands_version_after", kCurrentNeedsWidelandsVersionAfter);
 
 	prof.write("version", false, fs);
 }

=== modified file 'src/map_io/map_version_packet.h'
--- src/map_io/map_version_packet.h	2019-02-23 11:00:49 +0000
+++ src/map_io/map_version_packet.h	2019-06-22 11:17:12 +0000
@@ -20,11 +20,26 @@
 #ifndef WL_MAP_IO_MAP_VERSION_PACKET_H
 #define WL_MAP_IO_MAP_VERSION_PACKET_H
 
-#include "map_io/map_data_packet.h"
+class FileSystem;
+
+namespace Widelands {
+
+class EditorGameBase;
+class Map;
+class MapObjectLoader;
+struct MapObjectSaver;
 
 /*
  * This packet contains the version information of the map.
  */
-MAP_DATA_PACKET(MapVersionPacket)
+class MapVersionPacket {
+public:
+	void read(FileSystem&, EditorGameBase&, bool skip, bool is_post_one_world);
+	void write(FileSystem&, EditorGameBase&);
+
+	void pre_read(FileSystem&, Map*, bool skip, bool is_post_one_world);
+};
+
+} // namespace Widelands
 
 #endif  // end of include guard: WL_MAP_IO_MAP_VERSION_PACKET_H

=== modified file 'src/map_io/widelands_map_loader.cc'
--- src/map_io/widelands_map_loader.cc	2019-05-26 03:14:41 +0000
+++ src/map_io/widelands_map_loader.cc	2019-06-22 11:17:12 +0000
@@ -82,6 +82,10 @@
 		mp.pre_read(*fs_, &map_);
 		old_world_name_ = mp.old_world_name();
 	}
+	{
+		MapVersionPacket version_packet;
+		version_packet.pre_read(*fs_, &map_, false, old_world_name_.empty());
+	}
 
 	{
 		MapPlayerNamesAndTribesPacket p;
@@ -198,7 +202,7 @@
 		log("Reading Map Version Data ... ");
 		{
 			MapVersionPacket p;
-			p.read(*fs_, egbase, is_game, *mol_);
+			p.read(*fs_, egbase, is_game, old_world_name_.empty());
 		}
 		log("took %ums\n ", timer.ms_since_last_query());
 

=== modified file 'src/map_io/world_legacy_lookup_table.cc'
--- src/map_io/world_legacy_lookup_table.cc	2019-02-23 11:00:49 +0000
+++ src/map_io/world_legacy_lookup_table.cc	2019-06-22 11:17:12 +0000
@@ -33,16 +33,24 @@
 	// Implements OneWorldLegacyLookupTable.
 	std::string lookup_resource(const std::string& resource) const override;
 	std::string lookup_terrain(const std::string& terrain) const override;
-	std::string lookup_critter(const std::string& critter) const override;
+	std::string lookup_critter(const std::string& critter, uint16_t packet_version) const override;
 	std::string lookup_immovable(const std::string& immovable) const override;
 
 private:
+	// Old name, <packet version when it got changed, new name>
+	const std::map<std::string, std::map<uint16_t, std::string>> critters_;
 	const std::map<std::string, std::string> immovables_;
 	const std::map<std::string, std::string> resources_;
 	const std::map<std::string, std::string> terrains_;
 };
 
 PostOneWorldLegacyLookupTable::PostOneWorldLegacyLookupTable() :
+critters_
+{
+	// We need to bump the packet version in Critter every time we rename a critter.
+	// Also, don't forget to edit the OneWorldLegacyLookupTable! You can look up which world had which units in Build 18.
+	{"elk", {{2, "moose"}}},
+},
 immovables_
 {
 	{"blackland_stones1", "blackland_rocks1"},
@@ -113,8 +121,16 @@
 	return i->second;
 }
 
-std::string PostOneWorldLegacyLookupTable::lookup_critter(const std::string& critter) const {
-	return critter;
+std::string PostOneWorldLegacyLookupTable::lookup_critter(const std::string& critter, uint16_t packet_version) const {
+	std::string result = critter;
+	if (critters_.count(critter) == 1) {
+		for (const auto& candidate : critters_.at(result)) {
+			if (candidate.first >= packet_version) {
+				result = candidate.second;
+			}
+		}
+	}
+	return result;
 }
 
 std::string PostOneWorldLegacyLookupTable::lookup_immovable(const std::string& immovable) const {
@@ -132,7 +148,7 @@
 	// Implements OneWorldLegacyLookupTable.
 	std::string lookup_resource(const std::string& resource) const override;
 	std::string lookup_terrain(const std::string& terrain) const override;
-	std::string lookup_critter(const std::string& critter) const override;
+	std::string lookup_critter(const std::string& critter, uint16_t packet_version) const override;
 	std::string lookup_immovable(const std::string& immovable) const override;
 
 private:
@@ -205,6 +221,7 @@
         std::make_pair("greenland",
                        std::map<std::string, std::string>{
                           {"deer", "stag"},
+								  {"elk", "moose"},
                        }),
         std::make_pair("blackland",
                        std::map<std::string, std::string>{
@@ -213,6 +230,7 @@
         std::make_pair("winterland",
                        std::map<std::string, std::string>{
                           {"deer", "stag"},
+								  {"elk", "moose"},
                        }),
         std::make_pair("desert",
                        std::map<std::string, std::string>{
@@ -418,7 +436,7 @@
 	return terrain;
 }
 
-std::string OneWorldLegacyLookupTable::lookup_critter(const std::string& critter) const {
+std::string OneWorldLegacyLookupTable::lookup_critter(const std::string& critter, uint16_t) const {
 	const std::map<std::string, std::string>& world_critters = critters_.at(old_world_name_);
 	const auto& i = world_critters.find(critter);
 	if (i != world_critters.end()) {

=== modified file 'src/map_io/world_legacy_lookup_table.h'
--- src/map_io/world_legacy_lookup_table.h	2019-02-23 11:00:49 +0000
+++ src/map_io/world_legacy_lookup_table.h	2019-06-22 11:17:12 +0000
@@ -38,7 +38,7 @@
 	virtual std::string lookup_terrain(const std::string& terrain) const = 0;
 
 	/// Looks up the new name for the 'critter'.
-	virtual std::string lookup_critter(const std::string& critter) const = 0;
+	virtual std::string lookup_critter(const std::string& critter, uint16_t packet_version) const = 0;
 
 	/// Looks up the new name for the 'immovable'.
 	virtual std::string lookup_immovable(const std::string& immovable) const = 0;

=== modified file 'src/website/map_info.cc'
--- src/website/map_info.cc	2019-02-23 11:00:49 +0000
+++ src/website/map_info.cc	2019-06-22 11:17:12 +0000
@@ -92,6 +92,7 @@
 			json->add_int("width", map->get_width());
 			json->add_int("height", map->get_height());
 			json->add_int("nr_players", map->get_nrplayers());
+			json->add_int("needs_widelands_version_after", map->needs_widelands_version_after());
 
 			const std::string world_name =
 			   static_cast<Widelands::WidelandsMapLoader*>(ml.get())->old_world_name();


Follow ups