mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Show explanation message for http related errors (like server connecting timeout, SSL error), make showing http error messages more consistent in launcher
This commit is contained in:
parent
d78b31a941
commit
3819e93dad
@ -401,9 +401,6 @@
|
|||||||
<ClCompile Include="Widgets.c">
|
<ClCompile Include="Widgets.c">
|
||||||
<Filter>Source Files\2D</Filter>
|
<Filter>Source Files\2D</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Input.c">
|
|
||||||
<Filter>Source Files\Platform</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Utils.c">
|
<ClCompile Include="Utils.c">
|
||||||
<Filter>Source Files\Utils</Filter>
|
<Filter>Source Files\Utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -548,5 +545,8 @@
|
|||||||
<ClCompile Include="Protocol.c">
|
<ClCompile Include="Protocol.c">
|
||||||
<Filter>Source Files\Network</Filter>
|
<Filter>Source Files\Network</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Input.c">
|
||||||
|
<Filter>Source Files\Game</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
25
src/Http.c
25
src/Http.c
@ -15,6 +15,12 @@
|
|||||||
#define _UNICODE
|
#define _UNICODE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define Platform_DecodeString(dst, src, len) String_AppendUtf16(dst, (Codepoint*)(src), (len) * 2)
|
||||||
|
#else
|
||||||
|
#define Platform_DecodeString(dst, src, len) String_DecodeCP1252(dst, (uint8_t*)(src), len)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <wininet.h>
|
#include <wininet.h>
|
||||||
#elif defined CC_BUILD_WEB
|
#elif defined CC_BUILD_WEB
|
||||||
@ -252,6 +258,7 @@ static void Http_ParseHeader(struct HttpRequest* req, const String* line) {
|
|||||||
static void Http_SysInit(void) { }
|
static void Http_SysInit(void) { }
|
||||||
static void Http_SysFree(void) { }
|
static void Http_SysFree(void) { }
|
||||||
static void Http_DownloadAsync(struct HttpRequest* req);
|
static void Http_DownloadAsync(struct HttpRequest* req);
|
||||||
|
bool Http_DescribeError(ReturnCode res, String* dst) { return false; }
|
||||||
|
|
||||||
static void Http_DownloadNextAsync(void) {
|
static void Http_DownloadNextAsync(void) {
|
||||||
struct HttpRequest req;
|
struct HttpRequest req;
|
||||||
@ -400,6 +407,16 @@ static ReturnCode HttpCache_Lookup(struct HttpCacheEntry* e) {
|
|||||||
return HttpCache_Insert(i, e);
|
return HttpCache_Insert(i, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Http_DescribeError(ReturnCode res, String* dst) {
|
||||||
|
TCHAR chars[600];
|
||||||
|
res = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
GetModuleHandle(TEXT("wininet.dll")), res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), chars, 600, NULL);
|
||||||
|
if (!res) return false;
|
||||||
|
|
||||||
|
Platform_DecodeString(dst, chars, res);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void Http_SysInit(void) {
|
static void Http_SysInit(void) {
|
||||||
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
|
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
|
||||||
hInternet = InternetOpenA(GAME_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
hInternet = InternetOpenA(GAME_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||||
@ -548,6 +565,14 @@ static void Http_SysFree(void) {
|
|||||||
#elif defined CC_BUILD_CURL
|
#elif defined CC_BUILD_CURL
|
||||||
static CURL* curl;
|
static CURL* curl;
|
||||||
|
|
||||||
|
bool Http_DescribeError(ReturnCode res, String* dst) {
|
||||||
|
const char* err = curl_easy_strerror(res);
|
||||||
|
if (!err) return false;
|
||||||
|
|
||||||
|
String_AppendConst(dst, err);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void Http_SysInit(void) {
|
static void Http_SysInit(void) {
|
||||||
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);
|
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
if (res) Logger_Abort2(res, "Failed to init curl");
|
if (res) Logger_Abort2(res, "Failed to init curl");
|
||||||
|
@ -62,6 +62,8 @@ void Http_UrlEncodeUtf8(String* dst, const String* src);
|
|||||||
/* Formats a date for inclusion in HTTP headers. */
|
/* Formats a date for inclusion in HTTP headers. */
|
||||||
/* NOTE: Time is always assumed as being UTC. */
|
/* NOTE: Time is always assumed as being UTC. */
|
||||||
void Http_FormatDate(TimeMS ms, String* str);
|
void Http_FormatDate(TimeMS ms, String* str);
|
||||||
|
/* Outputs more detailed information about errors with http requests. */
|
||||||
|
bool Http_DescribeError(ReturnCode res, String* dst);
|
||||||
|
|
||||||
/* Attempts to retrieve a fully completed request. */
|
/* Attempts to retrieve a fully completed request. */
|
||||||
/* NOTE: You MUST also check Result/StatusCode, and check Size is > 0. */
|
/* NOTE: You MUST also check Result/StatusCode, and check Size is > 0. */
|
||||||
|
@ -692,17 +692,12 @@ CC_NOINLINE static void MainScreen_GetResume(struct ResumeInfo* info, bool full)
|
|||||||
CC_NOINLINE static void MainScreen_Error(struct LWebTask* task, const char* action) {
|
CC_NOINLINE static void MainScreen_Error(struct LWebTask* task, const char* action) {
|
||||||
String str; char strBuffer[STRING_SIZE];
|
String str; char strBuffer[STRING_SIZE];
|
||||||
struct MainScreen* s = &MainScreen_Instance;
|
struct MainScreen* s = &MainScreen_Instance;
|
||||||
|
|
||||||
String_InitArray(str, strBuffer);
|
String_InitArray(str, strBuffer);
|
||||||
s->SigningIn = false;
|
|
||||||
|
|
||||||
if (task->Status) {
|
LWebTask_DisplayError(task, action, &str);
|
||||||
String_Format1(&str, "&cclassicube.net returned: %i error", &task->Status);
|
|
||||||
} else {
|
|
||||||
String_Format1(&str, "&cError %i when connecting to classicube.net", &task->Res);
|
|
||||||
}
|
|
||||||
LLabel_SetText(&s->LblStatus, &str);
|
LLabel_SetText(&s->LblStatus, &str);
|
||||||
LWidget_Redraw(&s->LblStatus);
|
LWidget_Redraw(&s->LblStatus);
|
||||||
|
s->SigningIn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MainScreen_Login(void* w, int x, int y) {
|
static void MainScreen_Login(void* w, int x, int y) {
|
||||||
@ -886,7 +881,7 @@ static void MainScreen_TickGetToken(struct MainScreen* s) {
|
|||||||
if (GetTokenTask.Base.Success) {
|
if (GetTokenTask.Base.Success) {
|
||||||
SignInTask_Run(&s->IptUsername.Text, &s->IptPassword.Text);
|
SignInTask_Run(&s->IptUsername.Text, &s->IptPassword.Text);
|
||||||
} else {
|
} else {
|
||||||
MainScreen_Error(&GetTokenTask.Base, "sign in");
|
MainScreen_Error(&GetTokenTask.Base, "signing in");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,7 +905,7 @@ static void MainScreen_TickSignIn(struct MainScreen* s) {
|
|||||||
LLabel_SetText(&s->LblStatus, &fetchMsg);
|
LLabel_SetText(&s->LblStatus, &fetchMsg);
|
||||||
LWidget_Redraw(&s->LblStatus);
|
LWidget_Redraw(&s->LblStatus);
|
||||||
} else {
|
} else {
|
||||||
MainScreen_Error(&SignInTask.Base, "sign in");
|
MainScreen_Error(&SignInTask.Base, "signing in");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,7 +1159,7 @@ static void ServersScreen_Connect(void* w, int x, int y) {
|
|||||||
String* hash = &ServersScreen_Instance.IptHash.Text;
|
String* hash = &ServersScreen_Instance.IptHash.Text;
|
||||||
|
|
||||||
if (!hash->length && table->RowsCount) {
|
if (!hash->length && table->RowsCount) {
|
||||||
hash = <able_Get(table->TopRow)->Hash;
|
hash = <able_Get(table->TopRow)->hash;
|
||||||
}
|
}
|
||||||
Launcher_ConnectToServer(hash);
|
Launcher_ConnectToServer(hash);
|
||||||
}
|
}
|
||||||
@ -1217,7 +1212,7 @@ static void ServersScreen_ReloadServers(struct ServersScreen* s) {
|
|||||||
LTable_Sort(&s->Table);
|
LTable_Sort(&s->Table);
|
||||||
|
|
||||||
for (i = 0; i < FetchServersTask.NumServers; i++) {
|
for (i = 0; i < FetchServersTask.NumServers; i++) {
|
||||||
FetchFlagsTask_Add(&FetchServersTask.Servers[i].Country);
|
FetchFlagsTask_Add(&FetchServersTask.Servers[i].country);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1521,14 +1516,17 @@ static void UpdatesScreen_UpdateProgress(struct UpdatesScreen* s, struct LWebTas
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void UpdatesScreen_FetchTick(struct UpdatesScreen* s) {
|
static void UpdatesScreen_FetchTick(struct UpdatesScreen* s) {
|
||||||
static const String failedMsg = String_FromConst("&cFailed to fetch update");
|
String str; char strBuffer[STRING_SIZE];
|
||||||
if (!FetchUpdateTask.Base.Working) return;
|
if (!FetchUpdateTask.Base.Working) return;
|
||||||
|
|
||||||
LWebTask_Tick(&FetchUpdateTask.Base);
|
LWebTask_Tick(&FetchUpdateTask.Base);
|
||||||
UpdatesScreen_UpdateProgress(s, &FetchUpdateTask.Base);
|
UpdatesScreen_UpdateProgress(s, &FetchUpdateTask.Base);
|
||||||
if (!FetchUpdateTask.Base.Completed) return;
|
if (!FetchUpdateTask.Base.Completed) return;
|
||||||
|
|
||||||
if (!FetchUpdateTask.Base.Success) {
|
if (!FetchUpdateTask.Base.Success) {
|
||||||
LLabel_SetText(&s->LblStatus, &failedMsg);
|
String_InitArray(str, strBuffer);
|
||||||
|
LWebTask_DisplayError(&FetchUpdateTask.Base, "fetching update", &str);
|
||||||
|
LLabel_SetText(&s->LblStatus, &str);
|
||||||
LWidget_Redraw(&s->LblStatus);
|
LWidget_Redraw(&s->LblStatus);
|
||||||
} else {
|
} else {
|
||||||
/* WebTask handles saving of ClassiCube.update for us */
|
/* WebTask handles saving of ClassiCube.update for us */
|
||||||
|
148
src/LWeb.c
148
src/LWeb.c
@ -14,7 +14,7 @@
|
|||||||
#define TOKEN_FALSE 3
|
#define TOKEN_FALSE 3
|
||||||
#define TOKEN_NULL 4
|
#define TOKEN_NULL 4
|
||||||
/* Consumes n characters from the JSON stream */
|
/* Consumes n characters from the JSON stream */
|
||||||
#define JsonContext_Consume(ctx, n) ctx->Cur += n; ctx->Left -= n;
|
#define JsonContext_Consume(ctx, n) ctx->cur += n; ctx->left -= n;
|
||||||
|
|
||||||
static const String strTrue = String_FromConst("true");
|
static const String strTrue = String_FromConst("true");
|
||||||
static const String strFalse = String_FromConst("false");
|
static const String strFalse = String_FromConst("false");
|
||||||
@ -30,10 +30,10 @@ static bool Json_IsNumber(char c) {
|
|||||||
|
|
||||||
static bool Json_ConsumeConstant(struct JsonContext* ctx, const String* value) {
|
static bool Json_ConsumeConstant(struct JsonContext* ctx, const String* value) {
|
||||||
int i;
|
int i;
|
||||||
if (value->length > ctx->Left) return false;
|
if (value->length > ctx->left) return false;
|
||||||
|
|
||||||
for (i = 0; i < value->length; i++) {
|
for (i = 0; i < value->length; i++) {
|
||||||
if (ctx->Cur[i] != value->buffer[i]) return false;
|
if (ctx->cur[i] != value->buffer[i]) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonContext_Consume(ctx, value->length);
|
JsonContext_Consume(ctx, value->length);
|
||||||
@ -42,10 +42,10 @@ static bool Json_ConsumeConstant(struct JsonContext* ctx, const String* value) {
|
|||||||
|
|
||||||
static int Json_ConsumeToken(struct JsonContext* ctx) {
|
static int Json_ConsumeToken(struct JsonContext* ctx) {
|
||||||
char c;
|
char c;
|
||||||
for (; ctx->Left && Json_IsWhitespace(*ctx->Cur); ) { JsonContext_Consume(ctx, 1); }
|
for (; ctx->left && Json_IsWhitespace(*ctx->cur); ) { JsonContext_Consume(ctx, 1); }
|
||||||
if (!ctx->Left) return TOKEN_NONE;
|
if (!ctx->left) return TOKEN_NONE;
|
||||||
|
|
||||||
c = *ctx->Cur;
|
c = *ctx->cur;
|
||||||
if (c == '{' || c == '}' || c == '[' || c == ']' || c == ',' || c == '"' || c == ':') {
|
if (c == '{' || c == '}' || c == '[' || c == ']' || c == ',' || c == '"' || c == ':') {
|
||||||
JsonContext_Consume(ctx, 1); return c;
|
JsonContext_Consume(ctx, 1); return c;
|
||||||
}
|
}
|
||||||
@ -64,8 +64,8 @@ static int Json_ConsumeToken(struct JsonContext* ctx) {
|
|||||||
|
|
||||||
static String Json_ConsumeNumber(struct JsonContext* ctx) {
|
static String Json_ConsumeNumber(struct JsonContext* ctx) {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
for (; ctx->Left && Json_IsNumber(*ctx->Cur); len++) { JsonContext_Consume(ctx, 1); }
|
for (; ctx->left && Json_IsNumber(*ctx->cur); len++) { JsonContext_Consume(ctx, 1); }
|
||||||
return String_Init(ctx->Cur - len, len, len);
|
return String_Init(ctx->cur - len, len, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Json_ConsumeString(struct JsonContext* ctx, String* str) {
|
static void Json_ConsumeString(struct JsonContext* ctx, String* str) {
|
||||||
@ -73,23 +73,23 @@ static void Json_ConsumeString(struct JsonContext* ctx, String* str) {
|
|||||||
char c;
|
char c;
|
||||||
str->length = 0;
|
str->length = 0;
|
||||||
|
|
||||||
for (; ctx->Left;) {
|
for (; ctx->left;) {
|
||||||
c = *ctx->Cur; JsonContext_Consume(ctx, 1);
|
c = *ctx->cur; JsonContext_Consume(ctx, 1);
|
||||||
if (c == '"') return;
|
if (c == '"') return;
|
||||||
if (c != '\\') { String_Append(str, c); continue; }
|
if (c != '\\') { String_Append(str, c); continue; }
|
||||||
|
|
||||||
/* form of \X */
|
/* form of \X */
|
||||||
if (!ctx->Left) break;
|
if (!ctx->left) break;
|
||||||
c = *ctx->Cur; JsonContext_Consume(ctx, 1);
|
c = *ctx->cur; JsonContext_Consume(ctx, 1);
|
||||||
if (c == '/' || c == '\\' || c == '"') { String_Append(str, c); continue; }
|
if (c == '/' || c == '\\' || c == '"') { String_Append(str, c); continue; }
|
||||||
|
|
||||||
/* form of \uYYYY */
|
/* form of \uYYYY */
|
||||||
if (c != 'u' || ctx->Left < 4) break;
|
if (c != 'u' || ctx->left < 4) break;
|
||||||
|
|
||||||
if (!PackedCol_Unhex(ctx->Cur[0], &h[0])) break;
|
if (!PackedCol_Unhex(ctx->cur[0], &h[0])) break;
|
||||||
if (!PackedCol_Unhex(ctx->Cur[1], &h[1])) break;
|
if (!PackedCol_Unhex(ctx->cur[1], &h[1])) break;
|
||||||
if (!PackedCol_Unhex(ctx->Cur[2], &h[2])) break;
|
if (!PackedCol_Unhex(ctx->cur[2], &h[2])) break;
|
||||||
if (!PackedCol_Unhex(ctx->Cur[3], &h[3])) break;
|
if (!PackedCol_Unhex(ctx->cur[3], &h[3])) break;
|
||||||
|
|
||||||
codepoint = (h[0] << 12) | (h[1] << 8) | (h[2] << 4) | h[3];
|
codepoint = (h[0] << 12) | (h[1] << 8) | (h[2] << 4) | h[3];
|
||||||
/* don't want control characters in names/software */
|
/* don't want control characters in names/software */
|
||||||
@ -98,13 +98,13 @@ static void Json_ConsumeString(struct JsonContext* ctx, String* str) {
|
|||||||
JsonContext_Consume(ctx, 4);
|
JsonContext_Consume(ctx, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->Failed = true; str->length = 0;
|
ctx->failed = true; str->length = 0;
|
||||||
}
|
}
|
||||||
static String Json_ConsumeValue(int token, struct JsonContext* ctx);
|
static String Json_ConsumeValue(int token, struct JsonContext* ctx);
|
||||||
|
|
||||||
static void Json_ConsumeObject(struct JsonContext* ctx) {
|
static void Json_ConsumeObject(struct JsonContext* ctx) {
|
||||||
char keyBuffer[STRING_SIZE];
|
char keyBuffer[STRING_SIZE];
|
||||||
String value, oldKey = ctx->CurKey;
|
String value, oldKey = ctx->curKey;
|
||||||
int token;
|
int token;
|
||||||
ctx->OnNewObject(ctx);
|
ctx->OnNewObject(ctx);
|
||||||
|
|
||||||
@ -113,19 +113,19 @@ static void Json_ConsumeObject(struct JsonContext* ctx) {
|
|||||||
if (token == ',') continue;
|
if (token == ',') continue;
|
||||||
if (token == '}') return;
|
if (token == '}') return;
|
||||||
|
|
||||||
if (token != '"') { ctx->Failed = true; return; }
|
if (token != '"') { ctx->failed = true; return; }
|
||||||
String_InitArray(ctx->CurKey, keyBuffer);
|
String_InitArray(ctx->curKey, keyBuffer);
|
||||||
Json_ConsumeString(ctx, &ctx->CurKey);
|
Json_ConsumeString(ctx, &ctx->curKey);
|
||||||
|
|
||||||
token = Json_ConsumeToken(ctx);
|
token = Json_ConsumeToken(ctx);
|
||||||
if (token != ':') { ctx->Failed = true; return; }
|
if (token != ':') { ctx->failed = true; return; }
|
||||||
|
|
||||||
token = Json_ConsumeToken(ctx);
|
token = Json_ConsumeToken(ctx);
|
||||||
if (token == TOKEN_NONE) { ctx->Failed = true; return; }
|
if (token == TOKEN_NONE) { ctx->failed = true; return; }
|
||||||
|
|
||||||
value = Json_ConsumeValue(token, ctx);
|
value = Json_ConsumeValue(token, ctx);
|
||||||
ctx->OnValue(ctx, &value);
|
ctx->OnValue(ctx, &value);
|
||||||
ctx->CurKey = oldKey;
|
ctx->curKey = oldKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ static void Json_ConsumeArray(struct JsonContext* ctx) {
|
|||||||
if (token == ',') continue;
|
if (token == ',') continue;
|
||||||
if (token == ']') return;
|
if (token == ']') return;
|
||||||
|
|
||||||
if (token == TOKEN_NONE) { ctx->Failed = true; return; }
|
if (token == TOKEN_NONE) { ctx->failed = true; return; }
|
||||||
value = Json_ConsumeValue(token, ctx);
|
value = Json_ConsumeValue(token, ctx);
|
||||||
ctx->OnValue(ctx, &value);
|
ctx->OnValue(ctx, &value);
|
||||||
}
|
}
|
||||||
@ -162,10 +162,10 @@ static String Json_ConsumeValue(int token, struct JsonContext* ctx) {
|
|||||||
static void Json_NullOnNew(struct JsonContext* ctx) { }
|
static void Json_NullOnNew(struct JsonContext* ctx) { }
|
||||||
static void Json_NullOnValue(struct JsonContext* ctx, const String* v) { }
|
static void Json_NullOnValue(struct JsonContext* ctx, const String* v) { }
|
||||||
void Json_Init(struct JsonContext* ctx, String* str) {
|
void Json_Init(struct JsonContext* ctx, String* str) {
|
||||||
ctx->Cur = str->buffer;
|
ctx->cur = str->buffer;
|
||||||
ctx->Left = str->length;
|
ctx->left = str->length;
|
||||||
ctx->Failed = false;
|
ctx->failed = false;
|
||||||
ctx->CurKey = String_Empty;
|
ctx->curKey = String_Empty;
|
||||||
|
|
||||||
ctx->OnNewArray = Json_NullOnNew;
|
ctx->OnNewArray = Json_NullOnNew;
|
||||||
ctx->OnNewObject = Json_NullOnNew;
|
ctx->OnNewObject = Json_NullOnNew;
|
||||||
@ -226,6 +226,18 @@ void LWebTask_Tick(struct LWebTask* task) {
|
|||||||
HttpRequest_Free(&req);
|
HttpRequest_Free(&req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LWebTask_DisplayError(struct LWebTask* task, const char* action, String* dst) {
|
||||||
|
if (task->Res) {
|
||||||
|
/* Non HTTP error - this is not good */
|
||||||
|
Logger_SysWarn(task->Res, action, Http_DescribeError);
|
||||||
|
String_Format2(dst, "&cError %i when %c", &task->Res, action);
|
||||||
|
} else if (task->Status != 200) {
|
||||||
|
String_Format2(dst, "&c%i error when %c", &task->Status, action);
|
||||||
|
} else {
|
||||||
|
String_Format1(dst, "&cEmpty response when %c", action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-------------------------------------------------------GetTokenTask------------------------------------------------------*
|
*-------------------------------------------------------GetTokenTask------------------------------------------------------*
|
||||||
@ -234,7 +246,7 @@ struct GetTokenTaskData GetTokenTask;
|
|||||||
char tokenBuffer[STRING_SIZE];
|
char tokenBuffer[STRING_SIZE];
|
||||||
|
|
||||||
static void GetTokenTask_OnValue(struct JsonContext* ctx, const String* str) {
|
static void GetTokenTask_OnValue(struct JsonContext* ctx, const String* str) {
|
||||||
if (!String_CaselessEqualsConst(&ctx->CurKey, "token")) return;
|
if (!String_CaselessEqualsConst(&ctx->curKey, "token")) return;
|
||||||
String_Copy(&GetTokenTask.Token, str);
|
String_Copy(&GetTokenTask.Token, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,9 +289,9 @@ static void SignInTask_LogError(const String* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SignInTask_OnValue(struct JsonContext* ctx, const String* str) {
|
static void SignInTask_OnValue(struct JsonContext* ctx, const String* str) {
|
||||||
if (String_CaselessEqualsConst(&ctx->CurKey, "username")) {
|
if (String_CaselessEqualsConst(&ctx->curKey, "username")) {
|
||||||
String_Copy(&SignInTask.Username, str);
|
String_Copy(&SignInTask.Username, str);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "errors")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "errors")) {
|
||||||
SignInTask_LogError(str);
|
SignInTask_LogError(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,46 +333,46 @@ struct FetchServerData FetchServerTask;
|
|||||||
static struct ServerInfo* curServer;
|
static struct ServerInfo* curServer;
|
||||||
|
|
||||||
static void ServerInfo_Init(struct ServerInfo* info) {
|
static void ServerInfo_Init(struct ServerInfo* info) {
|
||||||
String_InitArray(info->Hash, info->_hashBuffer);
|
String_InitArray(info->hash, info->_hashBuffer);
|
||||||
String_InitArray(info->Name, info->_nameBuffer);
|
String_InitArray(info->name, info->_nameBuffer);
|
||||||
String_InitArray(info->IP, info->_ipBuffer);
|
String_InitArray(info->ip, info->_ipBuffer);
|
||||||
|
|
||||||
String_InitArray(info->Mppass, info->_mppassBuffer);
|
String_InitArray(info->mppass, info->_mppassBuffer);
|
||||||
String_InitArray(info->Software, info->_softBuffer);
|
String_InitArray(info->software, info->_softBuffer);
|
||||||
String_InitArray(info->Country, info->_countryBuffer);
|
String_InitArray(info->country, info->_countryBuffer);
|
||||||
|
|
||||||
info->Players = 0;
|
info->players = 0;
|
||||||
info->MaxPlayers = 0;
|
info->maxPlayers = 0;
|
||||||
info->Uptime = 0;
|
info->uptime = 0;
|
||||||
info->Featured = false;
|
info->featured = false;
|
||||||
info->_order = -100000;
|
info->_order = -100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ServerInfo_Parse(struct JsonContext* ctx, const String* val) {
|
static void ServerInfo_Parse(struct JsonContext* ctx, const String* val) {
|
||||||
struct ServerInfo* info = curServer;
|
struct ServerInfo* info = curServer;
|
||||||
if (String_CaselessEqualsConst(&ctx->CurKey, "hash")) {
|
if (String_CaselessEqualsConst(&ctx->curKey, "hash")) {
|
||||||
String_Copy(&info->Hash, val);
|
String_Copy(&info->hash, val);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "name")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "name")) {
|
||||||
String_Copy(&info->Name, val);
|
String_Copy(&info->name, val);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "players")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "players")) {
|
||||||
Convert_ParseInt(val, &info->Players);
|
Convert_ParseInt(val, &info->players);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "maxplayers")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "maxplayers")) {
|
||||||
Convert_ParseInt(val, &info->MaxPlayers);
|
Convert_ParseInt(val, &info->maxPlayers);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "uptime")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "uptime")) {
|
||||||
Convert_ParseInt(val, &info->Uptime);
|
Convert_ParseInt(val, &info->uptime);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "mppass")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "mppass")) {
|
||||||
String_Copy(&info->Mppass, val);
|
String_Copy(&info->mppass, val);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "ip")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "ip")) {
|
||||||
String_Copy(&info->IP, val);
|
String_Copy(&info->ip, val);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "port")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "port")) {
|
||||||
Convert_ParseInt(val, &info->Port);
|
Convert_ParseInt(val, &info->port);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "software")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "software")) {
|
||||||
String_Copy(&info->Software, val);
|
String_Copy(&info->software, val);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "featured")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "featured")) {
|
||||||
Convert_ParseBool(val, &info->Featured);
|
Convert_ParseBool(val, &info->featured);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "country_abbr")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "country_abbr")) {
|
||||||
/* Two letter country codes, see ISO 3166-1 alpha-2 */
|
/* Two letter country codes, see ISO 3166-1 alpha-2 */
|
||||||
String_Copy(&info->Country, val);
|
String_Copy(&info->country, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,11 +472,11 @@ CC_NOINLINE static TimeMS CheckUpdateTask_ParseTime(const String* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void CheckUpdateTask_OnValue(struct JsonContext* ctx, const String* str) {
|
static void CheckUpdateTask_OnValue(struct JsonContext* ctx, const String* str) {
|
||||||
if (String_CaselessEqualsConst(&ctx->CurKey, "release_version")) {
|
if (String_CaselessEqualsConst(&ctx->curKey, "release_version")) {
|
||||||
String_Copy(&CheckUpdateTask.LatestRelease, str);
|
String_Copy(&CheckUpdateTask.LatestRelease, str);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "latest_ts")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "latest_ts")) {
|
||||||
CheckUpdateTask.DevTimestamp = CheckUpdateTask_ParseTime(str);
|
CheckUpdateTask.DevTimestamp = CheckUpdateTask_ParseTime(str);
|
||||||
} else if (String_CaselessEqualsConst(&ctx->CurKey, "release_ts")) {
|
} else if (String_CaselessEqualsConst(&ctx->curKey, "release_ts")) {
|
||||||
CheckUpdateTask.RelTimestamp = CheckUpdateTask_ParseTime(str);
|
CheckUpdateTask.RelTimestamp = CheckUpdateTask_ParseTime(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
src/LWeb.h
15
src/LWeb.h
@ -12,10 +12,10 @@ typedef void (*JsonOnNew)(struct JsonContext* ctx);
|
|||||||
|
|
||||||
/* State for parsing JSON text */
|
/* State for parsing JSON text */
|
||||||
struct JsonContext {
|
struct JsonContext {
|
||||||
char* Cur; /* Pointer to current character in JSON stream being inspected. */
|
char* cur; /* Pointer to current character in JSON stream being inspected. */
|
||||||
int Left; /* Number of characters left to be inspected. */
|
int left; /* Number of characters left to be inspected. */
|
||||||
bool Failed; /* Whether there was an error parsing the JSON. */
|
bool failed; /* Whether there was an error parsing the JSON. */
|
||||||
String CurKey; /* Key/Name of current member */
|
String curKey; /* Key/Name of current member */
|
||||||
|
|
||||||
JsonOnNew OnNewArray; /* Invoked when start of an array is read. */
|
JsonOnNew OnNewArray; /* Invoked when start of an array is read. */
|
||||||
JsonOnNew OnNewObject; /* Invoked when start of an object is read. */
|
JsonOnNew OnNewObject; /* Invoked when start of an object is read. */
|
||||||
@ -31,9 +31,9 @@ void Json_Parse(struct JsonContext* ctx);
|
|||||||
|
|
||||||
/* Represents all known details about a server. */
|
/* Represents all known details about a server. */
|
||||||
struct ServerInfo {
|
struct ServerInfo {
|
||||||
String Hash, Name, IP, Mppass, Software, Country;
|
String hash, name, ip, mppass, software, country;
|
||||||
int Players, MaxPlayers, Port, Uptime;
|
int players, maxPlayers, port, uptime;
|
||||||
bool Featured;
|
bool featured;
|
||||||
int _order; /* (internal) order in servers table after filtering */
|
int _order; /* (internal) order in servers table after filtering */
|
||||||
char _hashBuffer[32], _nameBuffer[STRING_SIZE];
|
char _hashBuffer[32], _nameBuffer[STRING_SIZE];
|
||||||
char _ipBuffer[16], _mppassBuffer[STRING_SIZE];
|
char _ipBuffer[16], _mppassBuffer[STRING_SIZE];
|
||||||
@ -55,6 +55,7 @@ struct LWebTask {
|
|||||||
void (*Handle)(uint8_t* data, uint32_t len);
|
void (*Handle)(uint8_t* data, uint32_t len);
|
||||||
};
|
};
|
||||||
void LWebTask_Tick(struct LWebTask* task);
|
void LWebTask_Tick(struct LWebTask* task);
|
||||||
|
void LWebTask_DisplayError(struct LWebTask* task, const char* action, String* dst);
|
||||||
|
|
||||||
|
|
||||||
extern struct GetTokenTaskData {
|
extern struct GetTokenTaskData {
|
||||||
|
@ -634,26 +634,26 @@ void LSlider_Init(struct LSlider* w, int width, int height) {
|
|||||||
*------------------------------------------------------TableWidget--------------------------------------------------------*
|
*------------------------------------------------------TableWidget--------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
static void FlagColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
static void FlagColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
||||||
Bitmap* bmp = Flags_Get(&row->Country);
|
Bitmap* bmp = Flags_Get(&row->country);
|
||||||
if (bmp) Drawer2D_BmpCopy(&Launcher_Framebuffer, x + 2, y + 6, bmp);
|
if (bmp) Drawer2D_BmpCopy(&Launcher_Framebuffer, x + 2, y + 6, bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NameColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
static void NameColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
||||||
args->text = row->Name;
|
args->text = row->name;
|
||||||
}
|
}
|
||||||
static int NameColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
static int NameColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||||
return String_Compare(&b->Name, &a->Name);
|
return String_Compare(&b->name, &a->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PlayersColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
static void PlayersColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
||||||
String_Format2(&args->text, "%i/%i", &row->Players, &row->MaxPlayers);
|
String_Format2(&args->text, "%i/%i", &row->players, &row->maxPlayers);
|
||||||
}
|
}
|
||||||
static int PlayersColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
static int PlayersColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||||
return b->Players - a->Players;
|
return b->players - a->players;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UptimeColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
static void UptimeColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
||||||
int uptime = row->Uptime;
|
int uptime = row->uptime;
|
||||||
char unit = 's';
|
char unit = 's';
|
||||||
|
|
||||||
if (uptime >= SECS_PER_DAY * 7) {
|
if (uptime >= SECS_PER_DAY * 7) {
|
||||||
@ -666,14 +666,14 @@ static void UptimeColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args,
|
|||||||
String_Format2(&args->text, "%i%r", &uptime, &unit);
|
String_Format2(&args->text, "%i%r", &uptime, &unit);
|
||||||
}
|
}
|
||||||
static int UptimeColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
static int UptimeColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||||
return b->Uptime - a->Uptime;
|
return b->uptime - a->uptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SoftwareColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
static void SoftwareColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, int x, int y) {
|
||||||
args->text = row->Software;
|
args->text = row->software;
|
||||||
}
|
}
|
||||||
static int SoftwareColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
static int SoftwareColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||||
return String_Compare(&b->Software, &a->Software);
|
return String_Compare(&b->software, &a->software);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct LTableColumn tableColumns[5] = {
|
static struct LTableColumn tableColumns[5] = {
|
||||||
@ -712,7 +712,7 @@ static int LTable_GetSelectedIndex(struct LTable* w) {
|
|||||||
|
|
||||||
for (row = 0; row < w->RowsCount; row++) {
|
for (row = 0; row < w->RowsCount; row++) {
|
||||||
entry = LTable_Get(row);
|
entry = LTable_Get(row);
|
||||||
if (String_CaselessEquals(w->SelectedHash, &entry->Hash)) return row;
|
if (String_CaselessEquals(w->SelectedHash, &entry->hash)) return row;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -723,7 +723,7 @@ static void LTable_SetSelectedTo(struct LTable* w, int index) {
|
|||||||
if (index >= w->RowsCount) index = w->RowsCount - 1;
|
if (index >= w->RowsCount) index = w->RowsCount - 1;
|
||||||
if (index < 0) index = 0;
|
if (index < 0) index = 0;
|
||||||
|
|
||||||
String_Copy(w->SelectedHash, <able_Get(index)->Hash);
|
String_Copy(w->SelectedHash, <able_Get(index)->hash);
|
||||||
LTable_ShowSelected(w);
|
LTable_ShowSelected(w);
|
||||||
w->OnSelectedChanged();
|
w->OnSelectedChanged();
|
||||||
}
|
}
|
||||||
@ -759,8 +759,8 @@ static BitmapCol LTable_RowCol(struct LTable* w, struct ServerInfo* row) {
|
|||||||
bool selected;
|
bool selected;
|
||||||
|
|
||||||
if (row) {
|
if (row) {
|
||||||
selected = String_Equals(&row->Hash, w->SelectedHash);
|
selected = String_Equals(&row->hash, w->SelectedHash);
|
||||||
if (row->Featured) {
|
if (row->featured) {
|
||||||
return selected ? featSelCol : featuredCol;
|
return selected ? featSelCol : featuredCol;
|
||||||
} else if (selected) {
|
} else if (selected) {
|
||||||
return selectedCol;
|
return selectedCol;
|
||||||
@ -804,8 +804,8 @@ static void LTable_DrawGridlines(struct LTable* w) {
|
|||||||
x, w->Y + w->HdrHeight, w->Width, GRIDLINE_SIZE);
|
x, w->Y + w->HdrHeight, w->Width, GRIDLINE_SIZE);
|
||||||
|
|
||||||
for (i = 0; i < w->NumColumns; i++) {
|
for (i = 0; i < w->NumColumns; i++) {
|
||||||
x += w->Columns[i].Width;
|
x += w->Columns[i].width;
|
||||||
if (!w->Columns[i].ColumnGridline) continue;
|
if (!w->Columns[i].columnGridline) continue;
|
||||||
|
|
||||||
Drawer2D_Clear(&Launcher_Framebuffer, Launcher_BackgroundCol,
|
Drawer2D_Clear(&Launcher_Framebuffer, Launcher_BackgroundCol,
|
||||||
x, w->Y, GRIDLINE_SIZE, w->Height);
|
x, w->Y, GRIDLINE_SIZE, w->Height);
|
||||||
@ -829,13 +829,13 @@ static void LTable_DrawHeaders(struct LTable* w) {
|
|||||||
x = w->X; y = w->Y;
|
x = w->X; y = w->Y;
|
||||||
|
|
||||||
for (i = 0; i < w->NumColumns; i++) {
|
for (i = 0; i < w->NumColumns; i++) {
|
||||||
args.text = String_FromReadonly(w->Columns[i].Name);
|
args.text = String_FromReadonly(w->Columns[i].name);
|
||||||
Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args,
|
Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args,
|
||||||
x + CELL_XOFFSET, y + HDR_YOFFSET,
|
x + CELL_XOFFSET, y + HDR_YOFFSET,
|
||||||
w->Columns[i].Width - CELL_XPADDING);
|
w->Columns[i].width - CELL_XPADDING);
|
||||||
|
|
||||||
x += w->Columns[i].Width;
|
x += w->Columns[i].width;
|
||||||
if (w->Columns[i].ColumnGridline) x += GRIDLINE_SIZE;
|
if (w->Columns[i].columnGridline) x += GRIDLINE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,11 +865,11 @@ static void LTable_DrawRows(struct LTable* w) {
|
|||||||
if (args.text.length) {
|
if (args.text.length) {
|
||||||
Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args,
|
Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args,
|
||||||
x + CELL_XOFFSET, y + ROW_YOFFSET,
|
x + CELL_XOFFSET, y + ROW_YOFFSET,
|
||||||
w->Columns[i].Width - CELL_XPADDING);
|
w->Columns[i].width - CELL_XPADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
x += w->Columns[i].Width;
|
x += w->Columns[i].width;
|
||||||
if (w->Columns[i].ColumnGridline) x += GRIDLINE_SIZE;
|
if (w->Columns[i].columnGridline) x += GRIDLINE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -930,8 +930,8 @@ static void LTable_MouseMove(void* widget, int deltaX, int deltaY, bool wasOver)
|
|||||||
if (!deltaX || x >= w->X + w->Width - 20) return;
|
if (!deltaX || x >= w->X + w->Width - 20) return;
|
||||||
col = w->DraggingColumn;
|
col = w->DraggingColumn;
|
||||||
|
|
||||||
w->Columns[col].Width += deltaX;
|
w->Columns[col].width += deltaX;
|
||||||
Math_Clamp(w->Columns[col].Width, 20, w->Width - 20);
|
Math_Clamp(w->Columns[col].width, 20, w->Width - 20);
|
||||||
LWidget_Redraw(w);
|
LWidget_Redraw(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -946,7 +946,7 @@ static void LTable_RowsClick(struct LTable* w) {
|
|||||||
|
|
||||||
/* double click on row to join */
|
/* double click on row to join */
|
||||||
if (w->_lastClick + 1000 >= now && row == w->_lastRow) {
|
if (w->_lastClick + 1000 >= now && row == w->_lastRow) {
|
||||||
Launcher_ConnectToServer(<able_Get(row)->Hash);
|
Launcher_ConnectToServer(<able_Get(row)->hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
w->_lastRow = LTable_GetSelectedIndex(w);
|
w->_lastRow = LTable_GetSelectedIndex(w);
|
||||||
@ -959,25 +959,25 @@ static void LTable_HeadersClick(struct LTable* w) {
|
|||||||
|
|
||||||
for (i = 0, x = w->X; i < w->NumColumns; i++) {
|
for (i = 0, x = w->X; i < w->NumColumns; i++) {
|
||||||
/* clicked on gridline, begin dragging */
|
/* clicked on gridline, begin dragging */
|
||||||
if (mouseX >= (x - 8) && mouseX < (x + 8) && w->Columns[i].Interactable) {
|
if (mouseX >= (x - 8) && mouseX < (x + 8) && w->Columns[i].interactable) {
|
||||||
w->DraggingColumn = i - 1;
|
w->DraggingColumn = i - 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x += w->Columns[i].Width;
|
x += w->Columns[i].width;
|
||||||
if (w->Columns[i].ColumnGridline) x += GRIDLINE_SIZE;
|
if (w->Columns[i].columnGridline) x += GRIDLINE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, x = w->X; i < w->NumColumns; i++) {
|
for (i = 0, x = w->X; i < w->NumColumns; i++) {
|
||||||
if (mouseX >= x && mouseX < (x + w->Columns[i].Width) && w->Columns[i].Interactable) {
|
if (mouseX >= x && mouseX < (x + w->Columns[i].width) && w->Columns[i].interactable) {
|
||||||
sortingCol = i;
|
sortingCol = i;
|
||||||
w->Columns[i].InvertSort = !w->Columns[i].InvertSort;
|
w->Columns[i].invertSort = !w->Columns[i].invertSort;
|
||||||
LTable_Sort(w);
|
LTable_Sort(w);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x += w->Columns[i].Width;
|
x += w->Columns[i].width;
|
||||||
if (w->Columns[i].ColumnGridline) x += GRIDLINE_SIZE;
|
if (w->Columns[i].columnGridline) x += GRIDLINE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,7 +1085,7 @@ void LTable_ApplyFilter(struct LTable* w) {
|
|||||||
|
|
||||||
count = FetchServersTask.NumServers;
|
count = FetchServersTask.NumServers;
|
||||||
for (i = 0, j = 0; i < count; i++) {
|
for (i = 0, j = 0; i < count; i++) {
|
||||||
if (String_CaselessContains(&Servers_Get(i)->Name, w->Filter)) {
|
if (String_CaselessContains(&Servers_Get(i)->name, w->Filter)) {
|
||||||
FetchServersTask.Servers[j++]._order = FetchServersTask.Orders[i];
|
FetchServersTask.Servers[j++]._order = FetchServersTask.Orders[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1103,12 +1103,12 @@ static int LTable_SortOrder(const struct ServerInfo* a, const struct ServerInfo*
|
|||||||
int order;
|
int order;
|
||||||
if (sortingCol >= 0) {
|
if (sortingCol >= 0) {
|
||||||
order = tableColumns[sortingCol].SortOrder(a, b);
|
order = tableColumns[sortingCol].SortOrder(a, b);
|
||||||
return tableColumns[sortingCol].InvertSort ? -order : order;
|
return tableColumns[sortingCol].invertSort ? -order : order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default sort order. (most active server, then by highest uptime) */
|
/* Default sort order. (most active server, then by highest uptime) */
|
||||||
if (a->Players != b->Players) return a->Players - b->Players;
|
if (a->players != b->players) return a->players - b->players;
|
||||||
return a->Uptime - b->Uptime;
|
return a->uptime - b->uptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LTable_QuickSort(int left, int right) {
|
static void LTable_QuickSort(int left, int right) {
|
||||||
|
@ -116,9 +116,9 @@ struct DrawTextArgs;
|
|||||||
|
|
||||||
struct LTableColumn {
|
struct LTableColumn {
|
||||||
/* Name of this column. */
|
/* Name of this column. */
|
||||||
const char* Name;
|
const char* name;
|
||||||
/* Width of this column in pixels. */
|
/* Width of this column in pixels. */
|
||||||
int Width;
|
int width;
|
||||||
/* Draws the value of this column for the given row. */
|
/* Draws the value of this column for the given row. */
|
||||||
/* If args.Text is changed to something, that text gets drawn afterwards. */
|
/* If args.Text is changed to something, that text gets drawn afterwards. */
|
||||||
/* Most of the time that's all you need to do. */
|
/* Most of the time that's all you need to do. */
|
||||||
@ -126,12 +126,12 @@ struct LTableColumn {
|
|||||||
/* Returns sort order of two rows, based on value of this column in both rows. */
|
/* Returns sort order of two rows, based on value of this column in both rows. */
|
||||||
int (*SortOrder)(const struct ServerInfo* a, const struct ServerInfo* b);
|
int (*SortOrder)(const struct ServerInfo* a, const struct ServerInfo* b);
|
||||||
/* Whether a vertical gridline (and padding) appears after this. */
|
/* Whether a vertical gridline (and padding) appears after this. */
|
||||||
bool ColumnGridline;
|
bool columnGridline;
|
||||||
/* Whether user can interact with this column. */
|
/* Whether user can interact with this column. */
|
||||||
/* Non-interactable columns can't be sorted/resized. */
|
/* Non-interactable columns can't be sorted/resized. */
|
||||||
bool Interactable;
|
bool interactable;
|
||||||
/* Whether to invert the order of row sorting. */
|
/* Whether to invert the order of row sorting. */
|
||||||
bool InvertSort;
|
bool invertSort;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Represents a table of server entries. */
|
/* Represents a table of server entries. */
|
||||||
|
@ -45,18 +45,19 @@ CC_NOINLINE static void Launcher_StartFromInfo(struct ServerInfo* info) {
|
|||||||
String port; char portBuffer[STRING_INT_CHARS];
|
String port; char portBuffer[STRING_INT_CHARS];
|
||||||
String_InitArray(port, portBuffer);
|
String_InitArray(port, portBuffer);
|
||||||
|
|
||||||
String_AppendInt(&port, info->Port);
|
String_AppendInt(&port, info->port);
|
||||||
Launcher_StartGame(&SignInTask.Username, &info->Mppass, &info->IP, &port, &info->Name);
|
Launcher_StartGame(&SignInTask.Username, &info->mppass, &info->ip, &port, &info->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Launcher_ConnectToServer(const String* hash) {
|
bool Launcher_ConnectToServer(const String* hash) {
|
||||||
int i;
|
|
||||||
struct ServerInfo* info;
|
struct ServerInfo* info;
|
||||||
|
String logMsg;
|
||||||
|
int i;
|
||||||
if (!hash->length) return false;
|
if (!hash->length) return false;
|
||||||
|
|
||||||
for (i = 0; i < FetchServersTask.NumServers; i++) {
|
for (i = 0; i < FetchServersTask.NumServers; i++) {
|
||||||
info = &FetchServersTask.Servers[i];
|
info = &FetchServersTask.Servers[i];
|
||||||
if (!String_Equals(hash, &info->Hash)) continue;
|
if (!String_Equals(hash, &info->hash)) continue;
|
||||||
|
|
||||||
Launcher_StartFromInfo(info);
|
Launcher_StartFromInfo(info);
|
||||||
return true;
|
return true;
|
||||||
@ -71,18 +72,16 @@ bool Launcher_ConnectToServer(const String* hash) {
|
|||||||
Thread_Sleep(10);
|
Thread_Sleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FetchServerTask.Server.Hash.length) {
|
if (FetchServerTask.Server.hash.length) {
|
||||||
Launcher_StartFromInfo(&FetchServerTask.Server);
|
Launcher_StartFromInfo(&FetchServerTask.Server);
|
||||||
return true;
|
return true;
|
||||||
} else if (FetchServerTask.Base.Res) {
|
} else if (FetchServerTask.Base.Success) {
|
||||||
Logger_SimpleWarn(FetchServerTask.Base.Res, "fetching server info");
|
|
||||||
} else if (FetchServerTask.Base.Status != 200) {
|
|
||||||
/* TODO: Use a better dialog message.. */
|
|
||||||
Logger_SimpleWarn(FetchServerTask.Base.Status, "fetching server info");
|
|
||||||
} else {
|
|
||||||
Window_ShowDialog("Failed to connect", "No server has that hash");
|
Window_ShowDialog("Failed to connect", "No server has that hash");
|
||||||
|
} else {
|
||||||
|
logMsg = String_Init(NULL, 0, 0);
|
||||||
|
LWebTask_DisplayError(&FetchServerTask.Base, "fetching server info", &logMsg);
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ static void Server_CheckAsyncResources(void) {
|
|||||||
TexturePack_Extract_Req(&item);
|
TexturePack_Extract_Req(&item);
|
||||||
HttpRequest_Free(&item);
|
HttpRequest_Free(&item);
|
||||||
} else if (item.Result) {
|
} else if (item.Result) {
|
||||||
Chat_Add1("&cError %i when trying to download texture pack", &item.Result);
|
Logger_SysWarn(item.Result, "trying to download texture pack", Http_DescribeError);
|
||||||
} else {
|
} else {
|
||||||
int status = item.StatusCode;
|
int status = item.StatusCode;
|
||||||
if (status == 200 || status == 304) return;
|
if (status == 200 || status == 304) return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user