aboutsummaryrefslogtreecommitdiffstats
path: root/src/launch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/launch.c')
-rw-r--r--src/launch.c105
1 files changed, 104 insertions, 1 deletions
diff --git a/src/launch.c b/src/launch.c
index 7d1c2b5..a8ea689 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -6,6 +6,7 @@
#include "version.h"
#include "assets.h"
#include "args.h"
+#include "runtime.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -115,6 +116,47 @@ cleanup:
return -1;
}
+int l2_launch_init_runtime(struct l2_launch *launch)
+{
+ const char *jrecompname;
+ if (json_unpack(launch->version, "{s:{s:s}}", "javaVersion", "component", &jrecompname) < 0) {
+ CMD_DEBUG0("bad launch version (no javaVersion)");
+ return 0;
+ }
+
+ json_t *rtmanifest = NULL;
+ if (l2_runtime_load_manifest(&rtmanifest) < 0) {
+ return -1;
+ }
+
+ char *jrepath = NULL;
+
+ if (l2_runtime_install_component(rtmanifest, jrecompname, &jrepath) < 0) {
+ goto cleanup;
+ }
+
+ json_decref(rtmanifest);
+ launch->jrepath = jrepath;
+
+ return 1;
+
+cleanup:
+ if (rtmanifest) json_decref(rtmanifest);
+ return -1;
+}
+
+int l2_launch_init_runtime_manual(struct l2_launch *launch, const char *home)
+{
+ char *jrepath = realpath(home, NULL);
+ if (!jrepath) {
+ CMD_WARN("Could not resolve JRE path %s: %s", home, strerror(errno));
+ return -1;
+ }
+
+ launch->jrepath = jrepath;
+ return 0;
+}
+
void l2_launch_free_contents(struct l2_launch *launch)
{
json_decref(launch->version);
@@ -456,6 +498,57 @@ jobjectArray l2_launch__create_game_args(JNIEnv *env, char **game_args, size_t n
return jarr;
}
+struct l2_launch__java_search_data {
+ char *out_fname;
+
+};
+
+int l2_launch__java_search_ftw(const char *fname, const struct stat *sp, int flags, struct l2_ftw_data *data)
+{
+ L2_UNUSED(sp);
+
+ char **opath = data->user;
+ if ((flags & L2_FTW_TYPEMASK) == L2_FTW_FILE && !strcmp(fname + data->baseoffset, "libjvm.so")) {
+ char *temp = strdup(fname);
+ if (!temp) {
+ CMD_ERROR("Failed to duplicate path name %s: %s", fname, strerror(errno));
+ return -1;
+ }
+
+ *opath = temp;
+ return 1;
+ }
+
+ return 0;
+}
+
+int l2_launch__find_jni(struct l2_launch *launch, char **jnifile)
+{
+ int res;
+ if (!launch->jrepath) {
+ CMD_INFO0("Downloading Mojang-provided JRE");
+ res = l2_launch_init_runtime(launch);
+ if (res < 0) return -1;
+ else if (!res) {
+ CMD_WARN0("The JRE must be specified manually.");
+ return -1;
+ }
+ }
+
+ char *ofile = NULL;
+ res = l2_launcher_ftw(launch->jrepath, 32, &l2_launch__java_search_ftw, &ofile);
+ if (res < 0) {
+ CMD_WARN("Error searching for JNI binary in %s", launch->jrepath);
+ return -1;
+ } else if (res == 0) {
+ CMD_WARN("libjvm.so not found in %s", launch->jrepath);
+ return -1;
+ }
+
+ *jnifile = ofile;
+ return 0;
+}
+
int l2_launch_jni(struct l2_launch *launch)
{
int res = 0;
@@ -465,11 +558,21 @@ int l2_launch_jni(struct l2_launch *launch)
return -1;
}
- if (l2_jni_init("/usr/lib/jvm/adoptopenjdk-8-hotspot-amd64/jre/lib/amd64/server/libjvm.so") < 0) {
+ char *jnipath = NULL;
+ if (l2_launch__find_jni(launch, &jnipath) < 0) {
+ CMD_ERROR0("JNI library could not be found automatically.");
+ return -1;
+ }
+
+ if (l2_jni_init(jnipath) < 0) {
+ free(jnipath);
CMD_ERROR0("Failed to initialize JNI");
return -1;
}
+ free(jnipath);
+ jnipath = NULL;
+
JavaVMInitArgs args;
jint jres;
memset(&args, 0, sizeof(JavaVMInitArgs));