96 weather and crop calendar - #110
Draft
Grisu118 wants to merge 6 commits into
Draft
Conversation
…hannels The game's Anbaukalender screen has two halves, and they move at very different speeds: the crop table is fixed the moment a map loads, while the forecast turns over on the hour. So they ship as two channels rather than one. cropCalendar.json carries, per crop the map shows, which of the twelve periods it may be sown in and which it may be harvested in — read through the same three calls the game's own frame uses. Event-driven on DAY_CHANGED and PERIOD_LENGTH_CHANGED, since the only part that moves is the today marker. Growth mode is the exception, and it has no message to subscribe to: GrowthSystem:setGrowthMode writes missionInfo, fires its multiplayer event and logs, and publishes nothing (MessageType.SETTING_CHANGED covers the client's GameSettings, not the savegame's). The channel polls it every 2 s instead, comparing against the mode the last collect() used so a skipped write retries. It has to: outside SEASONAL the game answers "plantable" for all twelve periods, so a stale file shows an entirely wrong calendar rather than a slightly old one. weather.json carries the forecast — now, twelve two-hourly steps, six days — subscribed to HOUR_CHANGED and DAY_CHANGED, the same two the in-game screen reloads on. Three things it does not normalise, each for a reason in the header: period labels come from g_i18n because the month shifts by hemisphere; Beaufort is taken from the raw m/s because the game ceils before converting; and the wind angle is left as the engine's own, since the current reading and the forecast entries come from different sources and one compass convention would make one of them wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
environment.weather.temperature ran its three values through g_i18n:getTemperature, which converts to Fahrenheit for anyone who picked it, and then labelled them "°C" from a hardcoded string. A Fahrenheit player got Fahrenheit numbers under a Celsius label. The unit now comes from g_i18n:getTemperatureUnit, the same place the value's conversion does. Found while writing the weather channel, which has to get this pairing right and would have sat next to the wrong one. No shape change, so VDTelemetry.VERSION stands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CropCalendarData and WeatherForecastData, their parsers, their ServerMessage variants and the two watcher registrations — the same path every other channel takes, including the rule that an absent file broadcasts null so the app clears rather than freezing. On a different map the crop list is a different set of crops entirely, and a stale forecast is read to decide whether to cut hay. The forecast type is named WeatherForecastData because model.Weather is already taken by the telemetry channel's live min/max/current block. WeatherKind is parsed by hand rather than serialized as an enum, so a weather type a future game version adds costs one icon instead of the whole channel. Two derivations live in shared, where the panel and the widget both reach them and a test can call them off the composition: periodRuns merges a crop's periods into contiguous bars (grass sows March–October *and* February, which has to draw as two), and todayFraction places the marker, half-day offset included, the way the game's own updateTodayBar does. The four captures are Grisu's, taken 2026-08-16. They passed every assertion first time, and they pinned down three things that had only been reasoned about: the hourly strip really wraps past midnight, formatDayInPeriod drops the day number entirely at daysPerPeriod = 1, and only the current wind angle is snapped to 45° while the forecast angles are raw. noSeasons.json is vanilla.json's savegame flipped to GrowthMode.DAILY — the case where every crop reports all twelve periods and the calendar stops meaning anything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both were private copies about to gain a third: InvoicesSection's FilterChip and MapPanel's field/POI search box, which the calendar needs as-is. Moved into components/ and both call sites repointed — no visual change, the definitions came across verbatim. WidgetDashboard's own Chip is deliberately left alone. It looks different on purpose (bordered, on white, no ripple) for the page editor, and folding it in would have restyled that screen as a side effect of unrelated work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… widget The game's Anbaukalender, plus the two questions it makes you scan the whole grid to answer — what can I sow now, what can I harvest now — as a search box and two filter chips carrying their own counts. The chips are not exclusive: both on means both, which is how the question actually gets asked. Layout is four scroll containers over two shared ScrollStates rather than one per row: the header and the bars move sideways together so a column stays under its label, the names and the bars move vertically together so a row stays beside its name. Periods fill the width when there is room and scroll when there is not. Sowing and harvest are told apart four ways over, because the game's own legend does it by hue alone and that is the one thing this dashboard may not do: fixed lane order (sow above, harvest below), brightness, square versus capsule bar ends, and S/H letters in the name column. Rows alternate a guidance shade and highlight when pressed, held by crop id so re-filtering cannot move the highlight; the selected row also carries a solid leading edge bar and darker ink, since DarkGray drops to 3.9:1 on the selection wash. The grid rules are drawn as an alpha so they survive all three row backgrounds. WeatherIcons draws its eight glyphs rather than borrowing them. Weather type is carried by shape alone — rain slants, snow is angular, hail is round — and a set assembled half from Material would not read as one strip. The arrow is turned to windDirection + 180 like the game's, then negated: the engine measures counter-clockwise and Compose's rotate() turns clockwise, which had the vane mirrored about the vertical axis. Outside seasonal growth the game answers "plantable" for all twelve periods, so every bar fills and the filters mean nothing. The panel says so rather than letting the grid look broken. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four deferrals, each with the reason rather than a plan. The one worth knowing before anyone tries it: crop icons are unreachable — the game's row icon is fillType.hudOverlayFilename, which points inside dataS2/, and AssetResolver opens gameDir-relative paths and mod zips, neither of which reaches into a packed archive. The ground-layer legend is the only cheap substitute and only covers crops already growing on the map, which is precisely the set you do not need to look up. Three in-game checks left, all needing a session this branch could not reach: a multiplayer client (are forecastItems replicated at all?), a southern-hemisphere map, and a season length changed mid-session. The growth-mode watch and the non-seasonal calendar are already answered — noSeasons.json came out of flipping the setting live in a running savegame, so both the poll and the data are proven. The captures-wanted entry is retired for these two channels and replaced with what is still missing from them: HAIL, THUNDER and TWISTER have never appeared on the wire, so three of the eight drawn glyphs are unexercised by any fixture, as is a day caption from a map with more than one day per period. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #96