/// <summary>
        /// Harmony Prefix patch to catch any buildings trying to upgrade beyond their maximum permitted level.
        /// Note that this won't in itself solve any broken prefabs with illegal levels, as the game's BuildingUpgraded method will set their level to the maximum of the actual or prefab level.
        /// </summary>
        /// <param name="__instance">Instance reference</param>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="data">Building data</param>
        public static void Prefix(PrivateBuildingAI __instance, ushort buildingID, ref Building data)
        {
            byte maxLevel = LevelUtils.GetMaxLevel(buildingID);

            // Check against maxLevel (m_level is zero-based, maxLevel is 1-based, so >= to catch overflows).
            if (data.m_level >= maxLevel)
            {
                Logging.Error("prevented building ", buildingID.ToString(), " (", __instance.m_info.name, ") from upgrading to illegal level ", (data.m_level + 1).ToString(), "; setting to ", maxLevel.ToString());
                data.m_level = (byte)(maxLevel - 1);
            }
        }
        /// <summary>
        /// Harmony Prefix patch to catch any buildings being loaded with levels above their maximum permitted level.
        /// Note that this won't in itself solve any broken prefabs with illegal levels, as the game's BuildingUpgraded method will set their level to the maximum of the actual or prefab level.
        /// </summary>
        /// <param name="__instance">Instance reference</param>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="data">Building data</param>
        /// <param name="version">Data version</param>
        public static void Prefix(PrivateBuildingAI __instance, ushort buildingID, ref Building data)
        {
            // Only do this if settings permit.
            if (ModSettings.loadLevelCheck)
            {
                byte maxLevel = LevelUtils.GetMaxLevel(buildingID);

                // Check against maxLevel (m_level is zero-based, maxLevel is 1-based, so >= to catch overflows).
                if (data.m_level >= maxLevel)
                {
                    Logging.Error("building ", buildingID.ToString(), " (", __instance.m_info.name, ") had illegal level ", (data.m_level + 1).ToString(), "; setting to ", maxLevel.ToString());
                    data.m_level = (byte)(maxLevel - 1);
                }
            }
        }
        /// <summary>
        /// Handles a change in target building from the WorldInfoPanel.
        /// Sets the panel button state according to whether or not this building is 'levellable' and communicates changes to the ABLC panel.
        /// </summary>
        internal static void TargetChanged()
        {
            // Get current WorldInfoPanel building instance and determine maximum building level.
            if (LevelUtils.GetMaxLevel(WorldInfoPanel.GetCurrentInstanceID().Building) == 1)
            {
                // Only one building level - not a 'levellable' building, so disable the ABLC button and update the tooltip accordingly.
                panelButton.Disable();
                panelButton.tooltip = Translations.Translate("ABLC_BUT_DIS");
            }
            else
            {
                // Multiple levels available - enable the ABLC button and update the tooltip accordingly.
                panelButton.Enable();
                panelButton.tooltip = Translations.Translate("ABLC_NAME");
            }

            // Communicate target change to the panel (if it's currently instantiated).
            Panel?.BuildingChanged();
        }
 /// <summary>
 /// Updates the buildng's maximum level.
 /// </summary>
 /// <param name="buildingID">Building to set</param>
 /// <param name="maxLevel">New maximum level</param>
 internal static void UpdateMaxLevel(ushort buildingID, byte maxLevel)
 {
     // See if we've already got a dictionary entry for this building.
     if (levelRanges.ContainsKey(buildingID))
     {
         // We do - if this new maximum level is the maximum for this building and the minimum is zero, delete this entry.
         if (maxLevel == LevelUtils.GetMaxLevel(buildingID) && BuildingsABLC.levelRanges[buildingID].minLevel == 0)
         {
             levelRanges.Remove(buildingID);
         }
         else
         {
             // Otherwise, just update our entry's maximum target level.
             levelRanges[buildingID].maxLevel = maxLevel;
         }
     }
     else if (maxLevel < LevelUtils.GetMaxLevel(buildingID))
     {
         // If the new maximum level isn't the absolute maximum for this building, create a new dictionary entry with this maximum and default minimum levels.
         levelRanges.Add(buildingID, new LevelRange {
             minLevel = 0, maxLevel = maxLevel
         });
     }
 }
        /// <summary>
        /// Called when the selected building has changed.
        /// </summary>
        internal void BuildingChanged()
        {
            // Update selected building ID.
            targetID = WorldInfoPanel.GetCurrentInstanceID().Building;

            // Check maximum level for this building type.
            int maxLevel = LevelUtils.GetMaxLevel(targetID);

            // If building doesn't have more than one level, then we don't have any business to do here.
            if (maxLevel == 1)
            {
                BuildingPanelManager.panelButton.Disable();
                Hide();
                return;
            }
            else
            {
                // Enable info panel button.
                BuildingPanelManager.panelButton.Enable();

                // Make sure we're visible if we're not already.
                if (!isVisible)
                {
                    Show();
                }
            }

            // Disable events while we make changes to avoid triggering event handler.
            disableEvents = true;

            // Set name.
            nameLabel.text = Singleton <BuildingManager> .instance.GetBuildingName(targetID, InstanceID.Empty);

            // Build level dropdown ranges.
            minLevelDropDown.items = new string[maxLevel];
            maxLevelDropDown.items = new string[maxLevel];
            for (int i = 0; i < maxLevel; i++)
            {
                minLevelDropDown.items[i] = (i + 1).ToString();
                maxLevelDropDown.items[i] = (i + 1).ToString();
            }


            // Check to see if we have custom settings for this building.
            if (BuildingsABLC.levelRanges.ContainsKey(targetID))
            {
                // Update dropdown selection to match building's settings.
                minLevelDropDown.selectedIndex = BuildingsABLC.levelRanges[targetID].minLevel;
                maxLevelDropDown.selectedIndex = BuildingsABLC.levelRanges[targetID].maxLevel;
            }
            else
            {
                // Set min and max to default.
                minLevelDropDown.selectedIndex = 0;
                maxLevelDropDown.selectedIndex = maxLevelDropDown.items.Length - 1;
            }

            // Initialise panel with correct level settings.
            UpdatePanel();

            // All done: re-enable events.
            disableEvents = false;
        }