浏览代码

Map Zone parsing optimizations

aleos 1 年之前
父节点
当前提交
34065e4ca6
共有 4 个文件被更改,包括 176 次插入106 次删除
  1. 5 0
      doc/map_zones.txt
  2. 6 1
      src/common/utilities.hpp
  3. 160 31
      src/map/map.cpp
  4. 5 74
      src/map/map.hpp

+ 5 - 0
doc/map_zones.txt

@@ -16,12 +16,14 @@ Id: Zone ID (constant). These are defined in e_map_type::clif.hpp.
 ---------------------------------------
 
 DisabledCommands: @commands can be disabled for players below a certain group level.
+Setting the group level to 0 will remove from the DisabledCommands list. Useful for imports.
 
   heal: 70 # Makes @heal usable only to those group level 70 and above.
 
 ---------------------------------------
 
 DisabledSkills: Skills can be disabled for different game object types below a certain group level.
+Setting the group level to 0 will remove from the DisabledSkills list. Useful for imports.
 
 Object Types:
 Pc   - Player
@@ -42,6 +44,7 @@ Npc  - NPC
 ---------------------------------------
 
 DisabledItems: Items can be disabled from being used or equipped for players below a certain group level.
+Setting the group level to 0 will remove from the DisabledItems list. Useful for imports.
 
   Apple: 100 # Apple will not be able to be consumed by anyone.
   Cap: 100 # Cap will not be able to be equipped by anyone.
@@ -51,12 +54,14 @@ DisabledItems: Items can be disabled from being used or equipped for players bel
 
 DisabledStatuses: Statuses can be disabled in a zone for players below a certain group level. These
 statuses, if active, will be removed when entering a zone and will not be able to be re-applied while in the zone.
+Setting the group level to 0 will remove from the DisabledStatuses list. Useful for imports.
 
   Endure: 100 # Endure will be disabled from activing and being applied within the zone.
 
 ---------------------------------------
 
 RestrictedJobs: Jobs can be disabled from entering a zone for players below a certain group level.
+Setting the group level to 0 will remove from the RestrictedJobs list. Useful for imports.
 
   Priest: 30 # Makes the Priest job unable to enter the map zone to those group level less than 30.
 

+ 6 - 1
src/common/utilities.hpp

@@ -230,8 +230,9 @@ namespace rathena {
 		 * This will only erase the first occurrence of the value
 		 * @param vector: Vector to erase value from
 		 * @param value: Value to remove
+		 * @return True on removal or false otherwise
 		 */
-		template <typename K, typename V> void vector_erase_if_exists(std::vector<K> &vector, V value) {
+		template <typename K, typename V> bool vector_erase_if_exists(std::vector<K> &vector, V value) {
 			auto it = std::find(vector.begin(), vector.end(), value);
 
 			if (it != vector.end()) {
@@ -240,7 +241,11 @@ namespace rathena {
 					vector.shrink_to_fit();
 				} else
 					vector.erase(it);
+
+				return true;
 			}
+
+			return false;
 		}
 
 #if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION  ) && GCC_VERSION >= 50100 )

+ 160 - 31
src/map/map.cpp

@@ -20,6 +20,7 @@
 #include <common/socket.hpp> // WFIFO*()
 #include <common/strlib.hpp>
 #include <common/timer.hpp>
+#include <common/utilities.hpp>
 #include <common/utils.hpp>
 
 #include "achievement.hpp"
@@ -243,11 +244,14 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 				continue;
 
 			if (group_lv > 100) {
-				this->invalidWarning(commandNode, "Atcommand %s's Group Level can not be above 100, capping to 100.\n", command_name.c_str(), group_lv);
+				this->invalidWarning(commandNode, "Atcommand %s's Group Level can not be above 100, capping to 100.\n", command_name.c_str());
 				group_lv = 100;
 			}
 
-			zone->disabled_commands[command_name] = group_lv;
+			if (group_lv == 0)
+				zone->disabled_commands.erase(command_name);
+			else
+				zone->disabled_commands[command_name] = group_lv;
 		}
 	}
 
@@ -283,13 +287,19 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 				}
 
 				uint16 type = static_cast<uint16>(type_const);
