Skip to content

Commit c8459cf

Browse files
committed
Be more lenient when updating the minor version of the game
That includes an update from, for example, 1.21 -> 1.21.1, but not, for example, 1.21.1 -> 1.22 Also changes build order to first package actual artifacts (shade, plugin) and then runs tests
1 parent 4239d48 commit c8459cf

File tree

4 files changed

+80
-5
lines changed

4 files changed

+80
-5
lines changed

commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIConfig.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public abstract class CommandAPIConfig<Impl
3939
boolean verboseOutput = false;
4040
boolean silentLogs = false;
4141
boolean useLatestNMSVersion = false;
42+
boolean lenientForMinorVersions = false;
4243
String missingExecutorImplementationMessage = "This command has no implementations for %s";
4344

4445
File dispatcherFile = null;
@@ -90,6 +91,22 @@ public Impl useLatestNMSVersion(boolean value) {
9091
return instance();
9192
}
9293

94+
/**
95+
* Sets whether the CommandAPI should load a (potentially unsupported) NMS version
96+
* when updating to a minor release of Minecraft, for example this setting would
97+
* allow running a minor version of the game before the CommandAPI makes a proper
98+
* release for it. Unlike {@link #useLatestNMSVersion(boolean)}, this setting does
99+
* not blindly load the latest NMS version and as a result break cross version compatibility
100+
* but will actually prefer loading the correct NMS implementation.
101+
*
102+
* @param value whether the CommandAPI should assume that minor Minecraft releases do not cause incompatibilities
103+
* @return this CommandAPIConfig
104+
*/
105+
public Impl lenientForMinorVersions(boolean value) {
106+
this.lenientForMinorVersions = value;
107+
return instance();
108+
}
109+
93110
/**
94111
* Sets the message to display to users when a command has no executor.
95112
* Available formatting parameters are:

commandapi-core/src/main/java/dev/jorel/commandapi/InternalConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public class InternalConfig {
4040
// Whether we should use the latest NMS version (which may not be compatible)
4141
private final boolean useLatestNMSVersion;
4242

43+
private final boolean beMoreLenientForMinorVerions;
44+
4345
// The message to display when an executor implementation is missing
4446
private final String messageMissingExecutorImplementation;
4547

@@ -65,6 +67,7 @@ public InternalConfig(CommandAPIConfig<?> config) {
6567
this.verboseOutput = config.verboseOutput;
6668
this.silentLogs = config.silentLogs;
6769
this.useLatestNMSVersion = config.useLatestNMSVersion;
70+
this.beMoreLenientForMinorVerions = config.lenientForMinorVersions;
6871
this.messageMissingExecutorImplementation = config.missingExecutorImplementationMessage;
6972
this.dispatcherFile = config.dispatcherFile;
7073
this.skipSenderProxy = config.skipSenderProxy;
@@ -94,6 +97,13 @@ public boolean shouldUseLatestNMSVersion() {
9497
return this.useLatestNMSVersion;
9598
}
9699

100+
/**
101+
* @return Whether the CommandAPI should assume that minor versions of officially unsupported versions do not cause incompatibilities
102+
*/
103+
public boolean shouldBeMoreLenientForMinorVersions() {
104+
return this.beMoreLenientForMinorVerions;
105+
}
106+
97107
/**
98108
* @return The message to display if a command executor does not have an
99109
* implementation for a given type

commandapi-platforms/commandapi-bukkit/commandapi-bukkit-vh/src/main/java/dev/jorel/commandapi/CommandAPIVersionHandler.java

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ public interface CommandAPIVersionHandler {
4949
* @return an instance of NMS which can run on the specified Minecraft version
5050
*/
5151
static CommandAPIPlatform<?, ?, ?> getPlatform() {
52+
CommandAPIPlatform<?, ?, ?> latestNMS = new NMS_1_21_R1();
5253
if (CommandAPI.getConfiguration().shouldUseLatestNMSVersion()) {
53-
return new NMS_1_21_R1();
54+
return latestNMS;
5455
} else {
5556
String version = Bukkit.getBukkitVersion().split("-")[0];
56-
return switch (version) {
57+
Version minecraftVersion = new Version(version);
58+
CommandAPIPlatform<?, ?, ?> platform = switch (version) {
5759
case "1.16.5" -> new NMS_1_16_R3();
5860
case "1.17" -> new NMS_1_17();
5961
case "1.17.1" -> new NMS_1_17_R1();
@@ -68,9 +70,54 @@ public interface CommandAPIVersionHandler {
6870
case "1.20.3", "1.20.4" -> new NMS_1_20_R3();
6971
case "1.20.5", "1.20.6" -> new NMS_1_20_R4();
7072
case "1.21", "1.21.1" -> new NMS_1_21_R1();
71-
default -> throw new UnsupportedVersionException(version);
73+
default -> null;
7274
};
75+
if (platform != null) {
76+
return platform;
77+
} else {
78+
if (CommandAPI.getConfiguration().shouldBeMoreLenientForMinorVersions()) {
79+
return minecraftVersion.matchesPatch((NMS<?>) latestNMS);
80+
}
81+
throw new UnsupportedVersionException(version);
82+
}
7383
}
7484
}
7585

86+
class Version {
87+
88+
private final String version;
89+
90+
// The minor version is something like 1.x
91+
private final int minor;
92+
93+
private Version(String version) {
94+
this.version = version;
95+
String[] versionParts = version.split("\\.");
96+
minor = Integer.parseInt(versionParts[1]);
97+
}
98+
99+
private CommandAPIPlatform<?, ?, ?> matchesPatch(NMS<?> latestNMS) {
100+
if (minor <= 16) {
101+
// We absolutely do not support versions older than 1.16.5
102+
// As we match 1.16.5 in the getPlatform() method, this if branch means that
103+
// the server is on 1.16.4 or older
104+
throw new UnsupportedVersionException(version);
105+
} else {
106+
// Any other Minecraft that is older or exactly the last version we match in getPlatform()
107+
// does not appear here. Furthermore, we do not want to be lenient with 1.x versions so we
108+
// can simply return the latest NMS version here if its supported Minecraft version's minor version
109+
// is the same as the current Minecraft version
110+
String[] supportedNMSVersions = latestNMS.compatibleVersions();
111+
int minorVersion = Integer.parseInt(supportedNMSVersions[0].split("\\.")[1]); // Index 1 returns the minor version by SemVer's rules
112+
if (this.minor == minorVersion) {
113+
return (CommandAPIPlatform<?, ?, ?>) latestNMS;
114+
}
115+
}
116+
// If we end up here, that means the server's current minor version in SemVer terms is newer than the
117+
// latest minor version of Minecraft in SemVer terms that this method allows. We do not support that.
118+
throw new UnsupportedVersionException(version);
119+
}
120+
121+
}
122+
76123
}

commandapi-platforms/commandapi-bukkit/pom.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@
2626

2727
<!-- Outputs -->
2828
<module>commandapi-bukkit-plugin</module>
29-
<module>commandapi-bukkit-test</module>
3029
<module>commandapi-bukkit-shade</module>
31-
3230
<module>commandapi-bukkit-plugin-mojang-mapped</module>
3331
<module>commandapi-bukkit-shade-mojang-mapped</module>
32+
33+
<!-- Tests -->
34+
<module>commandapi-bukkit-test</module>
3435
</modules>
3536
</project>

0 commit comments

Comments
 (0)