aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--USAGE.md4
-rw-r--r--src/cmd-launch.c77
-rw-r--r--src/cmd-user.c195
-rw-r--r--src/cmd-version.c5
-rw-r--r--src/command.c98
-rw-r--r--src/commands.h4
-rw-r--r--src/l2su.h1
-rw-r--r--src/meson.build2
-rw-r--r--src/user.c26
-rw-r--r--src/user.h1
-rw-r--r--src/version.c18
11 files changed, 414 insertions, 17 deletions
diff --git a/USAGE.md b/USAGE.md
index 802cf3e..9e9969c 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -6,10 +6,10 @@
- `l2su user add`
- `l2su user remove <username-or-uuid-or-nickname>`
- `l2su user nick <username-or-uuid-or-nickname> [<new-nickname>]` - handy for users with long annoying names like `______HAHA______`
+- `l2su user login <username-or-uuid-or-nickname>`
+- `l2su user list`
- `l2su version list remote`
-- `l2su version list local`
-- `l2su version install <mojang-version>`
- `l2su profile add <name> <instance> <version>`
- `l2su profile delete <name>`
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 **);
diff --git a/src/l2su.h b/src/l2su.h
index a455b58..e56ecb4 100644
--- a/src/l2su.h
+++ b/src/l2su.h
@@ -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('.')
diff --git a/src/user.c b/src/user.c
index fd1acd5..eaaadf6 100644
--- a/src/user.c
+++ b/src/user.c
@@ -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) */
diff --git a/src/user.h b/src/user.h
index f84e3e1..5dbb4e2 100644
--- a/src/user.h
+++ b/src/user.h
@@ -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: