Weather Configuration

Register weather types — timing, server-side Lua hooks, and client-side visual layers — in a single per-mod config file.

Weather types are full-screen effects (rain, snow, fog, and similar) that the server randomly cycles through, each running for a randomized duration before transitioning to the next. A single file defines everything about a weather type: its timing, its optional server-side Lua behaviour, and its client-side visuals (animated layers and an optional shader).

Each entry is organised into up to three blocks by which side of the game owns it:

  • timing — how long the weather lasts and how long it fades in and out. Shared scheduling.
  • scripts — optional server-side Lua hooks.
  • client — optional client-side visuals: shader, scrolling, and animated layers.

How often a weather occurs is not set here. A registered weather only appears in the world when a biome lists it under weather-options (with a weight). See the biome terrain config. This file only defines what each weather type is.

At load time the server cross-checks the two sides and logs a warning if a biome references a weather name that no config registered (usually a typo), or if a registered weather is referenced by no biome (so it can never occur). Watch the server log if a weather you expect never shows up.


File Location

Register the file in your mod’s manifest (mods/<YourMod>/<YourMod>.yaml):

weather-config: weather-config.yaml

Then create the file it points to, relative to your mod’s folder:

mods/<YourMod>/weather-config.yaml

The file is a single list of weather entries:

weathers:
  - name: my_weather
    timing:
      min-ms: 20000
      max-ms: 40000
      transition-out-ms: 5000

Weather names are automatically prefixed with your mod name unless you write one already containing a colon, so my_weather becomes YourMod:my_weather.

Layer PNG images live under your mod’s texture folder, named after each layer’s name field (case-sensitive):

mods/<YourMod>/assets/textures/weathers/<layer name>.png

Minimal Example

A weather with no server behaviour and no visuals (a clear/calm type):

weathers:
  - name: clear_skies
    timing:
      min-ms: 20000
      max-ms: 40000
      transition-out-ms: 5000

Fields

Top level

FieldRequiredDescription
nameYesThe weather type’s registered name (auto-prefixed with your mod name).
timingYesThe scheduling block. See below.
scriptsNoServer-side Lua hooks — server-update, server-on-start, server-on-end. An unrecognized hook name fails the weather at load. See Shared Blocks → scripts. Omit for a weather with no server logic.
clientNoClient-side visuals. Omit for an invisible/default-look weather.

A missing or wrong-typed field discards the whole weather entry (logged as an error). Because each block is validated strictly, a misspelled key inside timing or scripts is reported at load time rather than silently ignored.

timing

FieldRequiredDefaultDescription
min-msYesMinimum time this weather runs before transitioning out, once selected.
max-msYesMaximum time this weather runs. The server picks a random duration in [min-ms, max-ms] each time this weather starts.
transition-out-msYesHow long the weather overlay fades out when this weather ends and another begins.
transition-in-msNo0How long the weather overlay fades in when this weather starts. 0 (the default) makes it appear instantly.

The fade is a client-side cross-fade: when the active weather changes, the old type fades out over its transition-out-ms, then the new type fades in over its transition-in-ms.

scripts

All three hooks are optional. Each is declared as a bare path to a .lua file that returns its handler function (the same shape as items’ server-on-primary-use). See the Server Weather API for hook signatures.

KeyWhen Called
server-updateEvery server tick while this weather is active.
server-on-startOnce when this weather starts in a region.
server-on-endOnce when this weather ends in a region, just before the next weather starts.
scripts:
  server-update: /weathers/my-weather/scripts/server_update.lua
  server-on-start: /weathers/my-weather/scripts/server_on_start.lua
  server-on-end: /weathers/my-weather/scripts/server_on_end.lua

client

FieldRequiredDefaultDescription
shaderNo(engine default)A namespaced shader name applied while this weather is active. See shader config.
vertical-loopNoIf present, all layers scroll downward.
vertical-loop.pixels-per-secondYes (if vertical-loop present)Downward scroll speed in pixels per second.
layersYes (if client present)One or more animated layers, drawn in declaration order (first = bottom).

Layer fields

FieldRequiredDefaultDescription
nameYesBase name of the PNG file. The file must be <name>.png in assets/textures/weathers/. Matches the name used by healthbar and biome-backdrop textures.
frame-countYesHow many frames the animation has. Use 1 for a static layer.
frame-widthYesWidth of a single frame in pixels.
frame-heightYesHeight of a single frame in pixels.
frame-time-msNo100Default milliseconds per frame. Used when frame-durations-ms is absent.
frame-durations-msNoPer-frame timing override. See Per-Frame Timing.
parallaxNo1.0Horizontal scroll speed multiplier relative to the base speed.
directionNorightHorizontal scroll direction: left or right (case-insensitive; lowercase matches what ships).
scale-resolutionNo1.0Scale factor applied to the layer.

Sprite Sheet Format

Each layer is a single PNG containing all animation frames in a horizontal strip:

[ frame 0 ][ frame 1 ][ frame 2 ] …
  • Total image width = frame-width × frame-count
  • Total image height = frame-height
  • Frames are read left to right during playback

For a static layer (frame-count: 1), the image is just the single full-size frame.


Per-Frame Timing

By default, all frames display for the same duration (frame-time-ms). To give individual frames different hold times, add frame-durations-ms to the layer.

Two entry formats are supported and can be mixed freely:

Flat — one value per frame:

frame-durations-ms: [200, 200, 200, 3000]

Batch — a duration applied to several consecutive frames:

frame-durations-ms:
  - count: 3
    duration-ms: 200
  - count: 1
    duration-ms: 3000

Both produce the same result: frames 0–2 last 200 ms each, frame 3 lasts 3000 ms.

Note: The total number of entries (after expanding batches) must equal frame-count exactly. If the counts do not match, frame-durations-ms is ignored and frame-time-ms is used for all frames instead.


Complete Example

Based on the real shipped weather types — a plain sunny type, a static rain layer, and an animated snow type with server hooks and mixed frame timing:

weathers:
  - name: sunny
    timing:
      min-ms: 30000
      max-ms: 45000
      transition-out-ms: 5000

  - name: rainy
    timing:
      min-ms: 20000
      max-ms: 40000
      transition-in-ms: 4000
      transition-out-ms: 5000
    client:
      layers:
        - name: rainy
          frame-count: 1
          frame-width: 1920
          frame-height: 1080
          frame-time-ms: 300

  - name: snowy
    timing:
      min-ms: 25000
      max-ms: 35000
      transition-in-ms: 4000
      transition-out-ms: 5000
    scripts:
      server-update: /weathers/snowy/scripts/server_update.lua
      server-on-start: /weathers/snowy/scripts/server_on_start.lua
    client:
      vertical-loop:
        pixels-per-second: 25
      layers:
        - name: snowy
          frame-count: 16
          frame-width: 1920
          frame-height: 1080
          frame-time-ms: 200
          parallax: 5.0
          direction: left
          frame-durations-ms:
            - count: 8
              duration-ms: 200
            - count: 8
              duration-ms: 3000

See Also