From 2050c0e0576f05156f192aa4caf48834d2f28b14 Mon Sep 17 00:00:00 2001 From: fschildt Date: Fri, 22 Aug 2025 15:23:11 +0200 Subject: first commit --- src/client/login.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 src/client/login.c (limited to 'src/client/login.c') 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +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; +} + -- cgit v1.2.3