private void DoExtractMinerals(IZone zone)
        {
            var terrainLock = GetLock().ThrowIfNotType <TerrainLock>(ErrorCodes.InvalidLockType);

            var ammo = GetAmmo() as MiningAmmo;

            if (ammo == null)
            {
                return;
            }

            var materialInfo = _materialHelper.GetMaterialInfo(ammo.MaterialType);

            CheckEnablerEffect(materialInfo);

            var mineralLayer   = zone.Terrain.GetMineralLayerOrThrow(materialInfo.Type);
            var materialAmount = materialInfo.Amount * _miningAmountModifier.Value;

            var extractedMaterials = Extract(mineralLayer, terrainLock.Location, (uint)materialAmount);

            extractedMaterials.Count.ThrowIfEqual(0, ErrorCodes.NoMineralOnTile);

            extractedMaterials.AddRange(_rareMaterialHandler.GenerateRareMaterials(materialInfo.EntityDefault.Definition));

            CreateBeam(terrainLock.Location, BeamState.AlignToTerrain);

            using (var scope = Db.CreateTransaction())
            {
                Debug.Assert(ParentRobot != null, "ParentRobot != null");
                var container = ParentRobot.GetContainer();
                Debug.Assert(container != null, "container != null");
                container.EnlistTransaction();

                var player = ParentRobot as Player;
                Debug.Assert(player != null, "player != null");

                foreach (var material in extractedMaterials)
                {
                    var item = (Item)Factory.CreateWithRandomEID(material.Definition);

                    item.Owner    = Owner;
                    item.Quantity = material.Quantity;

                    container.AddItem(item, true);

                    var drilledMineralDefinition = material.Definition;
                    var drilledQuantity          = material.Quantity;

                    player.MissionHandler.EnqueueMissionEventInfo(new DrillMineralEventInfo(player, drilledMineralDefinition, drilledQuantity, terrainLock.Location));
                    player.Zone?.MiningLogHandler.EnqueueMiningLog(drilledMineralDefinition, drilledQuantity);
                }

                //save container
                container.Save();
                OnGathererMaterial(zone, player);

                Transaction.Current.OnCommited(() => container.SendUpdateToOwnerAsync());
                scope.Complete();
            }
        }
        public IEnumerable <ItemInfo> HarvestPlant(Position position)
        {
            var result = new List <ItemInfo>();

            _zone.Terrain.Plants.UpdateValue(position, pi =>
            {
                pi.type.ThrowIfEqual(PlantType.NotDefined, ErrorCodes.NoPlantOnTile);
                var plantRule = _zone.Configuration.PlantRules.GetPlantRule(pi.type).ThrowIfNull(ErrorCodes.InvalidPlant);

                pi.material.ThrowIfLessOrEqual((byte)0, ErrorCodes.NoMaterialOnThePlant);
                pi.material--;

                if (pi.material <= 0)
                {
                    //elfogyott a material a novenybol
                    //megoljuk erobol
                    pi.Clear();
                    pi.state = 1; //force kidoles :)
                    //kill the blocking as well
                    _zone.Terrain.ClearPlantBlocking(position);
                }

                //resulting material
                var quantity = GetHarvestedAmountPerCycle(plantRule);
                result.Add(new ItemInfo(plantRule.FruitDefinition, quantity));
                result.AddRange(_rareMaterialHandler.GenerateRareMaterials(plantRule.FruitDefinition));
                return(pi);
            });

            return(result);
        }