diff options
| author | 2024-01-11 04:40:31 -0600 | |
|---|---|---|
| committer | 2024-01-11 04:40:31 -0600 | |
| commit | 8fd75f88d2c9fc3be927c620cf57bd47bb8984ef (patch) | |
| tree | 108d21d53487e769c34a8e130b00acbc3a6904aa /src | |
| parent | add auth (diff) | |
add launch command
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd-launch.c | 77 | ||||
| -rw-r--r-- | src/cmd-user.c | 195 | ||||
| -rw-r--r-- | src/cmd-version.c | 5 | ||||
| -rw-r--r-- | src/command.c | 98 | ||||
| -rw-r--r-- | src/commands.h | 4 | ||||
| -rw-r--r-- | src/l2su.h | 1 | ||||
| -rw-r--r-- | src/meson.build | 2 | ||||
| -rw-r--r-- | src/user.c | 26 | ||||
| -rw-r--r-- | src/user.h | 1 | ||||
| -rw-r--r-- | src/version.c | 18 |
10 files changed, 412 insertions, 15 deletions
diff --git a/src/cmd-launch.c b/src/cmd-launch.c new file mode 100644 index 0000000..4c445d5 --- /dev/null +++ b/src/cmd-launch.c @@ -0,0 +1,77 @@ +#include "commands.h" +#include "command.h" +#include "l2su.h" +#include "launch.h" +#include "user.h" +#include "version.h" + +#include <string.h> + +unsigned cmd_launch2(struct l2_context_node *ctx, char **args) +{ + unsigned ures; + int res; + + if (*args) { + CMD_FATAL0("sorry launch settings aren't implemented yet"); + } + + char *instancename = NULL; + char *versionname = NULL; + char *username = NULL; + + l2_cmd_collect_args(ctx, 3, "instance", &instancename, "version", &versionname, "user", &username); + + if ((ures = l2_instance_load_all()) != INSTANCE_SUCCESS) { + CMD_FATAL("Failed to load instance: %s", l2_instance_errormsg[ures]); + } + + if ((ures = l2_version_load_remote()) != VERSION_SUCCESS) { + CMD_FATAL("Failed to load versions: %s", l2_version_strerror(ures)); + } + + if ((res = l2_user_load()) < 0) { + CMD_FATAL0("Failed to load users"); + } + + struct l2_instance *inst = NULL; + + for (struct l2_instance *cur = l2_state.instance_head; cur; cur = cur->next) { + if (!strcmp(cur->name, instancename)) { + inst = cur; + break; + } + } + + if (!inst) { + CMD_FATAL("Could not find an instance by the name '%s'.", instancename); + } + + struct l2_user *user = l2_user_search(username); + if (!user) { + CMD_FATAL0("Failed to load user"); + } + + struct l2_launch launch = { 0 }; + if (l2_launch_init(&launch, versionname, inst) < 0) { + CMD_FATAL0("Failed to initialize launch context"); + } + + launch.user = user; + + if (l2_launch_init_substitutor(&launch) < 0) { + CMD_FATAL0("Failed to initialize argument substitutor"); + } + + if (l2_launch_init_args(&launch) < 0) { + CMD_FATAL0("Failed to set JVM and game arguments"); + } + + if (l2_launch_jni(&launch) < 0) { + CMD_FATAL0("Failed to launch the game"); + } + + l2_launch_free_contents(&launch); + + return CMD_RESULT_SUCCESS; +} diff --git a/src/cmd-user.c b/src/cmd-user.c new file mode 100644 index 0000000..cf875c8 --- /dev/null +++ b/src/cmd-user.c @@ -0,0 +1,195 @@ +#include "commands.h" +#include "command.h" +#include "user.h" +#include "l2su.h" +#include "uuid/uuid.h" + +#include <stdbool.h> + +#define CMD_MSG_USER_ERROR_LOADING "Error loading users." +#define CMD_MSG_USER_ERROR_SAVING "Error saving users." +#define CMD_MSG_USER_NO_USER_FOUND "User %s not found." + +unsigned cmd_user_add(struct l2_context_node *ctx, char **args) +{ + L2_UNUSED(ctx); + + if (*args) { + CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args); + } + + int res; + if ((res = l2_user_load()) < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_LOADING); + } + + struct l2_user *user = NULL; + l2_user_session_t *session = NULL; + + session = l2_user_session_new(); + if (!session) { + CMD_FATAL0("Failed to create a session"); + } + + if ((res = l2_user_session_login(session)) < 0) { + CMD_FATAL0("Failed to login"); + } else if (!res) { + CMD_FATAL0("User declined authorization"); + } + + user = calloc(1, sizeof(struct l2_user)); + if (!user) { + CMD_FATAL0("Failed to create a user"); + } + + l2_user_init(user); + + user->session = session; + + if (l2_user_update_profile(user) < 0) { + CMD_FATAL0("Failed to retrieve your profile"); + } + + for (struct l2_user *cur = l2_state.users_head; cur; cur = cur->next) { + if (!l2_uuid_compare(&cur->profile.uuid, &user->profile.uuid)) { + char uuidstr[UUID_STRLEN + 1]; + l2_uuid_to_string(&cur->profile.uuid, uuidstr); + CMD_FATAL("A profile with the UUID %s already exists!", uuidstr); + } + } + + l2_user_add(user); + + if (l2_user_save() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_SAVING); + } + + return CMD_RESULT_SUCCESS; +} + +unsigned cmd_user_remove(struct l2_context_node *ctx, char **args) +{ + char *username = NULL; + + if (*args) { + CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args); + } + + l2_cmd_collect_args(ctx, 1, "name", &username); + + if (l2_user_load() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_LOADING); + } + + struct l2_user *user = l2_user_search(username); + if (!user) { + CMD_FATAL(CMD_MSG_USER_NO_USER_FOUND, username); + } + + l2_user_delete(user); + l2_user_free(user); + + user = NULL; + + if (l2_user_save() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_SAVING); + } + + return CMD_RESULT_SUCCESS; +} + +unsigned cmd_user_nick(struct l2_context_node *ctx, char **args) +{ + char *username = NULL; + char *newnick = NULL; + + if (*args) { + CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args); + } + + l2_cmd_collect_args(ctx, 2, "name", &username, "#newnick", &newnick); + + if (l2_user_load() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_LOADING); + } + + struct l2_user *user = l2_user_search(username); + if (!user) { + CMD_FATAL(CMD_MSG_USER_NO_USER_FOUND, username); + } + + free(user->nickname); + user->nickname = newnick ? strdup(newnick) : NULL; + if (newnick && !user->nickname) { + CMD_FATAL0("Failed to set nickname"); + } + + if (l2_user_save() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_SAVING); + } + + return CMD_RESULT_SUCCESS; +} + +unsigned cmd_user_login(struct l2_context_node *ctx, char **args) +{ + char *username = NULL; + + if (*args) { + CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args); + } + + l2_cmd_collect_args(ctx, 1, "name", &username); + + if (l2_user_load() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_LOADING); + } + + struct l2_user *user = l2_user_search(username); + if (!user) { + CMD_FATAL(CMD_MSG_USER_NO_USER_FOUND, username); + } + + int res; + if ((res = l2_user_session_login(user->session)) < 0) { + CMD_FATAL0("Error logging in"); + } else if (!res) { + CMD_FATAL0("User declined authorization"); + } + + if (l2_user_update_profile(user) < 0) { + CMD_FATAL0("Failed to update your profile"); + } + + if (l2_user_save() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_SAVING); + } + + return CMD_RESULT_SUCCESS; +} + +unsigned cmd_user_list(struct l2_context_node *ctx, char **args) +{ + L2_UNUSED(ctx); + + if (*args) { + CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args); + } + + if (l2_user_load() < 0) { + CMD_FATAL0(CMD_MSG_USER_ERROR_LOADING); + } + + for (struct l2_user *cur = l2_state.users_head; cur; cur = cur->next) { + char uuidstr[UUID_STRLEN + 1]; + l2_uuid_to_string(&cur->profile.uuid, uuidstr); + + if (cur->nickname) { + printf("- %s (a.k.a. %s) - %s\n", cur->profile.name, cur->nickname, uuidstr); + } else { + printf("- %s - %s\n", cur->profile.name, uuidstr); + } + } + + return CMD_RESULT_SUCCESS; +} diff --git a/src/cmd-version.c b/src/cmd-version.c index b39daec..0e365ee 100644 --- a/src/cmd-version.c +++ b/src/cmd-version.c @@ -30,7 +30,10 @@ unsigned cmd_version_list_remote(struct l2_context_node *ctx, char **args) } for (struct l2_version_remote *rv = l2_state.ver_remote_head; rv; rv = rv->next) { - printf("%s\n", rv->id); + printf("%s", rv->id); + if (rv == l2_state.ver_latest) fputs(" (latest)", stdout); + if (rv == l2_state.ver_snapshot) fputs(" (latest snapshot)", stdout); + putchar('\n'); } return CMD_RESULT_SUCCESS; diff --git a/src/command.c b/src/command.c index 55e7970..7ea3b4c 100644 --- a/src/command.c +++ b/src/command.c @@ -111,29 +111,111 @@ struct l2_command_node l2_cmd_root = { .children = (struct l2_command_node []) { { .type = CMD_NODE_TYPE_LITERAL, - .name = "local", + .name = "remote", - .cmd_proc = &cmd_version_list_local + .cmd_proc = &cmd_version_list_remote }, + { 0 } + } + }, + { 0 } + } + }, + { + .type = CMD_NODE_TYPE_LITERAL, + .name = "user", + + .children = (struct l2_command_node []) { + { + .type = CMD_NODE_TYPE_LITERAL, + .name = "add", + + .cmd_proc = &cmd_user_add + }, + { + .type = CMD_NODE_TYPE_LITERAL, + .name = "remove", + + .children = (struct l2_command_node []) { { - .type = CMD_NODE_TYPE_LITERAL, - .name = "remote", + .type = CMD_NODE_TYPE_ARGUMENT, + .name = "name", - .cmd_proc = &cmd_version_list_remote + .cmd_proc = &cmd_user_remove }, { 0 } } }, { .type = CMD_NODE_TYPE_LITERAL, - .name = "install", + .name = "nick", .children = (struct l2_command_node []) { { .type = CMD_NODE_TYPE_ARGUMENT, - .name = "remotever", + .name = "name", - .cmd_proc = &cmd_version_install + .cmd_proc = &cmd_user_nick, + + .children = (struct l2_command_node []) { + { + .type = CMD_NODE_TYPE_ARGUMENT, + .name = "newnick", + + .cmd_proc = &cmd_user_nick + }, + { 0 } + } + }, + { 0 } + } + }, + { + .type = CMD_NODE_TYPE_LITERAL, + .name = "login", + + .children = (struct l2_command_node []) { + { + .type = CMD_NODE_TYPE_ARGUMENT, + .name = "name", + + .cmd_proc = &cmd_user_login + }, + { 0 } + } + }, + { + .type = CMD_NODE_TYPE_LITERAL, + .name = "list", + + .cmd_proc = &cmd_user_list + }, + { 0 } + } + }, + { + .type = CMD_NODE_TYPE_LITERAL, + .name = "launch2", + + .children = (struct l2_command_node []) { + { + .type = CMD_NODE_TYPE_ARGUMENT, + .name = "instance", + + .children = (struct l2_command_node []) { + { + .type = CMD_NODE_TYPE_ARGUMENT, + .name = "version", + + .children = (struct l2_command_node []) { + { + .type = CMD_NODE_TYPE_ARGUMENT, + .name = "user", + + .cmd_proc = &cmd_launch2 + }, + { 0 } + } }, { 0 } } diff --git a/src/commands.h b/src/commands.h index fe3f102..af00b3a 100644 --- a/src/commands.h +++ b/src/commands.h @@ -11,10 +11,10 @@ unsigned cmd_instance_rename(struct l2_context_node *, char **); unsigned cmd_user_add(struct l2_context_node *, char **); unsigned cmd_user_remove(struct l2_context_node *, char **); unsigned cmd_user_nick(struct l2_context_node *, char **); +unsigned cmd_user_login(struct l2_context_node *, char **); +unsigned cmd_user_list(struct l2_context_node *, char **); unsigned cmd_version_list_remote(struct l2_context_node *, char **); -unsigned cmd_version_list_local(struct l2_context_node *, char **); -unsigned cmd_version_install(struct l2_context_node *, char **); unsigned cmd_profile_add(struct l2_context_node *, char **); unsigned cmd_profile_delete(struct l2_context_node *, char **); @@ -27,6 +27,7 @@ struct tag_l2_state_t { struct l2_instance *instance_head; struct l2_instance *instance_tail; + struct l2_version_remote *ver_latest, *ver_snapshot; struct l2_version_remote *ver_remote_head; struct l2_version_remote *ver_remote_tail; diff --git a/src/meson.build b/src/meson.build index 9da4e88..0c11ddb 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,7 @@ 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', 'jniwrap.c', - 'runtime.c', 'user.c') + 'runtime.c', 'user.c', 'cmd-user.c', 'cmd-launch.c') configure_file(input : 'config.h.in', output : 'config.h', configuration : config_data) config_include_dir = include_directories('.') @@ -591,6 +591,32 @@ void l2_user_delete(struct l2_user *user) } } +struct l2_user *l2_user_search(const char *searchstr) +{ + uuid_t uuid; + bool have_uuid = false; + + if (l2_uuid_from_string(&uuid, searchstr) == 0) { + have_uuid = true; + } else { + if (l2_uuid_from_string_short(&uuid, searchstr) == 0) { + have_uuid = true; + } + } + + for (struct l2_user *cur = l2_state.users_head; cur; cur = cur->next) { + if (have_uuid && !l2_uuid_compare(&cur->profile.uuid, &uuid)) { + return cur; + } else if (cur->nickname && !strcmp(searchstr, cur->nickname)) { + return cur; + } else if (!strcmp(searchstr, cur->profile.name)) { + return cur; + } + } + + return NULL; +} + void l2_user_init(struct l2_user *user) { /* using calloc works as well, so that's what we do in this file (elsewhere should use this function though) */ @@ -46,6 +46,7 @@ void l2_user_add(struct l2_user *user); /* does NOT free the user */ void l2_user_delete(struct l2_user *user); +struct l2_user *l2_user_search(const char *searchstr); l2_user_session_t *l2_user_session_new(void); diff --git a/src/version.c b/src/version.c index 6aa32db..dd8506a 100644 --- a/src/version.c +++ b/src/version.c @@ -39,7 +39,7 @@ const char *const l2_version__messages[] = { unsigned l2_version__load_manifest(json_t **out_json); unsigned l2_version__load_all_from_json(json_t *json); -unsigned l2_version__add_remote(json_t *obj); +unsigned l2_version__add_remote(json_t *obj, const char *latestrel, const char *latestsnap); unsigned l2_version_load_remote(void) { @@ -485,15 +485,18 @@ unsigned l2_version__load_all_from_json(json_t *json) return VERSION_EFORMAT; } + l2_state.ver_latest = NULL; + l2_state.ver_snapshot = NULL; + json_array_foreach(versions, index, value) { - if ((res = l2_version__add_remote(value)) != VERSION_SUCCESS) + if ((res = l2_version__add_remote(value, latestrel, latestsnap)) != VERSION_SUCCESS) return res; } return VERSION_SUCCESS; } -unsigned l2_version__add_remote(json_t *js) +unsigned l2_version__add_remote(json_t *js, const char *latestrel, const char *latestsnap) { struct l2_version_remote *ver = NULL; json_t *val; @@ -511,6 +514,7 @@ unsigned l2_version__add_remote(json_t *js) val = json_object_get(js, "id"); if (!json_is_string(val)) goto cleanup; + const char *verid = json_string_value(val); /* I hate this code */ ver->id = strdup(json_string_value(val)); val = json_object_get(js, "type"); @@ -547,6 +551,14 @@ unsigned l2_version__add_remote(json_t *js) l2_state.ver_remote_head = l2_state.ver_remote_tail = ver; } + if (!strcmp(verid, latestrel)) { + l2_state.ver_latest = ver; + } + + if (!strcmp(verid, latestsnap)) { + l2_state.ver_snapshot = ver; + } + return VERSION_SUCCESS; cleanup: |
