void updateVernalizedHours(FruitTreeProperties props, float temp) { if (temp <= props.VernalizationTemp) { props.vernalizedHours += stateUpdateIntervalDays * Api.World.Calendar.HoursPerDay; } }
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); }
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++; } }