From 04b429d064fb2954e768abc8066013ad0faf2729 Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Fri, 5 Jan 2024 14:39:43 -0600 Subject: launch info all in one place TODO: build class path --- meson.build | 12 +++ meson.options | 4 + src/args.c | 24 ++--- src/args.h | 4 +- src/assets.c | 9 +- src/assets.h | 5 ++ src/cmd-version.c | 89 +++---------------- src/config.h.in | 2 + src/launch.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/launch.h | 37 ++++++++ src/meson.build | 2 +- src/subst.c | 4 +- src/version.c | 27 ++---- src/version.h | 6 +- 14 files changed, 358 insertions(+), 124 deletions(-) create mode 100644 src/launch.h 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 #include -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 + +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 #include @@ -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 +#include +#include -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 + +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); -- cgit v1.2.3-70-g09d2