private object OnHammerHit(BasePlayer player, HitInfo info)
        {
            BaseCombatEntity entity = info?.HitEntity as BaseCombatEntity;

            if (entity == null || entity.IsDestroyed)
            {
                return(null);
            }

            DecayEntity decay = entity as DecayEntity;

            if (decay != null && decay.buildingID == 0)
            {
                return(null);
            }

            if (!_storedData.RepairEnabled.ContainsKey(player.userID) && _pluginConfig.DefaultEnabled)
            {
                _storedData.RepairEnabled[player.userID] = true;
            }

            if (!_storedData.RepairEnabled[player.userID])
            {
                return(null);
            }

            if (IsNoEscapeBlocked(player))
            {
                Chat(player, Lang(LangKeys.NoEscape, player));
                return(null);
            }

            if (_repairingPlayers.Contains(player.userID))
            {
                Chat(player, Lang(LangKeys.RepairInProcess, player));
                return(null);
            }

            BuildingPrivlidge priv = player.GetBuildingPrivilege();

            if (priv == null || !priv.IsAuthed(player))
            {
                return(null);
            }

            PlayerRepairStats stats = new PlayerRepairStats();

            BuildingManager.Building building = priv.GetBuilding();
            ServerMgr.Instance.StartCoroutine(DoBuildingRepair(player, building, stats));
            return(true);
        }
        private void DoRepair(BasePlayer player, BaseCombatEntity entity, PlayerRepairStats stats, bool noCost)
        {
            if (!entity.repair.enabled || entity.health == entity.MaxHealth())
            {
                return;
            }

            if (Interface.CallHook("OnStructureRepair", this, player) != null)
            {
                return;
            }

            if (entity.SecondsSinceAttacked <= 30f)
            {
                entity.OnRepairFailed(null, string.Empty);
                stats.RecentlyDamaged++;
                return;
            }

            float missingHealth    = entity.MaxHealth() - entity.health;
            float healthPercentage = missingHealth / entity.MaxHealth();

            if (missingHealth <= 0f || healthPercentage <= 0f)
            {
                entity.OnRepairFailed(null, string.Empty);
                return;
            }

            if (!noCost)
            {
                List <ItemAmount> itemAmounts = entity.RepairCost(healthPercentage);
                if (itemAmounts.Sum(x => x.amount) <= 0f)
                {
                    entity.health += missingHealth;
                    entity.SendNetworkUpdate();
                    entity.OnRepairFinished();
                    return;
                }

                if (_pluginConfig.RepairCostMultiplier != 1f)
                {
                    foreach (ItemAmount amount in itemAmounts)
                    {
                        amount.amount *= _pluginConfig.RepairCostMultiplier;
                    }
                }

                if (itemAmounts.Any(ia => player.inventory.GetAmount(ia.itemid) < (int)ia.amount))
                {
                    entity.OnRepairFailed(null, string.Empty);

                    foreach (ItemAmount amount in itemAmounts)
                    {
                        stats.MissingAmounts[amount.itemid] += (int)amount.amount;
                    }

                    stats.TotalCantAfford++;
                    return;
                }

                foreach (ItemAmount amount in itemAmounts)
                {
                    player.inventory.Take(null, amount.itemid, (int)amount.amount);
                    stats.AmountTaken[amount.itemid] += (int)amount.amount;
                }
            }

            entity.health += missingHealth;
            entity.SendNetworkUpdate();

            if (entity.health < entity.MaxHealth())
            {
                entity.OnRepair();
            }
            else
            {
                entity.OnRepairFinished();
            }

            stats.TotalSuccess++;
        }
        private IEnumerator DoBuildingRepair(BasePlayer player, BuildingManager.Building building, PlayerRepairStats stats)
        {
            _repairingPlayers.Add(player.userID);
            bool noCostPerm = HasPermission(player, NoCostPermission);

            for (int index = 0; index < building.decayEntities.Count; index++)
            {
                DecayEntity entity = building.decayEntities[index];
                DoRepair(player, entity, stats, noCostPerm);

                foreach (BaseLadder ladder in entity.children.OfType <BaseLadder>())
                {
                    DoRepair(player, ladder, stats, noCostPerm);
                    yield return(null);
                }

                if (index % _pluginConfig.RepairsPerFrame == 0)
                {
                    yield return(null);
                }
            }

            List <IOEntity> buildingIoEntities = _ioEntity[building.ID];

            if (buildingIoEntities != null)
            {
                for (int index = 0; index < buildingIoEntities.Count; index++)
                {
                    DoRepair(player, buildingIoEntities[index], stats, noCostPerm);

                    if (index % _pluginConfig.RepairsPerFrame == 0)
                    {
                        yield return(null);
                    }
                }
            }

            StringBuilder main = new StringBuilder();

            main.AppendLine(Lang(LangKeys.AmountRepaired, player, stats.TotalSuccess));

            if (stats.RecentlyDamaged > 0)
            {
                main.AppendLine(Lang(LangKeys.RecentlyDamaged, player, stats.RecentlyDamaged));
            }

            Chat(player, main.ToString());

            if (stats.TotalCantAfford > 0)
            {
                StringBuilder cantAfford = new StringBuilder();
                cantAfford.AppendLine(Lang(LangKeys.CantAfford, player, stats.TotalCantAfford));
                cantAfford.AppendLine(Lang(LangKeys.MissingItems, player));

                foreach (KeyValuePair <int, int> missing in stats.MissingAmounts)
                {
                    int amountMissing = missing.Value - player.inventory.GetAmount(missing.Key);
                    if (amountMissing <= 0)
                    {
                        continue;
                    }

                    cantAfford.AppendLine(Lang(LangKeys.MissingItem, player,
                                               ItemManager.FindItemDefinition(missing.Key).displayName.translated, amountMissing));
                }

                Chat(player, cantAfford.ToString());
            }

            foreach (KeyValuePair <int, int> taken in stats.AmountTaken)
            {
                player.Command("note.inv", taken.Key, -taken.Value);
            }

            _repairingPlayers.Remove(player.userID);
        }