Map provider weather inputs
This commit is contained in:
@@ -429,7 +429,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
|||||||
- [x] Use Open-Meteo as the first global MVP weather source. Added `Data/Weather/open_meteo_mvp_source.json` as the provider contract, documented the global tile lookup rule, and added `Scripts/verify_open_meteo_mvp_source.py` to validate the static contract plus live Open-Meteo responses for every source-backed tile in the generated weather manifest.
|
- [x] Use Open-Meteo as the first global MVP weather source. Added `Data/Weather/open_meteo_mvp_source.json` as the provider contract, documented the global tile lookup rule, and added `Scripts/verify_open_meteo_mvp_source.py` to validate the static contract plus live Open-Meteo responses for every source-backed tile in the generated weather manifest.
|
||||||
- [x] Add NOAA/NWS fallback or enrichment for US tiles where useful. Added a US/NWS-eligible coordinate check, NOAA/NWS points and forecast-grid request hooks, fallback parsing for gridded temperature, precipitation probability, and wind speed, `Data/Weather/noaa_nws_us_fallback.json`, and live/static verification for source-backed US tiles.
|
- [x] Add NOAA/NWS fallback or enrichment for US tiles where useful. Added a US/NWS-eligible coordinate check, NOAA/NWS points and forecast-grid request hooks, fallback parsing for gridded temperature, precipitation probability, and wind speed, `Data/Weather/noaa_nws_us_fallback.json`, and live/static verification for source-backed US tiles.
|
||||||
- [x] Cache real-weather snapshots server-side so clients never call public weather APIs directly. Added provider/tile-keyed server cache entries with TTL, cache reuse before Open-Meteo or NOAA/NWS requests, cache clearing/debug helpers, and documentation that clients consume only replicated game-state weather and temperature.
|
- [x] Cache real-weather snapshots server-side so clients never call public weather APIs directly. Added provider/tile-keyed server cache entries with TTL, cache reuse before Open-Meteo or NOAA/NWS requests, cache clearing/debug helpers, and documentation that clients consume only replicated game-state weather and temperature.
|
||||||
- [ ] Map real weather inputs into Agrarian weather states: temperature, precipitation, wind, cloud cover, humidity, pressure, visibility, and weather code.
|
- [x] Map real weather inputs into Agrarian weather states: temperature, precipitation, wind, cloud cover, humidity, pressure, visibility, and weather code. Added replicated `FAgrarianMappedWeatherInputs`, provider snapshot mapping, Open-Meteo visibility derivation, NOAA/NWS grid enrichment for humidity/sky cover/pressure/visibility, and game-state application that preserves raw mapped inputs alongside the collapsed Agrarian weather state.
|
||||||
- [ ] Add deterministic fallback weather simulation when external weather data is unavailable.
|
- [ ] Add deterministic fallback weather simulation when external weather data is unavailable.
|
||||||
- [ ] Store weather source, provider timestamp, tile coordinate, and applied in-game weather state for debugging and persistence.
|
- [ ] Store weather source, provider timestamp, tile coordinate, and applied in-game weather state for debugging and persistence.
|
||||||
- [ ] Add weather save/load support.
|
- [ ] Add weather save/load support.
|
||||||
|
|||||||
@@ -182,6 +182,14 @@ call Open-Meteo or NOAA/NWS. Clients never call Open-Meteo or NOAA/NWS directly.
|
|||||||
They receive weather, temperature, source, and state through replicated game
|
They receive weather, temperature, source, and state through replicated game
|
||||||
state fields.
|
state fields.
|
||||||
|
|
||||||
|
Real-weather provider values are mapped into `FAgrarianMappedWeatherInputs`
|
||||||
|
before they affect gameplay. The mapped snapshot keeps temperature,
|
||||||
|
precipitation, wind, cloud cover, humidity, pressure, visibility, and provider
|
||||||
|
weather code available alongside the collapsed Agrarian weather state. Open-Meteo
|
||||||
|
fills those fields directly where available; NOAA/NWS fills them from grid data
|
||||||
|
where available and derives provisional visibility/weather-state values until a
|
||||||
|
deeper provider-specific mapping pass is added.
|
||||||
|
|
||||||
## Terrain And Tile Delivery
|
## Terrain And Tile Delivery
|
||||||
|
|
||||||
### MVP Tile
|
### MVP Tile
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
TYPES_H = ROOT / "Source" / "AgrarianGame" / "AgrarianTypes.h"
|
||||||
|
GAME_STATE_H = ROOT / "Source" / "AgrarianGame" / "AgrarianGameState.h"
|
||||||
|
GAME_STATE_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianGameState.cpp"
|
||||||
|
PROVIDER_H = ROOT / "Source" / "AgrarianGame" / "AgrarianWeatherProviderSubsystem.h"
|
||||||
|
PROVIDER_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianWeatherProviderSubsystem.cpp"
|
||||||
|
TDD = ROOT / "Docs" / "TechnicalDesignDocument.md"
|
||||||
|
ROADMAP = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md"
|
||||||
|
|
||||||
|
|
||||||
|
EXPECTED = {
|
||||||
|
TYPES_H: [
|
||||||
|
"FAgrarianMappedWeatherInputs",
|
||||||
|
"TemperatureC",
|
||||||
|
"PrecipitationMm",
|
||||||
|
"WindSpeedKmh",
|
||||||
|
"CloudCoverPercent",
|
||||||
|
"RelativeHumidityPercent",
|
||||||
|
"PressureMslHpa",
|
||||||
|
"VisibilityMeters",
|
||||||
|
"ProviderWeatherCode",
|
||||||
|
],
|
||||||
|
GAME_STATE_H: [
|
||||||
|
"FAgrarianMappedWeatherInputs ActiveWeatherInputs",
|
||||||
|
"ApplyMappedWeatherInputs",
|
||||||
|
],
|
||||||
|
GAME_STATE_CPP: [
|
||||||
|
"DOREPLIFETIME(AAgrarianGameState, ActiveWeatherInputs);",
|
||||||
|
"void AAgrarianGameState::ApplyMappedWeatherInputs",
|
||||||
|
"SetRegionalTemperatureProfile",
|
||||||
|
"SetRegionalObservedTemperature",
|
||||||
|
"SetWeather(ActiveWeatherInputs.MappedWeather)",
|
||||||
|
],
|
||||||
|
PROVIDER_H: [
|
||||||
|
"VisibilityMeters",
|
||||||
|
"MapSnapshotToAgrarianWeatherInputs",
|
||||||
|
],
|
||||||
|
PROVIDER_CPP: [
|
||||||
|
"FAgrarianMappedWeatherInputs UAgrarianWeatherProviderSubsystem::MapSnapshotToAgrarianWeatherInputs",
|
||||||
|
"GameState->ApplyMappedWeatherInputs",
|
||||||
|
"OutSnapshot.VisibilityMeters",
|
||||||
|
"relativeHumidity",
|
||||||
|
"skyCover",
|
||||||
|
"pressure",
|
||||||
|
"visibility",
|
||||||
|
],
|
||||||
|
TDD: [
|
||||||
|
"Real-weather provider values are mapped into `FAgrarianMappedWeatherInputs`",
|
||||||
|
"weather code available alongside the collapsed Agrarian weather state",
|
||||||
|
],
|
||||||
|
ROADMAP: [
|
||||||
|
"[x] Map real weather inputs into Agrarian weather states: temperature, precipitation, wind, cloud cover, humidity, pressure, visibility, and weather code.",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
missing = []
|
||||||
|
for path, snippets in EXPECTED.items():
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
for snippet in snippets:
|
||||||
|
if snippet not in text:
|
||||||
|
missing.append(f"{path.relative_to(ROOT)}: {snippet}")
|
||||||
|
if missing:
|
||||||
|
raise RuntimeError("Weather input mapping verification failed: " + "; ".join(missing))
|
||||||
|
print("Agrarian weather input mapping verification complete.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -98,6 +98,7 @@ void AAgrarianGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& O
|
|||||||
DOREPLIFETIME(AAgrarianGameState, ObservedTemperatureBlend);
|
DOREPLIFETIME(AAgrarianGameState, ObservedTemperatureBlend);
|
||||||
DOREPLIFETIME(AAgrarianGameState, bHasRegionalObservedTemperature);
|
DOREPLIFETIME(AAgrarianGameState, bHasRegionalObservedTemperature);
|
||||||
DOREPLIFETIME(AAgrarianGameState, RegionalWeatherSource);
|
DOREPLIFETIME(AAgrarianGameState, RegionalWeatherSource);
|
||||||
|
DOREPLIFETIME(AAgrarianGameState, ActiveWeatherInputs);
|
||||||
DOREPLIFETIME(AAgrarianGameState, DaysPerAgrarianYear);
|
DOREPLIFETIME(AAgrarianGameState, DaysPerAgrarianYear);
|
||||||
DOREPLIFETIME(AAgrarianGameState, ActiveSolarTileId);
|
DOREPLIFETIME(AAgrarianGameState, ActiveSolarTileId);
|
||||||
DOREPLIFETIME(AAgrarianGameState, ActiveTileLatitude);
|
DOREPLIFETIME(AAgrarianGameState, ActiveTileLatitude);
|
||||||
@@ -160,6 +161,33 @@ void AAgrarianGameState::SetRegionalObservedTemperature(float ObservedTemperatur
|
|||||||
UpdateAmbientTemperature();
|
UpdateAmbientTemperature();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AAgrarianGameState::ApplyMappedWeatherInputs(const FAgrarianMappedWeatherInputs& MappedInputs)
|
||||||
|
{
|
||||||
|
if (!HasAuthority())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveWeatherInputs = MappedInputs;
|
||||||
|
ActiveWeatherInputs.TemperatureC = FMath::Clamp(ActiveWeatherInputs.TemperatureC, -80.0f, 70.0f);
|
||||||
|
ActiveWeatherInputs.DailyLowTemperatureC = FMath::Clamp(ActiveWeatherInputs.DailyLowTemperatureC, -80.0f, 70.0f);
|
||||||
|
ActiveWeatherInputs.DailyHighTemperatureC = FMath::Clamp(ActiveWeatherInputs.DailyHighTemperatureC, -80.0f, 70.0f);
|
||||||
|
ActiveWeatherInputs.PrecipitationMm = FMath::Max(0.0f, ActiveWeatherInputs.PrecipitationMm);
|
||||||
|
ActiveWeatherInputs.WindSpeedKmh = FMath::Max(0.0f, ActiveWeatherInputs.WindSpeedKmh);
|
||||||
|
ActiveWeatherInputs.CloudCoverPercent = FMath::Clamp(ActiveWeatherInputs.CloudCoverPercent, 0.0f, 100.0f);
|
||||||
|
ActiveWeatherInputs.RelativeHumidityPercent = FMath::Clamp(ActiveWeatherInputs.RelativeHumidityPercent, 0.0f, 100.0f);
|
||||||
|
ActiveWeatherInputs.PressureMslHpa = FMath::Clamp(ActiveWeatherInputs.PressureMslHpa, 800.0f, 1100.0f);
|
||||||
|
ActiveWeatherInputs.VisibilityMeters = FMath::Max(0.0f, ActiveWeatherInputs.VisibilityMeters);
|
||||||
|
ActiveWeatherInputs.bHasProviderData = true;
|
||||||
|
|
||||||
|
SetRegionalTemperatureProfile(ActiveWeatherInputs.DailyLowTemperatureC, ActiveWeatherInputs.DailyHighTemperatureC);
|
||||||
|
SetRegionalObservedTemperature(
|
||||||
|
ActiveWeatherInputs.TemperatureC,
|
||||||
|
1.0f,
|
||||||
|
FString::Printf(TEXT("%s:%s"), *ActiveWeatherInputs.Provider, *ActiveWeatherInputs.ProviderTimestamp));
|
||||||
|
SetWeather(ActiveWeatherInputs.MappedWeather);
|
||||||
|
}
|
||||||
|
|
||||||
float AAgrarianGameState::GetClearSkyTemperatureForHour(float HourOfDay) const
|
float AAgrarianGameState::GetClearSkyTemperatureForHour(float HourOfDay) const
|
||||||
{
|
{
|
||||||
const float LowTemperature = FMath::Min(RegionalDailyLowTemperatureC, RegionalDailyHighTemperatureC);
|
const float LowTemperature = FMath::Min(RegionalDailyLowTemperatureC, RegionalDailyHighTemperatureC);
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
||||||
FString RegionalWeatherSource = TEXT("deterministic_tile_curve");
|
FString RegionalWeatherSource = TEXT("deterministic_tile_curve");
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Weather")
|
||||||
|
FAgrarianMappedWeatherInputs ActiveWeatherInputs;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
|
||||||
FName ActiveSolarTileId = TEXT("gz_us_ca_pacifica_utm10n_e544_n4160");
|
FName ActiveSolarTileId = TEXT("gz_us_ca_pacifica_utm10n_e544_n4160");
|
||||||
|
|
||||||
@@ -103,6 +106,9 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Temperature")
|
UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Temperature")
|
||||||
void SetRegionalObservedTemperature(float ObservedTemperatureC, float BlendWeight, const FString& WeatherSource);
|
void SetRegionalObservedTemperature(float ObservedTemperatureC, float BlendWeight, const FString& WeatherSource);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Weather")
|
||||||
|
void ApplyMappedWeatherInputs(const FAgrarianMappedWeatherInputs& MappedInputs);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Agrarian|World|Temperature")
|
UFUNCTION(BlueprintPure, Category = "Agrarian|World|Temperature")
|
||||||
float GetClearSkyTemperatureForHour(float HourOfDay) const;
|
float GetClearSkyTemperatureForHour(float HourOfDay) const;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,54 @@ enum class EAgrarianWeatherType : uint8
|
|||||||
Storm UMETA(DisplayName = "Storm")
|
Storm UMETA(DisplayName = "Storm")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FAgrarianMappedWeatherInputs
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float TemperatureC = 12.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float DailyLowTemperatureC = 9.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float DailyHighTemperatureC = 18.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float PrecipitationMm = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float WindSpeedKmh = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float CloudCoverPercent = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float RelativeHumidityPercent = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float PressureMslHpa = 1013.25f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float VisibilityMeters = 10000.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
int32 ProviderWeatherCode = 0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
EAgrarianWeatherType MappedWeather = EAgrarianWeatherType::Clear;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
FString Provider = TEXT("deterministic");
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
FString ProviderTimestamp;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
bool bHasProviderData = false;
|
||||||
|
};
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
UENUM(BlueprintType)
|
||||||
enum class EAgrarianSeason : uint8
|
enum class EAgrarianSeason : uint8
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -111,15 +111,30 @@ bool UAgrarianWeatherProviderSubsystem::ApplySnapshotToGameState(const FAgrarian
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState->SetRegionalTemperatureProfile(Snapshot.DailyLowTemperatureC, Snapshot.DailyHighTemperatureC);
|
GameState->ApplyMappedWeatherInputs(MapSnapshotToAgrarianWeatherInputs(Snapshot));
|
||||||
GameState->SetRegionalObservedTemperature(
|
|
||||||
Snapshot.CurrentTemperatureC,
|
|
||||||
1.0f,
|
|
||||||
FString::Printf(TEXT("%s:%s"), *Snapshot.Provider, *Snapshot.ProviderTimestamp));
|
|
||||||
GameState->SetWeather(Snapshot.MappedWeather);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FAgrarianMappedWeatherInputs UAgrarianWeatherProviderSubsystem::MapSnapshotToAgrarianWeatherInputs(const FAgrarianWeatherProviderSnapshot& Snapshot) const
|
||||||
|
{
|
||||||
|
FAgrarianMappedWeatherInputs MappedInputs;
|
||||||
|
MappedInputs.TemperatureC = Snapshot.CurrentTemperatureC;
|
||||||
|
MappedInputs.DailyLowTemperatureC = Snapshot.DailyLowTemperatureC;
|
||||||
|
MappedInputs.DailyHighTemperatureC = Snapshot.DailyHighTemperatureC;
|
||||||
|
MappedInputs.PrecipitationMm = Snapshot.PrecipitationMm;
|
||||||
|
MappedInputs.WindSpeedKmh = Snapshot.WindSpeedKmh;
|
||||||
|
MappedInputs.CloudCoverPercent = Snapshot.CloudCoverPercent;
|
||||||
|
MappedInputs.RelativeHumidityPercent = Snapshot.RelativeHumidityPercent;
|
||||||
|
MappedInputs.PressureMslHpa = Snapshot.PressureMslHpa > 0.0f ? Snapshot.PressureMslHpa : 1013.25f;
|
||||||
|
MappedInputs.VisibilityMeters = Snapshot.VisibilityMeters;
|
||||||
|
MappedInputs.ProviderWeatherCode = Snapshot.WeatherCode;
|
||||||
|
MappedInputs.MappedWeather = Snapshot.MappedWeather;
|
||||||
|
MappedInputs.Provider = Snapshot.Provider;
|
||||||
|
MappedInputs.ProviderTimestamp = Snapshot.ProviderTimestamp;
|
||||||
|
MappedInputs.bHasProviderData = Snapshot.bIsValid;
|
||||||
|
return MappedInputs;
|
||||||
|
}
|
||||||
|
|
||||||
bool UAgrarianWeatherProviderSubsystem::TryApplyCachedSnapshot(FName TileId, const FString& Provider, AAgrarianGameState* GameState)
|
bool UAgrarianWeatherProviderSubsystem::TryApplyCachedSnapshot(FName TileId, const FString& Provider, AAgrarianGameState* GameState)
|
||||||
{
|
{
|
||||||
if (!GameState || !GameState->HasAuthority())
|
if (!GameState || !GameState->HasAuthority())
|
||||||
@@ -331,6 +346,7 @@ bool UAgrarianWeatherProviderSubsystem::ParseOpenMeteoForecast(const FString& Re
|
|||||||
OutSnapshot.CloudCoverPercent = static_cast<float>(CloudCover);
|
OutSnapshot.CloudCoverPercent = static_cast<float>(CloudCover);
|
||||||
OutSnapshot.RelativeHumidityPercent = static_cast<float>(RelativeHumidity);
|
OutSnapshot.RelativeHumidityPercent = static_cast<float>(RelativeHumidity);
|
||||||
OutSnapshot.PressureMslHpa = static_cast<float>(Pressure);
|
OutSnapshot.PressureMslHpa = static_cast<float>(Pressure);
|
||||||
|
OutSnapshot.VisibilityMeters = FMath::Clamp(10000.0f - (OutSnapshot.CloudCoverPercent * 35.0f) - (OutSnapshot.PrecipitationMm * 250.0f), 250.0f, 10000.0f);
|
||||||
OutSnapshot.WeatherCode = FMath::RoundToInt(WeatherCode);
|
OutSnapshot.WeatherCode = FMath::RoundToInt(WeatherCode);
|
||||||
OutSnapshot.MappedWeather = MapOpenMeteoWeatherCode(OutSnapshot.WeatherCode, OutSnapshot.PrecipitationMm, OutSnapshot.WindSpeedKmh);
|
OutSnapshot.MappedWeather = MapOpenMeteoWeatherCode(OutSnapshot.WeatherCode, OutSnapshot.PrecipitationMm, OutSnapshot.WindSpeedKmh);
|
||||||
OutSnapshot.bIsValid = true;
|
OutSnapshot.bIsValid = true;
|
||||||
@@ -378,8 +394,16 @@ bool UAgrarianWeatherProviderSubsystem::ParseNoaaNwsGridData(const FString& Resp
|
|||||||
|
|
||||||
double PrecipitationPercent = 0.0;
|
double PrecipitationPercent = 0.0;
|
||||||
double WindSpeedKmh = 0.0;
|
double WindSpeedKmh = 0.0;
|
||||||
|
double RelativeHumidity = 0.0;
|
||||||
|
double SkyCover = 0.0;
|
||||||
|
double Pressure = 0.0;
|
||||||
|
double Visibility = 0.0;
|
||||||
ReadFirstGridValue(*PropertiesObject, TEXT("probabilityOfPrecipitation"), PrecipitationPercent);
|
ReadFirstGridValue(*PropertiesObject, TEXT("probabilityOfPrecipitation"), PrecipitationPercent);
|
||||||
ReadFirstGridValue(*PropertiesObject, TEXT("windSpeed"), WindSpeedKmh);
|
ReadFirstGridValue(*PropertiesObject, TEXT("windSpeed"), WindSpeedKmh);
|
||||||
|
ReadFirstGridValue(*PropertiesObject, TEXT("relativeHumidity"), RelativeHumidity);
|
||||||
|
ReadFirstGridValue(*PropertiesObject, TEXT("skyCover"), SkyCover);
|
||||||
|
ReadFirstGridValue(*PropertiesObject, TEXT("pressure"), Pressure);
|
||||||
|
ReadFirstGridValue(*PropertiesObject, TEXT("visibility"), Visibility);
|
||||||
|
|
||||||
OutSnapshot.TileId = TileId;
|
OutSnapshot.TileId = TileId;
|
||||||
OutSnapshot.Latitude = FMath::Clamp(Latitude, -90.0f, 90.0f);
|
OutSnapshot.Latitude = FMath::Clamp(Latitude, -90.0f, 90.0f);
|
||||||
@@ -391,6 +415,10 @@ bool UAgrarianWeatherProviderSubsystem::ParseNoaaNwsGridData(const FString& Resp
|
|||||||
OutSnapshot.DailyHighTemperatureC = static_cast<float>(TemperatureC + 4.0);
|
OutSnapshot.DailyHighTemperatureC = static_cast<float>(TemperatureC + 4.0);
|
||||||
OutSnapshot.PrecipitationMm = PrecipitationPercent > 30.0 ? 0.1f : 0.0f;
|
OutSnapshot.PrecipitationMm = PrecipitationPercent > 30.0 ? 0.1f : 0.0f;
|
||||||
OutSnapshot.WindSpeedKmh = static_cast<float>(WindSpeedKmh);
|
OutSnapshot.WindSpeedKmh = static_cast<float>(WindSpeedKmh);
|
||||||
|
OutSnapshot.CloudCoverPercent = static_cast<float>(SkyCover);
|
||||||
|
OutSnapshot.RelativeHumidityPercent = static_cast<float>(RelativeHumidity);
|
||||||
|
OutSnapshot.PressureMslHpa = Pressure > 0.0 ? static_cast<float>(Pressure / 100.0) : 1013.25f;
|
||||||
|
OutSnapshot.VisibilityMeters = Visibility > 0.0 ? static_cast<float>(Visibility) : FMath::Clamp(10000.0f - (OutSnapshot.CloudCoverPercent * 35.0f), 250.0f, 10000.0f);
|
||||||
OutSnapshot.WeatherCode = PrecipitationPercent > 30.0 ? 61 : 0;
|
OutSnapshot.WeatherCode = PrecipitationPercent > 30.0 ? 61 : 0;
|
||||||
OutSnapshot.MappedWeather = MapOpenMeteoWeatherCode(OutSnapshot.WeatherCode, OutSnapshot.PrecipitationMm, OutSnapshot.WindSpeedKmh);
|
OutSnapshot.MappedWeather = MapOpenMeteoWeatherCode(OutSnapshot.WeatherCode, OutSnapshot.PrecipitationMm, OutSnapshot.WindSpeedKmh);
|
||||||
OutSnapshot.bIsValid = true;
|
OutSnapshot.bIsValid = true;
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ struct FAgrarianWeatherProviderSnapshot
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
float PressureMslHpa = 0.0f;
|
float PressureMslHpa = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
|
float VisibilityMeters = 10000.0f;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather")
|
||||||
int32 WeatherCode = 0;
|
int32 WeatherCode = 0;
|
||||||
|
|
||||||
@@ -142,6 +145,9 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Weather")
|
UFUNCTION(BlueprintCallable, Category = "Agrarian|Weather")
|
||||||
bool ApplySnapshotToGameState(const FAgrarianWeatherProviderSnapshot& Snapshot, AAgrarianGameState* GameState) const;
|
bool ApplySnapshotToGameState(const FAgrarianWeatherProviderSnapshot& Snapshot, AAgrarianGameState* GameState) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Agrarian|Weather")
|
||||||
|
FAgrarianMappedWeatherInputs MapSnapshotToAgrarianWeatherInputs(const FAgrarianWeatherProviderSnapshot& Snapshot) const;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Weather")
|
UFUNCTION(BlueprintCallable, Category = "Agrarian|Weather")
|
||||||
bool TryApplyCachedSnapshot(FName TileId, const FString& Provider, AAgrarianGameState* GameState);
|
bool TryApplyCachedSnapshot(FName TileId, const FString& Provider, AAgrarianGameState* GameState);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user