diff options
| author | 2024-01-05 04:53:20 -0600 | |
|---|---|---|
| committer | 2024-01-05 04:53:20 -0600 | |
| commit | 11672146b9bf67cae05e8e3207c9bd1e47d52220 (patch) | |
| tree | 4d72fd88efbabeeb37509cdc99c5404528183ca1 /src/args.c | |
| parent | downloads assets correctly (diff) | |
extracts natives
Diffstat (limited to 'src/args.c')
| -rw-r--r-- | src/args.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/args.c b/src/args.c new file mode 100644 index 0000000..7b307a8 --- /dev/null +++ b/src/args.c @@ -0,0 +1,206 @@ +#include "args.h" +#include "l2su.h" +#include "instance.h" +#include "version.h" +#include "macros.h" + +#include <jansson.h> +#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(json_t *version, l2_subst_t *subst, l2_version_feature_match_proc_t *feature_matcher, char ***out_args, size_t *out_nargs) +{ + const char *mc_args = NULL; + json_t *jargs = NULL; + + if (json_unpack(version, "{s?:{s:o}, s?:s}", "arguments", "game", &jargs, "minecraftArguments", &mc_args) < 0) { + return -1; + } + + if (jargs) { + if (!json_is_array(jargs)) return -1; + + + return l2_args__get_args_json(subst, jargs, feature_matcher, out_args, out_nargs); + } else if (mc_args) { + return l2_args__get_game_args(subst, mc_args, feature_matcher, out_args, out_nargs); + } else { + return -1; + } +} + +int L2_SENTINEL l2_args__array_append(l2_subst_t *sp, char ***arr, size_t *nargs, ...) +{ + size_t nadd = 0; + const char *to_add; + + va_list parg; + va_start(parg, nargs); + do { + to_add = va_arg(parg, const char *); + ++nadd; + } while (to_add); + --nadd; + va_end(parg); + + char **temp = realloc(*arr, (*nargs + nadd) * sizeof(char *)); + if (!temp) return -1; + *arr = temp; + + memset(temp + *nargs, 0, sizeof(char *) * nadd); + + va_start(parg, nargs); + + for (; nadd; --nadd) { + if (l2_subst_apply(sp, va_arg(parg, const char *), temp + (*nargs)++) < 0) goto cleanup; + } + + va_end(parg); + return 0; + +cleanup: + va_end(parg); + 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) +{ + char **args = NULL; + size_t nargs = 0; + + char *arg_start; + size_t sz; + L2_ASTRDUP(arg_start, sz, argsline); + + for (char *argcur = arg_start; *argcur; ++argcur) { + if (*argcur == ' ') { + *argcur = '\0'; + if (l2_args__array_append(subst, &args, &nargs, arg_start, NULL) < 0) goto cleanup; + arg_start = argcur + 1; + } + } + + 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 (l2_args__array_append(subst, &args, &nargs, "--demo", NULL) < 0) goto cleanup; + } + + if ((*feature_matcher)("has_custom_resolution", json_true())) { + if (l2_args__array_append(subst, &args, &nargs, "--width", "${resolution_width}", "--height", "${resolution_height}", NULL) < 0) goto cleanup; + } + + *out_args = args; + *out_nargs = nargs; + return 0; + +cleanup: + for (char **cur = args; nargs; --nargs, ++cur) { + free(*cur); + } + + free(args); + + 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) +{ + json_t *jarguments = json_object_get(version, "arguments"); + if (!jarguments) { + char **args = NULL; + size_t nargs = 0; + + if (l2_args__array_append(subst, &args, &nargs, +#ifdef L2SU_LAUNCHER_IS_WINDOWS + "-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump", +#endif +#ifdef L2SU_LAUNCHER_IS_OSX + "-Xdock:icon=${asset=icons/minecraft.icns}", + "-Xdock:name=Minecraft", +#endif + "-Djava.library.path=${natives_directory}", + "-Dminecraft.launcher.brand=${launcher_name}", + "-Dminecraft.launcher.version=${launcher_version}", + "-Dminecraft.client.jar=${primary_jar}", + "-cp", + "${classpath}", + NULL) < 0) { + return -1; + } + + *out_args = args; + *out_nargs = nargs; + + return 0; + } else if (!json_is_object(jarguments)) { + return -1; + } + + json_t *jjvmargs = json_object_get(jarguments, "jvm"); + if (!json_is_array(jjvmargs)) { + return -1; + } + + return l2_args__get_args_json(subst, jjvmargs, feature_matcher, 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) +{ + char **args = NULL; + size_t nargs = 0; + + size_t idx; + json_t *value; + + json_array_foreach(jargs, idx, value) { + if (json_is_string(value)) { + if (l2_args__array_append(subst, &args, &nargs, json_string_value(value), NULL) < 0) goto cleanup; + } else if (json_is_object(value)) { + json_t *rules; + json_t *values; + if (json_unpack(value, "{s:o, s:o}", "rules", &rules, "value", &values) < 0) { + goto cleanup; + } + + if (!json_is_array(rules)) goto cleanup; + + switch (l2_version_check_rules(rules, feature_matcher)) { + case RULE_CHECK_ALLOW: { + json_t *argval; + size_t argidx; + if (json_is_string(values)) { + if (l2_args__array_append(subst, &args, &nargs, json_string_value(values), NULL) < 0) goto cleanup; + } else { + /* this code strongly prefers brevity over performance (breaking news) */ + json_array_foreach(values, argidx, argval) { + if (!json_is_string(argval)) goto cleanup; + if (l2_args__array_append(subst, &args, &nargs, json_string_value(argval), NULL) < 0) goto cleanup; + } + } + break; + } + case RULE_CHECK_ERROR: + goto cleanup; + default: + continue; + } + } + } + + *out_args = args; + *out_nargs = nargs; + return 0; + +cleanup: + for (char **cur = args; nargs; --nargs, ++cur) { + free(*cur); + } + + free(args); + + return -1; +} |
