aboutsummaryrefslogtreecommitdiff
path: root/src/client/login.c
diff options
context:
space:
mode:
authorfschildt <florian.schildt@protonmail.com>2025-08-22 15:23:11 +0200
committerfschildt <florian.schildt@protonmail.com>2025-08-22 15:23:11 +0200
commit2050c0e0576f05156f192aa4caf48834d2f28b14 (patch)
treeee58bd35b0df0a1bacfbc9700ed99ce80c99294e /src/client/login.c
first commitHEADmaster
Diffstat (limited to 'src/client/login.c')
-rw-r--r--src/client/login.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/client/login.c b/src/client/login.c
new file mode 100644
index 0000000..10c032d
--- /dev/null
+++ b/src/client/login.c
@@ -0,0 +1,320 @@
+#include <client/server_connection.h>
+#include <basic/string32.h>
+#include <client/login.h>
+#include <client/fscord.h>
+#include <client/string32_handles.h>
+#include <client/draw.h>
+#include <client/font.h>
+#include <crypto/rsa.h>
+
+#include <basic/basic.h>
+#include <basic/math.h>
+#include <os/os.h>
+
+#include <stdlib.h>
+
+internal_var Fscord *s_fscord;
+
+void
+login_draw(Login *login)
+{
+ OSOffscreenBuffer *offscreen = os_window_get_offscreen_buffer(s_fscord->window);
+ Arena *frame_arena = &s_fscord->frame_arena;
+
+
+ // draw background color
+
+ RectF32 bg_rect = rectf32(0, 0, offscreen->width, offscreen->height);
+ V3F32 bg_col = v3f32(0.4, 0.2, 0.2);
+ draw_rectf32(offscreen, bg_rect, bg_col);
+
+
+
+ // draw widgets background
+
+ f32 zoom = 1.f;
+ f32 font_size = s_fscord->font.y_advance;
+ V2F32 widgets_bg_size = v2f32(zoom*font_size*28, zoom*font_size*20);
+ V2F32 widgets_bg_pos = v2f32_center(widgets_bg_size, v2f32(offscreen->width, offscreen->height));
+ RectF32 widgets_bg_rect = rectf32(widgets_bg_pos.x,
+ widgets_bg_pos.y,
+ widgets_bg_pos.x + widgets_bg_size.x,
+ widgets_bg_pos.y + widgets_bg_size.y);
+ draw_rectf32(offscreen, widgets_bg_rect, v3f32(0.8, 0.6, 0.4));
+
+
+
+ // draw widgets
+
+ Font *font = &s_fscord->font;
+
+ f32 text_height = font_get_height(font);
+ f32 text_width = text_height * 16;
+ V2F32 widgets_size = v2f32(text_width, text_height*8);
+ V2F32 widgets_gap = v2f32((widgets_bg_size.x - widgets_size.x) / 2,
+ (widgets_bg_size.y - widgets_size.y) / 2);
+ V2F32 widgets_pos = v2f32(widgets_bg_pos.x + widgets_gap.x,
+ widgets_bg_pos.y + widgets_gap.y);
+
+
+ String32 *servername = string32_buffer_to_string32(frame_arena, login->servername);
+ String32 *username = string32_buffer_to_string32(frame_arena, login->username);
+
+
+ V2F32 curr_pos = widgets_pos;
+ f32 cursor_y; // Todo: draw UiInputText or something or draw_string32_buffer straight
+
+ draw_string32(offscreen, curr_pos, string32_value(login->warning), font);
+ curr_pos.y += text_height * 3;
+
+ draw_string32(offscreen, curr_pos, username, font);
+ if (login->is_username_active) {
+ cursor_y = curr_pos.y;
+ }
+ curr_pos.y += text_height * 1.4;
+
+ draw_string32(offscreen, curr_pos, string32_value(SH_LOGIN_USERNAME_HINT), font);
+ curr_pos.y += text_height * 2.4;
+
+ draw_string32(offscreen, curr_pos, servername, font);
+ if (!login->is_username_active) {
+ cursor_y = curr_pos.y;
+ }
+ curr_pos.y += text_height * 1.4;
+
+ draw_string32(offscreen, curr_pos, string32_value(SH_LOGIN_SERVERNAME_HINT), font);
+
+
+ V2F32 start_pos = {curr_pos.x, cursor_y};
+ if (login->is_username_active) {
+ draw_cursor(offscreen, start_pos, font, username, login->username->cursor);
+ }
+ else {
+ draw_cursor(offscreen, start_pos, font, servername, login->servername->cursor);
+ }
+}
+
+
+internal_fn b32
+parse_servername(String32Buffer *servername, char *address, size_t address_size, u16 *port)
+{
+ u32 *l = servername->codepoints;
+ u32 *r = servername->codepoints;
+ u32 *end = servername->codepoints + servername->len - 1;
+
+
+ // address
+
+ while (r <= end && *r != ':') {
+ r++;
+ }
+
+ size_t address_len = r - l;
+ if (address_len > 0 && address_len < address_size) {
+ for (size_t i = 0; i < address_len; i++) {
+ address[i] = l[i];
+ }
+ address[address_len] = '\0';
+ } else {
+ return false;
+ }
+
+
+ // port
+
+ l = r + 1;
+ r = end;
+ if (l > r) {
+ return false;
+ }
+
+ size_t port_len = r - l + 1;
+ char port_cstr[6];
+ if (port_len >= 6) {
+ return false;
+ }
+ for (size_t i = 0; i < port_len; i++) {
+ port_cstr[i] = l[i];
+ }
+ port_cstr[port_len] = '\0';
+
+ *port = atoi(port_cstr);
+ if (*port == 0) {
+ return false;
+ }
+
+
+ return true;
+}
+
+internal_fn void
+login_process_special_key_press(Login *login, OSEventKeyPress key_press)
+{
+ String32Buffer *buffer;
+ if (login->is_username_active) {
+ buffer = login->username;
+ } else {
+ buffer = login->servername;
+ }
+
+ switch (key_press.code) {
+ case OS_KEYCODE_LEFT: {
+ string32_buffer_move_cursor_left(buffer);
+ } break;
+
+ case OS_KEYCODE_RIGHT: {
+ string32_buffer_move_cursor_right(buffer);
+ } break;
+
+ default:;
+ }
+}
+
+void
+login_process_login_result(Login *login, u32 result)
+{
+ assert(login->is_trying_to_login);
+
+ if (result == S2C_LOGIN_SUCCESS) {
+ s_fscord->is_logged_in = true;
+ }
+ else {
+ login->warning = SH_LOGIN_WARNING_COULD_NOT_CONNECT; // Todo: "could not login"
+ }
+
+ login->is_trying_to_login = false;
+ login->is_c2s_login_sent = false;
+}
+
+void
+login_update_login_attempt(Login *login)
+{
+ Arena *frame_arena = &s_fscord->frame_arena;
+ ServerConnectionStatus status = server_connection_get_status();
+ if (status == SERVER_CONNECTION_NOT_ESTABLISHED) {
+ login->is_trying_to_login = false;
+ login->is_c2s_login_sent = false;
+ login->warning = SH_LOGIN_WARNING_COULD_NOT_CONNECT;
+ return;
+ }
+ else if (status == SERVER_CONNECTION_ESTABLISHING) {
+ return;
+ }
+ else if (status == SERVER_CONNECTION_ESTABLISHED) {
+ if (!login->is_c2s_login_sent) {
+ String32 *username = string32_buffer_to_string32(frame_arena, login->username);
+ send_c2s_login(username, string32_value(SH_EMPTY));
+ login->is_c2s_login_sent = true;
+ }
+ return;
+ }
+ else {
+ InvalidCodePath;
+ }
+}
+
+internal_fn void
+login_process_unicode_key_press(Login *login, OSEventKeyPress key_press)
+{
+ Arena *frame_arena = &s_fscord->frame_arena;
+ switch (key_press.code) {
+ case '\t': {
+ login->is_username_active = !login->is_username_active;
+ } break;
+
+ case '\r': {
+ ServerConnectionStatus status = server_connection_get_status();
+ if (status == SERVER_CONNECTION_ESTABLISHED) {
+ return;
+ } else if (status == SERVER_CONNECTION_ESTABLISHING) {
+ return;
+ }
+
+ assert(status == SERVER_CONNECTION_NOT_ESTABLISHED);
+
+ if (login->username->len == 0) {
+ login->warning = SH_LOGIN_WARNING_USERNAME_INVALID;
+ break;
+ }
+
+ char address[64];
+ u16 port;
+ if (!parse_servername(login->servername, address, ARRAY_COUNT(address), &port)) {
+ login->warning = SH_LOGIN_WARNING_SERVERNAME_INVALID;
+ break;
+ }
+
+ persist_var EVP_PKEY *server_rsa_pub = 0;
+ if (!server_rsa_pub) {
+ server_rsa_pub = rsa_create_via_file(frame_arena, "./server_rsa_pub.pem", true);
+ if (!server_rsa_pub) {
+ break;
+ }
+ }
+
+ server_connection_establish(address, port, server_rsa_pub);
+
+ login->is_trying_to_login = true;
+ login->warning = SH_LOGIN_WARNING_CONNECTING;
+ } break;
+
+ default: {
+ String32Buffer *buffer;
+ if (login->is_username_active) {
+ buffer = login->username;
+ } else {
+ buffer = login->servername;
+ }
+ printf("received key_press: %c\n", key_press.code);
+ string32_buffer_edit(buffer, key_press);
+ }
+ }
+}
+
+internal_fn void
+login_process_key_press(Login *login, OSEventKeyPress key_press)
+{
+ login->warning = SH_EMPTY;
+
+ if (key_press.is_unicode) {
+ login_process_unicode_key_press(login, key_press);
+ } else {
+ login_process_special_key_press(login, key_press);
+ }
+}
+
+void
+login_process_event(Login *login, OSEvent *event)
+{
+ if (login->is_trying_to_login) {
+ return;
+ }
+
+ if (event->type == OS_EVENT_KEY_PRESS) {
+ login_process_key_press(login, event->ev.key_press);
+ }
+}
+
+Login *
+login_create(Arena *arena, Fscord *fscord)
+{
+ s_fscord = fscord;
+
+ Login *login = arena_push(arena, sizeof(Login));
+ login->is_username_active = false;
+ login->is_trying_to_login = false;
+ login->is_c2s_login_sent = false;
+ login->username = string32_buffer_create(arena, 32);
+ login->servername = string32_buffer_create(arena, 32);
+ login->warning = SH_EMPTY;
+
+ #if !defined(NDEBUG)
+ string32_buffer_append_ascii_cstr(login->username, "user_a");
+ login->username->cursor = login->username->len;
+ string32_buffer_append_ascii_cstr(login->servername, "127.0.0.1:1905");
+ login->servername->cursor = login->servername->len;
+ #endif
+
+ return login;
+}
+