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
, andAnimationMT
springsettings. These were just in case, but MT seems safe enough after some time live testing. - removed
/AdvModelShading
command and theAdvUnitShading
springsetting, 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}BuildStep
to replace, if desired. Backwards compatibility feature check:Engine.FeatureSupport.noHandicapForReclaim
. /group add N
no longer selects the entire group, just adds./groupN
(without space) unaffected. Feature support tag:Engine.FeatureSupport.groupAddDoesntSelect
.- immobile units that
canKamikaze
no longer disregard theblocking
unit def tag. BeamLaser
andLightningCannon
type weapons now pass their actual projectileID to callins rather than-1
.BeamLaser
andLightningCannon
now 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.textColorCodes
still only lists the old ones. - default value for
LogRepeatLimit
springsetting 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:Explosion
callin. There are some arcane visibility rules that boil down to it revealing much more info than the existingwidget:ShockFront
callin. - 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
,DrawShield
andDrawMaterial
are 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
ghostedBuildings
engineoption. 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/say
with 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
DebugGLReportGroups
boolean springsetting, default true. Shows OpenGL push/pop groups in GL debug. - the
/debugGL
option 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
CBitmapMuzzleFlame
type CEG particles:particleSpeed
,particleSpeedSpread
,airdrag
,gravity
. These work the same as they already do forCSimpleParticleSystem
type particles. - added
animParams1
andanimParams2
to CEGs, similar to weapons. Texture 1 is used forCSimpleParticleSystem
and the “front” texture ofCBitmapMuzzleFlame
, texture 2 is used for the “side” texture of muzzle flame. Other CEG classes don’t support this yet. NumberlessanimParams
used as a fallback. - added
drawSideX
anddrawSizeY
bool tags toCBitmapMuzzleFlame
, allows to skip some of the two “forward” sprites. X is the one parallel to the ground when shooting horizontally. There is nodrawSideZ
because you can just set that texture to empty.
Infotex commands
- added
/showLoS
. - added
/showInfoTex foo
, wherefoo
is one of the existing info textures (e.g./showInfoTex elevation
is equivalent to/showElevation
). - all the
/showFoo
commands 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.transformsInGL4
backwards compatibility check.
Base64
- added
Encoding
global table (likeSpring
ormath
etc), 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
, andIsValidBase64Url
toEncoding
. Same as above, except uses the base64url character set.
Duplicate logs
- the
LogRepeatLimit
springsetting, 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
.gltf
and.glb
model 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
s3ocompat
bool 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
leavesGhost
unit def tag. Controls whether the unit leaves a ghost. Defaults to true for buildings (maintains previous behaviour). - add
leavesGhost
UnitDefs entry, same. - add
Spring.GetUnitLeavesGhost(unitID) → bool
. - add
Spring.SetUnitLeavesGhost(unitID, bool leavesGhost, bool? existingGhostRemains = false)
. IfleavesGhost
becomes 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
ghostedBuildings
engineoption still exists and makes all of the above interfaces no-op, but is scheduled for removal.
Text coloring
- added
AllowColorFonts
bool 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.textColorCodes
still only lists the old ones.- added
TextDisableOldColorIndicators
bool springsetting, defaults to false. If true, the previous 255 and 254 color codes stop working andEngine.textColorCodes
lists the new ones.
Explosion event in unsynced
- add
Script.SetWatchExplosion(weaponDefID, bool)
, and the corresponding Get, to unsynced. - widgets can now receive the
Explosion
callin, 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:ShockFront
callin 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.AddFeatureDamage
with the same signature asSpring.AddUnitDamage
. Note that one of the args is paralyze time, but features don’t take paralyze damage. - add a new
checkDeath
bool 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 offalse
preserves this, set it totrue
to let features die immediately from HP removal. - add
Spring.SetFeatureFireTime(featureID, fireTime)
, sets a feature “on fire” (similar to being damaged with afirestarter
tagged 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
accurateLeading
numerical 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) → number
checks the queue length in a factory’s build queue (note thatGetUnitCommandCount
is for the rally queue in factories). - add
ThreadPinPolicy
springsetting to control which CPUs to use. (0) = Off; (1) = System Default; (2) = Exclusive Performance Core; (3) = Share Performance Cores. - added new CEG impact filters,
shield
andintercepted
. BeamLaser
andLightningCannon
type weapons now pass their actual projectileID to callins rather than-1
.BeamLaser
andLightningCannon
now obey ellipsoid and/or cylinder target volumes correctly.- immobile units that
canKamikaze
no longer disregard theblocking
unit 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
MiniMapDrawPings
boolean 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 N
no 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 sizeInBytesOnCPU
to grab the size of the model uniforms buffer on the CPU side. - add
LuaVBO:CopyTo(otherVBO, sizeInBytes) → bool ok
to 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
mouse2
tomouse10
“keys” for mousebuttons that can be bound, dittosc_mouse2-10
scancodes. LMB (mouse1
/sc_mouse1
) is planned to be made bindable later. - added
DWMFlush
numerical 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. /smoothmesh
renderer stays enabled even if you disable cheats.- trying to set a deprecated/nonexistent springsetting via Lua now produces a warning.
/give
now gives a correct hint for @x,y,z usage.- added
GL.TEXTURE_2D_ARRAY
Lua 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.