Running changelog
Running changelog
This is the bleeding-edge changelog since version 2025.04, which is still in the pre-release phase. See the 2025.04 page for the upcoming release.
Caveats
- unit shaders receive TRS transforms instead of matrices, breaking shaders. See the “Smooth script piece animations” section below.
- removed Python bindings for AI. Apparently unmaintained and unused.
- removed
UpdateWeaponVectorsMT,UpdateBoundingVolumeMT, andAnimationMTspringsettings. These were just in case, but MT seems safe enough after some time live testing. - removed
/AdvModelShadingcommand and theAdvUnitShadingspringsetting, the adv mode is now always on. In practice there wasn’t any difference since GLSL became mandatory. - removed
gl.UnitGL4,gl.FeatureGL4,gl.FeatureShapeGL4, andgl.UnitShapeGL4. These did not do anything. - handicap (native income multiplier) no longer applies to reclaim. Use
gadget:Allow{Unit,Feature}BuildStepto replace, if desired. Backwards compatibility feature check:Engine.FeatureSupport.noHandicapForReclaim. /group add Nno longer selects the entire group, just adds./groupN(without space) unaffected. Feature support tag:Engine.FeatureSupport.groupAddDoesntSelect.- immobile units that
canKamikazeno longer disregard theblockingunit def tag. BeamLaserandLightningCannontype weapons now pass their actual projectileID to callins rather than-1.BeamLaserandLightningCannonnow obey ellipsoid and/or cylinder target volumes correctly, this will result in a slightly different effective range volume.- in-line text color codes: 0x11 and 0x12 (decimal 17 and 18) now work as color code indicators, in addition to 255 and 254 respectively.
Engine.textColorCodesstill only lists the old ones. - default value for
LogRepeatLimitspringsetting 10 → 0, see below. - area resurrect command now puts a leash on repair sub-commands (behaviour change, but also the repair subcommands now have 5 args instead of 1).
- widgets can now sign up to receive the
widget:Explosioncallin. There are some arcane visibility rules that boil down to it revealing much more info than the existingwidget:ShockFrontcallin. - removed the 10 mutator limit, can now have arbitrarily many (this may affect lobbies, autohosts etc who may have assumed the limit).
- fully removed support for 32-bit builds.
Deprecation notice
wupget:DrawUnit,DrawFeature,DrawShieldandDrawMaterialare deprecated. Nothing changes in behaviour, but they are (and have been for a long time) a bad idea to use as a performance anti-pattern. Use shaders as a replacement.- deprecated
Spring.GetUnitCommands(unitID, 0) → number commandCount, useSpring.GetUnitCommandCount(unitID). The non-0 overloads still return a table of commands and are not affected. - similarly deprecated
Spring.GetFactoryCommands(unitID, 0), use the newSpring.GetFactoryCommandCount. - deprecated
Spring.GetCommandQueue, useSpring.GetUnitCommands(which has always been 100% equivalent), except for the case above. - deprecated the
ghostedBuildingsengineoption. You can read it manually as a modoption and set every unitdef not to leave ghosts.
Features
Camera callins
- added
wupget:CameraRotationChanged(rotX, rotY, rotZ) → nil. - added
wupget:CameraPositionChanged(posX, posY, posZ) → nil.
Chat via widgets
- added
Spring.SendPublicChat(msg) → nil, for sending a chat message. Equivalent to/say. - added
Spring.SendAllyChat, andSpring.SendSpectatorChat, same interface as above, for sending chat to allies/spectators. Equivalent to using/saywith the “a:” or “s:” magic destination prefixes. - added
Spring.SendPrivateChat(msg, playerID) → nil, for sending a private message (aka whisper) to a specific playerID. Almost equivalent to/wbynum, but does not support the magic 255 destination.
GL debugging
- added
DebugGLReportGroupsboolean springsetting, default true. Shows OpenGL push/pop groups in GL debug. - the
/debugGLoption now takes an optional numerical argument, 0-15. 0 and 1 control the whole debug view without touching anything else (i.e. work as before). Otherwise values 2-15 are treated as a bitmask: 8 controls stacktraces, 4 report groups, 2 the whole debug enabled/disabled state, 1 ignored.
New Website
- Slashscreen, in an effort to procrastinate from university finals, completely redid the website.
- Reworked the Api docs.
- New guides.
- Documented RmlUi bindings.
CEG rendering
- adds the following tags to
CBitmapMuzzleFlametype CEG particles:particleSpeed,particleSpeedSpread,airdrag,gravity. These work the same as they already do forCSimpleParticleSystemtype particles. - added
animParams1andanimParams2to CEGs, similar to weapons. Texture 1 is used forCSimpleParticleSystemand the “front” texture ofCBitmapMuzzleFlame, texture 2 is used for the “side” texture of muzzle flame. Other CEG classes don’t support this yet. NumberlessanimParamsused as a fallback. - added
drawSideXanddrawSizeYbool tags toCBitmapMuzzleFlame, allows to skip some of the two “forward” sprites. X is the one parallel to the ground when shooting horizontally. There is nodrawSideZbecause you can just set that texture to empty.
Infotex commands
- added
/showLoS. - added
/showInfoTex foo, wherefoois one of the existing info textures (e.g./showInfoTex elevationis equivalent to/showElevation). - all the
/showFoocommands can now accept 0/1, in addition to argument-less toggling.
Smooth script piece animations
- unit shaders receive TRS transforms instead of matrices, breaking shaders. This will require gamedevs to update GL4 shaders that used to employ the engine provided transformation matrices SSBO.
- the new format is not directly documented anywhere, but you can look at basecontent shaders.
- added
Engine.FeatureSupport.transformsInGL4backwards compatibility check.
Base64
- added
Encodingglobal table (likeSpringormathetc), available everywhere. So far contains base64 encoding, more (such as JSON) to be added lated. - added
Encoding.EncodeBase64(string plain, bool? stripPadding = true) → string encoded. Can optionally remove the extra=at the end. - added
Encoding.DecodeBase64(string encoded) → string plain, decodes a base64 string (if there’s an invalid character, it parses just the valid prefix). - added
Encoding.IsValidBase64(string) → bool. - added
EncodeBase64Url,DecodeBase64Url, andIsValidBase64UrltoEncoding. Same as above, except uses the base64url character set.
Duplicate logs
- the
LogRepeatLimitspringsetting, which controls how many duplicate logs in a row can end up in the infolog, can now accept 0 for infinite. - default value for
LogRepeatLimit: 10 → 0 - native ingame console no longer filters duplicates (max 1 in a row → infinite)
GLTF/GLB model format support
.gltfand.glbmodel formats are now supported.- GLTF parser will insert a few empty pieces as root / sub-root.
- materials, textures and vertex colors embedded in the GLTF itself are not supported. Mostly because GLTF expects PBR workflow, which the standard engine shader doesn’t do.
- GLTF can use a Lua metadata file similar to Assimp, custom model attributes in GLTF can also be used to provide the same data. Supports the existing tags:
tex1,tex2,midpos,mins,maxs,height,radius,fliptextures,invertteamcolor. - add a new
s3ocompatbool attribute, both for GLTF and Assimp models. Enables the same right handed - left handed flip of the model as it’s done in s3o. This is experimental and probably very bugged. If your model is converted from s3o and animates incorrectly, give this option a try. - does not support re-parenting or the baked rotation angles. Use your 3d editor to change them instead. Assimp not affected.
Ghosts
- add
leavesGhostunit def tag. Controls whether the unit leaves a ghost. Defaults to true for buildings (maintains previous behaviour). - add
leavesGhostUnitDefs entry, same. - add
Spring.GetUnitLeavesGhost(unitID) → bool. - add
Spring.SetUnitLeavesGhost(unitID, bool leavesGhost, bool? existingGhostRemains = false). IfleavesGhostbecomes false and the unit already had a ghost, whether the existing ghost is removed or sticks around is controlled by the second arg. - note that the
ghostedBuildingsengineoption still exists and makes all of the above interfaces no-op, but is scheduled for removal.
Text coloring
- added
AllowColorFontsbool springsetting, defaults to false. Allows fonts to be colored instead of monochromatic. In practice this means emojis render as expected, though a fancy enough font could also do something to normal text. - in-line text color codes: 0x11 and 0x12 (decimal 17 and 18) now work as color code indicators, in addition to 0xFF and 0xFE (decimal 255 and 254) respectively. The significance of this is that 255/254 are normal, printable characters from reasonable languages so treating them as color codes can ruin otherwise normal text by eating characters and setting random colors.
Engine.textColorCodesstill only lists the old ones.- added
TextDisableOldColorIndicatorsbool springsetting, defaults to false. If true, the previous 255 and 254 color codes stop working andEngine.textColorCodeslists the new ones.
Explosion event in unsynced
- add
Script.SetWatchExplosion(weaponDefID, bool), and the corresponding Get, to unsynced. - widgets can now receive the
Explosioncallin, same arguments as the gadget one but can’t use the return value to block the CEG. There are some arcane visibility rules (that include the visibility of the explosion’s CEG) that boil down to it revealing a bit more info than the existingwidget:ShockFrontcallin which used to fulfil a similar role.
Death metal
- add
Spring.CreateUnitWreck(unitID, int? wreckLevel = 1, bool? emitSmoke = true) → featureID?. Creates a wreck as if the unit died. - add
Spring.CreateFeatureWreck(featureID, int? wreckLevel = 1, bool? emitSmoke = false) → featureID?. Creates a wreck as if the unit died. - add
Spring.AddFeatureDamagewith the same signature asSpring.AddUnitDamage. Note that one of the args is paralyze time, but features don’t take paralyze damage. - add a new
checkDeathbool arg toSpring.SetFeatureHealth(featureID, health, bool? checkDeath = false). It was discovered that the current behaviour is that features set to negative health don’t die from HP removal and it takes an instance of damage to “poke” them into death. The default offalsepreserves this, set it totrueto let features die immediately from HP removal. - add
Spring.SetFeatureFireTime(featureID, fireTime), sets a feature “on fire” (similar to being damaged with afirestartertagged weapon) with that much time to live, in seconds. Set to 0 to cancel. - add
Spring.SetFeatureSmokeTime(featureID, smokeTime), makes the feature emit smoke (similar to freshly killed wrecks) for that many seconds. Note that smoke size is proportional to time remaining. - add the corresponding getters (
Spring.GetFeatureFireTime,Spring.GetFeatureSmokeTime) for the above.
Misc
- removed the 10 mutator limit, can now have arbitrarily many.
- add
accurateLeadingnumerical unit weapon tag (note, not weaponDef). Controls how many extra accuracy iterations are done when calculating shots. 0: current behaviour (single iteration, fails to hit at large speed disparities and/or weird angles). 1: one extra iteration, enough to get a perfect solution for non-ballistic shots and usually good enough for non-extreme ballistic shots too. 2+: extra iterations for ballistic shots, if needed. In practice, shouldn’t need to go higher than low single-digit values. Note that the calculation always stops when 1-frame resolution accuracy is achieved (since unit and projectile movement are all frame-discrete), so setting this arbitrarily high should still be safe and reasonably performant. - math extras (
math.hypot,math.normalize, bit ops etc) now available in LuaParser envs (modrules, defs parsing, etc). - added
Spring.GetFactoryCommandCount(unitID) → numberchecks the queue length in a factory’s build queue (note thatGetUnitCommandCountis for the rally queue in factories). - add
ThreadPinPolicyspringsetting to control which CPUs to use. (0) = Off; (1) = System Default; (2) = Exclusive Performance Core; (3) = Share Performance Cores. - added new CEG impact filters,
shieldandintercepted. BeamLaserandLightningCannontype weapons now pass their actual projectileID to callins rather than-1.BeamLaserandLightningCannonnow obey ellipsoid and/or cylinder target volumes correctly.- immobile units that
canKamikazeno longer disregard theblockingunit def tag. - add ‘system.nativeExcessSharing’ modrule, controls whether the resource sharing level (aka “red slider”) applies. Note that this also prevents excess from flowing back to the allyteam. If you want excess to flow to allies and only block changing the share level, use the existing
gadget:AllowResourceLevel. - add
MiniMapDrawPingsboolean springsetting, defaults to true. Whether engine renders pulsating white squares on the minimap when a label is placed. - if a factory “changes” a build order into a build order of the same type (e.g. by using command insert) it no longer resets build progress.
/group add Nno longer selects the entire group, just adds./groupN(without space) unaffected. Feature support tag:Engine.FeatureSupport.groupAddDoesntSelect.- expose the rmlUI data model backing table as
__GetTable(). - add
gl.GetEngineModelUniformDataSize(number index) → number sizeInElements, number sizeInBytesOnCPUto grab the size of the model uniforms buffer on the CPU side. - add
LuaVBO:CopyTo(otherVBO, sizeInBytes) → bool okto copy the GPU side content from the current LuaVBO to another. - add a second bool arg and an optional second return value to
Spring.GetGroundDecalTextures(bool? mainTex, bool? alsoFilenames = false) → string[] textures, string[]? filenames. - add
mouse2tomouse10“keys” for mousebuttons that can be bound, dittosc_mouse2-10scancodes. LMB (mouse1/sc_mouse1) is planned to be made bindable later. - added
DWMFlushnumerical springsetting, for Windows only. Forces Windows Desktop Compositors DWMFlush before each SDL_GL_SwapWindow, preventing dropped frames (use nVidias FrameView to validate dropped frames, or BARs Jitter Timer widget). Value of 1 does DWMFlush before SwapBuffers, value of 2 does DWMFlush after swapbuffers. - enabling dev mode (either via startscript or at runtime) adds
debug.*functions to synced Lua. /smoothmeshrenderer stays enabled even if you disable cheats.- trying to set a deprecated/nonexistent springsetting via Lua now produces a warning.
/givenow gives a correct hint for @x,y,z usage.- added
GL.TEXTURE_2D_ARRAYLua constant.
Fixes
- fixed crashing aircraft sometimes bouncing off the ground without dying.
- disabling cheats no longer disables debug airmesh view.
- fix RmlUi crash when reloading stylesheets with documents containing scripts in head section.
- fix some graphical interfaces producing harmless warnings/errors on headless builds.
- fix some RmlUI crashes.
- fix some remaining performance issues with fonts.
- fix some pathing/QTPFS issues.
- fix some jitter on Windows in mostly-idle and/or low speed multiplayer games.
- fix some issues with models rendering at world origin before game start.