Example #1
0
 void updateVernalizedHours(FruitTreeProperties props, float temp)
 {
     if (temp <= props.VernalizationTemp)
     {
         props.vernalizedHours += stateUpdateIntervalDays * Api.World.Calendar.HoursPerDay;
     }
 }
Example #2
0
        public void RegisterTreeType(string treeType)
        {
            if (treeType == null)
            {
                return;
            }
            if (propsByType.ContainsKey(treeType))
            {
                return;
            }

            FruitTreeTypeProperties typeProps;

            if (!blockBranch.TypeProps.TryGetValue(bebr.TreeType, out typeProps))
            {
                Api.Logger.Error("Missing fruitTreeProperties for dynamic tree of type '" + bebr.TreeType + "', will use default values.");
                typeProps = new FruitTreeTypeProperties();
            }

            var rnd   = Api.World.Rand;
            var props = propsByType[treeType] = new FruitTreeProperties()
            {
                EnterDormancyTemp    = typeProps.EnterDormancyTemp.nextFloat(1, rnd),
                LeaveDormancyTemp    = typeProps.LeaveDormancyTemp.nextFloat(1, rnd),
                FloweringDays        = typeProps.FloweringDays.nextFloat(1, rnd),
                FruitingDays         = typeProps.FruitingDays.nextFloat(1, rnd),
                RipeDays             = typeProps.RipeDays.nextFloat(1, rnd),
                GrowthStepDays       = typeProps.GrowthStepDays.nextFloat(1, rnd),
                DieBelowTemp         = typeProps.DieBelowTemp.nextFloat(1, rnd),
                FruitStacks          = typeProps.FruitStacks,
                CycleType            = typeProps.CycleType,
                VernalizationHours   = typeProps.VernalizationHours?.nextFloat(1, rnd) ?? 0,
                VernalizationTemp    = typeProps.VernalizationTemp?.nextFloat(1, rnd) ?? 0,
                BlossomAtYearRel     = typeProps.BlossomAtYearRel?.nextFloat(1, rnd) ?? 0,
                LooseLeavesBelowTemp = typeProps.LooseLeavesBelowTemp?.nextFloat(1, rnd) ?? 0,
                RootSizeMul          = typeProps.RootSizeMul?.nextFloat(1, rnd) ?? 0
            };

            // Genetic variability
            if (parentPlantStack != null)
            {
                props.EnterDormancyTemp    = typeProps.EnterDormancyTemp.ClampToRange(props.EnterDormancyTemp + parentPlantStack.Attributes?.GetFloat("enterDormancyTempDiff") ?? 0);
                props.LeaveDormancyTemp    = typeProps.LeaveDormancyTemp.ClampToRange(props.LeaveDormancyTemp + parentPlantStack.Attributes?.GetFloat("leaveDormancyTempDiff") ?? 0);
                props.FloweringDays        = typeProps.FloweringDays.ClampToRange(props.FloweringDays + parentPlantStack.Attributes?.GetFloat("floweringDaysDiff") ?? 0);
                props.FruitingDays         = typeProps.FruitingDays.ClampToRange(props.FruitingDays + parentPlantStack.Attributes?.GetFloat("fruitingDaysDiff") ?? 0);
                props.RipeDays             = typeProps.RipeDays.ClampToRange(props.RipeDays + parentPlantStack.Attributes?.GetFloat("ripeDaysDiff") ?? 0);
                props.GrowthStepDays       = typeProps.GrowthStepDays.ClampToRange(props.GrowthStepDays + parentPlantStack.Attributes?.GetFloat("growthStepDaysDiff") ?? 0);
                props.DieBelowTemp         = typeProps.DieBelowTemp.ClampToRange(props.DieBelowTemp + parentPlantStack.Attributes?.GetFloat("dieBelowTempDiff") ?? 0);
                props.VernalizationHours   = typeProps.VernalizationHours.ClampToRange(props.VernalizationHours + parentPlantStack.Attributes?.GetFloat("vernalizationHoursDiff") ?? 0);
                props.VernalizationTemp    = typeProps.VernalizationTemp.ClampToRange(props.VernalizationTemp + parentPlantStack.Attributes?.GetFloat("vernalizationTempDiff") ?? 0);
                props.BlossomAtYearRel     = typeProps.BlossomAtYearRel.ClampToRange(props.BlossomAtYearRel + parentPlantStack.Attributes?.GetFloat("blossomAtYearRelDiff") ?? 0);
                props.LooseLeavesBelowTemp = typeProps.LooseLeavesBelowTemp.ClampToRange(props.LooseLeavesBelowTemp + parentPlantStack.Attributes?.GetFloat("looseLeavesBelowTempDiff") ?? 0);
                props.RootSizeMul          = typeProps.RootSizeMul.ClampToRange(props.RootSizeMul + parentPlantStack.Attributes?.GetFloat("rootSizeMulDiff") ?? 0);
            }
        }
        public virtual bool GenFoliageMesh(bool withSticks, out MeshData foliageMesh, out MeshData sticksMesh)
        {
            foliageMesh = null;
            sticksMesh  = null;

            if (Api?.Side == EnumAppSide.Server || TreeType == null || TreeType == "")
            {
                return(false);
            }

            var foliageProps = blockFoliage.foliageProps[TreeType];

            LeafParticlesColor    = getOrCreateTexPos(foliageProps.LeafParticlesTexture.Base).RndColors;
            BlossomParticlesColor = getOrCreateTexPos(foliageProps.BlossomParticlesTexture.Base).RndColors;


            Dictionary <int, MeshData[]> meshesByKey = ObjectCacheUtil.GetOrCreate(Api, foliageDictCacheKey, () => new Dictionary <int, MeshData[]>());

            MeshData[] meshes;
            int        meshCacheKey = getHashCodeLeaves();

            if (meshesByKey.TryGetValue(meshCacheKey, out meshes))
            {
                sticksMesh  = meshes[0];
                foliageMesh = meshes[1];
                return(true);
            }

            meshes = new MeshData[2];

            // Foliage shape
            {
                string shapekey = "foliage-ver";
                if (GrowthDir.IsHorizontal)
                {
                    shapekey = "foliage-hor-" + GrowthDir.Code[0];
                }

                if (!blockBranch.Shapes.TryGetValue(shapekey, out var shapeData))
                {
                    return(false);
                }

                nowTesselatingShape = shapeData.Shape;

                List <string> selectiveElements = new List <string>();

                bool everGreen            = false;
                FruitTreeProperties props = null;
                if (rootBh?.propsByType.TryGetValue(TreeType, out props) == true)
                {
                    everGreen = props.CycleType == EnumTreeCycleType.Evergreen;
                }

                if (withSticks)
                {
                    selectiveElements.Add("sticks/*");
                    capi.Tesselator.TesselateShape("fruittreefoliage", nowTesselatingShape, out meshes[0], this, new Vec3f(shapeData.CShape.rotateX, shapeData.CShape.rotateY, shapeData.CShape.rotateZ), 0, 0, 0, null, selectiveElements.ToArray());
                }

                selectiveElements.Clear();
                if (FoliageState == EnumFoliageState.Flowering)
                {
                    selectiveElements.Add("blossom/*");
                }
                if (FoliageState != EnumFoliageState.Dead && FoliageState != EnumFoliageState.DormantNoLeaves && (FoliageState != EnumFoliageState.Flowering || everGreen))
                {
                    nowTesselatingShape.WalkElements("leaves/*", (elem) => { elem.SeasonColorMap = foliageProps.SeasonColorMap; elem.ClimateColorMap = foliageProps.ClimateColorMap; });
                    selectiveElements.Add("leaves/*");
                }

                float rndydeg = GameMath.MurmurHash3Mod(Pos.X, Pos.Y, Pos.Z, 3) * 22.5f - 22.5f;
                capi.Tesselator.TesselateShape("fruittreefoliage", nowTesselatingShape, out meshes[1], this, new Vec3f(shapeData.CShape.rotateX, shapeData.CShape.rotateY + rndydeg, shapeData.CShape.rotateZ), 0, 0, 0, null, selectiveElements.ToArray());

                sticksMesh  = meshes[0];
                foliageMesh = meshes[1];
            }

            // Fruit shape
            if (FoliageState == EnumFoliageState.Fruiting || FoliageState == EnumFoliageState.Ripe)
            {
                string shapekey = "fruit-" + TreeType;

                if (!blockBranch.Shapes.TryGetValue(shapekey, out var shapeData))
                {
                    return(false);
                }

                nowTesselatingShape = shapeData.Shape;

                List <string> selectiveElements = new List <string>();
                for (int i = 0; i < 4; i++)
                {
                    char f = BlockFacing.HORIZONTALS[i].Code[0];
                    if ((fruitingSide & (1 << i)) > 0)
                    {
                        selectiveElements.Add("fruits-" + f + "/*");
                    }
                }

                float rndydeg = GameMath.MurmurHash3Mod(Pos.X, Pos.Y, Pos.Z, 3) * 22.5f - 22.5f;
                capi.Tesselator.TesselateShape("fruittreefoliage", nowTesselatingShape, out var fruitMesh, this, new Vec3f(shapeData.CShape.rotateX, shapeData.CShape.rotateY, shapeData.CShape.rotateZ), 0, 0, 0, null, selectiveElements.ToArray());

                foliageMesh.AddMeshData(fruitMesh);
            }

            meshesByKey[meshCacheKey] = meshes;


            return(true);
        }
