Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 85 additions & 20 deletions src/main/java/org/quiltmc/installer/CliInstaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import org.jetbrains.annotations.Nullable;
import org.quiltmc.installer.action.Action;
Expand Down Expand Up @@ -70,22 +69,23 @@ private static Action<?> parse(String input) {
switch (arg) {
case "help":
return Action.DISPLAY_HELP;
case "listVersions":
case "listVersions": {
if (split.size() == 0) {
System.err.println("Loader type is required");
return Action.DISPLAY_HELP;
}

String rawType = split.remove();
LoaderType type = LoaderType.of(rawType);
int intermediaryGen = -1;

if (type == null) {
System.err.println("Unknown loader type: " + rawType);
return Action.DISPLAY_HELP;
}

if (split.size() == 0) {
return Action.listVersions(type, false, false);
return Action.listVersions(type, intermediaryGen, false, false);
}

boolean minecraftSnapshots = false;
Expand All @@ -102,13 +102,38 @@ private static Action<?> parse(String input) {
} else if (option.startsWith("--")) {
System.err.printf("Invalid option \"%s\"%n", arg);
hasError = true;
} else if (option.startsWith("--intermediary-generation")) {
if (option.indexOf('=') == -1) {
System.err.println("Option \"--intermediary-generation\" must specify a value");
return Action.DISPLAY_HELP;
}

if (!option.startsWith("--intermediary-generation=")) {
System.err.println("Option \"--intermediary-generation\" must have a equals sign (=) right after the option name to get the value");
return Action.DISPLAY_HELP;
}

String value = unqoute(option.substring(26));

if (value == null) {
System.err.println("Option \"--intermediary-generation\" must have value quoted at start and end of value");
return Action.DISPLAY_HELP;
}

intermediaryGen = Integer.parseInt(value);

if (intermediaryGen < 1 || intermediaryGen > IntermediaryGenerations.latest()) {
System.err.println("Option \"--intermediary-generation\" value \"" + intermediaryGen + "\" is not valid! Value must be between 1 and " + IntermediaryGenerations.latest() + ".");
return Action.DISPLAY_HELP;
}
} else {
System.err.printf("Unexpected additional argument \"%s\"%n", arg);
hasError = true;
}
}

return !hasError ? Action.listVersions(type, minecraftSnapshots, loaderBetas) : Action.DISPLAY_HELP;
return !hasError ? Action.listVersions(type, intermediaryGen, minecraftSnapshots, loaderBetas) : Action.DISPLAY_HELP;
}
case "install":
if (split.size() == 0) {
System.err.println("Side is required: \"client\" or \"server\"");
Expand Down Expand Up @@ -137,6 +162,7 @@ private static Action<?> parse(String input) {
String rawLoaderType = split.remove();
LauncherType launcherType = LauncherType.of(rawLauncherType);
LoaderType loaderType = LoaderType.of(rawLoaderType);
int intermediaryGen = -1;

if (launcherType == null) {
System.err.println("Unknown launcher type: " + rawLauncherType);
Expand All @@ -147,11 +173,9 @@ private static Action<?> parse(String input) {
return Action.DISPLAY_HELP;
}

String intermediary = fetchIntermediary(GameSide.CLIENT, minecraftVersion);

// At this point all the require arguments have been parsed
if (split.size() == 0) {
return Action.installClient(minecraftVersion, launcherType, loaderType, null, intermediary, null, false, false);
return Action.installClient(minecraftVersion, launcherType, loaderType, null, intermediaryGen, null, null, false, false);
}

// Try to parse loader version first
Expand All @@ -166,7 +190,7 @@ private static Action<?> parse(String input) {

// No more arguments, just loader version
if (split.size() == 0) {
return Action.installClient(minecraftVersion, launcherType, loaderType, loaderVersion, intermediary, null, false, false);
return Action.installClient(minecraftVersion, launcherType, loaderType, loaderVersion, intermediaryGen, null, null, false, false);
}

// There are some additional options
Expand Down Expand Up @@ -218,13 +242,37 @@ private static Action<?> parse(String input) {
}

options.put("--install-dir", value);
} else if (option.startsWith("--intermediary-generation")) {
if (option.indexOf('=') == -1) {
System.err.println("Option \"--intermediary-generation\" must specify a value");
return Action.DISPLAY_HELP;
}

if (!option.startsWith("--intermediary-generation=")) {
System.err.println("Option \"--intermediary-generation\" must have a equals sign (=) right after the option name to get the value");
return Action.DISPLAY_HELP;
}

String value = unqoute(option.substring(26));

if (value == null) {
System.err.println("Option \"--intermediary-generation\" must have value quoted at start and end of value");
return Action.DISPLAY_HELP;
}

intermediaryGen = Integer.parseInt(value);

if (intermediaryGen < 1 || intermediaryGen > IntermediaryGenerations.latest()) {
System.err.println("Option \"--intermediary-generation\" value \"" + intermediaryGen + "\" is not valid! Value must be between 1 and " + IntermediaryGenerations.latest() + ".");
return Action.DISPLAY_HELP;
}
} else {
System.err.printf("Invalid option %s%n", option);
return Action.DISPLAY_HELP;
}
}

return Action.installClient(minecraftVersion, launcherType, loaderType, loaderVersion, intermediary, options.get("--install-dir"), !options.containsKey("--no-profile"), options.containsKey("--copy-profile-path"));
return Action.installClient(minecraftVersion, launcherType, loaderType, loaderVersion, intermediaryGen, null, options.get("--install-dir"), !options.containsKey("--no-profile"), options.containsKey("--copy-profile-path"));
}
case "server": {
if (split.size() < 1) {
Expand All @@ -239,6 +287,7 @@ private static Action<?> parse(String input) {
String minecraftVersion = split.remove();
String rawLoaderType = split.remove();
LoaderType loaderType = LoaderType.of(rawLoaderType);
int intermediaryGen = -1;

if (loaderType == null) {
System.err.println("Unknown loader type: " + rawLoaderType);
Expand All @@ -247,7 +296,7 @@ private static Action<?> parse(String input) {

// At this point all the require arguments have been parsed
if (split.size() == 0) {
return Action.installServer(minecraftVersion, loaderType, null, null, false, false);
return Action.installServer(minecraftVersion, loaderType, null, intermediaryGen, null, null, false, false);
}

// Try to parse loader version first
Expand All @@ -262,7 +311,7 @@ private static Action<?> parse(String input) {

// No more arguments, just loader version
if (split.size() == 0) {
return Action.installServer(minecraftVersion, loaderType, loaderVersion, null, false, false);
return Action.installServer(minecraftVersion, loaderType, loaderVersion, intermediaryGen, null, null, false, false);
}

// There are some additional options
Expand Down Expand Up @@ -313,13 +362,37 @@ private static Action<?> parse(String input) {
}

options.put("--install-dir", value);
} else if (option.startsWith("--intermediary-generation")) {
if (option.indexOf('=') == -1) {
System.err.println("Option \"--intermediary-generation\" must specify a value");
return Action.DISPLAY_HELP;
}

if (!option.startsWith("--intermediary-generation=")) {
System.err.println("Option \"--intermediary-generation\" must have a equals sign (=) right after the option name to get the value");
return Action.DISPLAY_HELP;
}

String value = unqoute(option.substring(26));

if (value == null) {
System.err.println("Option \"--intermediary-generation\" must have value quoted at start and end of value");
return Action.DISPLAY_HELP;
}

intermediaryGen = Integer.parseInt(value);

if (intermediaryGen < 1 || intermediaryGen > IntermediaryGenerations.latest()) {
System.err.println("Option \"--intermediary-generation\" value \"" + intermediaryGen + "\" is not valid! Value must be between 1 and " + IntermediaryGenerations.latest() + ".");
return Action.DISPLAY_HELP;
}
} else {
System.err.printf("Invalid option %s%n", option);
return Action.DISPLAY_HELP;
}
}

return Action.installServer(minecraftVersion, loaderType, loaderVersion, options.get("--install-dir"), options.containsKey("--create-scripts"), options.containsKey("--download-server"));
return Action.installServer(minecraftVersion, loaderType, loaderVersion, intermediaryGen, null, options.get("--install-dir"), options.containsKey("--create-scripts"), options.containsKey("--download-server"));
}
default:
System.err.printf("Invalid side \"%s\", expected \"client\" or \"server\"%n", arg);
Expand All @@ -332,14 +405,6 @@ private static Action<?> parse(String input) {
}
}

private static String fetchIntermediary(GameSide side, String minecraftVersion) {
return OrnitheMeta.create(OrnitheMeta.ORNITHE_META_URL, Set.of(OrnitheMeta.INTERMEDIARY_VERSIONS_ENDPOINT)).thenApply(meta -> {
VersionManifest manifest = VersionManifest.create().join();
VersionManifest.Version version = manifest.getVersion(minecraftVersion);
return meta.getEndpoint(OrnitheMeta.INTERMEDIARY_VERSIONS_ENDPOINT).get(version.id(side));
}).join();
}

/**
* Takes a string and splits it at spaces while leaving quoted segements unsplit.
*
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/org/quiltmc/installer/GameSide.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
package org.quiltmc.installer;

public enum GameSide {
CLIENT("client", "/v3/versions/%s-loader/%s/%s/profile/json"),
SERVER("server", "/v3/versions/%s-loader/%s/%s/server/json");
CLIENT("client", "/%s-loader/%s/%s/profile/json"),
SERVER("server", "/%s-loader/%s/%s/server/json");

private final String id;
private final String launchJsonEndpoint;
Expand All @@ -35,4 +35,18 @@ public String id() {
public String launchJsonEndpoint() {
return this.launchJsonEndpoint;
}

public String stripFromVersion(String version) {
return version.endsWith(this.id) ? version.substring(0, version.length() - (this.id.length() + 1)) : version;
}

public boolean versionMatches(String version) {
for (GameSide side : GameSide.values()) {
if (version.endsWith(side.id)) {
return side == this;
}
}

return true;
}
}
36 changes: 36 additions & 0 deletions src/main/java/org/quiltmc/installer/Intermediary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2023 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.installer;

public class Intermediary {

private final String version;
private final String maven;

public Intermediary(String version, String maven) {
this.version = version;
this.maven = maven;
}

public String getVersion() {
return this.version;
}

public String getMavenNotation() {
return this.maven;
}
}
48 changes: 48 additions & 0 deletions src/main/java/org/quiltmc/installer/IntermediaryGenerations.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2023 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.installer;

import java.util.Set;

import org.quiltmc.installer.OrnitheMeta.Endpoint;

public class IntermediaryGenerations {

static {
try {
Endpoint<int[]> endpoint = OrnitheMeta.intermediaryGenerationsEndpoint();
OrnitheMeta meta = OrnitheMeta.create(OrnitheMeta.ORNITHE_META_URL, Set.of(endpoint)).get();
int[] gens = meta.getEndpoint(endpoint);

latest = gens[0];
stable = gens[1];
} catch (Exception e) {
throw new RuntimeException("unable to fetch latest and stable intermediary generations", e);
}
}

private static int latest;
private static int stable;

public static int latest() {
return latest;
}

public static int stable() {
return stable;
}
}
Loading
Loading