+
+				if (type == BL_NUL) {
+					this->invalidWarning(it, "Skill %s's Object Type can not be BL_NUL, skipping.\n", bl_name.c_str());
+					continue;
+				}
+
 				uint16 group_lv;
 
 				if (!this->asUInt16(it, bl_name, group_lv))
 					continue;
 
 				if (group_lv > 100) {
-					this->invalidWarning(it, "Skill %s's Group Level can not be above 100, capping to 100.\n", bl_name.c_str(), group_lv);
+					this->invalidWarning(it, "Skill %s's Group Level can not be above 100, capping to 100.\n", bl_name.c_str());
 					group_lv = 100;
 				}
 
@@ -302,7 +312,7 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 						if (zone->disabled_skills[skill_id].first == BL_NUL)
 							zone->disabled_skills.erase(skill_id);
 					}
-				} else
+				} else if (group_lv > 0)
 					zone->disabled_skills.insert({ skill_id, std::pair<uint16, uint16>(type, group_lv) });
 			}
 		}
@@ -327,11 +337,14 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 				continue;
 
 			if (group_lv > 100) {
-				this->invalidWarning(itemNode, "Item %s's Group Level can not be above 100, capping to 100.\n", item_name.c_str(), group_lv);
+				this->invalidWarning(itemNode, "Item %s's Group Level can not be above 100, capping to 100.\n", item_name.c_str());
 				group_lv = 100;
 			}
 
-			zone->disabled_items[item->nameid] = group_lv;
+			if (group_lv == 0)
+				zone->disabled_items.erase(item->nameid);
+			else
+				zone->disabled_items[item->nameid] = group_lv;
 		}
 	}
 
@@ -355,11 +368,14 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 				continue;
 
 			if (group_lv > 100) {
-				this->invalidWarning(statusNode, "Status %s's Group Level can not be above 100, capping to 100.\n", status_name.c_str(), group_lv);
+				this->invalidWarning(statusNode, "Status %s's Group Level can not be above 100, capping to 100.\n", status_name.c_str());
 				group_lv = 100;
 			}
 
-			zone->disabled_statuses[static_cast<sc_type>(status)] = group_lv;
+			if (group_lv == 0)
+				zone->disabled_statuses.erase(static_cast<sc_type>(status));
+			else
+				zone->disabled_statuses[static_cast<sc_type>(status)] = group_lv;
 		}
 	}
 
@@ -383,11 +399,14 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 				continue;
 
 			if (group_lv > 100) {
-				this->invalidWarning(jobNode, "Job Group Level can not be above 100, capping to 100.\n", group_lv);
+				this->invalidWarning(jobNode, "Job Group Level can not be above 100, capping to 100.\n");
 				group_lv = 100;
 			}
 
-			zone->restricted_jobs[static_cast<uint32>(job_id)] = group_lv;
+			if (group_lv == 0)
+				zone->restricted_jobs.erase(static_cast<uint32>(job_id));
+			else
+				zone->restricted_jobs[static_cast<uint32>(job_id)] = group_lv;
 		}
 	}
 
@@ -397,9 +416,9 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		for (const auto &it : mapNode) {
 			std::string map_name;
 			c4::from_chars(it.key(), &map_name);
-			int16 map_id = map_mapname2mapid(map_name.c_str());
+			int16 mapidx = mapindex_name2idx(map_name.c_str(), nullptr);
 
-			if (map_id == -1) {
+			if (mapidx == 0) {
 				this->invalidWarning(mapNode, "Map %s does not exist.\n", map_name.c_str());
 				continue;
 			}
@@ -409,15 +428,21 @@ uint64 MapZoneDatabase::parseBodyNode(const ryml::NodeRef& node) {
 			if (!this->asBool(mapNode, map_name, enabled))
 				continue;
 
+			int16 map_id = map_mapname2mapid(map_name.c_str());
+
 			if (enabled) {
 				if (util::vector_exists(zone->maps, map_id)) {
-					this->invalidWarning(mapNode, "Map %s already part of this zone.\n", map_name.c_str());
+					this->invalidWarning(mapNode, "Map %s is already part of this zone.\n", map_name.c_str());
 					continue;
 				}
 
 				zone->maps.push_back(map_id);
-			} else
-				util::vector_erase_if_exists(zone->maps, map_id);
+			} else {
+				if (!util::vector_erase_if_exists(zone->maps, map_id)) {
+					this->invalidWarning(mapNode, "Map %s is not part of this zone.\n", map_name.c_str());
+					continue;
+				}
+			}
 		}
 	}
 
