-
Notifications
You must be signed in to change notification settings - Fork 294
Fix and improve version normalization for old Minecraft versions #1041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix and improve version normalization for old Minecraft versions #1041
Conversation
f759e9f
to
a6715c7
Compare
11b0ab2
to
e6c1728
Compare
4fd11b9
to
1221edc
Compare
1221edc
to
db32fcd
Compare
- proper handling of classic versions - fix handling of multiple indev/infdev versions that occur on the same day - fix handling of experimental snapshots - fix 2.0 april fools version handling - add handling for test builds and pre-releases in beta - add support for timestamp suffixes used in omniarchive version ids
db32fcd
to
fa18e6b
Compare
This looks promising so far, thanks.
These seem out of order now, Semver is supposedly using numeric comparison and Additionally to testing compareTo we should validate conversions of a variety of versions to make sure no code changes accidentally change them. At this point it might be worth changing the static Pattern declarations to just Strings and compile the pattern as they are used. Combined with checking modern and frequently used patterns first this should save a bit of overhead for most users. |
Good catch! For now I'll set the time component of |
only allow 1.x.y instead of x.y.z - this helps in differentiating between classic and release versions
this is because some pre-release 1s are simply known as "Prerelease" in the jar
and use them in the semver for these versions
apparently there was no handling for this april fools version yet??
it would fail when called from McVersion.Builder.setNameAndRelease anyway
I had to revert back to the previous handling of Indev/Infdev versions, as the new approach made the numbers too large (the semver parser can only handle 32bit ints). I added unit tests for all special cases and oddities for mc version normalization, and tests for the semver comparison as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks!
One last request though: It might help future maintenance a lot if the Pattern initializers and their use sites had a comment that lists an existing example version (maybe multiple if there are substantially different options) like this:
private static final Pattern RELEASE_PATTERN = Pattern.compile("\\d+\\.\\d+(\\.\\d+)?"); // 1.3 1.7.10
[...]
if ((matcher = RELEASE_PATTERN.matcher(name)).matches()) { // 1.3 1.7.10
case "22w13oneblockatatime": | ||
case "af-2022": | ||
// Minecraft 22w13oneblockatatime | ||
return "1.19.1-alpha.22.13.oneblockatatime"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is definitely wrong. I think the correct answer is 1.18.3-alpha.22.13.oneblockatatime
(if we're fine with nonexistent main version) or 1.19-alpha.22.13.oneblockatatime
(if we don't care that oBAAT is not forked from 1.19 snapshot series).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the correct answer is
1.18.3-alpha.22.13.oneblockatatime
(if we're fine with nonexistent main version)
I think you're right (see the combat snapshots forked from 1.14.4) - I'll be using this, thanks!
change from 1.19.1-alpha.22.13.oneblockatatime to 1.18.3-alpha.22.13.oneblockatatime the version is forked from 1.18.2, not the 1.19.1 snapshot series!
8db054b
to
80b51d9
Compare
private static final Pattern TEST_BUILD_PATTERN = Pattern.compile(".+(?:-tb| Test Build )(\\d+)?(?:-(\\d+))?"); // ... Test Build 1, ...-tb2, ...-tb3-1234 | ||
private static final Pattern PRE_RELEASE_PATTERN = Pattern.compile(".+(?:-pre| Pre-?[Rr]elease ?)(?:(\\d+)(?: ;\\))?)?(?:-(\\d+))?"); // ... Prerelease, ... Pre-release 1, ... Pre-Release 2, ...-pre3, ...-pre4-1234 | ||
private static final Pattern RELEASE_CANDIDATE_PATTERN = Pattern.compile(".+(?:-rc| RC| [Rr]elease Candidate )(\\d+)(?:-(\\d+))?"); // ... RC1, ... Release Candidate 2, ...-rc3, ...-rc4-1234 | ||
private static final Pattern SNAPSHOT_PATTERN = Pattern.compile("(?:Snapshot )?(\\d+)w0?(0|[1-9]\\d*)([a-z])(?:-(\\d+))?"); // Snapshot 16w02a, 20w13b, 22w18c-1234 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't there a snapshot that had a tilde?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes there is 13w12~ and 20w14~ (20w14 infinite) but they're handled by special cases in normalizeSpecialVersion
.
* fix regressions in version normalization * fix comment * more fixes * more special cases for combat snapshots * fix experimental snapshot parsing again * support server- prefix for alpha servers * semver handling for classic servers * improve handling of special semver cases * fix sorting of classic servers
I noticed several issues with version normalization for old Minecraft versions, which I'll detail below. This PR fixes those problems, and also adds handling for Omniarchive version ids.
Classic
The current handling of classic merely strips the
c
prefix and doing basic normalization of the remaining string (separator digits and non-digits by.
, replacing_
with.
). This gives invalid semver like0.0.11.a
.I chose to revamp this entirely for two reasons. The alphabetic chars do not denote versioning (
st
is for survival test versions, anda
is used in all early classic versions), and early classic has an extra leading0.
, and leaving that out makes normalizing those versions easier.The updated handling gives these results:
c0.0.11a
->0.11
c0.0.23a_01
->0.23.1
c0.24_st_03
->0.24.3
c0.25_05_st
->0.25.5
c0.29
->0.29
c0.30-c
->0.30-c
c0.30-s
->0.30-s
c0.30-c-renew
->0.30-c.renew
Alpha and Beta
There was special handling for trailing alphabetic chars for Alpha and Beta versions, which wasn't needed at all, since that was only used in Classic. I removed this without any change in output.
Additionally, there are some test builds and pre-releases in Beta, which Loader had no handling for. After discussion on Discord, I opted to handle those the following way.
r
as a patch version at the end ('r' for 'release').0
to ensure it and its pre-releases are sorted before subsequent minor updates.The use of an alphabetic char for the release ensures it is sorted after the test builds and pre-releases. The updated handling gives the following results:
b1.6-tb3
->1.0.0-beta.6.0.3
b1.6
->1.0.0-beta.6.0.r
b1.6.1
->1.0.0-beta.6.1
b1.8-pre2
->1.0.0-beta.8.0.2
b1.8
->1.0.0-beta.8.0.r
b1.8.1
->1.0.0-beta.8.1
1.0.0
Added a special case for parsing release candidates for 1.0.0 from the jar, where they are simply called
Minecraft RC1
andMinecraft RC2
. The semver follows the convention for release candidates for later versions:Minecraft RC1
->1.0.0-rc.1
Minecraft RC2
->1.0.0-rc.2
The downside is that this does conflict with pre-releases for old versions (which also use the
rc
identifier) but since 1.0.0 does not have any pre-releases I do not see this as a problem.2.0 April Fools update
There were special cases for normalizing
2point0_purple
to1.5.2-purple
and similar to the red and blue versions. But those versions are known as2.0
in the jar, and there was no special case for that, meaning Loader would simply normalize that version to2.0
.To reconcile this I updated the special cases as follows:
2.0
->1.5.2-2.0
2point0_purple
->1.5.2-2.0+purple
2point0_red
->1.5.2-2.0+red
2point0_blue
->1.5.2-2.0+blue
22w13oneBlockAtATime (2022 April Fools update)
There was no special handling for this version which led to inconsistent normalization. I added a special case for it.
Release Versions
I made the pattern matching for release versions a little stricter. It now only matches 1.x.y instead of x.y.z. This way the Release version pattern does not match Classic versions.
Experimental Snapshots
Pattern matching for experimental snapshots was already implemented, but the special cases for it in
getRelease
were missing so it was never used. I added these special cases to fix that.Omniarchive versions
Omniarchive deviate from Mojang's manifest ids in a few ways.
af-yyyy
whereyyyy
is the year in which the version was released. I added special cases for these.-pre
suffix. I added handling to remove those suffixes to be consistent with early Loader behavior.+
separator).