Skip to content
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

Updating Launcher #1

Open
wants to merge 52 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6f7624a
Add embedded logging configs
hedgehog1029 Dec 31, 2021
725f747
Ensure installer temporary directory exists when installing
hedgehog1029 Dec 31, 2021
28017e8
Fix edge case in logging config handling
hedgehog1029 Jan 1, 2022
291f62a
Allow Microsoft authentication to use xdg-open on Linux
hedgehog1029 Jan 4, 2022
288da94
Fix pastebin uploader
Magi1053 Jan 23, 2022
6530ece
Fix pastebin uploader (#457)
hedgehog1029 Jan 23, 2022
53ba054
Change Java runtime selector to show "unknown" instead of "null"
hedgehog1029 Apr 18, 2022
bad4363
Remove broken skin fetching for Yggdrasil auth
hedgehog1029 Apr 18, 2022
79b1289
Check for launcher updates when the game closes
hedgehog1029 Apr 21, 2022
3c4c38e
Improve Java runtime finder resiliency
hedgehog1029 Apr 22, 2022
8e1337d
Disregard Java runtimes that don't have a bin folder
hedgehog1029 Apr 23, 2022
54c05d1
Upgrade to Gradle 7
hedgehog1029 Apr 26, 2022
8684264
Upgrade dependencies & fix deprecations
hedgehog1029 Apr 26, 2022
0a5abee
Make the build output one jar file per subproject again
hedgehog1029 Apr 27, 2022
2fe96e4
Fix NPE when manifests don't contain JVM arguments
hedgehog1029 Apr 27, 2022
debd822
Hotfix package builder emitting JSON with missing keys for empty values
hedgehog1029 May 1, 2022
39487dd
Make assets tree builder use hardlinks if available
hedgehog1029 May 3, 2022
23e01de
Add support for UTF-8 encoded locale files
hedgehog1029 May 4, 2022
90ff8df
Fix locale errors due to inconsistent mark/reset support
hedgehog1029 May 10, 2022
b8a6769
Fix stream-reading logic in locale control
hedgehog1029 May 10, 2022
1c64de1
GH-472 Add warning popup for mismatched Java versions
hedgehog1029 May 30, 2022
4decceb
GH-471 Re-label configuration option as "Fallback Java Runtime"
hedgehog1029 May 30, 2022
16f44a8
GH-473 Fix extra launcher windows opening after java version warning
hedgehog1029 May 30, 2022
2a6c5ee
GH-481 Add Quilt loader support
hedgehog1029 Aug 7, 2022
460070e
NOISSUE Fix forge manifests with empty artifact URLs failing
hedgehog1029 Aug 11, 2022
c61575d
Allow zip files as libraries.
Dreytac Aug 16, 2022
9060af7
Add application/zip to acceptable library types (#483)
hedgehog1029 Aug 17, 2022
13b6a77
GH-484 Work around bug with gradle shadow plugin
hedgehog1029 Aug 27, 2022
68bd6c3
Make the oauth response screen customizable html
Magi1053 Nov 4, 2022
f45033e
Make the oauth response screen customizable HTML (#488)
hedgehog1029 Nov 4, 2022
8dfb049
Migrate HTTP URLs to HTTPS
hedgehog1029 Jan 17, 2023
6003069
Fix update manager not displaying self-update errors
hedgehog1029 Feb 23, 2023
31a1311
copy logging config from loader version manifest
DaMatrix Aug 4, 2023
5668e56
move vanilla jar to the end of the classpath
DaMatrix Aug 4, 2023
9428dbb
Linux XDG folder support
cking Sep 13, 2023
5712eb1
rewritten xdg folder fetcher.
cking Sep 20, 2023
1180845
Fix launcher trying to download processor outputs
hedgehog1029 Jan 2, 2024
b5fe175
Add support for NeoForge
hedgehog1029 Jan 2, 2024
93f6048
Prevent Forge's Log4j configuration from being overridden (#513)
hedgehog1029 Jan 2, 2024
847106f
Linux XDG folder support (#518)
hedgehog1029 Jan 2, 2024
5eca6c2
Visually improve oauth login response page
Magi1053 Mar 30, 2024
d197bc8
Fix maven for 'insubstantial' library
hedgehog1029 Apr 15, 2024
9147cb2
Add icon to favicon
Magi1053 May 2, 2024
7ad438d
Add null check to xdgFolderName. Fixes Linux fail to launch.
KishCom Jun 23, 2024
9c24f85
Fix new Linux installs failing to launch (#529)
hedgehog1029 Jun 23, 2024
d27c746
Fix Microsoft auth account type ID being incorrect
hedgehog1029 Jun 9, 2024
669e3f5
Fix launcher not prompting for re-login if refresh token expired
hedgehog1029 Oct 26, 2024
c236e4d
Visually improve OAuth login response page (#527)
hedgehog1029 Oct 26, 2024
6e2e17c
Tweak login success page
hedgehog1029 Oct 26, 2024
ebaddaa
GH-532 Fix license name in About dialog
hedgehog1029 Nov 30, 2024
950ad3d
GH-530 Fix multiple library versions existing in the game's classpath
hedgehog1029 Jan 6, 2025
9da1b6a
NOISSUE Add embedded logging config for 1.21 and above
hedgehog1029 Jan 6, 2025
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
49 changes: 34 additions & 15 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
buildscript {
repositories {
mavenCentral()
jcenter()
}

dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:2.0.1"
}
}

plugins {
id "com.github.johnrengelman.shadow" version "4.0.4"
id "com.github.johnrengelman.shadow" version "7.1.2"
id 'io.freefair.lombok' version '5.3.0'
}

Expand All @@ -24,13 +13,15 @@ println """

subprojects {
apply plugin: 'java'
apply plugin: 'maven'

group = 'com.skcraft'
version = '4.6-SNAPSHOT'

sourceCompatibility = 1.8
targetCompatibility = 1.8
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
}
}

repositories {
mavenCentral()
Expand All @@ -47,6 +38,34 @@ subprojects {
workingDir = new File(rootDir, "run/")
workingDir.mkdirs()
}

// Work around gradle shadow bug
// see https://github.com/johnrengelman/shadow/issues/713
afterEvaluate {
startScripts {
dependsOn(shadowJar)
}

distTar {
dependsOn(shadowJar)
}

distZip {
dependsOn(shadowJar)
}

startShadowScripts {
dependsOn(jar)
}

shadowDistTar {
dependsOn(jar)
}

shadowDistZip {
dependsOn(jar)
}
}
}

task clean {
Expand Down
17 changes: 10 additions & 7 deletions creator-tools/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ plugins {
}

version = "2.1.0-SNAPSHOT"
sourceCompatibility = 1.8
targetCompatibility = 1.8

mainClassName = "com.skcraft.launcher.creator.Creator"
application {
mainClassName = "com.skcraft.launcher.creator.Creator"
}

dependencies {
compile project(':launcher-builder')
compile 'org.eclipse.jetty:jetty-server:9.3.1.v20150714'
compile 'com.jidesoft:jide-oss:3.6.10'
implementation project(path: ':launcher-builder')
implementation 'org.eclipse.jetty:jetty-server:9.3.1.v20150714'
implementation 'com.jidesoft:jide-oss:3.6.18'
}

processResources {
Expand All @@ -25,6 +25,9 @@ processResources {
}

shadowJar {
archiveClassifier.set("")
}

build.dependsOn(shadowJar)
build {
dependsOn(shadowJar)
}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
13 changes: 9 additions & 4 deletions launcher-bootstrap/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ plugins {
id 'io.freefair.lombok'
}

mainClassName = "com.skcraft.launcher.Bootstrap"
application {
mainClassName = "com.skcraft.launcher.Bootstrap"
}

dependencies {
compile 'com.googlecode.json-simple:json-simple:1.1.1'
compile 'javax.xml.bind:jaxb-api:2.3.0'
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
}

processResources {
Expand All @@ -20,6 +22,9 @@ processResources {
}

shadowJar {
archiveClassifier.set("")
}

build.dependsOn(shadowJar)
build {
dependsOn(shadowJar)
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,21 @@ private File getUserLauncherDir() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
return new File(getFileChooseDefaultDir(), getProperties().getProperty("homeFolderWindows"));
} else {
return new File(System.getProperty("user.home"), getProperties().getProperty("homeFolder"));
}

File dotFolder = new File(System.getProperty("user.home"), getProperties().getProperty("homeFolder"));
String xdgFolderName = getProperties().getProperty("homeFolderLinux");

if (osName.contains("linux") && !dotFolder.exists() && xdgFolderName != null && !xdgFolderName.isEmpty()) {
String xdgDataHome = System.getenv("XDG_DATA_HOME");
if (xdgDataHome.isEmpty()) {
xdgDataHome = System.getProperty("user.home") + "/.local/share";
}

return new File(xdgDataHome, xdgFolderName);
}

return dotFolder;
}

private static boolean isPortableMode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#

homeFolderWindows=Example Launcher
homeFolderLinux=example_launcher
homeFolder=.examplelauncher
launcherClass=com.skcraft.launcher.Launcher
latestUrl=http://update.skcraft.com/quark/launcher/latest.json
latestUrl=http://update.skcraft.com/quark/launcher/latest.json
18 changes: 14 additions & 4 deletions launcher-builder/build.gradle
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
plugins {
id 'application'
id 'java-library'
id "com.github.johnrengelman.shadow"
id 'io.freefair.lombok'
}

mainClassName = "com.skcraft.launcher.builder.PackageBuilder"
application {
mainClassName = "com.skcraft.launcher.builder.PackageBuilder"
}

dependencies {
compile project(':launcher')
compile 'org.tukaani:xz:1.0'
compile 'org.apache.commons:commons-compress:1.9'
api project(':launcher')
implementation 'org.apache.commons:commons-compress:1.21'
}

shadowJar {
dependsOn ':launcher:shadowJar'
archiveClassifier.set("")
}

// Work around gradle shadow bug
// see https://github.com/johnrengelman/shadow/issues/713
startScripts.dependsOn(':launcher:shadowJar')
distTar.dependsOn(':launcher:shadowJar')
distZip.dependsOn(':launcher:shadowJar')

build.dependsOn(shadowJar)
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ public void addFiles(File dir, File destDir) throws IOException {
public void addLoaders(File dir, File librariesDir) {
logSection("Checking for mod loaders to install...");

LinkedHashSet<Library> collected = new LinkedHashSet<Library>();
VersionManifest version = manifest.getVersionManifest();
LinkedHashSet<Library> collected = new LinkedHashSet<>();

File[] files = dir.listFiles(new JarFileFilter());
if (files != null) {
Expand All @@ -140,7 +141,6 @@ public void addLoaders(File dir, File librariesDir) {

this.loaderLibraries.addAll(collected);

VersionManifest version = manifest.getVersionManifest();
collected.addAll(version.getLibraries());
version.setLibraries(collected);
}
Expand All @@ -164,11 +164,13 @@ private void processLoader(LinkedHashSet<Library> loaderLibraries, File file, Fi

if (basicProfile.isLegacy()) {
processor = new OldForgeLoaderProcessor();
} else if (basicProfile.getProfile().equalsIgnoreCase("forge")) {
} else {
processor = new ModernForgeLoaderProcessor();
}
} else if (BuilderUtils.getZipEntry(jarFile, "fabric-installer.json") != null) {
processor = new FabricLoaderProcessor();
processor = new FabricLoaderProcessor(FabricLoaderProcessor.Variant.FABRIC);
} else if (BuilderUtils.getZipEntry(jarFile, "quilt_installer.json") != null) {
processor = new FabricLoaderProcessor(FabricLoaderProcessor.Variant.QUILT);
}
} finally {
closer.close();
Expand Down Expand Up @@ -204,9 +206,10 @@ public void downloadLibraries(File librariesDir) throws IOException, Interrupted
if (!outputPath.exists()) {
Files.createParentDirs(outputPath);
boolean found = false;
boolean urlEmpty = artifact.getUrl().isEmpty();

// Try just the URL, it might be a full URL to the file
if (!artifact.getUrl().isEmpty()) {
// If URL doesn't end with a /, it might be the direct file
if (!urlEmpty && !artifact.getUrl().endsWith("/")) {
found = tryDownloadLibrary(library, artifact, artifact.getUrl(), outputPath);
}

Expand All @@ -219,7 +222,7 @@ public void downloadLibraries(File librariesDir) throws IOException, Interrupted
}

// Assume artifact URL is a maven repository URL and try that
if (!found) {
if (!found && !urlEmpty) {
URL url = LauncherUtils.concat(url(artifact.getUrl()), artifact.getPath());
found = tryDownloadLibrary(library, artifact, url.toString(), outputPath);
}
Expand Down Expand Up @@ -261,7 +264,9 @@ private boolean tryDownloadLibrary(Library library, Library.Artifact artifact, S

try {
log.info("Downloading library " + library.getName() + " from " + url + "...");
HttpRequest.get(url).execute().expectResponseCode(200).saveContent(tempFile);
HttpRequest.get(url).execute().expectResponseCode(200)
.expectContentType("application/java-archive", "application/octet-stream", "application/zip")
.saveContent(tempFile);
} catch (IOException e) {
log.info("Could not get file from " + url + ": " + e.getMessage());
return false;
Expand Down Expand Up @@ -367,7 +372,7 @@ public void writeManifest(@NonNull File path) throws IOException {

private static BuilderOptions parseArgs(String[] args) {
BuilderOptions options = new BuilderOptions();
new JCommander(options, args);
new JCommander(options).parse(args);
options.choosePaths();
return options;
}
Expand Down Expand Up @@ -407,7 +412,7 @@ public static void main(String[] args) throws IOException, InterruptedException
// Initialize
SimpleLogFormatter.configureGlobalLogger();
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);

Manifest manifest = new Manifest();
manifest.setMinimumVersion(Manifest.MIN_PROTOCOL_VERSION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
import com.google.common.io.Closer;
import com.skcraft.launcher.builder.BuilderUtils;
import com.skcraft.launcher.model.loader.FabricMod;
import com.skcraft.launcher.model.loader.QuiltMod;
import com.skcraft.launcher.model.loader.Versionable;
import com.skcraft.launcher.model.minecraft.Library;
import com.skcraft.launcher.model.minecraft.MavenName;
import com.skcraft.launcher.model.minecraft.VersionManifest;
import com.skcraft.launcher.model.modpack.Manifest;
import com.skcraft.launcher.util.HttpRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;

import java.io.File;
Expand All @@ -18,39 +22,56 @@
import java.util.zip.ZipEntry;

@Log
@RequiredArgsConstructor
public class FabricLoaderProcessor implements ILoaderProcessor {
private final Variant variant;

@Override
public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapper, File baseDir) throws IOException {
JarFile jarFile = new JarFile(loaderJar);
LoaderResult result = new LoaderResult();
Closer closer = Closer.create();

try {
String loaderVersion;
Versionable loaderMod;

ZipEntry modEntry = BuilderUtils.getZipEntry(jarFile, "fabric.mod.json");
ZipEntry modEntry = BuilderUtils.getZipEntry(jarFile, variant.modJsonName);
if (modEntry != null) {
InputStreamReader reader = new InputStreamReader(jarFile.getInputStream(modEntry));
FabricMod loaderMod = mapper.readValue(
BuilderUtils.readStringFromStream(closer.register(reader)), FabricMod.class);

loaderVersion = loaderMod.getVersion();
loaderMod = mapper.readValue(
BuilderUtils.readStringFromStream(closer.register(reader)), variant.mappedClass);
} else {
log.warning("Fabric loader has no 'fabric.mod.json' file, is it really a Fabric Loader jar?");
log.warning(String.format("%s loader has no '%s' file, is it really a %s Loader jar?",
variant.friendlyName, variant.modJsonName, variant.friendlyName));
return null;
}

log.info("Downloading fabric metadata...");
log.info(String.format("Downloading %s metadata...", variant.friendlyName));
URL metaUrl = HttpRequest.url(
String.format("https://meta.fabricmc.net/v2/versions/loader/%s/%s/profile/json",
manifest.getGameVersion(), loaderVersion));
String.format(variant.metaUrl, manifest.getGameVersion(), loaderMod.getVersion()));
VersionManifest fabricManifest = HttpRequest.get(metaUrl)
.execute()
.expectResponseCode(200)
.returnContent()
.asJson(VersionManifest.class);

for (Library library : fabricManifest.getLibraries()) {
// To quote a famous comment: "And here we come upon a sad state of affairs."
// Quilt's meta API returns broken data about how to launch the game. It specifies its own incomplete
// and ultimately broken set of intermediary mappings called "hashed". If the loader finds "hashed" in
// the classpath it tries to use it and blows up because it doesn't work.
// We work around this here by just throwing the hashed library out - they do now at least specify
// fabric's intermediary mappings in the library list, which DO work.
// Historical note: previously they didn't do this! Every launcher that added Quilt support had to add
// a hack that replaced hashed with intermediary! This is a lot of technical debt that is gonna come
// back to bite them in the ass later, because it's all still there!
// TODO pester Quilt again about fixing this....
MavenName libraryName = library.getName();
if (libraryName.getGroup().equals("org.quiltmc") && libraryName.getPath().equals("hashed") && loaderMod instanceof QuiltMod) {
continue;
}

result.getLoaderLibraries().add(library);
log.info("Adding loader library " + library.getName());
}
Expand All @@ -61,12 +82,24 @@ public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapp
log.info("Using main class " + mainClass);
}
} catch (InterruptedException e) {
log.warning("HTTP request to fabric metadata API was interrupted, this will probably not work!");
log.warning(String.format("HTTP request to %s metadata API was interrupted!", variant.friendlyName));
throw new IOException(e);
} finally {
closer.close();
jarFile.close();
}

return result;
}

@RequiredArgsConstructor
public enum Variant {
FABRIC("Fabric", "fabric.mod.json", "https://meta.fabricmc.net/v2/versions/loader/%s/%s/profile/json", FabricMod.class),
QUILT("Quilt", "quilt.mod.json", "https://meta.quiltmc.org/v3/versions/loader/%s/%s/profile/json", QuiltMod.class);

private final String friendlyName;
private final String modJsonName;
private final String metaUrl;
private final Class<? extends Versionable> mappedClass;
}
}
Loading