Game.version as a number

Game.version as a number

Requests for features in the spring code.

Moderator: Moderators

Post Reply
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Game.version as a number

Post by zwzsg »

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.
User avatar
aegis
Posts: 2456
Joined: 11 Jul 2007, 17:47

Re: Game.version as a number

Post by aegis »

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
User avatar
Tribulex
A.N.T.S. Developer
Posts: 1894
Joined: 26 Sep 2009, 21:26

Re: Game.version as a number

Post by Tribulex »

i still like aegis's idea
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Game.version as a number

Post by jK »

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]
you can continue it like this:

table.concat({81, 2, 0},"") -> tonumber("0." .. "8120") =: version-float

so you just have one float number which can be compared with others
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: Game.version as a number

Post by zwzsg »

aegis wrote:
I didn't know you could compare list like that. Thanks.

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

jK wrote:
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.813



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.
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Re: Game.version as a number

Post by KDR_11k »

jK wrote:
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]
you can continue it like this:

table.concat({81, 2, 0},"") -> tonumber("0." .. "8120") =: version-float

so you just have one float number which can be compared with others
Yeah but if we end up with something like version 0.89.11.2 you're screwed.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Game.version as a number

Post by jK »

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)) )
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Game.version as a number

Post by Argh »

Oh noes, don't teach them grep lol.

Here, this is useful reading:

http://en.wikipedia.org/wiki/Regular_expression
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: Game.version as a number

Post by zwzsg »

You fail at reading, Argh:
zwzsg wrote:I have monkeyed something that use Lua's regexp to extract digits seperated by dots
jK wrote:%02d
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.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Game.version as a number

Post by Argh »

'(%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.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: Game.version as a number

Post by zwzsg »

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:
  • 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
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.


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
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.


Code: Select all

local version=tonumber(string.match(Game.version,"^(%d+%.%d+)"))+(string.match(Game.version,"^[%d%.]+(%+)") and 0.009 or 0)
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.
Argh wrote:I agree with that request.
Thanks!
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Game.version as a number

Post by Argh »

:roll:

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)
That should solve your problem until version 1.0+ of Spring, unless the base conversion's wrong, assuming that buildbot / git uses the current system for numbers on builds. At the very least, it will do gross checks correctly (i.e. 0.8120 > 0.8100 etc.).
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Game.version as a number

Post by hoijui »

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).
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: Game.version as a number

Post by zwzsg »

First, thanks for addressing my actual question instead of telling me to parse the string.
2. this approach fails with different branches, which are already used relatively extensively, and this will more likely increase then decrease.
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.
1. this number will only be set with buildbot builds, and be empty or 0 or something, otherwise.
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.

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).
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...

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.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Game.version as a number

Post by Tobi »

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.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: Game.version as a number

Post by zwzsg »

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.
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.

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.)
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.

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 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.
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.

Wrt the topic, I would like a better method too
Cool, we agree!
Auswaschbar
Spring Developer
Posts: 1254
Joined: 24 Jun 2007, 08:34

Re: Game.version as a number

Post by Auswaschbar »

zwzsg wrote:
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.
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.
Yes please. One commit to increase the number for each real commit ftw.
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.
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.

On T: for the version thing, don't forget that there is a "+" inside sometime (which is obviously not a number).
Post Reply

Return to “Feature Requests”