Forge 1.17 support

This commit is contained in:
ArtDev 2022-05-12 22:17:48 +03:00 committed by GitHub
commit 40aa51f78f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 99 additions and 41 deletions

View File

@ -1 +1 @@
1647645869468 1652206097040

View File

@ -73,6 +73,12 @@ public class JMinecraftVersionList {
public static class ArgRules { public static class ArgRules {
public String action; public String action;
public String features; public String features;
public ArgOS os;
public static class ArgOS {
public String name;
public String version;
}
} }
} }
} }

View File

@ -58,16 +58,22 @@ import net.kdt.pojavlaunch.value.PerVersionConfig;
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile; import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
public class PojavLoginActivity extends BaseActivity { public class PojavLoginActivity extends BaseActivity {
private final Object mLockStoragePerm = new Object(); private final Object mLockStoragePerm = new Object();
@ -261,8 +267,7 @@ public class PojavLoginActivity extends BaseActivity {
PojavProfile.setCurrentProfile(this, null); PojavProfile.setCurrentProfile(this, null);
} }
private boolean unpackComponent(AssetManager am, String component) throws IOException {
private void unpackComponent(AssetManager am, String component) throws IOException {
File versionFile = new File(Tools.DIR_GAME_HOME + "/" + component + "/version"); File versionFile = new File(Tools.DIR_GAME_HOME + "/" + component + "/version");
InputStream is = am.open("components/" + component + "/version"); InputStream is = am.open("components/" + component + "/version");
if(!versionFile.exists()) { if(!versionFile.exists()) {
@ -292,8 +297,10 @@ public class PojavLoginActivity extends BaseActivity {
} }
} else { } else {
Log.i("UnpackPrep", component + ": Pack is up-to-date with the launcher, continuing..."); Log.i("UnpackPrep", component + ": Pack is up-to-date with the launcher, continuing...");
return false;
} }
} }
return true;
} }
public static void disableSplash(String dir) { public static void disableSplash(String dir) {
mkdirs(dir + "/config"); mkdirs(dir + "/config");
@ -340,7 +347,11 @@ public class PojavLoginActivity extends BaseActivity {
AssetManager am = this.getAssets(); AssetManager am = this.getAssets();
unpackComponent(am, "caciocavallo"); unpackComponent(am, "caciocavallo");
// Since the Java module system doesn't allow multiple JARs to declare the same module,
// we repack them to a single file here
unpackComponent(am, "lwjgl3"); unpackComponent(am, "lwjgl3");
if(!installRuntimeAutomatically(am,MultiRTUtils.getRuntimes().size() > 0)) { if(!installRuntimeAutomatically(am,MultiRTUtils.getRuntimes().size() > 0)) {
MultiRTConfigDialog.openRuntimeSelector(this, MultiRTConfigDialog.MULTIRT_PICK_RUNTIME_STARTUP); MultiRTConfigDialog.openRuntimeSelector(this, MultiRTConfigDialog.MULTIRT_PICK_RUNTIME_STARTUP);
synchronized (mLockSelectJRE) { synchronized (mLockSelectJRE) {

View File

@ -130,7 +130,7 @@ public final class Tools {
LauncherPreferences.PREF_CUSTOM_JAVA_ARGS = minecraftProfile.javaArgs; LauncherPreferences.PREF_CUSTOM_JAVA_ARGS = minecraftProfile.javaArgs;
} }
PojavLoginActivity.disableSplash(gamedirPath); PojavLoginActivity.disableSplash(gamedirPath);
String[] launchArgs = getMinecraftArgs(profile, versionInfo, gamedirPath); String[] launchArgs = getMinecraftClientArgs(profile, versionInfo, gamedirPath);
// Select the appropriate openGL version // Select the appropriate openGL version
OldVersionsUtils.selectOpenGlVersion(versionInfo); OldVersionsUtils.selectOpenGlVersion(versionInfo);
@ -165,6 +165,7 @@ public final class Tools {
if (versionInfo.logging != null) { if (versionInfo.logging != null) {
javaArgList.add("-Dlog4j.configurationFile=" + Tools.DIR_GAME_NEW + "/" + versionInfo.logging.client.file.id); javaArgList.add("-Dlog4j.configurationFile=" + Tools.DIR_GAME_NEW + "/" + versionInfo.logging.client.file.id);
} }
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionName, gamedirPath)));
javaArgList.add("-cp"); javaArgList.add("-cp");
javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath); javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath);
@ -198,7 +199,47 @@ public final class Tools {
javaArgList.add(cacioClasspath.toString()); javaArgList.add(cacioClasspath.toString());
} }
public static String[] getMinecraftArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, String strGameDir) { public static String[] getMinecraftJVMArgs(String versionName, String strGameDir) {
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(null, versionName, true);
// Parse Forge 1.17+ additional JVM Arguments
if (versionInfo.inheritsFrom == null || versionInfo.arguments == null || versionInfo.arguments.jvm == null) {
return new String[0];
}
Map<String, String> varArgMap = new ArrayMap<>();
varArgMap.put("classpath_separator", ":");
varArgMap.put("library_directory", strGameDir + "/libraries");
varArgMap.put("version_name", versionInfo.id);
List<String> minecraftArgs = new ArrayList<String>();
if (versionInfo.arguments != null) {
for (Object arg : versionInfo.arguments.jvm) {
if (arg instanceof String) {
minecraftArgs.add((String) arg);
} else {
/*
JMinecraftVersionList.Arguments.ArgValue argv = (JMinecraftVersionList.Arguments.ArgValue) arg;
if (argv.values != null) {
minecraftArgs.add(argv.values[0]);
} else {
for (JMinecraftVersionList.Arguments.ArgValue.ArgRules rule : arg.rules) {
// rule.action = allow
// TODO implement this
}
}
*/
}
}
}
String[] argsFromJson = JSONUtils.insertJSONValueList(minecraftArgs.toArray(new String[0]), varArgMap);
// Tools.dialogOnUiThread(this, "Result args", Arrays.asList(argsFromJson).toString());
return argsFromJson;
}
public static String[] getMinecraftClientArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, String strGameDir) {
String username = profile.username; String username = profile.username;
String versionName = versionInfo.id; String versionName = versionInfo.id;
if (versionInfo.inheritsFrom != null) { if (versionInfo.inheritsFrom != null) {
@ -521,11 +562,19 @@ public final class Tools {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
act.startActivity(browserIntent); act.startActivity(browserIntent);
} }
private static boolean checkRules(JMinecraftVersionList.Arguments.ArgValue.ArgRules[] rules) {
if(rules == null) return true; // always allow
for (JMinecraftVersionList.Arguments.ArgValue.ArgRules rule : rules) {
if (rule.action.equals("allow") && rule.os != null && rule.os.name.equals("osx")) {
return false; //disallow
}
}
return true; // allow if none match
}
public static String[] generateLibClasspath(JMinecraftVersionList.Version info) { public static String[] generateLibClasspath(JMinecraftVersionList.Version info) {
List<String> libDir = new ArrayList<String>(); List<String> libDir = new ArrayList<String>();
for (DependentLibrary libItem: info.libraries) { for (DependentLibrary libItem: info.libraries) {
if(!checkRules(libItem.rules)) continue;
String[] libInfos = libItem.name.split(":"); String[] libInfos = libItem.name.split(":");
libDir.add(Tools.DIR_HOME_LIBRARY + "/" + Tools.artifactToPath(libInfos[0], libInfos[1], libInfos[2])); libDir.add(Tools.DIR_HOME_LIBRARY + "/" + Tools.artifactToPath(libInfos[0], libInfos[1], libInfos[2]));
} }
@ -533,6 +582,10 @@ public final class Tools {
} }
public static JMinecraftVersionList.Version getVersionInfo(BaseLauncherActivity bla, String versionName) { public static JMinecraftVersionList.Version getVersionInfo(BaseLauncherActivity bla, String versionName) {
return getVersionInfo(bla, versionName, false);
}
public static JMinecraftVersionList.Version getVersionInfo(BaseLauncherActivity bla, String versionName, boolean skipInheriting) {
try { try {
JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class); JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class);
for (DependentLibrary lib : customVer.libraries) { for (DependentLibrary lib : customVer.libraries) {
@ -540,7 +593,7 @@ public final class Tools {
customVer.optifineLib = lib; customVer.optifineLib = lib;
} }
} }
if (customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) { if (skipInheriting || customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) {
return customVer; return customVer;
} else { } else {
JMinecraftVersionList.Version inheritsVer = null; JMinecraftVersionList.Version inheritsVer = null;

View File

@ -1,9 +1,11 @@
package net.kdt.pojavlaunch.value; package net.kdt.pojavlaunch.value;
import androidx.annotation.Keep; import androidx.annotation.Keep;
import net.kdt.pojavlaunch.JMinecraftVersionList.Arguments.ArgValue.ArgRules;
@Keep @Keep
public class DependentLibrary { public class DependentLibrary {
public ArgRules[] rules;
public String name; public String name;
public LibraryDownloads downloads; public LibraryDownloads downloads;
public String url; public String url;

View File

@ -114,18 +114,6 @@ jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr) {
return JNI_FALSE; return JNI_FALSE;
} }
void getJavaInputBridge(jclass* clazz, jmethodID* method) {
#ifdef DEBUG
LOGD("Debug: Initializing input bridge, method.isNull=%d, jnienv.isNull=%d\n", *method == NULL, runtimeJNIEnvPtr_ANDROID == NULL);
#endif
if (*method == NULL && runtimeJNIEnvPtr_ANDROID != NULL) {
*clazz = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID, "org/lwjgl/glfw/CallbackBridge");
assert(*clazz != NULL);
*method = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, *clazz, "receiveCallback", "(IIIII)V");
assert(*method != NULL);
}
}
void sendData(int type, int i1, int i2, int i3, int i4) { void sendData(int type, int i1, int i2, int i3, int i4) {
#ifdef DEBUG #ifdef DEBUG
LOGD("Debug: Send data, jnienv.isNull=%d\n", runtimeJNIEnvPtr_ANDROID == NULL); LOGD("Debug: Send data, jnienv.isNull=%d\n", runtimeJNIEnvPtr_ANDROID == NULL);
@ -134,6 +122,7 @@ void sendData(int type, int i1, int i2, int i3, int i4) {
LOGE("BUG: Input is ready but thread is not attached yet."); LOGE("BUG: Input is ready but thread is not attached yet.");
return; return;
} }
if(inputBridgeClass_ANDROID == NULL) return;
(*runtimeJNIEnvPtr_ANDROID)->CallStaticVoidMethod( (*runtimeJNIEnvPtr_ANDROID)->CallStaticVoidMethod(
runtimeJNIEnvPtr_ANDROID, runtimeJNIEnvPtr_ANDROID,
inputBridgeClass_ANDROID, inputBridgeClass_ANDROID,
@ -183,8 +172,6 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThread
if (isUseStackQueueCall && isAndroid && result) { if (isUseStackQueueCall && isAndroid && result) {
isPrepareGrabPos = true; isPrepareGrabPos = true;
} }
getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID);
return result; return result;
} }
@ -392,3 +379,9 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetWindowAttrib(
(jlong) showingWindow, attrib, value (jlong) showingWindow, attrib, value
); );
} }
JNIEXPORT void JNICALL
Java_org_lwjgl_glfw_CallbackBridge_setClass(JNIEnv *env, jclass clazz) {
inputBridgeMethod_ANDROID = (*env)->GetStaticMethodID(env, clazz, "receiveCallback", "(IIIII)V");
inputBridgeClass_ANDROID = (*env)->NewGlobalRef(env, clazz);
}

View File

@ -14,6 +14,12 @@ jar {
// Auto update the version with a timestamp so the project jar gets updated by Pojav // Auto update the version with a timestamp so the project jar gets updated by Pojav
File versionFile = file("../app_pojavlauncher/src/main/assets/components/lwjgl3/version") File versionFile = file("../app_pojavlauncher/src/main/assets/components/lwjgl3/version")
versionFile.write(String.valueOf(new Date().getTime())) versionFile.write(String.valueOf(new Date().getTime()))
from {
configurations.default.collect {
println(it.getName())
it.isDirectory() ? it : zipTree(it)
}
}
} }
java { java {

View File

@ -1,7 +1,5 @@
package org.lwjgl.glfw; package org.lwjgl.glfw;
import java.io.*;
import java.util.*; import java.util.*;
import android.util.*;
public class CallbackBridge { public class CallbackBridge {
public static final int CLIPBOARD_COPY = 2000; public static final int CLIPBOARD_COPY = 2000;
@ -51,7 +49,6 @@ public class CallbackBridge {
GLFW.mGLFWIsGrabbing = grab; GLFW.mGLFWIsGrabbing = grab;
nativeSetGrabbing(grab, xset, yset); nativeSetGrabbing(grab, xset, yset);
} }
// Called from Android side // Called from Android side
public static void receiveCallback(int type, int i1, int i2, int i3, int i4) { public static void receiveCallback(int type, int i1, int i2, int i3, int i4) {
/* /*
@ -72,12 +69,11 @@ public class CallbackBridge {
public static void sendData(int type, String data) { public static void sendData(int type, String data) {
nativeSendData(false, type, data); nativeSendData(false, type, data);
} }
public static native void nativeSendData(boolean isAndroid, int type, String data); public static native void nativeSendData(boolean isAndroid, int type, String data);
public static native boolean nativeSetInputReady(boolean ready); public static native boolean nativeSetInputReady(boolean ready);
public static native String nativeClipboard(int action, String copy); public static native String nativeClipboard(int action, String copy);
public static native void nativeAttachThreadToOther(boolean isAndroid, boolean isUseStackQueueBool); public static native void nativeAttachThreadToOther(boolean isAndroid, boolean isUseStackQueueBool);
private static native void nativeSetGrabbing(boolean grab, int xset, int yset); private static native void nativeSetGrabbing(boolean grab, int xset, int yset);
public static native void setClass();
} }

View File

@ -12,7 +12,6 @@ import java.nio.*;
import javax.annotation.*; import javax.annotation.*;
import org.lwjgl.*; import org.lwjgl.*;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.*; import org.lwjgl.system.*;
import static org.lwjgl.system.APIUtil.*; import static org.lwjgl.system.APIUtil.*;
@ -524,7 +523,7 @@ public class GLFW
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
e.printStackTrace(); e.printStackTrace();
} }
CallbackBridge.setClass();
mGLFWErrorCallback = GLFWErrorCallback.createPrint(); mGLFWErrorCallback = GLFWErrorCallback.createPrint();
mGLFWKeyCodes = new ArrayMap<>(); mGLFWKeyCodes = new ArrayMap<>();
@ -1067,21 +1066,13 @@ public class GLFW
mGLFWIsInputReady = true; mGLFWIsInputReady = true;
mGLFWIsUseStackQueue = CallbackBridge.nativeSetInputReady(true); mGLFWIsUseStackQueue = CallbackBridge.nativeSetInputReady(true);
} }
if(!CallbackBridge.PENDING_EVENT_READY) { if(!CallbackBridge.PENDING_EVENT_READY) {
CallbackBridge.PENDING_EVENT_READY = true; CallbackBridge.PENDING_EVENT_READY = true;
// nglfwSetInputReady();
} }
// Indirect event // Indirect event
while (CallbackBridge.PENDING_EVENT_LIST.size() > 0) { while (CallbackBridge.PENDING_EVENT_LIST.size() > 0) {
Integer[] dataArr = CallbackBridge.PENDING_EVENT_LIST.remove(0); Integer[] dataArr = CallbackBridge.PENDING_EVENT_LIST.remove(0);
if (dataArr == null) { // It should not be null, but still should be catched
// System.out.println("GLFW: popped callback is null, skipping");
continue;
}
for (Long ptr : mGLFWWindowMap.keySet()) { for (Long ptr : mGLFWWindowMap.keySet()) {
try { try {
switch (dataArr[0]) { switch (dataArr[0]) {