kpmpgsmkii/client/src/login.c

274 lines
6.3 KiB
C

/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#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.
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
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
}