public void OnBlockInteractStop(float secondsUsed, IPlayer byPlayer, BlockSelection blockSel)
        {
            if (secondsUsed > 1.1 && FoliageState == EnumFoliageState.Ripe)
            {
                FoliageState = EnumFoliageState.Plain;
                MarkDirty(true);

                var loc   = AssetLocation.Create(Block.Attributes["branchBlock"].AsString(), Block.Code.Domain);
                var block = Api.World.GetBlock(loc) as BlockFruitTreeBranch;

                var drops = block.TypeProps[TreeType].FruitStacks;

                foreach (var drop in drops)
                {
                    ItemStack stack = drop.GetNextItemStack(1);
                    if (stack == null)
                    {
                        continue;
                    }

                    if (!byPlayer.InventoryManager.TryGiveItemstack(stack, true))
                    {
                        Api.World.SpawnItemEntity(stack, byPlayer.Entity.Pos.XYZ.Add(0, 0.5, 0));
                    }

                    if (drop.LastDrop)
                    {
                        break;
                    }
                }
            }
        }
        protected bool getRootBhSetupListener()
        {
            if (RootOff == null || RootOff.IsZero)
            {
                rootBh = GetBehavior <FruitTreeRootBH>();
            }
            else
            {
                var be = Api.World.BlockAccessor.GetBlockEntity(Pos.AddCopy(RootOff)) as BlockEntityFruitTreeBranch;
                rootBh = be?.GetBehavior <FruitTreeRootBH>();
            }

            if (TreeType == null)
            {
                Api.World.Logger.Error("Coding error. Fruit tree without fruit tree type @" + Pos);
                return(false);
            }

            if (rootBh != null && rootBh.propsByType.TryGetValue(TreeType, out var val))
            {
                switch (val.State)
                {
                case EnumFruitTreeState.EnterDormancy: FoliageState = EnumFoliageState.Plain; break;

                case EnumFruitTreeState.Dormant: FoliageState = EnumFoliageState.DormantNoLeaves; break;

                case EnumFruitTreeState.Flowering: FoliageState = EnumFoliageState.Flowering; break;

                case EnumFruitTreeState.Fruiting: FoliageState = EnumFoliageState.Fruiting; break;

                case EnumFruitTreeState.Ripe: FoliageState = EnumFoliageState.Ripe; break;

                case EnumFruitTreeState.Empty: FoliageState = EnumFoliageState.Plain; break;

                case EnumFruitTreeState.Young: FoliageState = EnumFoliageState.Plain; break;

                case EnumFruitTreeState.Dead: FoliageState = EnumFoliageState.Dead; break;
                }

                if (Api.Side == EnumAppSide.Server)
                {
                    rootBh.propsByType[TreeType].OnFruitingStateChange += RootBh_OnFruitingStateChange;
                }
                listenerOk = true;
                return(true);
            }

            return(false);
        }
        public override void FromTreeAttributes(ITreeAttribute tree, IWorldAccessor worldAccessForResolve)
        {
            base.FromTreeAttributes(tree, worldAccessForResolve);

            EnumFoliageState prevState = FoliageState;

            PartType     = (EnumTreePartType)tree.GetInt("partType");
            FoliageState = (EnumFoliageState)tree.GetInt("foliageState");
            GrowthDir    = BlockFacing.ALLFACES[tree.GetInt("growthDir")];
            TreeType     = tree.GetString("treeType");
            Height       = tree.GetInt("height");
            fruitingSide = tree.GetInt("fruitingSide", fruitingSide);

            if (tree.HasAttribute("rootOffX"))
            {
                RootOff = new Vec3i(tree.GetInt("rootOffX"), tree.GetInt("rootOffY"), tree.GetInt("rootOffZ"));
            }

            if (Api != null && Api.Side == EnumAppSide.Client && prevState != FoliageState)
            {
                MarkDirty(true);
            }
        }
        protected void RootBh_OnFruitingStateChange(EnumFruitTreeState nowState)
        {
            switch (nowState)
            {
            case EnumFruitTreeState.EnterDormancy: FoliageState = EnumFoliageState.Plain; break;

            case EnumFruitTreeState.Dormant: FoliageState = EnumFoliageState.DormantNoLeaves; break;

            case EnumFruitTreeState.Flowering: FoliageState = EnumFoliageState.Flowering; break;

            case EnumFruitTreeState.Fruiting: FoliageState = EnumFoliageState.Fruiting; break;

            case EnumFruitTreeState.Ripe: FoliageState = EnumFoliageState.Ripe; break;

            case EnumFruitTreeState.Empty: FoliageState = EnumFoliageState.Plain; break;

            case EnumFruitTreeState.Young: FoliageState = EnumFoliageState.Plain; break;

            case EnumFruitTreeState.Dead: FoliageState = EnumFoliageState.Dead; break;
            }

            calcFruitingSide();
            MarkDirty();
        }