diff options
Diffstat (limited to 'src/client/login.c')
| -rw-r--r-- | src/client/login.c | 320 | 
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; +} +  | 
