[WIP] Update checker
This commit is contained in:
parent
fd6dd9bd2c
commit
91eb1966a0
9
Makefile
9
Makefile
|
@ -904,6 +904,13 @@ endif
|
|||
# Zlib
|
||||
LDFLAGS += -lz
|
||||
|
||||
# Update checker library
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
LDFLAGS += -lwininet
|
||||
else
|
||||
LDFLAGS += -lcurl
|
||||
endif
|
||||
|
||||
# Lua
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
ifeq ($(TARGET_BITS), 32)
|
||||
|
@ -927,7 +934,7 @@ else
|
|||
LDFLAGS += -Llib/lua/linux -l:liblua53.a -ldl
|
||||
endif
|
||||
|
||||
# coopnet
|
||||
# CoopNet
|
||||
COOPNET_LIBS :=
|
||||
ifeq ($(COOPNET),1)
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
|
|
|
@ -12605,7 +12605,7 @@ MINOR_VERSION_NUMBER = 1
|
|||
PATCH_VERSION_NUMBER = 0
|
||||
|
||||
--- @type string
|
||||
SM64COOPDX_VERSION = "v0.1.4"
|
||||
SM64COOPDX_VERSION = "0.1.5"
|
||||
|
||||
--- @type integer
|
||||
VERSION_NUMBER = 36
|
||||
|
|
|
@ -28,6 +28,9 @@ COOPNET_VERSION = "\\#ffa0a0\\Your version is no longer compatible with CoopNet.
|
|||
PEER_FAILED = "\\#ffa0a0\\Failed to connect to player '@'"
|
||||
UNKNOWN = "unknown"
|
||||
LOBBY_HOST = "the lobby's host"
|
||||
UPDATE_AVAILABLE = "A new update is available!"
|
||||
LATEST_VERSION = "Latest version"
|
||||
YOUR_VERSION = "Your version"
|
||||
|
||||
[CHAT]
|
||||
KICKING = "Kicking '@'!"
|
||||
|
|
|
@ -290,7 +290,7 @@ static void crash_handler_add_info_str(CrashHandlerText** pTextP, f32 x, f32 y,
|
|||
|
||||
static void crash_handler_add_version_str(CrashHandlerText** pTextP, f32 x, f32 y) {
|
||||
CrashHandlerText* pText = *pTextP;
|
||||
crash_handler_set_text(x, y, 0xFF, 0xFF, 0x00, "%s", "sm64coopdx ");
|
||||
crash_handler_set_text(x, y, 0xFF, 0xFF, 0x00, "%s", "sm64coopdx v");
|
||||
crash_handler_set_text(-1, y, 0x00, 0xFF, 0xFF, "%s", SM64COOPDX_VERSION);
|
||||
*pTextP = pText;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "pc/network/network.h"
|
||||
#include "pc/utils/misc.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/update_checker.h"
|
||||
|
||||
static struct DjuiRect* sRectPort = NULL;
|
||||
static struct DjuiRect* sRectPassword = NULL;
|
||||
|
@ -201,6 +202,14 @@ void djui_panel_host_create(struct DjuiBase* caller) {
|
|||
? &button1->base
|
||||
: &button2->base;
|
||||
}
|
||||
|
||||
if (gUpdateMessage) {
|
||||
struct DjuiText* message = djui_text_create(&panel->base, DLANG(NOTIF, UPDATE_AVAILABLE));
|
||||
djui_base_set_size_type(&message->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&message->base, 1.0f, 1.0f);
|
||||
djui_base_set_color(&message->base, 255, 255, 160, 255);
|
||||
djui_text_set_alignment(message, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
|
||||
}
|
||||
}
|
||||
|
||||
djui_panel_add(caller, panel, defaultBase);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "djui_panel_join_direct.h"
|
||||
#include "pc/network/network.h"
|
||||
#include "pc/utils/misc.h"
|
||||
#include "pc/update_checker.h"
|
||||
#ifdef DISCORD_SDK
|
||||
#include "pc/discord/discord.h"
|
||||
#endif
|
||||
|
@ -38,6 +39,14 @@ void djui_panel_join_create(struct DjuiBase* caller) {
|
|||
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back);
|
||||
}
|
||||
|
||||
if (gUpdateMessage) {
|
||||
struct DjuiText* message = djui_text_create(&panel->base, DLANG(NOTIF, UPDATE_AVAILABLE));
|
||||
djui_base_set_size_type(&message->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&message->base, 1.0f, 1.0f);
|
||||
djui_base_set_color(&message->base, 255, 255, 160, 255);
|
||||
djui_text_set_alignment(message, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
|
||||
}
|
||||
|
||||
djui_panel_add(caller, panel, NULL);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "djui_panel_confirm.h"
|
||||
#include "src/pc/controller/controller_sdl.h"
|
||||
#include "src/pc/pc_main.h"
|
||||
#include "src/pc/update_checker.h"
|
||||
|
||||
extern ALIGNED8 u8 texture_coopdx_logo[];
|
||||
|
||||
|
@ -46,11 +47,20 @@ void djui_panel_main_create(struct DjuiBase* caller) {
|
|||
djui_base_set_location(&button4->base, 0, -30.0f);
|
||||
}
|
||||
|
||||
struct DjuiText* version = djui_text_create(&panel->base, SM64COOPDX_VERSION);
|
||||
djui_base_set_size_type(&version->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&version->base, 1.0f, 1.0f);
|
||||
djui_base_set_color(&version->base, 50, 50, 50, 255);
|
||||
djui_text_set_alignment(version, DJUI_HALIGN_RIGHT, DJUI_VALIGN_BOTTOM);
|
||||
// these two cannot co-exist for some reason
|
||||
if (gUpdateMessage) {
|
||||
struct DjuiText* message = djui_text_create(&panel->base, DLANG(NOTIF, UPDATE_AVAILABLE));
|
||||
djui_base_set_size_type(&message->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&message->base, 1.0f, 1.0f);
|
||||
djui_base_set_color(&message->base, 255, 255, 160, 255);
|
||||
djui_text_set_alignment(message, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
|
||||
} else {
|
||||
struct DjuiText* version = djui_text_create(&panel->base, get_version_dx());
|
||||
djui_base_set_size_type(&version->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&version->base, 1.0f, 1.0f);
|
||||
djui_base_set_color(&version->base, 50, 50, 50, 255);
|
||||
djui_text_set_alignment(version, DJUI_HALIGN_RIGHT, DJUI_VALIGN_BOTTOM);
|
||||
}
|
||||
}
|
||||
|
||||
djui_panel_add(caller, panel, NULL);
|
||||
|
|
|
@ -4396,7 +4396,7 @@ char gSmluaConstants[] = ""
|
|||
"COOP_OBJ_FLAG_LUA = (1 << 1)\n"
|
||||
"COOP_OBJ_FLAG_NON_SYNC = (1 << 2)\n"
|
||||
"COOP_OBJ_FLAG_INITIALIZED = (1 << 3)\n"
|
||||
"SM64COOPDX_VERSION = 'v0.1.4'\n"
|
||||
"SM64COOPDX_VERSION = '0.1.5'\n"
|
||||
"VERSION_TEXT = 'beta'\n"
|
||||
"VERSION_NUMBER = 36\n"
|
||||
"MINOR_VERSION_NUMBER = 1\n"
|
||||
|
|
|
@ -193,7 +193,7 @@ static u32 mods_count_directory(char* modsBasePath) {
|
|||
}
|
||||
|
||||
static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath) {
|
||||
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs in %s mod path:\n\\#808080\\%s", isUserModPath ? "user" : "local", modsBasePath)); }
|
||||
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath)); }
|
||||
|
||||
// generate bins
|
||||
dynos_generate_packs(modsBasePath);
|
||||
|
@ -223,7 +223,7 @@ static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath)
|
|||
}
|
||||
f32 count = (f32) mods_count_directory(modsBasePath);
|
||||
|
||||
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading mods in %s mod path:\n\\#808080\\%s", isUserModPath ? "user" : "local", modsBasePath)); }
|
||||
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mods In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath)); }
|
||||
|
||||
// iterate
|
||||
char path[SYS_MAX_PATH] = { 0 };
|
||||
|
@ -232,7 +232,7 @@ static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath)
|
|||
// sanity check / fill path[]
|
||||
if (!directory_sanity_check(dir, modsBasePath, path)) { continue; }
|
||||
|
||||
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading mod:\n\\#808080\\%s/%s", modsBasePath, dir->d_name)); }
|
||||
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mod:\n\\#808080\\%s/%s", modsBasePath, dir->d_name)); }
|
||||
|
||||
// load the mod
|
||||
if (!mod_load(mods, modsBasePath, dir->d_name)) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
static char sVersionString[MAX_VERSION_LENGTH] = { 0 };
|
||||
static char sLocalVersionString[MAX_LOCAL_VERSION_LENGTH] = { 0 };
|
||||
static char sDxVersionString[MAX_VERSION_LENGTH] = { 0 };
|
||||
|
||||
const char* get_version(void) {
|
||||
if (configCoopCompatibility) {
|
||||
|
@ -25,9 +26,9 @@ const char* get_version(void) {
|
|||
#endif
|
||||
} else {
|
||||
#if defined(VERSION_US)
|
||||
snprintf(sVersionString, MAX_VERSION_LENGTH, "%s", SM64COOPDX_VERSION);
|
||||
snprintf(sVersionString, MAX_VERSION_LENGTH, "v%s", SM64COOPDX_VERSION);
|
||||
#else
|
||||
snprintf(sVersionString, MAX_VERSION_LENGTH, "%s %s", SM64COOPDX_VERSION, VERSION_REGION);
|
||||
snprintf(sVersionString, MAX_VERSION_LENGTH, "v%s %s", SM64COOPDX_VERSION, VERSION_REGION);
|
||||
#endif
|
||||
}
|
||||
return sVersionString;
|
||||
|
@ -46,15 +47,26 @@ const char* get_version_local(void) {
|
|||
#endif
|
||||
} else {
|
||||
#if defined(VERSION_US)
|
||||
snprintf(sLocalVersionString, MAX_LOCAL_VERSION_LENGTH, "%s", SM64COOPDX_VERSION);
|
||||
snprintf(sLocalVersionString, MAX_LOCAL_VERSION_LENGTH, "v%s", SM64COOPDX_VERSION);
|
||||
#else
|
||||
snprintf(sLocalVersionString, MAX_LOCAL_VERSION_LENGTH, "%s %s", VERSION_TEXT, SM64COOPDX_VERSION, VERSION_REGION);
|
||||
snprintf(sLocalVersionString, MAX_LOCAL_VERSION_LENGTH, "v%s %s", VERSION_TEXT, SM64COOPDX_VERSION, VERSION_REGION);
|
||||
#endif
|
||||
}
|
||||
|
||||
return sLocalVersionString;
|
||||
}
|
||||
|
||||
// I want to redo this whole file when I remove sm64ex-coop compatibility
|
||||
const char* get_version_dx(void) {
|
||||
#if defined(VERSION_US)
|
||||
snprintf(sDxVersionString, MAX_LOCAL_VERSION_LENGTH, "v%s", SM64COOPDX_VERSION);
|
||||
#else
|
||||
snprintf(sDxVersionString, MAX_LOCAL_VERSION_LENGTH, "v%s %s", VERSION_TEXT, SM64COOPDX_VERSION, VERSION_REGION);
|
||||
#endif
|
||||
|
||||
return sDxVersionString;
|
||||
}
|
||||
|
||||
const char* get_game_name(void) {
|
||||
if (configCoopCompatibility) {
|
||||
#ifdef DEVELOPMENT
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define SM64COOPDX_VERSION "v0.1.4"
|
||||
#define SM64COOPDX_VERSION "0.1.5"
|
||||
|
||||
#define VERSION_TEXT "beta"
|
||||
#define VERSION_NUMBER 36
|
||||
|
@ -22,6 +22,7 @@
|
|||
#define MAX_LOCAL_VERSION_LENGTH 36
|
||||
const char* get_version(void);
|
||||
const char* get_version_local(void);
|
||||
const char* get_version_dx(void);
|
||||
const char* get_game_name(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "pc/network/version.h"
|
||||
#include "pc/network/socket/domain_res.h"
|
||||
#include "pc/network/network_player.h"
|
||||
#include "pc/update_checker.h"
|
||||
#include "pc/djui/djui.h"
|
||||
#include "pc/djui/djui_unicode.h"
|
||||
#include "pc/djui/djui_panel.h"
|
||||
|
@ -278,6 +279,9 @@ void* main_game_init(UNUSED void* arg) {
|
|||
configfile_load();
|
||||
configWindow.settings_changed = true;
|
||||
if (!djui_language_init(configLanguage)) { snprintf(configLanguage, MAX_CONFIG_STRING, "%s", ""); }
|
||||
|
||||
check_for_updates();
|
||||
|
||||
dynos_packs_init();
|
||||
sync_objects_init_system();
|
||||
|
||||
|
@ -369,6 +373,8 @@ int main(int argc, char *argv[]) {
|
|||
djui_init_late();
|
||||
djui_console_message_dequeue();
|
||||
|
||||
show_update_popup();
|
||||
|
||||
// Init network
|
||||
if (gCLIOpts.Network == NT_CLIENT) {
|
||||
network_set_system(NS_SOCKET);
|
||||
|
|
|
@ -60,7 +60,7 @@ extern "C" {
|
|||
#ifdef GIT_HASH
|
||||
#define TITLE ({ char title[96] = ""; snprintf(title, 96, "sm64coopdx [%s]", GIT_HASH); title; })
|
||||
#else
|
||||
#define TITLE ({ char title[96] = ""; snprintf(title, 96, "sm64coopdx %s", SM64COOPDX_VERSION); title; })
|
||||
#define TITLE ({ char title[96] = ""; snprintf(title, 96, "sm64coopdx v%s", SM64COOPDX_VERSION); title; })
|
||||
#endif
|
||||
|
||||
#define AT_STARTUP __attribute__((constructor))
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
#include <stdio.h>
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#include <wininet.h>
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
#include "update_checker.h"
|
||||
#include "pc/djui/djui.h"
|
||||
#include "pc/network/version.h"
|
||||
#include "pc/loading.h"
|
||||
|
||||
#define URL "https://sm64coopdx.com/download/version.txt"
|
||||
|
||||
static char sVersionUpdateTextBuffer[256] = { 0 };
|
||||
static char sRemoteVersion[8];
|
||||
|
||||
bool gUpdateMessage = false;
|
||||
|
||||
void show_update_popup(void) {
|
||||
if (sVersionUpdateTextBuffer[0] == '\0') { return; }
|
||||
djui_popup_create(sVersionUpdateTextBuffer, 3);
|
||||
}
|
||||
|
||||
#if !(defined(_WIN32) || defined(_WIN64))
|
||||
size_t write_callback(char *ptr, size_t size, size_t nmemb, char **data) {
|
||||
size_t realsize = size * nmemb;
|
||||
|
||||
// allocate memory for the received data and copy it into the buffer
|
||||
*data = realloc(*data, realsize + 1);
|
||||
if (*data == NULL) { return 0; }
|
||||
|
||||
memcpy(*data, ptr, realsize);
|
||||
(*data)[realsize] = '\0'; // null-terminate the string
|
||||
|
||||
return realsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
// function to download a text file from the internet
|
||||
const char* get_version_remote(void) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HINTERNET hInternet, hUrl;
|
||||
DWORD bytesRead;
|
||||
char buffer[8];
|
||||
|
||||
// initialize WinINet
|
||||
hInternet = InternetOpenA("sm64coopdx", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||
if (!hInternet) {
|
||||
printf("Failed to check for updates!\n");
|
||||
InternetCloseHandle(hInternet);
|
||||
InternetCloseHandle(hUrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// open the URL
|
||||
hUrl = InternetOpenUrlA(hInternet, URL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
|
||||
if (!hUrl) {
|
||||
printf("Failed to check for updates!\n");
|
||||
InternetCloseHandle(hInternet);
|
||||
InternetCloseHandle(hUrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// calculate the size of the file
|
||||
DWORD contentLength;
|
||||
DWORD dwSize = sizeof(contentLength);
|
||||
HttpQueryInfo(hUrl, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &dwSize, NULL);
|
||||
|
||||
// read data from the URL
|
||||
if (!InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead)) {
|
||||
printf("Failed to check for updates!\n");
|
||||
InternetCloseHandle(hInternet);
|
||||
InternetCloseHandle(hUrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(sRemoteVersion, buffer, 8);
|
||||
|
||||
// close handles
|
||||
InternetCloseHandle(hUrl);
|
||||
InternetCloseHandle(hInternet);
|
||||
#else
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
char *data = NULL;
|
||||
|
||||
// initialize libcurl
|
||||
curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
printf("Failed to check for updates!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set the URL to retrieve data from
|
||||
curl_easy_setopt(curl, CURLOPT_URL, URL);
|
||||
|
||||
// set the write callback function to store received data into the buffer
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
// perform the request
|
||||
res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
printf("Failed to check for updates!\n");
|
||||
curl_easy_cleanup(curl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(sRemoteVersion, data, 8);
|
||||
|
||||
// Clean up
|
||||
curl_easy_cleanup(curl);
|
||||
#endif
|
||||
|
||||
return sRemoteVersion;
|
||||
}
|
||||
|
||||
void check_for_updates(void) {
|
||||
REFRESH_MUTEX(
|
||||
gCurrLoadingSegment.percentage = 0;
|
||||
snprintf(gCurrLoadingSegment.str, 256, "Checking For Updates");
|
||||
);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
const char* remoteVersion = get_version_remote();
|
||||
if (strcmp(get_version_remote(), SM64COOPDX_VERSION)) {
|
||||
snprintf(
|
||||
sVersionUpdateTextBuffer, 256,
|
||||
"\\#ffffa0\\%s\n\\#dcdcdc\\%s: v%s\n%s: v%s",
|
||||
DLANG(NOTIF, UPDATE_AVAILABLE),
|
||||
DLANG(NOTIF, LATEST_VERSION),
|
||||
remoteVersion,
|
||||
DLANG(NOTIF, YOUR_VERSION),
|
||||
SM64COOPDX_VERSION
|
||||
);
|
||||
gUpdateMessage = true;
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _UPDATE_CHECKER_H
|
||||
#define _UPDATE_CHECKER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern bool gUpdateMessage;
|
||||
|
||||
void show_update_popup(void);
|
||||
void check_for_updates(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue