/* * Kangaroo Punch MultiPlayer Game Server Mark II * Copyright (C) 2020-2021 Scott Duensing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "textbox.h" #include "button.h" #include "msgbox.h" #include "timer.h" #include "runtime.h" #include "config.h" #include "comport.h" #include "network.h" #include "taglist.h" #include "file.h" #include "login.h" #include "signup.h" #include "welcome.h" #include "menu.h" #include "hangup.h" typedef enum LoginStateE { S_START_LOGIN = 0, S_WAIT_LOGIN } LoginStateT; static WindowT *_winLogin = NULL; static TextboxT *_txtUser = NULL; static TextboxT *_txtPass = NULL; static ButtonT *_btnCancel = NULL; static ButtonT *_btnSignUp = NULL; static ButtonT *_btnLogin = NULL; static TimerT *_timProgress = NULL; static LoginStateT _state = S_START_LOGIN; static uint8_t _channel = 0; static void btnCancelClick(WidgetT *widget); static void btnLoginClick(WidgetT *widget); static void btnSignUpClick(WidgetT *widget); static void btnMsgBoxCancel(MsgBoxButtonT button); static void btnMsgBoxContinue(MsgBoxButtonT button); static void loginFilesReady(char *updatedFile); static void packetHandler(PacketDecodeDataT *packet); static void setButtons(uint8_t enabled); static void timLoginProgress(WidgetT *widget); static void btnCancelClick(WidgetT *widget) { (void)widget; setButtons(0); msgBoxTwo("Cancel?", MSGBOX_ICON_QUESTION, "Cancel login?\n \nThis will disconnect you from the server.", "Okay", btnMsgBoxCancel, "Cancel", btnMsgBoxCancel); } static void btnLoginClick(WidgetT *widget) { (void)widget; setButtons(0); _state = S_START_LOGIN; timerQuarterSecondsSet(_timProgress, 0); timerStart(_timProgress); } static void btnSignUpClick(WidgetT *widget) { (void)widget; netChannelRelease(_channel); guiDelete(D(_winLogin)); signupShow(); } static void btnMsgBoxCancel(MsgBoxButtonT button) { if (button == MSGBOX_BUTTON_ONE) { netChannelRelease(_channel); guiDelete(D(_winLogin)); hangupShow(welcomeShow); } else { setButtons(1); } } static void btnMsgBoxContinue(MsgBoxButtonT button) { (void)button; setButtons(1); } static void loginFilesReady(char *updatedFile) { BEGIN // Is this an updated file or the end of the transfer list? if (updatedFile) { // client.dat was updated - read it into DB. runtimeDataUpdate(); } else { // End of cache update. Display UI. guiMouseBusyPop(); runtimeDataLoad(); // ***TODO*** We used to have a FORGOT PASSWORD link here, too. TagItemT uiLogin[] = { T_START, T_WINDOW, O(_winLogin), T_TITLE, P("Login"), T_WIDTH, 300, T_HEIGHT, 155, T_TEXTBOX, O(_txtUser), T_TITLE, P("User Name:"), T_X, 42, T_Y, 10, T_WIDTH, 200, T_LENGTH, RUNTIME_INT("maxUser"), T_TEXTBOX, T_DONE, T_TEXTBOX, O(_txtPass), T_TITLE, P(" Password:"), T_X, 42, T_Y, 40, T_WIDTH, 200, T_LENGTH, RUNTIME_INT("maxPass"), T_MASK, '*', T_TEXTBOX, T_DONE, T_BUTTON, O(_btnCancel), T_TITLE, P("Cancel"), T_X, 25, T_Y, 85, T_CLICK, P(btnCancelClick), T_BUTTON, T_DONE, T_BUTTON, O(_btnSignUp), T_TITLE, P("Sign Up"), T_X, 110, T_Y, 85, T_CLICK, P(btnSignUpClick), T_BUTTON, T_DONE, T_BUTTON, O(_btnLogin), T_TITLE, P("Login"), T_X, 199, T_Y, 85, T_CLICK, P(btnLoginClick), T_BUTTON, T_DONE, T_TIMER, O(_timProgress), T_EVENT, P(timLoginProgress), T_VALUE, 0, T_ENABLED, 0, T_TIMER, T_DONE, T_WINDOW, T_DONE, T_END }; tagListRun(uiLogin); _channel = netChannelGet(packetHandler); textboxValueSet(_txtUser, "test"); textboxValueSet(_txtPass, "test"); } END } void loginShow() { char *fileList[] = { "generated:client.dat", NULL }; BEGIN guiMouseBusyPush(); fileCacheCheck(loginFilesReady, fileList); END } static void packetHandler(PacketDecodeDataT *packet) { char *packetData; int32_t success; BEGIN switch (packet->packetType) { case PACKET_TYPE_LOGIN_RESULT: packetContentUnpack(packet->data, "is", &success, &packetData); if (success) { netChannelRelease(_channel); guiDelete(D(_winLogin)); menuShow(); } else { msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, packetData, "Okay", btnMsgBoxContinue); } DEL(packetData); timerStop(_timProgress); break; default: timerStop(_timProgress); msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "Unexpected packet received.", "Okay", btnMsgBoxContinue); break; } packetDecodeDataDestroy(&packet); END } static void setButtons(uint8_t enabled) { // ***TODO*** This should disable the entire dialog instead of just the buttons. Need to finish the Enable GUI code first. widgetEnableSet(W(_btnCancel), enabled); widgetEnableSet(W(_btnSignUp), enabled); widgetEnableSet(W(_btnLogin), enabled); } static void timLoginProgress(WidgetT *widget) { uint8_t *packetData; uint16_t length; PacketEncodeDataT encoded; TimerT *t = (TimerT *)widget; BEGIN switch (_state) { case S_START_LOGIN: setButtons(0); packetData = packetContentPack(&length, "ss", textboxValueGet(_txtUser), textboxValueGet(_txtPass)); // Send login request. encoded.packetType = PACKET_TYPE_LOGIN; encoded.control = PACKET_CONTROL_DAT; encoded.channel = _channel; encoded.encrypt = 1; packetEncode(__packetThreadData, &encoded, packetData, length); packetSend(__packetThreadData, &encoded); DEL(packetData); // Wait for response. timerQuarterSecondsSet(t, 10 * 4); _state = S_WAIT_LOGIN; break; case S_WAIT_LOGIN: timerStop(t); msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "No response received.", "Okay", btnMsgBoxContinue); break; } END }