aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meson.build12
-rw-r--r--meson.options4
-rw-r--r--src/args.c24
-rw-r--r--src/args.h4
-rw-r--r--src/assets.c9
-rw-r--r--src/assets.h5
-rw-r--r--src/cmd-version.c89
-rw-r--r--src/config.h.in2
-rw-r--r--src/launch.c257
-rw-r--r--src/launch.h37
-rw-r--r--src/meson.build2
-rw-r--r--src/subst.c4
-rw-r--r--src/version.c27
-rw-r--r--src/version.h6
14 files changed, 358 insertions, 124 deletions
diff --git a/meson.build b/meson.build
index c5588b7..d6093e0 100644
--- a/meson.build
+++ b/meson.build
@@ -23,6 +23,7 @@ launcher_os = get_option('launcher_os')
launcher_arch_bits = get_option('launcher_arch_bits')
launcher_arch = get_option('launcher_arch')
launcher_jre_arch = get_option('launcher_jre_arch')
+launcher_java_path_sep = get_option('launcher_java_path_sep')
if launcher_os == 'auto'
if host_machine.system() == 'linux'
@@ -80,6 +81,14 @@ if launcher_jre_arch == 'auto'
endif
endif
+if launcher_java_path_sep == ''
+ if host_machine.system() == 'windows'
+ launcher_java_path_sep = ';'
+ else
+ launcher_java_path_sep = ':'
+ endif
+endif
+
message('Using launcher OS', launcher_os)
config_data.set_quoted('L2SU_LAUNCHER_OS', launcher_os)
@@ -100,6 +109,9 @@ config_data.set_quoted('L2SU_LAUNCHER_ARCH', launcher_arch)
message('Using launcher JRE arch', launcher_jre_arch)
config_data.set_quoted('L2SU_JRE_ARCH', launcher_jre_arch)
+message('Using launcher classpath separator', launcher_java_path_sep)
+config_data.set_quoted('L2SU_CLASSPATH_SEP', launcher_java_path_sep)
+
if launcher_jre_arch == 'gamecore'
message('(launcher_jre_arch == gamecore, so JREs will most likely not be downloaded.)')
endif
diff --git a/meson.options b/meson.options
index ea5e01e..005f815 100644
--- a/meson.options
+++ b/meson.options
@@ -13,3 +13,7 @@ option('launcher_arch', type : 'string',
option('launcher_jre_arch', type : 'combo',
value : 'auto', choices : [ 'auto', 'gamecore', 'linux', 'linux-i386', 'mac-os', 'mac-os-arm64', 'windows-x86', 'windows-x64', 'windows-arm64' ],
description : 'launcher JRE architecture')
+
+option('launcher_java_path_sep', type : 'string',
+ value: '',
+ description : 'launcher path separator')
diff --git a/src/args.c b/src/args.c
index 7b307a8..69f1272 100644
--- a/src/args.c
+++ b/src/args.c
@@ -8,10 +8,10 @@
#include <stdarg.h>
#include <string.h>
-int l2_args__get_game_args(l2_subst_t *subst, const char *argsline, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs);
-int l2_args__get_args_json(l2_subst_t *subst, json_t *jargs, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs);
+int l2_args__get_game_args(l2_subst_t *subst, const char *argsline, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs);
+int l2_args__get_args_json(l2_subst_t *subst, json_t *jargs, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs);
-int l2_args_get_game_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs)
+int l2_args_get_game_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs)
{
const char *mc_args = NULL;
json_t *jargs = NULL;
@@ -24,9 +24,9 @@ int l2_args_get_game_args(json_t *version, l2_subst_t *subst, l2_version_feature
if (!json_is_array(jargs)) return -1;
- return l2_args__get_args_json(subst, jargs, feature_matcher, out_args, out_nargs);
+ return l2_args__get_args_json(subst, jargs, feature_matcher, muser, out_args, out_nargs);
} else if (mc_args) {
- return l2_args__get_game_args(subst, mc_args, feature_matcher, out_args, out_nargs);
+ return l2_args__get_game_args(subst, mc_args, feature_matcher, muser, out_args, out_nargs);
} else {
return -1;
}
@@ -66,7 +66,7 @@ cleanup:
return -1;
}
-int l2_args__get_game_args(l2_subst_t *subst, const char *argsline, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs)
+int l2_args__get_game_args(l2_subst_t *subst, const char *argsline, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs)
{
char **args = NULL;
size_t nargs = 0;
@@ -85,11 +85,11 @@ int l2_args__get_game_args(l2_subst_t *subst, const char *argsline, l2_version_f
if (*arg_start && l2_args__array_append(subst, &args, &nargs, arg_start, NULL) < 0) goto cleanup;
- if ((*feature_matcher)("is_demo_user", json_true())) {
+ if ((*feature_matcher)("is_demo_user", json_true(), muser)) {
if (l2_args__array_append(subst, &args, &nargs, "--demo", NULL) < 0) goto cleanup;
}
- if ((*feature_matcher)("has_custom_resolution", json_true())) {
+ if ((*feature_matcher)("has_custom_resolution", json_true(), muser)) {
if (l2_args__array_append(subst, &args, &nargs, "--width", "${resolution_width}", "--height", "${resolution_height}", NULL) < 0) goto cleanup;
}
@@ -107,7 +107,7 @@ cleanup:
return -1;
}
-int l2_args_get_jvm_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs)
+int l2_args_get_jvm_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs)
{
json_t *jarguments = json_object_get(version, "arguments");
if (!jarguments) {
@@ -145,10 +145,10 @@ int l2_args_get_jvm_args(json_t *version, l2_subst_t *subst, l2_version_feature_
return -1;
}
- return l2_args__get_args_json(subst, jjvmargs, feature_matcher, out_args, out_nargs);
+ return l2_args__get_args_json(subst, jjvmargs, feature_matcher, muser, out_args, out_nargs);
}
-int l2_args__get_args_json(l2_subst_t *subst, json_t *jargs, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs)
+int l2_args__get_args_json(l2_subst_t *subst, json_t *jargs, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs)
{
char **args = NULL;
size_t nargs = 0;
@@ -168,7 +168,7 @@ int l2_args__get_args_json(l2_subst_t *subst, json_t *jargs, l2_version_feature_
if (!json_is_array(rules)) goto cleanup;
- switch (l2_version_check_rules(rules, feature_matcher)) {
+ switch (l2_version_check_rules(rules, feature_matcher, muser)) {
case RULE_CHECK_ALLOW: {
json_t *argval;
size_t argidx;
diff --git a/src/args.h b/src/args.h
index 3f15c61..d2e740f 100644
--- a/src/args.h
+++ b/src/args.h
@@ -7,7 +7,7 @@
#include "l2su.h"
#include "version.h"
-int l2_args_get_game_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs);
-int l2_args_get_jvm_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs);
+int l2_args_get_game_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs);
+int l2_args_get_jvm_args(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, void *muser, char ***out_args, size_t *out_nargs);
#endif /* include guard */
diff --git a/src/assets.c b/src/assets.c
index 695e0ab..031c679 100644
--- a/src/assets.c
+++ b/src/assets.c
@@ -139,7 +139,7 @@ void l2_assets__free_download_info(struct l2_assets__download_info *info)
free(info);
}
-int l2_assets__download_assets(json_t *asset_index, char **path)
+int l2_assets_download_assets(json_t *asset_index, char **path)
{
int res = -1;
json_t *objects;
@@ -251,15 +251,12 @@ int l2_assets__download_assets(json_t *asset_index, char **path)
}
if (virtual) {
- resbasepath = l2_launcher_sprintf_alloc("%s/assets/virtual", l2_state.paths.data);
-
CMD_ERROR0("virtual resources are not yet implemented. please nag figboot");
res = -1;
goto cleanup;
- } else {
- resbasepath = l2_launcher_sprintf_alloc("%s/assets/objects", l2_state.paths.data);
}
+ resbasepath = l2_launcher_sprintf_alloc("%s/assets/virtual", l2_state.paths.data);
if (!resbasepath) {
res = -1;
goto cleanup;
@@ -313,7 +310,7 @@ int l2_assets__download_index(json_t *version, char **path)
return res;
}
-int l2_assets__load_index(json_t *version, json_t **asset_index)
+int l2_assets_load_index(json_t *version, json_t **asset_index)
{
char *path = NULL;
int res;
diff --git a/src/assets.h b/src/assets.h
index 6f8496f..82e2e6f 100644
--- a/src/assets.h
+++ b/src/assets.h
@@ -1,4 +1,9 @@
#ifndef L2SU_ASSETS_H_INCLUDED
#define L2SU_ASSETS_H_INCLUDED
+#include <jansson.h>
+
+int l2_assets_load_index(json_t *version, json_t **asset_index);
+int l2_assets_download_assets(json_t *asset_index, char **path);
+
#endif /* include guard */
diff --git a/src/cmd-version.c b/src/cmd-version.c
index 4ee4309..adb501f 100644
--- a/src/cmd-version.c
+++ b/src/cmd-version.c
@@ -5,6 +5,9 @@
#include "l2su.h"
#include "macros.h"
#include "args.h"
+#include "assets.h"
+#include "launch.h"
+#include "instance.h"
#include <jansson.h>
#include <stdio.h>
@@ -36,97 +39,33 @@ unsigned cmd_version_list_local(struct l2_context_node *ctx, char **args)
return CMD_RESULT_SUCCESS;
}
-bool feat_match_cb(const char *name, json_t *js) {
+bool feat_match_cb(const char *name, json_t *js, void *unused) {
L2_UNUSED(name);
L2_UNUSED(js);
+ L2_UNUSED(unused);
return false;
}
-int l2_assets__load_index(json_t *version, json_t **asset_index);
-int l2_assets__download_assets(json_t *asset_index, char **path);
-
+void l2_launch__test(struct l2_launch *launch);
unsigned cmd_version_install(struct l2_context_node *ctx, char **args)
{
unsigned res = l2_version_load_remote();
- char *jarpath = NULL;
-
- if (res != VERSION_SUCCESS) {
- CMD_FATAL("failed to load versions: %s", l2_version_strerror(res));
- }
-
- json_t *js;
- res = l2_version_load_local(*args, &js);
if (res != VERSION_SUCCESS) {
- CMD_FATAL("failed to load 1.8.9: %s", l2_version_strerror(res));
- }
-
- CMD_INFO0("Retrieving library list...");
- struct l2_version_library *libs = NULL;
- if ((res = l2_version_collect_libraries(js, &libs, &feat_match_cb)) != VERSION_SUCCESS) {
- CMD_FATAL("Failed to collect library list: %s", l2_version_strerror(res));
- }
-
- CMD_INFO0("Downloading libraries...");
- if ((res = l2_version_download_libraries(libs)) != VERSION_SUCCESS) {
- CMD_FATAL("Failed to download libraries: %s", l2_version_strerror(res));
- }
-
- CMD_INFO0("Downloading client jar...");
- if ((res = l2_version_download_jar(js, "client", &jarpath)) != VERSION_SUCCESS) {
- CMD_FATAL("Failed to download client jar: %s", l2_version_strerror(res));
- }
-
- CMD_INFO0("Downloading asset index...");
- json_t *assets = NULL;
- if (l2_assets__load_index(js, &assets) < 0) {
- CMD_FATAL0("Failed to load asset index.");
- }
-
- CMD_INFO0("Downloading assets...");
- char *assetsbase = NULL;
- if (l2_assets__download_assets(assets, &assetsbase) < 0) {
- CMD_FATAL0("Failed to download assets.");
- }
-
- char *nativesdir = NULL;
- CMD_INFO0("Extracting natives...");
- if ((res = l2_version_extract_natives(libs, &nativesdir)) != VERSION_SUCCESS) {
- CMD_FATAL("Failed to extract natives: %s", l2_version_strerror(res));
+ CMD_FATAL("Failed to load versions: %s", l2_version_strerror(res));
}
- char **game_args;
- size_t ngame_args;
- l2_subst_t *st;
- l2_subst_init(&st);
- l2_subst_add(st, "version_name", "1.8.9");
- if (l2_args_get_game_args(js, st, &feat_match_cb, &game_args, &ngame_args) < 0) {
- CMD_FATAL0("Failed to find game arguments");
- }
- for (size_t n = 0; n < ngame_args; ++n) {
- CMD_DEBUG("arg: %s", game_args[n]);
- free(game_args[n]);
+ if ((res = l2_instance_load_all()) != INSTANCE_SUCCESS) {
+ CMD_FATAL("Failed to load instances: %s", l2_instance_errormsg[res]);
}
- free(game_args);
- if (l2_args_get_jvm_args(js, st, &feat_match_cb, &game_args, &ngame_args) < 0) {
- CMD_FATAL0("Failed to find JVM arguments");
- }
- for (size_t n = 0; n < ngame_args; ++n) {
- CMD_DEBUG("jvm arg: %s", game_args[n]);
- free(game_args[n]);
+ struct l2_launch launch = { 0 };
+ if (l2_launch_init(&launch, *args, l2_state.instance_head) < 0) {
+ CMD_FATAL0("Failed to launch the game");
}
- free(game_args);
-
- l2_subst_free(st);
-
- CMD_INFO("Assets base: %s", assetsbase);
- free(assetsbase);
- json_decref(assets);
+ l2_launch__test(&launch);
- l2_version_free_libraries(libs);
- free(jarpath);
- json_decref(js);
+ l2_launch_free_contents(&launch);
return CMD_RESULT_SUCCESS;
}
diff --git a/src/config.h.in b/src/config.h.in
index 5584e92..39d6bd3 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -16,4 +16,6 @@
#mesondefine L2SU_LAUNCHER_IS_OSX
#mesondefine L2SU_LAUNCHER_IS_WINDOWS
+#mesondefine L2SU_CLASSPATH_SEP
+
#endif /* include guard */
diff --git a/src/launch.c b/src/launch.c
index cc0721f..6ac2ff7 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -1,31 +1,276 @@
#include "l2su.h"
+#include "launch.h"
+#include "macros.h"
+#include "version.h"
+#include "assets.h"
+#include "args.h"
-/* TODO launch struct */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
-int l2_launch_fill_substitutor(l2_subst_t *st, void *reserved, json_t *version, struct l2_instance *inst)
+bool l2_launch__check_feature(const char *name, json_t *val, void *user);
+
+int l2_launch_init(struct l2_launch *launch, const char *vername, struct l2_instance *inst)
+{
+ unsigned res;
+ json_t *verjson = NULL;
+ struct l2_version_library *libs = NULL;
+ char *jarpath = NULL;
+ json_t *jassetidx = NULL;
+ char *assetrootpath = NULL;
+ char *assetpath = NULL;
+ char *nativesdir = NULL;
+ char *main_class_dup = NULL;
+
+ l2_subst_t *subst = NULL;
+
+ if (l2_subst_init(&subst) < 0) {
+ CMD_ERROR0("Failed to create argument substitutor");
+ goto cleanup;
+ }
+
+ CMD_INFO("Attempting to load version %s...", vername);
+ if ((res = l2_version_load_local(vername, &verjson)) != VERSION_SUCCESS) {
+ CMD_ERROR("Failed to load version: %s", l2_version_strerror(res));
+ goto cleanup;
+ }
+
+ const char *main_class;
+ if (json_unpack(verjson, "{s:s}", "mainClass", &main_class) < 0) {
+ CMD_ERROR0("Failed to find main class.");
+ goto cleanup;
+ }
+
+ main_class_dup = strdup(main_class);
+ if (!main_class_dup) {
+ CMD_ERROR0("Allocation failed.");
+ goto cleanup;
+ }
+
+ CMD_INFO0("Collecting libraries");
+ if ((res = l2_version_collect_libraries(verjson, &libs, &l2_launch__check_feature, launch)) != VERSION_SUCCESS) {
+ CMD_ERROR("Failed to collect libraries: %s", l2_version_strerror(res));
+ goto cleanup;
+ }
+
+ CMD_INFO0("Downloading libraries");
+ if ((res = l2_version_download_libraries(libs)) != VERSION_SUCCESS) {
+ CMD_ERROR("Failed to download libraries: %s", l2_version_strerror(res));
+ goto cleanup;
+ }
+
+ CMD_INFO0("Downloading client jar");
+ if ((res = l2_version_download_jar(verjson, "client", &jarpath)) != VERSION_SUCCESS) {
+ CMD_ERROR("Failed to download client jar: %s", l2_version_strerror(res));
+ goto cleanup;
+ }
+
+ CMD_INFO0("Downloading asset index");
+ if (l2_assets_load_index(verjson, &jassetidx) < 0) {
+ CMD_ERROR0("Failed to load asset index.");
+ goto cleanup;
+ }
+
+ CMD_INFO0("Downloading assets");
+ if (l2_assets_download_assets(jassetidx, &assetpath) < 0) {
+ CMD_ERROR0("Failed to download assets.");
+ goto cleanup;
+ }
+
+ assetrootpath = l2_launcher_sprintf_alloc("%s/assets", l2_state.paths.data);
+ if (!assetrootpath) {
+ CMD_ERROR0("Allocation failed");
+ goto cleanup;
+ }
+
+ CMD_INFO0("Extracting natives");
+ if ((res = l2_version_extract_natives(libs, &nativesdir)) != VERSION_SUCCESS) {
+ CMD_ERROR("Failed to extract natives: %s", l2_version_strerror(res));
+ goto cleanup;
+ }
+
+ launch->instance = inst;
+ launch->version = verjson;
+ launch->libraries = libs;
+ launch->jarpath = jarpath;
+ launch->asset_index = jassetidx;
+ launch->assets_root = assetrootpath;
+ launch->virtual_assets = assetpath;
+ launch->natives = nativesdir;
+ launch->arg_subst = subst;
+ launch->main_class = main_class_dup;
+
+ return 0;
+
+cleanup:
+ json_decref(verjson);
+ l2_version_free_libraries(libs);
+ free(jarpath);
+ free(assetrootpath);
+ json_decref(jassetidx);
+ free(assetpath);
+ free(nativesdir);
+ free(main_class_dup);
+ if (subst) l2_subst_free(subst);
+
+ return -1;
+}
+
+void l2_launch_free_contents(struct l2_launch *launch)
+{
+ json_decref(launch->version);
+ l2_version_free_libraries(launch->libraries);
+ free(launch->jarpath);
+ free(launch->assets_root);
+ json_decref(launch->asset_index);
+ free(launch->virtual_assets);
+ free(launch->natives);
+ if (launch->arg_subst) l2_subst_free(launch->arg_subst);
+ free(launch->main_class);
+}
+
+bool l2_launch__check_feature(const char *name, json_t *val, void *user)
+{
+ L2_UNUSED(name);
+ L2_UNUSED(val);
+ L2_UNUSED(user);
+ return false;
+}
+
+int L2_FORMAT(printf, 3, 4) l2_launch__sprintf_resize(char **buf, size_t *cap, const char *fmt, ...)
+{
+ va_list pv;
+ va_start(pv, fmt);
+ size_t reqlen = vsnprintf(NULL, 0, fmt, pv);
+ va_end(pv);
+
+ if (*cap <= reqlen) {
+ char *temp = realloc(*buf, reqlen + 1);
+ if (!temp) return -1;
+ *buf = temp;
+ *cap = reqlen + 1;
+ }
+
+ va_start(pv, fmt);
+ vsnprintf(*buf, *cap, fmt, pv);
+ va_end(pv);
+ return 0;
+}
+
+int l2_launch__fill_substitutor(struct l2_launch *launch)
{
#define L2_LAUNCH_ADD_SUB(_st, _name, _val) \
- if (l2_subst_add(_st, _name, _val) < 0) return -1
+ if (l2_subst_add(_st, _name, _val) < 0) goto cleanup
+
+ l2_subst_t *st = launch->arg_subst;
+ char *keyname = NULL, *apath = NULL;
+ size_t keycap = 0, acap = 0;
const char *ver_name;
- if (json_unpack(version, "{s:s}", "id", &ver_name) < 0) {
+ const char *assets_idx_name;
+ const char *version_type;
+ if (json_unpack(launch->version, "{s:s, s:{s:s}, s:s}", "id", &ver_name, "assetIndex", "id", &assets_idx_name, "type", &version_type) < 0) {
return -1;
}
/* auth_access_token */
/* user_properties */
/* user_property_map */
+ /* auth_xuid */
+ /* clientid (lowercase i is real) */
L2_LAUNCH_ADD_SUB(st, "auth_session", "-");
L2_LAUNCH_ADD_SUB(st, "auth_player_name", "figboot");
L2_LAUNCH_ADD_SUB(st, "auth_uuid", "00000000000000000000000000000000");
L2_LAUNCH_ADD_SUB(st, "user_type", "legacy");
- L2_LAUNCH_ADD_SUB(st, "profile_name", inst->name);
+ if (launch->instance) {
+ L2_LAUNCH_ADD_SUB(st, "profile_name", launch->instance->name);
+ }
+
L2_LAUNCH_ADD_SUB(st, "version_name", ver_name);
L2_LAUNCH_ADD_SUB(st, "game_directory", ".");
-
+ L2_LAUNCH_ADD_SUB(st, "game_assets", launch->virtual_assets);
+ L2_LAUNCH_ADD_SUB(st, "assets_root", launch->assets_root);
+ L2_LAUNCH_ADD_SUB(st, "assets_index_name", assets_idx_name);
+ L2_LAUNCH_ADD_SUB(st, "version_type", version_type);
+
+ if (l2_launch__check_feature("has_custom_resolution", json_true(), launch)) {
+ char *widthstr, *heightstr;
+ size_t tempsz;
+ L2_ASPRINTF(widthstr, tempsz, "%u", launch->resolution.width);
+ L2_ASPRINTF(heightstr, tempsz, "%u", launch->resolution.height);
+
+ L2_LAUNCH_ADD_SUB(st, "resolution_width", widthstr);
+ L2_LAUNCH_ADD_SUB(st, "resolution_height", heightstr);
+ }
+
+ L2_LAUNCH_ADD_SUB(st, "language", "en-us");
+
+ L2_LAUNCH_ADD_SUB(st, "launcher_name", PROJECT_NAME);
+ L2_LAUNCH_ADD_SUB(st, "launcher_version", "0.1.0");
+ L2_LAUNCH_ADD_SUB(st, "natives_directory", launch->natives);
+ L2_LAUNCH_ADD_SUB(st, "classpath", "TODO");
+ L2_LAUNCH_ADD_SUB(st, "classpath_separator", L2SU_CLASSPATH_SEP);
+ L2_LAUNCH_ADD_SUB(st, "primary_jar", launch->jarpath);
+
+ const char *assetpath, *assethash;
+ json_t *objects = json_object_get(launch->asset_index, "objects");
+ if (json_is_object(objects)) {
+ json_t *val;
+ json_object_foreach(objects, assetpath, val) {
+ json_t *hash_obj = json_object_get(val, "hash");
+ if (!json_is_string(hash_obj)) goto cleanup;
+ assethash = json_string_value(hash_obj);
+
+ if (l2_launch__sprintf_resize(&apath, &acap, "%s/assets/objects/%2.2s/%s", l2_state.paths.data, assethash, assethash) < 0) goto cleanup;
+ if (l2_launch__sprintf_resize(&keyname, &keycap, "asset=%s", assetpath) < 0) goto cleanup;
+
+ L2_LAUNCH_ADD_SUB(st, keyname, apath);
+ }
+ }
+
+ free(keyname);
+ free(apath);
+
+ keyname = NULL;
+ apath = NULL;
return 0;
+
+cleanup:
+ free(keyname);
+ free(apath);
+
+ return -1;
#undef L2_LAUNCH_ADD_SUB
}
+
+void l2_launch__test(struct l2_launch *launch)
+{
+ if (l2_launch__fill_substitutor(launch) < 0) CMD_FATAL0("fill");
+
+ char **jvm_args, **game_args;
+ size_t njvm_args, ngame_args;
+ if (l2_args_get_jvm_args(launch->version, launch->arg_subst, &l2_launch__check_feature, launch, &jvm_args, &njvm_args) < 0) {
+ CMD_FATAL0("jvm");
+ }
+
+ if (l2_args_get_game_args(launch->version, launch->arg_subst, &l2_launch__check_feature, launch, &game_args, &ngame_args) < 0) {
+ CMD_FATAL0("game");
+ }
+
+ for (size_t s = 0; s < njvm_args; ++s) {
+ CMD_DEBUG("jvm: %s", jvm_args[s]);
+ free(jvm_args[s]);
+ }
+
+ for(size_t s = 0; s < ngame_args; ++s) {
+ CMD_DEBUG("game: %s", game_args[s]);
+ free(game_args[s]);
+ }
+
+ free(jvm_args);
+ free(game_args);
+}
diff --git a/src/launch.h b/src/launch.h
new file mode 100644
index 0000000..d329358
--- /dev/null
+++ b/src/launch.h
@@ -0,0 +1,37 @@
+#ifndef L2SU_LAUNCH_H_INCLUDED
+#define L2SU_LAUNCH_H_INCLUDED
+
+#include "l2su.h"
+#include "instance.h"
+#include "version.h"
+
+#include <jansson.h>
+
+struct l2_launch {
+ json_t *version;
+ json_t *asset_index;
+ struct l2_instance *instance;
+
+ struct {
+ unsigned width;
+ unsigned height;
+ } resolution;
+
+ char *virtual_assets; /* aka game_assets */
+ char *assets_root;
+
+ struct l2_version_library *libraries;
+ char *natives;
+ char *jarpath;
+
+ char *main_class;
+ char *classpath;
+
+ l2_subst_t *arg_subst;
+};
+
+int l2_launch_init(struct l2_launch *launch, const char *vername, struct l2_instance *inst);
+
+void l2_launch_free_contents(struct l2_launch *launch);
+
+#endif /* include guard */
diff --git a/src/meson.build b/src/meson.build
index 9c9e545..61d1d2f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,4 +1,4 @@
-launcher_srcs = files('l2su.c', 'command.c', 'cmd-instance.c', 'uuid/uuid.c', 'launcherutil.c', 'instance.c', 'cmd-version.c', 'digest/sha1.c', 'version.c', 'subst.c', 'downloadpool.c', 'assets.c', 'args.c')
+launcher_srcs = files('l2su.c', 'command.c', 'cmd-instance.c', 'uuid/uuid.c', 'launcherutil.c', 'instance.c', 'cmd-version.c', 'digest/sha1.c', 'version.c', 'subst.c', 'downloadpool.c', 'assets.c', 'args.c', 'launch.c')
configure_file(input : 'config.h.in', output : 'config.h', configuration : config_data)
config_include_dir = include_directories('.')
diff --git a/src/subst.c b/src/subst.c
index 6c8bec6..20a6790 100644
--- a/src/subst.c
+++ b/src/subst.c
@@ -6,6 +6,7 @@
struct l2_subst__item {
char *name;
char *value;
+ size_t namelen;
struct l2_subst__item *next;
};
@@ -46,6 +47,7 @@ int l2_subst_add(l2_subst_t *sp, const char *name, const char *value)
item->name = namedup;
item->value = valdup;
+ item->namelen = strlen(name);
item->next = sp->items;
sp->items = item;
@@ -55,7 +57,7 @@ int l2_subst_add(l2_subst_t *sp, const char *name, const char *value)
const char *l2_subst__find(l2_subst_t *sp, const char *name, size_t len)
{
for (struct l2_subst__item *item = sp->items; item; item = item->next) {
- if (!strncmp(item->name, name, len)) return item->value;
+ if (item->namelen == len && !strncmp(item->name, name, len)) return item->value;
}
return NULL;
}
diff --git a/src/version.c b/src/version.c
index af7b56e..e7e064d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -566,7 +566,7 @@ cleanup:
return res;
}
-unsigned l2_version__collect_libraries(json_t *jlibs, l2_subst_t *subst, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher);
+unsigned l2_version__collect_libraries(json_t *jlibs, l2_subst_t *subst, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher, void *muser);
void l2_version_free_libraries(struct l2_version_library *libs);
int l2_version__get_library_artifact_path(json_t *lib, l2_subst_t *subst, const char *classifier, char **path);
@@ -901,7 +901,7 @@ cleanup:
return res;
}
-unsigned l2_version_collect_libraries(json_t *version, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher)
+unsigned l2_version_collect_libraries(json_t *version, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher, void *muser)
{
json_t *jlibs;
unsigned res;
@@ -921,7 +921,7 @@ unsigned l2_version_collect_libraries(json_t *version, struct l2_version_library
goto cleanup;
}
- res = l2_version__collect_libraries(jlibs, subst, libs, feature_matcher);
+ res = l2_version__collect_libraries(jlibs, subst, libs, feature_matcher, muser);
cleanup:
if (subst) l2_subst_free(subst);
@@ -1084,7 +1084,7 @@ cleanup:
return res;
}
-unsigned l2_version__collect_libraries(json_t *jlibs, l2_subst_t *subst, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher)
+unsigned l2_version__collect_libraries(json_t *jlibs, l2_subst_t *subst, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher, void *muser)
{
struct l2_version_library *libraries = NULL, *tail = NULL;
struct l2_version_library *curlib = NULL;
@@ -1104,7 +1104,7 @@ unsigned l2_version__collect_libraries(json_t *jlibs, l2_subst_t *subst, struct
json_t *rules = json_object_get(val, "rules");
if (rules) {
- applies = l2_version_check_rules(rules, feature_matcher);
+ applies = l2_version_check_rules(rules, feature_matcher, muser);
if (applies == RULE_CHECK_ERROR) {
ret = VERSION_EJSON;
goto cleanup;
@@ -1235,7 +1235,7 @@ int l2_version__whole_string_matches(const char *pattern, const char *subject)
return errcode >= 0 ? 1 : -1;
}
-enum l2_version_check_result l2_version__check_one_rule(json_t *rule, l2_version_feature_match_proc_t *feature_matcher)
+enum l2_version_check_result l2_version__check_one_rule(json_t *rule, l2_version_feature_match_proc_t *feature_matcher, void *muser)
{
if (!json_is_object(rule))
return RULE_CHECK_ERROR;
@@ -1289,7 +1289,7 @@ enum l2_version_check_result l2_version__check_one_rule(json_t *rule, l2_version
const char *fname;
json_object_foreach(val, fname, feat) {
- if (!(*feature_matcher)(fname, feat)) {
+ if (!(*feature_matcher)(fname, feat, muser)) {
return RULE_CHECK_DEFAULT;
}
}
@@ -1300,7 +1300,7 @@ enum l2_version_check_result l2_version__check_one_rule(json_t *rule, l2_version
return myaction;
}
-enum l2_version_check_result l2_version_check_rules(json_t *rules, l2_version_feature_match_proc_t *feature_matcher)
+enum l2_version_check_result l2_version_check_rules(json_t *rules, l2_version_feature_match_proc_t *feature_matcher, void *muser)
{
size_t idx;
json_t *val;
@@ -1312,7 +1312,7 @@ enum l2_version_check_result l2_version_check_rules(json_t *rules, l2_version_fe
json_array_foreach(rules, idx, val) {
/* first, check if the rule actually matches us */
- switch (l2_version__check_one_rule(val, feature_matcher)) {
+ switch (l2_version__check_one_rule(val, feature_matcher, muser)) {
case RULE_CHECK_ERROR:
return RULE_CHECK_ERROR;
case RULE_CHECK_ALLOW:
@@ -1466,15 +1466,6 @@ unsigned l2_version_extract_natives(struct l2_version_library *libs, char **out_
char template[] = "/tmp/l2su-natives-XXXXXX"; /* TODO: make portable */
char *nativesdir;
- for (struct l2_version_library *cur = libs; cur; cur = cur->next) {
- if (cur->extract.extract) goto found;
- }
-
- CMD_INFO0("Not extracting natives, there are no libraries that require it.");
- return 0;
-
-found:
-
if (!mkdtemp(template)) {
CMD_WARN("Failed to create directory for extracted natives: %s", strerror(errno));
return VERSION_ERRNO;
diff --git a/src/version.h b/src/version.h
index 89341cb..6c1472d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -47,7 +47,7 @@ enum {
VERSION_DOWNLOAD_MAX
};
-typedef bool (l2_version_feature_match_proc_t)(const char *name, json_t *val);
+typedef bool (l2_version_feature_match_proc_t)(const char *name, json_t *val, void *user);
struct l2_version_download {
char *url;
@@ -90,9 +90,9 @@ enum l2_version_check_result {
RULE_CHECK_DEFAULT,
RULE_CHECK_ALLOW,
RULE_CHECK_DISALLOW,
-} l2_version_check_rules(json_t *rules, l2_version_feature_match_proc_t *matcher);
+} l2_version_check_rules(json_t *rules, l2_version_feature_match_proc_t *matcher, void *muser);
-unsigned l2_version_collect_libraries(json_t *version, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher);
+unsigned l2_version_collect_libraries(json_t *version, struct l2_version_library **libs, l2_version_feature_match_proc_t *feature_matcher, void *muser);
unsigned l2_version_download_libraries(struct l2_version_library *libs);
void l2_version_free_libraries(struct l2_version_library *libs);