Jump to content

Leadwerks Patcher / Updater


gamecreator
 Share

Recommended Posts

This program checks a file online to see if its timestamp is different from one you have saved.  If it's different, it downloads the file and patches your old file with it.  This is thanks to the libcurl library (which is bundled with Leadwerks, so you can use it immediately).

Usage: Simply create a new C++ project and replace your code with the code below.  This prints info to the console so have that enabled if you want to see that (in Visual Studio this in under Project Properties, Linker, System, SubSystem).  Make sure you have/create the necessary files and change the first four variables appropriately to point to the proper files.

#include "leadwerks.h"

using namespace Leadwerks;


//  This is the patch file we download
char onlinepatchfileURL[200] = "http://www.yoursite.com/yourfile.exe";

//  This is the name of the temporary downloaded patch file we save
char localdownloadedpatchfile[80] = "patchfile";

//  This is the executable we replace with the above patch file and then launch
char localfiletobepatched[80] = "yourgamefile.exe";

//  This file contains the timestamp we compare to the online file above
char localtimestampfile[80] = "patchfiletimestamp.txt";


char onlinetimestamp[25];
char localtimestamp[25];

long downloadprogresstimer;



//  Callback function called regularly by libcurl as a file is downloaded
int downloadprogress(void *p, double dltotal, double dlnow, double ultotal, double ulnow)
{
	//  Print download progress once a second
	if(Time::Millisecs()>downloadprogresstimer)
	{
		cout << "Downloaded bytes: " << dlnow << " / " << dltotal << "\n";
		downloadprogresstimer=Time::Millisecs()+1000;
	}
	return 0;
}


//  Compare online timestamp with one we have saved in a file
bool ispatchfiletimestampdifferent()
{
	//  Retrieve timestamp from local file
	FILE *fp=fopen(localtimestampfile, "r");
	if(fp==NULL)
	{
		printf("Error opening local timestamp file: %s\n",localtimestampfile);
		exit(1);
	}
	fgets(localtimestamp, 80, fp);
	fclose(fp);


	//  Retrieve timestamp from online file
	//  WARNING: some sites may not return a timestamp so this may fail
	CURL *curl=curl_easy_init();
	time_t fileTime = 1;
	curl_easy_setopt(curl, CURLOPT_URL, onlinepatchfileURL);
	curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
	curl_easy_setopt(curl, CURLOPT_FILETIME, 1);
	curl_easy_perform(curl);
	curl_easy_getinfo(curl, CURLINFO_FILETIME, &fileTime);
	curl_easy_cleanup(curl);


	//  Format online timestamp string
	char buf[80];
	struct tm  *ts=localtime(&fileTime);
	strftime(onlinetimestamp, sizeof(buf), "%a %Y-%m-%d %H:%M:%S", ts);


	//  Sanity check to compare two strings
//	printf("-%s-\n-%s-\n", onlinetimestamp, localtimestamp);


	//  Compare the two dates.  Are they different?
	if(strcmp(onlinetimestamp, localtimestamp)==0) return false;
	else return true;
}


bool downloadpatchfile()
{
	CURL *curl;
	CURLcode res;
	FILE *fp;

	curl = curl_easy_init();

	if(curl)
	{
		fp = fopen(localdownloadedpatchfile, "wb");
		if(fp==NULL)
		{
			printf("Error opening local patch file: %s\n", localdownloadedpatchfile);
			exit(1);
		}

		curl_easy_setopt(curl, CURLOPT_URL, onlinepatchfileURL);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, downloadprogress);

		res = curl_easy_perform(curl);
		curl_easy_cleanup(curl);

		fclose(fp);

		if(res == CURLE_OK)
		{
			printf("Patch file download complete.\n");
			return true;
		}
		else printf("Error downloading patch file.\n");
	}

	//  Something went wrong...
	return false;
}


void savenewtimestamptofile()
{
	FILE *fp;
	fp = fopen(localtimestampfile, "wb");
	if(fp==NULL)
	{
		printf("Error opening local timestamp file: %s\n", localtimestampfile);
		exit(1);
	}
	fputs(onlinetimestamp, fp);
	fclose(fp);
}


int main(int argc, TCHAR *argv[])
{
	//  Compare online patch file timestamp to one stored in local file
	//  If it's different, download new file and replace old one
	if(ispatchfiletimestampdifferent())
	{
		printf("Patch file date is different from stored date.  Downloading patch file...\n");

		downloadprogresstimer=Time::Millisecs();

		if(downloadpatchfile())
		{
			savenewtimestamptofile();

			//  Remove old file
			remove(localfiletobepatched);

			//  Rename patch file to old file
			rename(localdownloadedpatchfile, localfiletobepatched);
		}
	}
	else printf("Patch file date is the same as stored date.  There is no need to download patch file.\n");


	//  Launch program
	STARTUPINFO info={sizeof(info)};
	PROCESS_INFORMATION processInfo;
	if(CreateProcess(argv[1], localfiletobepatched, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
	{
//		WaitForSingleObject(processInfo.hProcess, INFINITE);
		CloseHandle(processInfo.hProcess);
		CloseHandle(processInfo.hThread);
	}
	else printf("Could not launch program.  CreateProcess failed (%d).\n", GetLastError());
}

 

  • Like 3
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...