Refactor weather system to consolidate weather data handling; remove redundant weather API endpoint and related components, ensuring a single weather reading represents the entire world. Update UI to toggle weather effects and enhance rendering logic for improved visual consistency. Adjust documentation to reflect changes in weather data structure and API responses.
This commit is contained in:
@@ -18,6 +18,9 @@ public sealed class WorldSimulation : IDisposable
|
||||
/// </summary>
|
||||
private static readonly TimeSpan MaxWeatherStep = TimeSpan.FromHours(6);
|
||||
|
||||
/// <summary>The pressure field is only ever read here - one point speaks for the whole map.</summary>
|
||||
private const float MapCentre = 0.5f;
|
||||
|
||||
private readonly object _gate = new();
|
||||
private readonly World _ecs;
|
||||
private readonly Entity _clockEntity;
|
||||
@@ -225,17 +228,17 @@ public sealed class WorldSimulation : IDisposable
|
||||
|
||||
// Snow lies on the ground, so it has to be integrated as the sky moves rather than derived from the
|
||||
// instant. The middle of the map speaks for all of it; over ten kilometres that is no lie worth care.
|
||||
var overhead = SampleRawUnlocked(0.5f, 0.5f, gameTime);
|
||||
var overhead = SampleRawUnlocked(gameTime);
|
||||
WeatherSystem.AccumulateSnow(_ecs, overhead.TemperatureC, overhead.PrecipitationMmH, hours);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private WeatherSample SampleRawUnlocked(float x, float y, DateTime gameTime)
|
||||
private WeatherSample SampleRawUnlocked(DateTime gameTime)
|
||||
{
|
||||
Span<PressureSystem> systems = stackalloc PressureSystem[WeatherSystem.MaxSystems];
|
||||
var count = WeatherSystem.CopySystems(_ecs, systems);
|
||||
var (anomaly, gradientX, gradientY) = WeatherModel.SampleField(systems[..count], x, y);
|
||||
var (anomaly, gradientX, gradientY) = WeatherModel.SampleField(systems[..count], MapCentre, MapCentre);
|
||||
return WeatherModel.Sample(_climate, _latitude, gameTime, anomaly, gradientX, gradientY);
|
||||
}
|
||||
|
||||
@@ -308,12 +311,9 @@ public sealed class WorldSimulation : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nodes per side of the weather grid served to the renderer. Fine enough to carry the shape of the
|
||||
/// smallest pressure system without aliasing, and still only a couple of hundred numbers on the wire.
|
||||
/// The world's weather. One reading covers the whole map: a generated world is a town, not a continent,
|
||||
/// and a shower does not fall on half of one.
|
||||
/// </summary>
|
||||
public const int WeatherGridSize = 12;
|
||||
|
||||
/// <summary>Weather at the middle of the map - what the HUD and the world list show.</summary>
|
||||
public WeatherDto SnapshotWeather()
|
||||
{
|
||||
lock (_gate)
|
||||
@@ -322,54 +322,19 @@ public sealed class WorldSimulation : IDisposable
|
||||
|
||||
Span<PressureSystem> systems = stackalloc PressureSystem[WeatherSystem.MaxSystems];
|
||||
var count = WeatherSystem.CopySystems(_ecs, systems);
|
||||
return SampleUnlocked(systems[..count], 0.5f, 0.5f);
|
||||
return SampleUnlocked(systems[..count]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The whole weather field as a square grid, row-major from the south-west corner. Sampled in one pass so
|
||||
/// every node sees the same instant and the same pressure systems.
|
||||
/// </summary>
|
||||
public WeatherFieldDto SnapshotWeatherField()
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
Span<PressureSystem> systems = stackalloc PressureSystem[WeatherSystem.MaxSystems];
|
||||
var count = WeatherSystem.CopySystems(_ecs, systems);
|
||||
var live = systems[..count];
|
||||
|
||||
var nodes = new WeatherDto[WeatherGridSize * WeatherGridSize];
|
||||
for (var row = 0; row < WeatherGridSize; row++)
|
||||
{
|
||||
for (var column = 0; column < WeatherGridSize; column++)
|
||||
{
|
||||
var x = column / (float)(WeatherGridSize - 1);
|
||||
var y = row / (float)(WeatherGridSize - 1);
|
||||
nodes[(row * WeatherGridSize) + column] = SampleUnlocked(live, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return new WeatherFieldDto
|
||||
{
|
||||
Climate = _climate.Kind,
|
||||
Size = WeatherGridSize,
|
||||
Nodes = nodes,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private WeatherDto SampleUnlocked(ReadOnlySpan<PressureSystem> systems, float x, float y)
|
||||
private WeatherDto SampleUnlocked(ReadOnlySpan<PressureSystem> systems)
|
||||
{
|
||||
var gameTime = new DateTime(_ecs.Get<GameClock>(_clockEntity).Ticks, DateTimeKind.Unspecified);
|
||||
var (anomaly, gradientX, gradientY) = WeatherModel.SampleField(systems, x, y);
|
||||
var (anomaly, gradientX, gradientY) = WeatherModel.SampleField(systems, MapCentre, MapCentre);
|
||||
var sample = WeatherModel.Sample(_climate, _latitude, gameTime, anomaly, gradientX, gradientY);
|
||||
|
||||
return new WeatherDto
|
||||
{
|
||||
SnowDepthMm = Math.Round(
|
||||
WeatherModel.LocalSnowDepth(WeatherSystem.SnowDepthMm(_ecs), sample.TemperatureC), 1),
|
||||
SnowDepthMm = Math.Round(WeatherSystem.SnowDepthMm(_ecs), 1),
|
||||
Condition = sample.Condition,
|
||||
TemperatureC = Math.Round(sample.TemperatureC, 1),
|
||||
FeelsLikeC = Math.Round(sample.FeelsLikeC, 1),
|
||||
@@ -414,7 +379,7 @@ public sealed class WorldSimulation : IDisposable
|
||||
{
|
||||
Clock = SnapshotClockUnlocked(),
|
||||
Climate = _climate.Kind,
|
||||
Weather = SampleUnlocked(systems[..count], 0.5f, 0.5f),
|
||||
Weather = SampleUnlocked(systems[..count]),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user