/********** UI building ***********/

        void AddComponents()
        {
            m_bookPanel = this.gameObject.AddComponent <BookPanel>();
            m_bookPanel.transform.parent = m_zonedBuildingInfoPanel.component.transform;
            m_bookPanel.size             = new Vector3(m_zonedBuildingInfoPanel.component.size.x, m_zonedBuildingInfoPanel.component.size.y);//maybe excahnge line with prvious one?
            m_bookPanel.position         = new Vector3(-m_bookPanel.size.x - m_bookInfoPanelLeftMargin, +m_bookPanel.size.y);

            m_bookInfoPanelInitialHeight   = m_bookPanel.height;
            m_bookInfoPanelPageWidth       = m_bookPanel.size.x / 2 - m_bookInfoPanelLeftMargin - m_bookInfoPanelRightPadding;
            m_bookInfoPanelLeftMarginPage2 = m_bookPanel.size.x / 2 + m_bookInfoPanelLeftMargin;

            m_bookInfoPanel = m_bookPanel;

            m_historyTitleLabel           = m_bookInfoPanel.AddUIComponent <UILabel> ();
            m_historyTitleLabel.name      = "History Title";
            m_historyTitleLabel.textScale = 1.2f;
            m_historyTitleLabel.text      = Localization.trad.GetHistoryTitle();
            m_historyTitleLabel.textColor = m_bookTextColor;

            m_recordTitleLabel           = m_bookInfoPanel.AddUIComponent <UILabel> ();
            m_recordTitleLabel.name      = "Record Title";
            m_recordTitleLabel.textScale = 1.2f;
            m_recordTitleLabel.text      = Localization.trad.GetRecordTitle();
            m_recordTitleLabel.textColor = m_bookTextColor;

            m_descriptionTextField                     = m_bookInfoPanel.AddUIComponent <UIMultilineTextField> ();
            m_descriptionTextField.name                = "Building Description";
            m_descriptionTextField.text                = "Enter description";
            m_descriptionTextField.textScale           = 0.8f;
            m_descriptionTextField.width               = m_bookInfoPanelPageWidth;
            m_descriptionTextField.height              = 100f;
            m_descriptionTextField.disabledTextColor   = new Color32(7, 7, 7, 255);
            m_descriptionTextField.textColor           = m_bookTextColor;
            m_descriptionTextField.eventTextSubmitted += (component, param) =>
            {
                SaveDescription(param);
            };
//			m_descriptionTextField.title = "Description";
//			m_descriptionTextField.showTitle = true;
            m_descriptionTextField.defaultText        = Localization.trad.GetDescriptionEmpty();
            m_descriptionTextField.eventHeightChange += (component, height) => {
                ResizePanelHeight();
            };

            int spriteWidth  = 32;
            int spriteHeight = 32;

            string[] tooltips =
            {
                Localization.trad.GetTooltipOff(),
                Localization.trad.GetTooltipHistoryOn(),
                Localization.trad.GetTooltipResiliencyOn()
            };
            m_resilientStateButton = new StatesButton(m_zonedBuildingInfoPanel.component, spriteWidth, spriteHeight, 3, "icons.book.png", "ResilientOwners", tooltips);

            m_resilientStateButton.msb.eventActiveStateIndexChanged += (component, value) => {
                if (!m_allowEvents)
                {
                    return;
                }

                switch (value)
                {
                case 0:
                    m_info.UnsuscribeBuilding(m_currentSelectedBuildingID);
                    HideHistory();
                    break;

                case 1:
                    m_info.AddBuilding(m_currentSelectedBuildingID, false);
                    ShowHistory();
                    CheckUpdateUI(m_currentSelectedBuildingID);
                    break;

                case 2:
                    m_info.AddBuilding(m_currentSelectedBuildingID, true);
                    ShowHistory();
                    break;
                }
            };
            m_resilientStateButton.msb.AlignTo(m_zonedBuildingInfoPanel.component, UIAlignAnchor.TopRight);
            m_resilientStateButton.msb.relativePosition += new Vector3(-50f, 60f, 0f);

            m_familiesHistoryLabel            = m_bookInfoPanel.AddUIComponent <UILabel> ();
            m_familiesHistoryLabel.name       = "Families History";
            m_familiesHistoryLabel.text       = Localization.trad.GetEmptyHouse();
            m_familiesHistoryLabel.textScale  = 0.8f;
            m_familiesHistoryLabel.textColor  = m_bookTextColor;
            m_familiesHistoryLabel.width      = m_bookInfoPanelPageWidth;
            m_familiesHistoryLabel.wordWrap   = true;
            m_familiesHistoryLabel.autoSize   = false;
            m_familiesHistoryLabel.autoHeight = true;

            m_activatedDateLabel           = m_bookInfoPanel.AddUIComponent <UILabel> ();
            m_activatedDateLabel.name      = "Activation Date";
            m_activatedDateLabel.text      = Localization.trad.GetActivationDate();
            m_activatedDateLabel.textScale = 0.8f;
            m_activatedDateLabel.textColor = m_bookTextColor;
            m_activatedDateLabel.width     = m_bookInfoPanelPageWidth;

            m_ageLabel           = m_bookInfoPanel.AddUIComponent <UILabel> ();
            m_ageLabel.name      = "Age";
            m_ageLabel.text      = Localization.trad.GetActivationDate();
            m_ageLabel.textScale = 0.8f;
            m_ageLabel.textColor = m_bookTextColor;
            m_ageLabel.width     = m_bookInfoPanelPageWidth;

            m_statsLabel            = m_bookInfoPanel.AddUIComponent <UILabel> ();
            m_statsLabel.name       = "Stats";
            m_statsLabel.text       = Localization.trad.GetEmptyHouse();      //long enough string
            m_statsLabel.textScale  = 0.8f;
            m_statsLabel.textColor  = m_bookTextColor;
            m_statsLabel.width      = m_bookInfoPanelPageWidth;
            m_statsLabel.wordWrap   = true;
            m_statsLabel.autoSize   = false;
            m_statsLabel.autoHeight = true;

            placeComponents();

//			m_zonedBuildingInfoPanelComponent.eventVisibilityChanged +=(component, param) =>
//			{
//				if(param)
//					OnSelected();
//					//m_info.StartCoroutine(OnSelected());//StartCoroutine on a MonoBehaviour...
//			};

            //m_zonedBuildingInfoPanel.m_IsEmbbeded = true;//one of the condition call to OnPositionChanged, ensure it
            m_zonedBuildingInfoPanel.component.eventPositionChanged += (inst1, inst2) =>
            {
                if (m_zonedBuildingInfoPanel.component.isVisible)
                {
                    OnSelected();
                }
            };

            m_zonedBuildingInfoPanel.component.eventOpacityChanged += (inst1, inst2) =>
            {
                if (m_zonedBuildingInfoPanel.component.isVisible)
                {
                    OnSelected();
                }
            };

            //m_zonedBuildingInfoPanel.component.eventClick += (inst1, inst2) =>
            //{
            //    if (m_zonedBuildingInfoPanel.component.isVisible)
            //        OnSelected();
            //};

            // district panel modifications

            string[] tooltips2 =
            {
                Localization.trad.GetTooltipDistrictOff(),
                Localization.trad.GetTooltipDistrictOn()
            };
            m_resilientStateButton2 = new StatesButton(m_districtInfoPanel.component, spriteWidth, spriteHeight, 2, "icons.star.png", "ResilientOwnersDistricts", tooltips2);

            m_resilientStateButton2.msb.eventActiveStateIndexChanged += (component, value) => {
                if (!m_allowEvents)
                {
                    return;
                }

                switch (value)
                {
                case 0:
                    m_info.UnsuscribeDistrict(m_currentSelectedDistrictID);
                    break;

                case 1:
                    m_info.AddDistrict(m_currentSelectedDistrictID);
                    break;
                }
            };
            m_resilientStateButton2.msb.AlignTo(m_districtInfoPanel.component, UIAlignAnchor.TopRight);
            m_resilientStateButton2.msb.relativePosition += new Vector3(-20f, 90f, 0f);

            m_districtInfoPanel.component.eventPositionChanged += (inst1, inst2) =>
            {
                if (m_districtInfoPanel.component.isVisible)
                {
                    OnSelectedDistricts();
                }
            };

            m_districtInfoPanel.component.eventOpacityChanged += (inst1, inst2) =>
            {
                if (m_districtInfoPanel.component.isVisible)
                {
                    OnSelectedDistricts();
                }
            };
        }
        public override void OnAfterSimulationFrame()
        {
            if (!LoadingExtension.installed)
            {
                return;
            }

            if (s_info == null)
            {
                return;
            }

            BuildingManager instance = Singleton <BuildingManager> .instance;

            int    num6          = (int)(Singleton <SimulationManager> .instance.m_currentFrameIndex & 255u);
            ushort minBuildingID = (ushort)(num6 * 192);
            ushort maxBuildingID = (ushort)((num6 + 1) * 192 - 1);

            //check if building should be added as part of a resilient district
            DistrictManager instance2 = Singleton <DistrictManager> .instance;

            for (ushort i = minBuildingID; i < maxBuildingID; i++)
            {
                if (instance.m_buildings.m_buffer[i].m_flags == Building.Flags.None)
                {
                    continue;
                }
                Building build         = instance.m_buildings.m_buffer[i];
                byte     districtID    = instance2.GetDistrict(build.m_position);
                int      districtIndex = s_info.GetResilientDistrictIndex(districtID);
                if (districtIndex != -1)
                {
                    if (s_info.m_districts[districtIndex].unsuscribed)
                    {
                        //s_info.RemoveBuilding(i);
                        s_info.UnsuscribeBuilding(i);
                    }
                    else if (s_info.m_districts[districtIndex].resiliencyActivated)
                    {
                        bool newly_added = s_info.AddBuilding(i, true);
                        if (newly_added)
                        {
                            ResilientBuildings.ResilientDistrict rd = s_info.m_districts[districtIndex];
                            rd.totalBuildings++;
                            s_info.m_districts[districtIndex] = rd;
                        }
                    }
                }
            }

            //districts timers
            for (int i = 0; i < s_info.m_districts.Count; i++)
            {
                if (s_info.m_districts[i].unsuscribed)
                {
                    ResilientBuildings.ResilientDistrict rd = s_info.m_districts[i];
                    rd.unsuscribeTimer++;
                    s_info.m_districts[i] = rd;
                    if (rd.unsuscribeTimer > REMOVE_DISTRICT_AFTER_UPDATES)
                    {
                        s_info.RemoveDistrict(rd.districtID);
                    }
                }
            }


            //check all buildings in resilients list
            for (int i = 0; i < s_info.m_resilients.Count; i++)
            {
                ushort buildingID = s_info.m_resilients[i].buildingID;

                //sync with buildManager, update only buildings that just had a SimulationStep
                if (buildingID < minBuildingID || buildingID >= maxBuildingID)
                {
                    continue;
                }

                ResilientBuildings.ResilientInfoV1 build = s_info.m_resilients[i];

                if (s_info.m_resilients[i].unsuscribed)                //building unsuscribed
                {
                    build.unsuscribeTimer++;
                    if (build.unsuscribeTimer > REMOVE_AFTER_UPDATES)
                    {
                        s_info.m_resilients.RemoveAt(i);
                        i--;
                        continue;
                    }
                    s_info.m_resilients[i] = build;
                    continue;
                }

                if (instance.m_buildings.m_buffer[buildingID].m_flags == Building.Flags.None)                //building was bulldozed, remove it from the list
                {
                    s_info.m_resilients.RemoveAt(i);
                    i--;
                    continue;
                }


                //update infos
                BuildingInfo buildinfo = Singleton <BuildingManager> .instance.m_buildings.m_buffer[buildingID].Info;

                if (buildinfo.m_class.m_service == ItemClass.Service.Residential)
                {
                    s_info.UpdateResidentFamilies(i);
                }
                else
                {
                    s_info.UpdateWorkers(i);

                    if (buildinfo.m_class.m_service == ItemClass.Service.Commercial)
                    {
                        s_info.UpdateVisitsCount(i);
                    }
                    else if (buildinfo.m_class.m_service == ItemClass.Service.Industrial)
                    {
                        if (buildinfo.m_buildingAI.GetType().Equals(typeof(IndustrialExtractorAI)))
                        {
                            s_info.UpdatePrimaryResourceExport(i);
                        }
                        else if (buildinfo.m_buildingAI.GetType().Equals(typeof(IndustrialBuildingAI)))
                        {
                            s_info.UpdateGoodsExport(i);
                        }
                    }
                }

                if (build.resiliencyActivated)
                {
                    //instance.m_buildings.m_buffer[buildingID].m_electricityProblemTimer = 0;
                    //instance.m_buildings.m_buffer[buildingID].m_majorProblemTimer = 0;
                    //instance.m_buildings.m_buffer[buildingID].m_problems = Notification.Problem.TurnedOff;

                    //building will not be removed when dezoning, it must be bulldozed
                    //instance.m_buildings.m_buffer[buildingID].m_flags &= ~Building.Flags.ZonesUpdated;

                    //avoid major problem to trigger abandonment
                    instance.m_buildings.m_buffer[buildingID].m_majorProblemTimer = 0;
                    instance.m_buildings.m_buffer[buildingID].m_problems         &= ~Notification.Problem.MajorProblem;

                    //lower cap on unhappiness if problems
                    if (instance.m_buildings.m_buffer[buildingID].m_problems != Notification.Problem.None)
                    {
                        instance.m_buildings.m_buffer[buildingID].m_happiness = 60;
                    }

                    //reoccupy building when it is abandoned/burned down
                    if ((instance.m_buildings.m_buffer[buildingID].m_flags & (Building.Flags.Abandoned | Building.Flags.BurnedDown)) != Building.Flags.None)
                    {
                        //reset timers
                        instance.m_buildings.m_buffer[buildingID].m_electricityProblemTimer = 0;
                        instance.m_buildings.m_buffer[buildingID].m_waterProblemTimer       = 0;
                        instance.m_buildings.m_buffer[buildingID].m_majorProblemTimer       = 0;
                        instance.m_buildings.m_buffer[buildingID].m_deathProblemTimer       = 0;
                        instance.m_buildings.m_buffer[buildingID].m_serviceProblemTimer     = 0;
                        instance.m_buildings.m_buffer[buildingID].m_taxProblemTimer         = 0;
                        instance.m_buildings.m_buffer[buildingID].m_outgoingProblemTimer    = 0;
                        instance.m_buildings.m_buffer[buildingID].m_incomingProblemTimer    = 0;
                        instance.m_buildings.m_buffer[buildingID].m_heatingProblemTimer     = 0;
                        instance.m_buildings.m_buffer[buildingID].m_healthProblemTimer      = 0;
                        instance.m_buildings.m_buffer[buildingID].m_workerProblemTimer      = 0;

                        //reset buffers
                        instance.m_buildings.m_buffer[buildingID].m_crimeBuffer       = 0;
                        instance.m_buildings.m_buffer[buildingID].m_customBuffer1     = 0;
                        instance.m_buildings.m_buffer[buildingID].m_customBuffer2     = 0;
                        instance.m_buildings.m_buffer[buildingID].m_electricityBuffer = 0;
                        instance.m_buildings.m_buffer[buildingID].m_heatingBuffer     = 0;
                        instance.m_buildings.m_buffer[buildingID].m_garbageBuffer     = 0;
                        instance.m_buildings.m_buffer[buildingID].m_sewageBuffer      = 0;
                        instance.m_buildings.m_buffer[buildingID].m_waterBuffer       = 0;

                        //renovate building
                        Building.Frame carpentry = instance.m_buildings.m_buffer[buildingID].GetLastFrameData();
                        carpentry.m_constructState /= 2;
                        carpentry.m_fireDamage      = 0;
                        instance.m_buildings.m_buffer[buildingID].SetFrameData(Singleton <SimulationManager> .instance.m_currentFrameIndex, carpentry);

                        //repopulate building
                        instance.m_buildings.m_buffer[buildingID].m_flags = Building.Flags.Created;
                        instance.m_buildings.m_buffer[buildingID].Info.m_buildingAI.CreateBuilding(buildingID, ref instance.m_buildings.m_buffer[buildingID]);

                        //user feedback : remove notification
                        instance.m_buildings.m_buffer[buildingID].m_problems = Notification.Problem.None;
                    }

                    if (instance.m_buildings.m_buffer[buildingID].GetLastFrameData().m_fireDamage > 230 && Settings.inst.extinguishFires)                    //extinguish fire at last minute
                    {
                        instance.m_buildings.m_buffer[buildingID].m_fireIntensity = 0;
//						Building.Frame carpentry = instance.m_buildings.m_buffer[buildingID].GetLastFrameData();
//						carpentry.m_fireDamage = 0;
//						instance.m_buildings.m_buffer[buildingID].SetFrameData(Singleton<SimulationManager>.instance.m_currentFrameIndex+1, carpentry);
                    }
                }

                s_UI.CheckUpdateUI(buildingID);
            }
        }