Game.version as a number
Moderator: Moderators
Game.version as a number
Game.version is a string, which makes it impossible for code to test if the version being run is higher or lower than a given version.
Please add a new Lua constant that returns a number that gets incremented at each release or each build.
Please add a new Lua constant that returns a number that gets incremented at each release or each build.
Re: Game.version as a number
Game.version = "0.81.2.0 (0.81.2-0-g76e4cf5{@}-cmake-mingw32)"
split on the first space to get "0.81.2.0"
split on periods to get ['0', '81', '2', '0']
then parse as ints to get [0, 81, 2, 0]
you can compare against another version list with priority given to leftmost numbers for seeing if it's newer
split on the first space to get "0.81.2.0"
split on periods to get ['0', '81', '2', '0']
then parse as ints to get [0, 81, 2, 0]
you can compare against another version list with priority given to leftmost numbers for seeing if it's newer
Re: Game.version as a number
i still like aegis's idea
Re: Game.version as a number
you can continue it like this:aegis wrote:Game.version = "0.81.2.0 (0.81.2-0-g76e4cf5{@}-cmake-mingw32)"
split on the first space to get "0.81.2.0"
split on periods to get ['0', '81', '2', '0']
then parse as ints to get [0, 81, 2, 0]
table.concat({81, 2, 0},"") -> tonumber("0." .. "8120") =: version-float
so you just have one float number which can be compared with others
Re: Game.version as a number
I didn't know you could compare list like that. Thanks.aegis wrote:
I dunno how to "split". Code please? I checked http://www.lua.org/manual/5.1/ and it has nothing about "split".
Also, your method does not take into account how 0.81+ is possibly higher than 0.81.2
I don't want any number, I want a number that gets higher the more recent Spring is. For instance, 0.8.5 is older than 0.81.3 despite 0.85>0.813jK wrote:
I have monkeyed something that use Lua's regexp to extract digits seperated by dots then add them with some factors, but it's ugly and bound to fail on unexpected version strings.
If you don't reset the build number, I'd rather have it accessible in Lua. (maybe floored to last release it syncs with inside synced gadgets).
Extracting the version number from the version strings simply isn't reliable enough.
Re: Game.version as a number
Yeah but if we end up with something like version 0.89.11.2 you're screwed.jK wrote:you can continue it like this:aegis wrote:Game.version = "0.81.2.0 (0.81.2-0-g76e4cf5{@}-cmake-mingw32)"
split on the first space to get "0.81.2.0"
split on periods to get ['0', '81', '2', '0']
then parse as ints to get [0, 81, 2, 0]
table.concat({81, 2, 0},"") -> tonumber("0." .. "8120") =: version-float
so you just have one float number which can be compared with others
Re: Game.version as a number
You guys are really inflexible ...
local array = {0, 81, 2, 0}
local format_str = "%d." .. (("%02d"):rep(#array-1))
local version_float = toumber( format_str:format(unpack(array)) )
local array = {0, 81, 2, 0}
local format_str = "%d." .. (("%02d"):rep(#array-1))
local version_float = toumber( format_str:format(unpack(array)) )
Re: Game.version as a number
Oh noes, don't teach them grep lol.
Here, this is useful reading:
http://en.wikipedia.org/wiki/Regular_expression
Here, this is useful reading:
http://en.wikipedia.org/wiki/Regular_expression
Re: Game.version as a number
You fail at reading, Argh:
zwzsg wrote:I have monkeyed something that use Lua's regexp to extract digits seperated by dots
So, yeah, you workarounded that one KDR_11k exemple. But you that still didn't adress the spirit of it: Trying to make a number out of that version string is inherently ugly and prone to error. I request a robust way to know if a Spring is under or over a given version. A way that won't break when you sudently decide to change a dash by a dot in the version string. A way that knows if a 0.81+ is under or over 0.81.2.jK wrote:%02d
Re: Game.version as a number
'(%d+.)'
tonumber(g76e4cf5)
string:gsub("-",""):gsub("."."")
string:gsub("%D","") ... if you just want to strip non-numeric, IIRC.
When you say "robust", I guess what I'm mainly reading there is that you are requesting that the nomenclature remain stable. I agree with that request.
tonumber(g76e4cf5)
string:gsub("-",""):gsub("."."")
string:gsub("%D","") ... if you just want to strip non-numeric, IIRC.
When you say "robust", I guess what I'm mainly reading there is that you are requesting that the nomenclature remain stable. I agree with that request.
Re: Game.version as a number
Let me reboot my topic.
Currently, Lua can get the Spring version number and that is very good. I like how Game.version is a complete string with all the details, including build version and compiler, as it looks very nifty when I print it in the bottom of my menu.
However, sometimes I also need to fetch the engine version number to know if it is past or before a given update. Sure we can already retrieve some info from the Game.version string and I already have a couple gadget or widget that use regular expressions to construct a version number out of the Game.version string.
However:
So, I would like that in addition to Game.version, a new constant be added, that would be just an integer, that gets incremented every time buildbot builds. It would make comparing engine version much easier and reliable.
________________________________________
Maybe I should also have posted my codes so you stop taking me for a lazy idiot:
In August, back when jK broke gl.Text, I wrote code like that. It is pretty bad, as when the digit separating dot is misplaced, it errors out. I added the "or 0" so it wouldn't take down the whole widget/gadget after I had a Spring version with two dots within the first three characters.
This weekend I wrote that, when I found out then new Spring version want Mapname without the .smf suffix. Afterward I realised I forgot the tonumber(), but it somehows worked anyway. But I'm not proud of how I arbitrarly add 0.9 for test version. Also, Lua rounding errors on decimals number means you have to take care about using a little margin in your comparaison.
Please takes notes of how it uses at least four regular expression, Argh! That means I'm not asking for a lecture on them. Not from you anyway.
Later I realised I just needed to compare 0.81 to over 0.81 (betting on the new Spring being at least 0.82), so simplified my parsing to that single line.
Even though I managed to get it working for my current purposes, it's not the first time this problem cropped up before me, and I wish there was a clean way to get a numeric version number, instead of having to parse the string myself.
I do not doubt that jK could write a super efficient formula to parse the version string with much fewer operation and much greater elegance. I do not doubt that Argh could write a full page of kludge to cover every known format of the version string. But it seems a defiency that we need such code to get a usable version number in the first place. And covering the corner cases is not trivial, even aegis and jK failed to take into account fairly obvious ones in their first try. So expecting every Lua coder out there to be able to write a perfect version string parser is ludicrous. It should be implemented engine side, and should not rely on string parsing in the first place.
Also, before someones says it: Yes, I know the Lua manual states that calling them regular expression is erroneous, and we're supposed to call them patterns in Lua. But I still call them regexp because anyway they're just like them and it's easier to understand what we're talking about.
Currently, Lua can get the Spring version number and that is very good. I like how Game.version is a complete string with all the details, including build version and compiler, as it looks very nifty when I print it in the bottom of my menu.
However, sometimes I also need to fetch the engine version number to know if it is past or before a given update. Sure we can already retrieve some info from the Game.version string and I already have a couple gadget or widget that use regular expressions to construct a version number out of the Game.version string.
However:
- It shouldn't require half a dozen line of code just to get a usable version number.
- The Game.version string may change format one day, making code that parse it error out.
- There are lots of corner case to cover, making the parsing very tricky.
So, I would like that in addition to Game.version, a new constant be added, that would be just an integer, that gets incremented every time buildbot builds. It would make comparing engine version much easier and reliable.
________________________________________
Maybe I should also have posted my codes so you stop taking me for a lazy idiot:
Code: Select all
if (tonumber(string.sub(Game.version,1,3) or 0) or 0)>=0.80 and (tonumber(string.sub(Game.version,6,6) or 0) or 0)>=1 then
Code: Select all
local function GetBetterSpringVersion()
local version=100*string.match(Game.version,"^(%d+%.%d+)")
local subversion=string.match(Game.version,"^%d+%.%d+%.(%d+)")
local subsubversion=string.match(Game.version,"^%d+%.%d+%.%d+%.(%d+)")
local TestBuild=string.match(Game.version,"^[%d%.]+(%+)")
if subversion then
version=version+subversion/100
end
if subsubversion then
version=version+subsubversion/10000
end
if TestBuild then
version=version+0.9
end
return version,test
end
Please takes notes of how it uses at least four regular expression, Argh! That means I'm not asking for a lecture on them. Not from you anyway.
Code: Select all
local version=tonumber(string.match(Game.version,"^(%d+%.%d+)"))+(string.match(Game.version,"^[%d%.]+(%+)") and 0.009 or 0)
Even though I managed to get it working for my current purposes, it's not the first time this problem cropped up before me, and I wish there was a clean way to get a numeric version number, instead of having to parse the string myself.
I do not doubt that jK could write a super efficient formula to parse the version string with much fewer operation and much greater elegance. I do not doubt that Argh could write a full page of kludge to cover every known format of the version string. But it seems a defiency that we need such code to get a usable version number in the first place. And covering the corner cases is not trivial, even aegis and jK failed to take into account fairly obvious ones in their first try. So expecting every Lua coder out there to be able to write a perfect version string parser is ludicrous. It should be implemented engine side, and should not rely on string parsing in the first place.
Also, before someones says it: Yes, I know the Lua manual states that calling them regular expression is erroneous, and we're supposed to call them patterns in Lua. But I still call them regexp because anyway they're just like them and it's easier to understand what we're talking about.
Thanks!Argh wrote:I agree with that request.
Re: Game.version as a number

Code: Select all
local gameSubVersion = Game.version
local gameVersion = Game.version
local catch
for k in string.gmatch(gameSubVersion,"-(%w+){") do
catch = k
end
gameSubVersion = tonumber(catch,35)
local catchTwo= string.match(gameVersion,"%d+.%d+.%d+.%d+")
gameVersion = catchTwo
local version = tostring(gameVersion).."."..tostring(gameSubVersion)
version = "0."..string.gsub(version,"(%p)","")
version = tonumber(version)
Spring.Echo("Clean version is: ",version)
Re: Game.version as a number
the problems with a single, incrementing number:
it could be done by extending springs GameVersion.(h|cpp); letting the buildbot put the number of commits since the mother-or-all-commits into a var in these files.
problems:
1. this number will only be set with buildbot builds, and be empty or 0 or something, otherwise.
2. this approach fails with different branches, which are already used relatively extensively, and this will more likely increase then decrease.
i can not see any reliable way to perfectly solve this problem, exactly cause of the two problems above,.
1 might have a solution somehow, even doh it would not be very pretty, most likely, while 2 is logically impossible to do, as you can not directly/perfectly say which version is ahead of the other, in two parallel dev branches.
could you possibly explain what exactly you need to compare the versions? cause.. usually you should rather care whether versions are different or not, and not so much which one is ahead of which (exactly because this is sometimes impossible).
it could be done by extending springs GameVersion.(h|cpp); letting the buildbot put the number of commits since the mother-or-all-commits into a var in these files.
problems:
1. this number will only be set with buildbot builds, and be empty or 0 or something, otherwise.
2. this approach fails with different branches, which are already used relatively extensively, and this will more likely increase then decrease.
i can not see any reliable way to perfectly solve this problem, exactly cause of the two problems above,.
1 might have a solution somehow, even doh it would not be very pretty, most likely, while 2 is logically impossible to do, as you can not directly/perfectly say which version is ahead of the other, in two parallel dev branches.
could you possibly explain what exactly you need to compare the versions? cause.. usually you should rather care whether versions are different or not, and not so much which one is ahead of which (exactly because this is sometimes impossible).
Re: Game.version as a number
First, thanks for addressing my actual question instead of telling me to parse the string.
Of course I could be lazy and just adapt the mod I maintain to the new Spring version breaking compatibility with the old Spring. However I insist of keeping the mod compatible with old Spring versions, because I know that not every change is a step forward, and one of this day I might have to fall back on using an old Spring after something too important goes broken (it already happened). You probably won't like to hear that, but please understand it pains me as well, I'd much prefer every new Spring version to be bug free, regression free, and to only bring Good Stuff, but sadly we don't live in an ideal world, and sometimes in order to maintain a game in working order, I have to do dirty stuff. Then I rarely test the new mod version against old Spring builds, so I'm probably deluding myself in thinking it would still work, but at least if I have to make new mod works under old Spring, I know that it would require minimal work, since every time Spring behavior change, I make sure to write the mod fix in a way intended to work both with old and new Spring.
Here are three cases where I had to test Spring version:
- Between 0.78 and 0.79, the value returned by gl.GetTextWidth changed.
- Between 0.80.0 and 0.80.1, the default vertical alignment of gl.Text changed.
- Between 0.81.2 and future, the Mapname field in startscript lost the ".smf" suffix.
I hadn't thought of branching. Indeed when Spring starts forking, the whole concept of ordering Spring version falls down. But then, since I knew Spring, there always was a main "official" branch and all the forks were limited in use to the one person that coded them. I have yet to see binaries based on unofficial branches being distributed.2. this approach fails with different branches, which are already used relatively extensively, and this will more likely increase then decrease.
Well, then if one day Spring is getting built with something else than buildbot, that something else will have to keep increasing the build count? If someone builds his own version of Spring, I'm not worried about the build count not being properly set as long as he keeps that version to himself. If someone builds his own version of Spring then start distributing it, or if self-built Spring have to sync with bot-built Spring, then yeah we have an issue.1. this number will only be set with buildbot builds, and be empty or 0 or something, otherwise.
Basically because since the Swedish Yankspankers left, Spring developpers don't care much about retro-compatibility, so periodically a function behavior will change, or will require a different input, etc...could you possibly explain what exactly you need to compare the versions? cause.. usually you should rather care whether versions are different or not, and not so much which one is ahead of which (exactly because this is sometimes impossible).
Of course I could be lazy and just adapt the mod I maintain to the new Spring version breaking compatibility with the old Spring. However I insist of keeping the mod compatible with old Spring versions, because I know that not every change is a step forward, and one of this day I might have to fall back on using an old Spring after something too important goes broken (it already happened). You probably won't like to hear that, but please understand it pains me as well, I'd much prefer every new Spring version to be bug free, regression free, and to only bring Good Stuff, but sadly we don't live in an ideal world, and sometimes in order to maintain a game in working order, I have to do dirty stuff. Then I rarely test the new mod version against old Spring builds, so I'm probably deluding myself in thinking it would still work, but at least if I have to make new mod works under old Spring, I know that it would require minimal work, since every time Spring behavior change, I make sure to write the mod fix in a way intended to work both with old and new Spring.
Here are three cases where I had to test Spring version:
- Between 0.78 and 0.79, the value returned by gl.GetTextWidth changed.
- Between 0.80.0 and 0.80.1, the default vertical alignment of gl.Text changed.
- Between 0.81.2 and future, the Mapname field in startscript lost the ".smf" suffix.
Re: Game.version as a number
Linux builds aren't built by buildbot and often there is no access to the internet (for security reasons) in the environment where packages are build, so unless the build number is hardcoded in the source package that solution will not work.
Also you're plain wrong about Spring devs not caring much about retro compatibility. In your comparison you forget to list the 100s of changes in behaviour for which backward compatibility was preserved, you only mention the occasional bug. (Hints: TDF still works, legacy AI API, many Lua functions have new arguments be optional, etc.)
Wrt the map name suffix, you didn't even report that in mantis yet
Wrt the topic, I would like a better method too, but I haven't found one yet except checking for the specific behaviour when possible. (E.g.: in the spawn gadget, instead of doing complicated checks against version number, I check whether engine already spawned start units and only if it didn't then the gadget spawns them.)
Probably such an approach could work for GetTextWidth and the .smf suffix too.
Also you're plain wrong about Spring devs not caring much about retro compatibility. In your comparison you forget to list the 100s of changes in behaviour for which backward compatibility was preserved, you only mention the occasional bug. (Hints: TDF still works, legacy AI API, many Lua functions have new arguments be optional, etc.)
Wrt the map name suffix, you didn't even report that in mantis yet

Wrt the topic, I would like a better method too, but I haven't found one yet except checking for the specific behaviour when possible. (E.g.: in the spawn gadget, instead of doing complicated checks against version number, I check whether engine already spawned start units and only if it didn't then the gadget spawns them.)
Probably such an approach could work for GetTextWidth and the .smf suffix too.
Re: Game.version as a number
Maybe the build number could be stored in some .h, and the buildbot would run a script to increment it. People who pull the source locally and compile without the build bot script would get a fixed build number until they update their source, which sounds like an acceptable compromise.Linux builds aren't built by buildbot and often there is no access to the internet (for security reasons) in the environment where packages are build, so unless the build number is hardcoded in the source package that solution will not work.
Yeah, we never thanks the dev for the 100s of changes that go well. We only bitch and rant about the 1 that went not so well.Also you're plain wrong about Spring devs not caring much about retro compatibility. In your comparison you forget to list the 100s of changes in behaviour for which backward compatibility was preserved, you only mention the occasional bug. (Hints: TDF still works, legacy AI API, many Lua functions have new arguments be optional, etc.)
Wrt the map name suffix, you didn't even report that in mantis yet
- I know that Auswaschbar knows about it since he mentionned it.
- I was under the impression it was not a bug but a deliberate change (to make it "cleaner" or something).
- I'm pretty sure that if I had complained about that change I would just have been told to use SpringLobby instead of coding my own start-script-writer.
- As soon as I saw the problem, it didn't took me long to write a workaround by checking the version and adding or removing the suffix as needed. I tend to be quiet about bugs I can fix modside, cause it draw enough energy to draw attention about the unavoidable bugs already.
I tend to avoid checking version number whenever possible too. For exemple, regarding the gl.Text exemple I mentionned earlier, nowadays instead of doing a version check, I simply add the "d" option when there is no option. Or when package.loadlib got removed, then Spring.Restart got added instead of checking version number I just check "if Spring.Restart then" and "elseif package and package.loadlib then". For the Mapname I could just check if the one in Game.mapName has the suffix. And for GetTextWidth I guess I could check its output on a string I already know the width of. But sometimes analysing the game behavior to guess which engine version is running would be as complicated and hacky as getting the version itself. And there's some cases where it's plain impossible, like for when the result is different only graphically, or when testing could cause a crash.I haven't found one yet except checking for the specific behaviour when possible. (E.g.: in the spawn gadget, instead of doing complicated checks against version number, I check whether engine already spawned start units and only if it didn't then the gadget spawns them.)
Probably such an approach could work for GetTextWidth and the .smf suffix too.
Cool, we agree!Wrt the topic, I would like a better method too
-
- Spring Developer
- Posts: 1254
- Joined: 24 Jun 2007, 08:34
Re: Game.version as a number
Yes please. One commit to increase the number for each real commit ftw.zwzsg wrote:Maybe the build number could be stored in some .h, and the buildbot would run a script to increment it. People who pull the source locally and compile without the build bot script would get a fixed build number until they update their source, which sounds like an acceptable compromise.Linux builds aren't built by buildbot and often there is no access to the internet (for security reasons) in the environment where packages are build, so unless the build number is hardcoded in the source package that solution will not work.
If you would use the lua callins for getting archive names and / or unitsync you wouldn't have that problem, as those will return the right names in every version.zwzsg wrote:Wrt the map name suffix, you didn't even report that in mantis yet
- I know that Auswaschbar knows about it since he mentionned it.
- I was under the impression it was not a bug but a deliberate change (to make it "cleaner" or something).
- I'm pretty sure that if I had complained about that change I would just have been told to use SpringLobby instead of coding my own start-script-writer.
- As soon as I saw the problem, it didn't took me long to write a workaround by checking the version and adding or removing the suffix as needed. I tend to be quiet about bugs I can fix modside, cause it draw enough energy to draw attention about the unavoidable bugs already.
On T: for the version thing, don't forget that there is a "+" inside sometime (which is obviously not a number).