private void DamageWallOnTile(ref PlantInfo plantInfo, ref BlockingInfo blockInfo, int x, int y)
        {
            if (plantInfo.type == PlantType.NotDefined)
            {
                return;
            }

            var plantRule = _zone.Configuration.PlantRules.GetPlantRule(plantInfo.type);

            if (plantRule == null)
            {
                return;
            }

            //is it wall?
            if (!plantRule.AllowedOnNonNatural)
            {
                return;
            }

            //only degrades in the last few phases
            if (!plantInfo.IsWallInLastFewStates(plantRule))
            {
                return;
            }

            var globalX = x + _area.X1;
            var globalY = y + _area.Y1;

            //pbs might save it
            if (_pbsPositions != null && _pbsPositions.Count > 0)
            {
                if (PBSHelper.IsPBSInRange(_wallDistanceFromPBS, _pbsPositions, globalX, globalY))
                {
                    var closestPBSDistance = PBSHelper.GetMinimalDistance(_pbsPositions, globalX, globalY);

                    if (closestPBSDistance <= _intactDistance)
                    {
                        //pbs object in intact distance, wall is protected
                        return;
                    }

                    //in fading range

                    //near 1 .. far 0
                    var chanceToSurvive = 1 - ((closestPBSDistance - _intactDistance) / _gradientRange);

                    var random = FastRandom.NextDouble();

                    if (random < chanceToSurvive)
                    {
                        //it will happen inwards more often

                        //so the plant wont get unhealed as it is closer to a pbs but within the range
                        return;
                    }
                }
            }



            plantInfo.UnHealPlant();

            if (plantInfo.health > 0)
            {
                return;
            }

            blockInfo.Plant  = false;
            blockInfo.Height = 0;

            plantInfo.Clear();
            plantInfo.state = 1;
        }
        private void GrowPlantOnTile(int x, int y, ref PlantInfo plantInfo, ref BlockingInfo blockInfo)
        {
            var plantRule = _zone.Configuration.PlantRules.GetPlantRule(plantInfo.type);

            if (plantRule == null)
            {
                return;
            }

            if (plantInfo.time < plantRule.GrowRate)
            {
                //increase tile time
                plantInfo.time = (byte)(plantInfo.time + 1).Clamp(0, 255);
            }
            else
            {
                //make it grow!
                //Reset time
                plantInfo.time = 0;

                //get new state
                PlantType nextAction;
                byte      nextState;

                plantRule.GetNextState(plantInfo.state, out nextState, out nextAction);

                if (nextAction == 0)
                {
                    plantInfo.Clear();
                    plantInfo.state  = 1; //kill signal for client --> resulting type:0 state:1 which should NOT be cleaned, just next round!!!
                    blockInfo.Height = 0;
                    blockInfo.Plant  = false;

                    if (!plantRule.PlacesConcrete)
                    {
                        return;
                    }

                    var gx = x + _area.X1;
                    var gy = y + _area.Y1;
                    _zone.Terrain.Controls.UpdateValue(gx, gy, ci =>
                    {
                        ci.ClearAllConcrete();
                        return(ci);
                    });
                }
                else
                {
                    var healthRatio = plantInfo.GetHealthRatio(plantRule);

                    plantInfo.type   = nextAction;
                    plantInfo.state  = nextState;
                    plantInfo.health = (byte)(healthRatio * plantRule.Health[plantInfo.state]).Clamp(1, 255);

                    if (!plantRule.NotFruiting)
                    {
                        //yes, fruiting

                        if (plantRule.FruitingState <= nextState)
                        {
                            if (plantRule.FruitingState == nextState)
                            {
                                // first phase when the plant reached fruiting state
                                plantInfo.material = (byte)(Math.Min((int)(FastRandom.NextDouble(plantRule.FruitAmount * 0.05, plantRule.FruitAmount * 0.15)).Clamp(0, 255), plantRule.FruitAmount));
                            }
                            else
                            {
                                // change happened
                                plantInfo.material = (byte)(Math.Min((plantInfo.material + FastRandom.NextDouble(plantRule.FruitAmount * 0.15, plantRule.FruitAmount * 0.25)), plantRule.FruitAmount)).Clamp(0, 255);
                            }
                        }
                        else
                        {
                            plantInfo.material = 0;
                        }
                    }
                    else
                    {
                        plantInfo.material = 0;
                    }

                    blockInfo.Height = plantRule.GetBlockingHeight(plantInfo.state);
                    blockInfo.Plant  = blockInfo.Height > 0;
                }
            }
        }