public override void CheckTransition(float dt) { tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); double rainLevel = 0; bool rainCheck = Api.Side == EnumAppSide.Server && Api.World.Rand.NextDouble() < 0.15 && Api.World.BlockAccessor.GetRainMapHeightAt(Pos.X, Pos.Z) <= Pos.Y && (rainLevel = wsys.GetPrecipitation(tmpPos)) > 0.04 ; if (rainCheck && Api.World.Rand.NextDouble() < rainLevel * 5) { Api.World.PlaySoundAt(new AssetLocation("sounds/effect/extinguish"), Pos.X + 0.5, Pos.Y + 0.75, Pos.Z + 0.5, null, false, 16); if (Api.World.Rand.NextDouble() < 0.2 + rainLevel / 2f) { Block block = Api.World.BlockAccessor.GetBlock(Pos); if (block.Attributes == null) { return; } var toCode = block.CodeWithVariant("state", "extinct").ToShortString(); tryTransition(toCode); } } if (Api.World.Rand.NextDouble() < 0.3) { base.CheckTransition(dt); } }
private void OnSlowServerTick(float dt) { if (!canBurn(FuelPos)) { KillFire(false); return; } Entity[] entities = Api.World.GetEntitiesAround(FirePos.ToVec3d().Add(0.5, 0.5, 0.5), 3, 3, (e) => true); Vec3d ownPos = FirePos.ToVec3d(); for (int i = 0; i < entities.Length; i++) { Entity entity = entities[i]; if (!CollisionTester.AabbIntersect(entity.SelectionBox, entity.ServerPos.X, entity.ServerPos.Y, entity.ServerPos.Z, fireCuboid, ownPos)) { continue; } if (entity.Alive) { entity.ReceiveDamage(new DamageSource() { Source = EnumDamageSource.Block, SourceBlock = fireBlock, SourcePos = ownPos, Type = EnumDamageType.Fire }, 2f); } if (Api.World.Rand.NextDouble() < 0.125) { entity.Ignite(); } } if (FuelPos != FirePos && Api.World.BlockAccessor.GetBlock(FirePos).LiquidCode == "water") { KillFire(false); return; } if (Api.World.BlockAccessor.GetRainMapHeightAt(FirePos.X, FirePos.Z) <= FirePos.Y) // It's more efficient to do this quick check before GetPrecipitation { // Die on rainfall tmpPos.Set(FirePos.X + 0.5, FirePos.Y + 0.5, FirePos.Z + 0.5); double rain = wsys.GetPrecipitation(tmpPos); if (rain > 0.15) { Api.World.PlaySoundAt(new AssetLocation("sounds/effect/extinguish"), FirePos.X + 0.5, FirePos.Y, FirePos.Z + 0.5, null, false, 16); if (rand.NextDouble() < rain / 2) { KillFire(false); return; } } } }
private void OnSlowTick(float dt) { if (Api.Side == EnumAppSide.Client) { return; } BlockPos neibPos = Pos.AddCopy(fromFacing.Opposite); neibBlock = Api.World.BlockAccessor.GetBlock(neibPos); if (!canBurn(neibBlock, neibPos)) { Api.World.BlockAccessor.SetBlock(0, Pos); Api.World.BlockAccessor.TriggerNeighbourBlockUpdate(Pos); return; } Entity[] entities = Api.World.GetEntitiesAround(Pos.ToVec3d().Add(0.5, 0.5, 0.5), 3, 3, (e) => e.Alive); Vec3d ownPos = Pos.ToVec3d(); for (int i = 0; i < entities.Length; i++) { Entity entity = entities[i]; if (CollisionTester.AabbIntersect(entity.CollisionBox, entity.ServerPos.X, entity.ServerPos.Y, entity.ServerPos.Z, fireCuboid, ownPos)) { entity.ReceiveDamage(new DamageSource() { Source = EnumDamageSource.Block, SourceBlock = fireBlock, SourcePos = ownPos, Type = EnumDamageType.Fire }, 2f); } } if (Api.World.BlockAccessor.GetRainMapHeightAt(Pos.X, Pos.Y) <= Pos.Y) // It's more efficient to do this quick check before GetPrecipitation { // Die on rainfall tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); double rain = wsys.GetPrecipitation(tmpPos); if (rain > 0.1) { Api.World.PlaySoundAt(new AssetLocation("sounds/effect/extinguish"), Pos.X + 0.5, Pos.Y, Pos.Z + 0.5, null, false, 16); if (rand.NextDouble() < rain / 2) { Api.World.BlockAccessor.SetBlock(0, Pos); Api.World.BlockAccessor.TriggerNeighbourBlockUpdate(Pos); return; } } } }
public bool shouldExtinguishFromRainFall(out float rainLevel) { rainLevel = 0; if (Api.Side == EnumAppSide.Server && IsBurning && Api.World.Rand.NextDouble() > 0.5) { if (Api.World.BlockAccessor.GetRainMapHeightAt(Pos.X, Pos.Z) <= Pos.Y) // It's more efficient to do this quick check before GetPrecipitation { // Die on rainfall tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); rainLevel = wsys.GetPrecipitation(tmpPos); if (rainLevel > 0.04 && Api.World.Rand.NextDouble() < rainLevel * 5) { return(true); } } } return(false); }
/// <summary> /// /// </summary> /// <returns>true if it was a longer interval check (checked rain as well) so that an UpdateFarmlandBlock() is advisable</returns> bool updateMoistureLevel(double totalDays, float waterDistance, bool skyExposed, ClimateCondition baseClimate = null) { tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); double hoursPassed = Math.Min((totalDays - lastMoistureLevelUpdateTotalDays) * Api.World.Calendar.HoursPerDay, 48); if (hoursPassed < 0.03f) { // Get wet from a water source moistureLevel = Math.Max(moistureLevel, GameMath.Clamp(1 - waterDistance / 4f, 0, 1)); return(false); } // Dry out moistureLevel = Math.Max(0, moistureLevel - (float)hoursPassed / 48f); // Get wet from a water source moistureLevel = Math.Max(moistureLevel, GameMath.Clamp(1 - waterDistance / 4f, 0, 1)); // Get wet from all the rainfall since last update if (skyExposed) { if (baseClimate == null && hoursPassed > 0) { baseClimate = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.WorldGenValues, totalDays - hoursPassed * Api.World.Calendar.HoursPerDay / 2); } while (hoursPassed > 0) { double rainLevel = wsys.GetPrecipitation(Pos, totalDays - hoursPassed * Api.World.Calendar.HoursPerDay, baseClimate); moistureLevel = GameMath.Clamp(moistureLevel + (float)rainLevel / 3f, 0, 1); hoursPassed--; } } lastMoistureLevelUpdateTotalDays = totalDays; return(true); }
bool updateMoistureLevel(double totalDays, float waterDistance) { tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); double hoursPassed = Math.Min((totalDays - lastMoistureLevelUpdateTotalDays) * Api.World.Calendar.HoursPerDay, 48); if (hoursPassed < 0.03f) { // Get wet from a water source moistureLevel = Math.Max(moistureLevel, GameMath.Clamp(1 - waterDistance / 4f, 0, 1)); return(true); } // Dry out moistureLevel = Math.Max(0, moistureLevel - (float)hoursPassed / 48f); // Get wet from a water source moistureLevel = Math.Max(moistureLevel, GameMath.Clamp(1 - waterDistance / 4f, 0, 1)); // Get wet from all the rainfall since last update if (Api.World.BlockAccessor.GetRainMapHeightAt(Pos.X, Pos.Z) <= Pos.Y + 1) { while (hoursPassed > 0) { double rainLevel = wsys.GetPrecipitation(tmpPos.X, tmpPos.Y, tmpPos.Z, totalDays - hoursPassed * Api.World.Calendar.HoursPerDay); moistureLevel = GameMath.Clamp(moistureLevel + (float)rainLevel / 3f, 0, 1); hoursPassed--; } } UpdateFarmlandBlock(); lastMoistureLevelUpdateTotalDays = totalDays; return(true); }
// Sync to client every 500ms private void On500msTick(float dt) { if (Api is ICoreServerAPI && (IsBurning || prevFurnaceTemperature != furnaceTemperature)) { MarkDirty(); } prevFurnaceTemperature = furnaceTemperature; if (Api.Side == EnumAppSide.Server && IsBurning && Api.World.Rand.NextDouble() > 0.5) { if (Api.World.BlockAccessor.GetRainMapHeightAt(Pos.X, Pos.Z) <= Pos.Y) // It's more efficient to do this quick check before GetPrecipitation { // Die on rainfall tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); double rainLevel = wsys.GetPrecipitation(tmpPos); if (rainLevel > 0.04 && Api.World.Rand.NextDouble() < rainLevel * 5) { Api.World.PlaySoundAt(new AssetLocation("sounds/effect/extinguish"), Pos.X + 0.5, Pos.Y, Pos.Z + 0.5, null, false, 16); fuelBurnTime -= (float)rainLevel / 10f; if (Api.World.Rand.NextDouble() < rainLevel / 5f || fuelBurnTime <= 0) { setBlockState("cold"); extinguishedTotalHours = -99; canIgniteFuel = false; fuelBurnTime = 0; maxFuelBurnTime = 0; } MarkDirty(true); } } } }
private void OnCommonTick(float dt) { if (burning) { double hoursPassed = Api.World.Calendar.TotalHours - lastTickTotalHours; if (fuelLevel > 0) { fuelLevel = Math.Max(0, fuelLevel - (float)(2.5 / 24 * hoursPassed)); } if (fuelLevel <= 0) { burning = false; } if (contents != null) { float temp = contents.Collectible.GetTemperature(Api.World, contents); if (temp < 1100) { float tempGain = (float)(hoursPassed * 1500); contents.Collectible.SetTemperature(Api.World, contents, Math.Min(1100, temp + tempGain)); } } } tmpPos.Set(Pos.X + 0.5, Pos.Y + 0.5, Pos.Z + 0.5); double rainLevel = 0; bool rainCheck = Api.Side == EnumAppSide.Server && Api.World.Rand.NextDouble() < 0.15 && Api.World.BlockAccessor.GetRainMapHeightAt(Pos.X, Pos.Z) <= Pos.Y && (rainLevel = wsys.GetPrecipitation(tmpPos)) > 0.1 ; if (rainCheck && Api.World.Rand.NextDouble() < rainLevel * 5) { bool playsound = false; if (burning) { playsound = true; fuelLevel -= (float)rainLevel / 250f; if (Api.World.Rand.NextDouble() < rainLevel / 30f || fuelLevel <= 0) { burning = false; } MarkDirty(true); } float temp = contents == null ? 0 : contents.Collectible.GetTemperature(Api.World, contents); if (temp > 20) { playsound = temp > 100; contents.Collectible.SetTemperature(Api.World, contents, Math.Min(1100, temp - 8), false); MarkDirty(true); } if (playsound) { Api.World.PlaySoundAt(new AssetLocation("sounds/effect/extinguish"), Pos.X + 0.5, Pos.Y + 0.75, Pos.Z + 0.5, null, false, 16); } } lastTickTotalHours = Api.World.Calendar.TotalHours; }