This is the changelog since version 2025.01 until version 2025.03, which is still in pre-release phase.
Caveats
These are the entries which may require special attention when migrating:
- network protocol: scribbling-related (draw, point, erase) messages now send coordinates as
uint32
instead ofint16
. This may break replay parsing. - uniform location 5 in vertex shaders for models extended from uvec2 (boneID, boneWeight) to uvec3 (boneID low byte, boneWeight, boneID high byte). Existing shaders should generally keep working.
- missiles now obey
myGravity
when expired. math.clamp
now errors if the lower bound is higher than the upper bound.- added minimap rotation API which can screw up the minimap (see below), set it to nil at LuaUI entry point if you don’t want to handle it.
- server no longer automatically forcestarts the game if there is nobody connected after 30s.
- fixed the
SPRING_LOG_SECTIONS
environment var, it no longer requires a comma in front. gl.GetAtmosphere("skyDir")
now returns nil. The skyDir was never actually used for anything.- updated Tracy to v0.11.1, see the changelog at https://github.com/wolfpld/tracy/releases
- archive cache was reworked. Should be much faster to process, but will take up more disk space and it’s not yet known how stable it is.
- added GL debug annotations to main engine GL draw calls, this is similar to tracy scopes for regular code. The caveat here is that this can have a large performance cost in
/debugGL
mode. The next release is planned to feature improvements in this area.
Deprecation notice
- the metal view automatically toggling when building a metal extractor is now deprecated. Disable it via
Spring.SetAutoShowMetal
(see below) and reimplement manually. A replacement example has been provided at(basecontent)/examples/Widgets/gui_autoshowmetal.lua
.
Features
Lua language server support
LDoc has been replaced by Lua Language Server compatible annotations. This allows for language server support when editing Lua code (namely autocompletion and type checking). Type definitions can be found in the Lua library repo. This is intended to be included as a submodule in projects that use the engine. Lua API docs are now generated from LLS definitions instead of LDoc. This has caused a regression in docs quality, with all docs on a single page and some docs missing information. Improvements to the docs are being considered. For more information see the Lua Language Server guide.
Unit groups
- units no longer removed from groups at the start of their death animation.
- added
Spring.SetUnitNoGroup(unitID, bool noGroup) → nil
, whether a unit can be added to groups. - added
Spring.GetUnitNoGroup(unitID) → bool noGroup
.
Infra-adjacent
- added
--calc-checksum "Archive Name"
CLI param, writes a single archive’s checksum to archive cache. Use from a lobby for preloading content, though be wary not to call it in paralllel. - added
--only-local
CLI param tospring.exe
, prevents a replay from opening a connection. Use for mass replay parsing. - fixed the
SPRING_LOG_SECTIONS
environment var, it no longer requires a comma in front. - server no longer automatically forcestarts the game if there is nobody connected after 30s.
More model pieces
- models now support 65534 pieces, up from 255.
- this tends to have terrible performance for even hundred-piece models, so consider it a crutch and avoid it if possible.
- add
Engine.FeatureSupport.maxPiecesPerModel
constant you can read to get the piece number. - uniform location 5 in vertex shaders for models extended from uvec2 (boneID, boneWeight) to uvec3 (boneID low byte, boneWeight, boneID high byte). Existing shaders should generally keep working.
Automatic metalmap view
- added
Spring.SetAutoShowMetal(bool) → nil
. If you set it to false then selecting a “build mex” command won’t automatically enable the metal view (use the widget from(basecontent)/examples/Widgets/gui_autoshowmetal.lua
to replicate it). If you leave it at true (default), engine will keep automatically enabling the metal view but also spam deprecation warnings. This function will be removed at some point in the future. - added
Engine.FeatureSupport.noAutoShowMetal
, false. At some point in the future this will change totrue
at which point the engine will stop automatically enabling the metal view for mexes (and removeSpring.SetAutoShowMetal
).
Minimap 90°/270° rotations
- minimap can now be rotated to 90° and 270°, and can be rotated manually.
- added
Spring.SetMiniMapRotation(number angle) → nil
, sets the minimap angle (in radians). Snaps to cardinal directions. Only works if the springsettingMiniMapCanFlip
is set to 0 (if it’s 1, engine automatically flips vertically as previously). Geometry is kept, so it may end up stretched - readjust it manually viagl.ConfigMiniMap
. Spring.GetMiniMapRotation() → number angle
handles the new rotations (i.e. can returnπ/2
and3π/2
).
Misc rendering
- add
Platform.glVersionNum
, 1/10th the version of glsl (e.g. GL 3.0 → 30). - added
gl.ClearAttachmentFBO(number? target = GL.FRAMEBUFFER, string|number attachment, clearValue0, cv1, cv2, cv3) → bool ok
. Clears the “attachment” of the currently bound FBO type “target” with “clearValues”. Attachment can be either string (“color0” .. “color15”, “depth”, or “stencil”) or the equivalentGL.COLOR_ATTACHMENT#
constant. - minimap is sharper with super-sampling anti-aliasing enabled
- added 3D noise to basecontent bitmaps archive, under
bitmaps/noise/recoil_noise_2025_p5_p3_w6_w4_64x64x64_RGBA.dds
andbitmaps/noise/recoil_noise_2025_p5_p3_w6_w4_128x128x128_RGBA.dds
. This allows for reliable generation of cheaper 3D noise in shaders.
Praise the sun!
- the shading texture (used by minimap, water, and grass) now tracks sun position changes immediately.
- the “modern” sky renderer now uses the actual sun color instead of hardcoded RGB 253/251/211.
Spinning skybox
- added new tag to
Spring.SetAtmosphere
,skyAxisAngle
, array of 4 numbers: X, Y, Z (defining an axis) and rotation around that axis. Lets the skybox be drawn at an angle and possibly spin. Complex rotations involve doing math yourself. - added
skyAxisAngle
togl.GetAtmosphere
, same format. - added
atmosphere.skyAxisAngle
to mapinfo, same format. - removed
atmosphere.skyDir
from mapinfo, it didn’t actually affect anything. gl.GetAtmosphere("skyDir")
now returns nil.
Debugging for rendering
- added
VBO:GetID() → number
, gets the internal OpenGL ID for use in debugging. - added a second return value to
gl.CreateShader
, now also returns the internal ID for use in debugging. - added
gl.ObjectLabel(objType, objID, string identifier) → nil
. Type is one of the new GL object type constants (GL.BUFFER
,GL.PROGRAM_PIPELINE
etc., see the list at the bottom). Adds a text label to an object for debugging tools. Conditionally available based on gfx drivers etc (do a nil check). - added
gl.PushDebugGroup(number ID, string message, bool isThirdParty) → nil
. Conditionally available (depends on player’s platform, do a nil check). Creates a group (which is basically a scope, similar to tracy) with given message onto the debug stack. Meant for debugging tools, seems to be specifically for “nVidia nSight 2024.04”. Apparently tools can struggle to see the annotations when FBOs are raw bound. - added
gl.PopDebugGroup() → nil
, conditionally available, pops a previously pushed debug group from the stack. - the engine now natively pushes some GL debug groups in relevant scopes, similar to tracy. A caveat is that this can have a noticeable perf cost when GL debug is enabled.
Unit rotations
Spring.GetUnitDirection
andSpring.GetFeatureDirection
now return 9 values (from 3). The initial three stay as the XYZ of the “front” direction in unit space, the new ones are XYZ of the “right” direction and the XYZ of the “up” direction. ```diff- local frontX, frontY, frontZ = Spring.GetUnitDirection(unitID)
- local frontX, frontY, frontZ, rightX, rightY, rightZ, upX, upY, upZ = Spring.GetUnitDirection(unitID) ```
Spring.SetUnitDirection
andSpring.SetFeatureDirection
now accept up to 6 args (from 3). The new ones are the XYZ for the “right” direction (since just the “front” is ambiguous) and are optional (same behaviour as previous, i.e. some direction based on ground). Note there is no way to specify the “up” dir (but given the “right” dir it is unambiguous; and if you have front+up dirs you can unambiguously find the right dir). ```diff Spring.SetUnitDirection(unitID, frontX, frontY, frontZ) – still works- Spring.SetUnitDirection(unitID, frontX, frontY, frontZ, rightX, rightY, rightZ) – new ```
Engine feature support tags
Added a bunch of feature support entries to the Engine.FeatureSupport
tags. These are for the future. Most likely you don’t need to worry about those since games will receive patches if there is a change.
- number
gunshipCruiseAltitudeMultiplier
, currently1.5
. Right now gunship cruise altitude is multiplied by this. - bool
noRefundForConstructionDecay
, currentlyfalse
. At some point refunds for construction decay will be handed over to Lua. - bool
noRefundForFactoryCancel
, currentlyfalse
. At some point refunds for factory cancel will be handed over to Lua. - bool
noOffsetForFeatureID
, currentlyfalse
. At some point featureIDs in mixed contexts (e.g. target ID for reclaim) won’t require to be offset.
Font rendering performance
- added
UseFontConfigSystemFonts
boolean springsetting, default true. Whether to search system fonts for fallbacks. - added
FontConfigSearchAttributes
boolean springsetting, default true. Whether to try to match provided font attributes for fallbacks. Costs some perf but can result in better glyph matches. - added
FontConfigApplySubstitutions
boolean springsetting, default true. Whether to apply pattern config substitutions. Disabling substitutions can make fonts randomly break but you can take the gamble to save a bit of perf that way. - added
MaxPinnedFonts
integer springsetting, default 10. How many fonts are kept in a cache. Reduces perf spikes if many fonts are used (keep in mind players can send mixed chat with multiple exotic characters mxied), though if many fonts are loaded it can increase peak memory usage. - extra optimisations to baseline fonts perf even if you don’t touch any of the above.
Misc
- add
Spring.GetSoundDevices() → { { name = "...", }, { name = "...", }, ... }
. May be extended with more info than just name in the future. - add
wupget:ActiveCommandChanged(cmdID?, cmdType?) → nil
. - the
Spring.GiveOrder
family of functions now acceptnil
as params (same as{}
) and options (same as0
). - add
Spring.SetUnitStorage(unitID, "m"|"e", value) → nil
. - add
Spring.GetUnitStorage(unitID) → numbers metal, energy
. - added
Game.buildGridResolution
, number which is currently 2. This means that buildings created via native build orders are aligned to 2 squares. - add
Platform.totalRAM
, in megabytes. - added
Engine.gameSpeed
andEngine.textColorCodes
, same as the existing entries inGame.
. The practical effect is that the Engine table is available in some LuaParser environments that Game isn’t. - missiles now obey
myGravity
when expired. - NaN and infinity coming from Lua is now sometimes rejected. Coverage isn’t yet comprehensive.
socket.lua
moved from being a loosely distributed file under./socket.lua
to basecontent./LuaSocket/socket.lua
.- add
experience.experienceGrade
number modrule, same as calling Spring.SetExperienceGrade. - the
allowHoverUnitStrafing
modrule now defaults tofalse
. Previously it defaulted tofalse
for HAPFS andtrue
for QTPFS. - bumpmapped water (aka
/water 4
) now has a different default texture.
Fixes
- fix
Spring.SetUnitHealth(build < 1)
not reverting the unit into a nanoframe. - fix minimap icons revealing whether a building ghost was dead or not.
- fix CPU pinning, no longer tries to pin itself to bad choices (efficiency cores, hyperthreads on the same physical core, performance cores on a dedicated server)
- fixed
Spring.ShareResources(teamID, "units", nil)
breaking due to the explicit nil. - fix scribblings and labels breaking on maps larger than 64xN.
- fix basecontent
actions.lua
providing an incorrectKeyAction
handler. - fix height of buildings under construction not updating properly.
- fix landed aircraft starting to levitate when EMPed.
- fix units being stuck if an overlapping push-resistant unit stops.
- fix the “modern” sky renderer not adjusting to changes via
Spring.SetAtmosphere
.
GL object type constants
For use with the new gl.ObjectLabel
(see above):
GL.BUFFER
GL.SHADER
GL.PROGRAM
GL.VERTEX_ARRAY
GL.QUERY
GL.PROGRAM_PIPELINE
GL.TRANSFORM_FEEDBACK
GL.RENDERBUFFER
GL.FRAMEBUFFER
Written by: sprunk