Reusable charting library for rendering line graphs and bar charts in Factorio mods.
Providing the player with new tools or adjusting the game interface, without fundamentally changing gameplay.
Version: 1.3.0
Date: 2026-10-24
Changes:
- New default look, like the vanilla Production statistics graph: black plot area, 1 px series lines, 8 grid lines (was 5), grid colour 0.25 grey at 1 px, labels in font "default" at scale 0.93 in 0.7 grey
- Chart chunks use out-of-map tiles on an always_day surface instead of lab tiles lit by nine lights (pure black, 9 fewer render objects per chunk); allocate_chunk and ensure_tile_coverage also set always_day, so surfaces from old saves do not go dark
- The background reaches 8 tiles past each chunk, so a camera that shows a little beyond the chart (Cybersyn's Breakdown tab does) sees black instead of the grey unexplored-map fog
- Line graph points are plot width / columns apart (was / (columns - 1)): each column is a time slot ending at its point, the newest on the right edge and the oldest one slot in from the left, so the X labels span exactly the plot ("10" on the left edge for 300 x 2 s); metadata dx and x_positions follow
- Bar chart grid, labels and hatching use the same style, with 1 px lines; bar chart labels are larger (scale 0.93, was 0.8)
- charts.colors.get_grid_color returns opaque 0.25 grey (was 0.3 grey at alpha 0.4) and get_label_color 0.7 grey (was 0.8)
- Time labels keep one decimal below 10 of a unit ("1.7m" instead of "2m"), and "si"/"time"/"percent" axis labels add decimals when two neighbouring ticks would read the same
- A fixed y_range = {min, max} without grid_lines keeps 5 grid lines, so a {0, 100} percent chart still reads 0/25/50/75/100 (auto ranges get the new 8)
Features:
- X axis for line graphs: x_axis = {ticks_per_point, format, labels, grid} draws time-ago labels under the plot ("10 ... 0.5 0" minutes), newest at the right; time_series.render fills ticks_per_point from interval.ticks
- Y axis options: label_format = "si" ("0", "16k", "1.2M"), grid_lines, y_range = "zero" (auto max, min pinned at 0) and nice_ticks (1/2/2.5/5 x 10^k steps)
- Crosshair hover for line graphs, like the vanilla graph: charts.interactive.get_hover_buttons builds transparent overlay buttons with native tooltips ("iron-plate / 35k - 6.6 minutes ago"); charts.events.handle_gui_hover / handle_gui_leave draw, per player, a vertical and a horizontal guide, a marker and the hovered series twice as thick; set_hover / clear_hover drive it directly; "cell" (nearest series) or "column" mode with a max_buttons budget; on_cell_hover / on_cell_leave callbacks
- Line graph options camera_zoom (default 1.5), line_px (default 1), line_width (raw width, wins over line_px) and smooth (centred moving average, default off); time_series.render passes them through
- Bar chart option camera_zoom
- charts.style: line_width(px, zoom), grid_width, draw_label, smooth and the style constants
- charts.format.si_label(value, decimals) and charts.format.time_ago(seconds)
- charts.surface.restyle_chunk converts a chunk allocated by an older version (idempotent)
- Line graph metadata adds columns, x_positions, seconds_ago, plot, series_order, y_ticks, x_labels, x_unit, x_step, ticks_per_point, label_format, camera_zoom, line_width, smooth, and raw_value on each point when smoothing
- charts.interaction.create_line_graph_hover_regions and draw_crosshair for mods that do not use charts.interactive; create_overlay_buttons accepts raise_hover_events and per-button tags
Info:
- Mods with existing saves: call charts.surface.restyle_chunk(surface_data, chunk) once per stored chunk (or free and re-allocate them) to get the black background; until then old chunks keep their lights and lab tiles
- Crosshair hover needs options.id: only states created with one are registered, and get_hover_buttons / set_hover / register raise an error without it (generated ids differ between server and joining clients). For states kept in storage, call charts.interactive.register(state, callbacks) in on_load and pass on_cell_hover / on_cell_leave / format_tooltip there, since functions cannot be saved
- tests/init.lua passes load_luassert = true, which FactorioTest 3.x needs for the luassert-style asserts
- get_hover_buttons requires opts.player (or opts.gui_zoom): the GUI-unit factor depends on the camera zoom against that player's display_scale and display_density_scale, and no default is right for every camera
Version: 1.2.0
Date: 2026-09-05
Info:
- Declared compatibility with Factorio 2.1
- No API or behavior changes; all 1.1.0 calls work unchanged
Version: 1.1.0
Date: 2026-02-22
Features:
- Added bar_icons option to the stacked bar chart renderer for drawing item or fluid sprites above bars
Version: 1.0.9
Date: 2026-02-19
Changes:
- Removed unused animation module (impractical in Factorio's rendering engine)
- Fixed test failure in create_overlay_buttons (require inside test body)
- Documented custom function support for label_format in line graphs
Version: 1.0.8
Date: 2026-02-19
Features:
- Reorganized source files into core/, charts/, and interaction/ subdirectories
- New sub-table API (charts.surface, charts.render, charts.interaction, etc.)
- Added create_overlay_buttons for z-ordered GUI button creation on camera widgets
- Expanded documentation covering interaction, time series, and overlay buttons
Info:
- All existing flat API calls (e.g. charts.create_surface) remain fully backward compatible
Version: 1.0.2
Date: 2026-01-03
Features:
- Added mod portal thumbnail
- Added factorio-test-harness integration for automated CLI testing
Version: 1.0.1
Date: 2026-01-03
Features:
- Added test suite using FactorioTest framework
- Tests for surface management, line graphs, bar charts, and edge cases
Version: 1.0.0
Date: 2026-01-03
Features:
- Initial release
- Line graph rendering with multi-series support
- Stacked bar chart rendering
- Hidden surface and chunk management
- 12-color series palette
- Time and percentage label formatting