@@ -470,28 +495,26 @@ void MapZoneDatabase::loadingFinished() {
 		for (const auto &map : zone.second->maps) {
 			map_data *mapdata = map_getmapdata(map);
 
-			if (mapdata != nullptr) {
-				mapdata->zone.id = zone.second->id;
-				mapdata->zone.disabled_commands = zone.second->disabled_commands;
-				mapdata->zone.disabled_items = zone.second->disabled_items;
-				mapdata->zone.disabled_skills = zone.second->disabled_skills;
-				mapdata->zone.disabled_statuses = zone.second->disabled_statuses;
-				mapdata->zone.restricted_jobs = zone.second->restricted_jobs;
+			if (mapdata == nullptr)
+				continue;
 
-				// Clear previous mapflags
-				mapdata->initMapFlags();
-				mapdata->skill_damage.clear();
-				mapdata->skill_duration.clear();
-			}
+			mapdata->zone.id = zone.second->id;
+			mapdata->zone.disabled_commands = zone.second->disabled_commands;
+			mapdata->zone.disabled_items = zone.second->disabled_items;
+			mapdata->zone.disabled_skills = zone.second->disabled_skills;
+			mapdata->zone.disabled_statuses = zone.second->disabled_statuses;
+			mapdata->zone.restricted_jobs = zone.second->restricted_jobs;
+
+			// Clear previous mapflags
+			mapdata->initMapFlags();
+			mapdata->skill_damage.clear();
+			mapdata->skill_duration.clear();
 
 			// Apply mapflags from Map Zone DB
 			for (const auto &flag : zone.second->mapflags) {
 				char flag_name[50] = {}, empty[1] = {};
 
-				if (map_getmapflag_name(static_cast<e_mapflag>(flag.first.first), flag_name))
-					npc_parse_mapflag(const_cast<char *>(map_mapid2mapname(map)), empty, flag_name, const_cast<char *>(flag.second.c_str()), empty, empty, empty);
-				else
-					ShowError("MapZoneDatabase::loadingFinished: Invalid mapflag %s from zone %s.\n", flag_name, script_get_constant_str("MAPTYPE_", zone.first));
+				npc_parse_mapflag(mapdata->name, empty, flag_name, const_cast<char *>(flag.second.c_str()), empty, empty, "MapZoneDatabase::loadingFinished");
 			}
 		}
 	}