Example #4
0
        protected void OnTick(float dt)
        {
            var rootBe = Api.World.BlockAccessor.GetBlockEntity(ownBe.Pos.AddCopy(ownBe.RootOff)) as BlockEntityFruitTreeBranch;

            if (rootBe == null)
            {
                if (Api.World.Rand.NextDouble() < 0.25)
                {
                    Api.World.BlockAccessor.BreakBlock(ownBe.Pos, null);
                }
                return;
            }

            if (ownBe.GrowTries > 60 || ownBe.FoliageState == EnumFoliageState.Dead)
            {
                return;
            }

            double totalDays = Api.World.Calendar.TotalDays;

            ownBe.lastGrowthAttemptTotalDays = Math.Max(ownBe.lastGrowthAttemptTotalDays, totalDays - Api.World.Calendar.DaysPerYear * 4); // Don't simulate more than 4 years

            if (totalDays - ownBe.lastGrowthAttemptTotalDays < 0.5)
            {
                return;
            }

            double hoursPerDay = Api.World.Calendar.HoursPerDay;


            FruitTreeProperties props = null;

            var rootBh = rootBe.GetBehavior <FruitTreeRootBH>();

            if (rootBh?.propsByType.TryGetValue(ownBe.TreeType, out props) != true)
            {
                return;
            }
            if (ownBe.FoliageState == EnumFoliageState.Dead)
            {
                ownBe.UnregisterGameTickListener(listenerId);
                return;
            }


            double growthStepDays = props.GrowthStepDays;


            while (totalDays - ownBe.lastGrowthAttemptTotalDays > growthStepDays)
            {
                // Get midday temperature for testing (which is roughly the daily average)
                float temp = Api.World.BlockAccessor.GetClimateAt(ownBe.Pos, EnumGetClimateMode.ForSuppliedDate_TemperatureOnly, (int)ownBe.lastGrowthAttemptTotalDays + hoursPerDay / 2f).Temperature;
                if (temp < 12)
                {
                    ownBe.lastGrowthAttemptTotalDays += growthStepDays;
                    continue;
                }

                TryGrow();
                ownBe.lastGrowthAttemptTotalDays += growthStepDays;
                ownBe.GrowTries++;
            }
        }