@@ -499,6 +522,112 @@ void MapZoneDatabase::loadingFinished() {
 
 MapZoneDatabase map_zone_db;
 
+/**
+ * Check if a command is disabled on a map based on group level.
+ * @param name: Command name
+ * @param group_lv: Group level
+ * @return True when command is disabled or false otherwise
+ */
+bool s_map_zone_data::isCommandDisabled(std::string name, uint16 group_lv) {
+	if (this->disabled_commands.empty())
+		return false;
+
+	auto cmd_lv = util::umap_find(this->disabled_commands, name);
+
+	if (cmd_lv == nullptr)
+		return false;
+
+	if (*cmd_lv < group_lv)
+		return false;
+	else
+		return true;
+}
+
+/**
+ * Check if a skill is disabled on a map based on group level.
+ * @param skill_id: Skill ID
+ * @param type: Object type
+ * @param group_lv: Group level
+ * @return True when skill is disabled or false otherwise
+ */
+bool s_map_zone_data::isSkillDisabled(uint16 skill_id, uint16 type, uint16 group_lv) {
+	if (this->disabled_skills.empty())
+		return false;
+
+	auto skill_lv = util::umap_find(this->disabled_skills, skill_id);
+
+	if (skill_lv == nullptr)
+		return false;
+
+	if ((!(type & BL_PC) && skill_lv->second > 0) || (skill_lv->second < group_lv))
+		return false;
+	else
+		return true;
+}
+
+/**
+ * Check if an item is disabled on a map based on group level.
+ * @param nameid: Item ID
+ * @param group_lv: Group level
+ * @return True when item is disabled or false otherwise
+ */
+bool s_map_zone_data::isItemDisabled(t_itemid nameid, uint16 group_lv) {
+	if (this->disabled_items.empty())
+		return false;
+
+	auto item_lv = util::umap_find(this->disabled_items, nameid);
+
+	if (item_lv == nullptr)
+		return false;
+
+	if (*item_lv < group_lv)
+		return false;
+	else
+		return true;
+}
+
+/**
+ * Check if a status is disabled on a map based on group level.
+ * @param sc: Status type
+ * @param group_lv: Group level
+ * @return True when status is disabled or false otherwise
+ */
+bool s_map_zone_data::isStatusDisabled(sc_type sc, uint16 group_lv) {
+	if (this->disabled_statuses.empty())
+		return false;
+
+	auto status_lv = util::umap_find(this->disabled_statuses, sc);
+
+	if (status_lv == nullptr)
+		return false;
+
+	if ((group_lv == 101 && *status_lv > 0) || (*status_lv < group_lv))
+		return false;
+	else
+		return true;
+}
+
+/**
+ * Check if a job is restricted on a map based on group level.
+ * @param job_id: Job ID
+ * @param group_lv: Group level
+ * @return True when job is restricted or false otherwise
+ */
+bool s_map_zone_data::isJobRestricted(int32 job_id, uint16 group_lv) {
+	if (this->restricted_jobs.empty())
+		return false;
+
+	auto job_lv = util::umap_find(this->restricted_jobs, job_id);
+
+	if (job_lv == nullptr)
+		return false;
+
+	if (*job_lv < group_lv)
+		return false;
+	else
+		return true;
+}
+
 /**
  * Get the map data
  * @param mapid: Map ID to lookup

+ 5 - 74
src/map/map.hpp

@@ -815,80 +815,11 @@ struct s_map_zone_data {
 	std::unordered_map<sc_type, uint16> disabled_statuses;
 	std::unordered_map<int32, uint16> restricted_jobs;
 
-	bool isCommandDisabled(std::string name, uint16 group_lv) {
-		if (this->disabled_commands.empty())
-			return false;
-
-		auto cmd_lv = util::umap_find(this->disabled_commands, name);
-
-		if (cmd_lv == nullptr)
-			return false;
-
-		if (*cmd_lv < group_lv)
-			return false;
-		else
-			return true;
-	}
-
-	bool isSkillDisabled(uint16 skill_id, uint16 type, uint16 group_lv) {
-		if (this->disabled_skills.empty())
-			return false;
-
-		auto skill_lv = util::umap_find(this->disabled_skills, skill_id);
-
-		if (skill_lv == nullptr)
-			return false;
-
-		if ((!(type & BL_PC) && skill_lv->second > 0) || (skill_lv->second < group_lv))
-			return false;
-		else
-			return true;
-	}
-
-	bool isItemDisabled(t_itemid nameid, uint16 group_lv) {
-		if (this->disabled_items.empty())
-			return false;
-
-		auto item_lv = util::umap_find(this->disabled_items, nameid);
-
-		if (item_lv == nullptr)
-			return false;
-
-		if (*item_lv < group_lv)
-			return false;
-		else
-			return true;
-	}
-
-	bool isStatusDisabled(sc_type sc, uint16 group_lv) {
-		if (this->disabled_statuses.empty())
-			return false;
-
-		auto status_lv = util::umap_find(this->disabled_statuses, sc);
-
-		if (status_lv == nullptr)
-			return false;
-
-		if ((group_lv == 101 && *status_lv > 0) || (*status_lv < group_lv))
-			return false;
-		else
-			return true;
-	}
-
-	bool isJobRestricted(int32 job_id, uint16 group_lv) {
-		if (this->restricted_jobs.empty())
-			return false;
-
-		auto job_lv = util::umap_find(this->restricted_jobs, job_id);
-
-		if (job_lv == nullptr)
-			return false;
-
-		if (*job_lv < group_lv)
-			return false;
-		else
-			return true;
-	}
+	bool isCommandDisabled(std::string name, uint16 group_lv);
+	bool isSkillDisabled(uint16 skill_id, uint16 type, uint16 group_lv);
+	bool isItemDisabled(t_itemid nameid, uint16 group_lv);
+	bool isStatusDisabled(sc_type sc, uint16 group_lv);
+	bool isJobRestricted(int32 job_id, uint16 group_lv);
 };
 
 struct map_data {