[Minecraft] 随手写了个自动下载与更新器

9月20日更新:C#版本完成,具有最简单的错误处理和图形界面(雾草这个只有字的窗口也能叫图形?)


程序很简单,本地一个文件记录本地版本,服务器端有个文件记录最新版本,如果服务器版本高于本地版本,就会自动下载相应的tar更新包,并自动解压,解压后再执行install.bat来完成更新的安装。

当然如果没有找到本地版本的记录文件,就会从服务器上下载一份完整的纯净客户端,然后再按补丁顺序依次安装。

C++的下载文件通过tools文件夹下的wget来实现,解压tar包则是靠的tar来完成。

C#的则是交给HttpWebRequest,HttpWebResponse和SharpZipLib来完成。

代码写得相当随意,基本上想到哪里写到哪里,而且也没有任何错误处理……不要打我最近网络赛和codeforces好多的

顺便求不吐槽英语……

以后会更新错误处理、本地包的安装和图形界面。

[点击此处下载C++版本]
[点击此处下载C#版本]
源码就丢这里一份吧:

#include 
#include 
#include 

const size_t STRINGLENGTH = 512;

const char *HttpVersion = "http://zh.server309.dimension.moe/minecraft/LastVersion.txt";
const char *localVersionFile = "version.txt";
const char *basePackage = "http://zh.server309.dimension.moe/minecraft/base.tar";

bool exist(const char *path);
void download(const char *url, const char *fileName);

int main() {
	//检查游戏是否已经下载完成
	if (!exist(localVersionFile)) {
		//如果用户不想下载,直接退出好了
		puts("Couldn\'t find any game files. \nDo you want to Download it NOW [Y/n]");
		if (toupper(getchar()) != 'Y') {
			puts("Aborting...");
			return 0;
		}
		//下载完整的纯净版游戏
		download(basePackage, "base.tar");
		//下载完了,解压呗
		puts("Download base package finished. Now installing it. It may take a few minutes...");
		system("tools\\tar xf base.tar");
	}
	//Now we are sure that we have the base game files. we just need to 
	//check if there's any update for mods and configure files
	
	//First, we need to get the newest version of game on server.
	download(HttpVersion, "tools\\ServerVerion.txt");
	FILE *serverVersion, *localVersion;
	int Sversion, Lversion;
	serverVersion = fopen("tools\\ServerVerion.txt", "rb");
	fscanf(serverVersion, "1.%d.0", &Sversion);
	fclose(serverVersion);
	localVersion = fopen("version.txt", "rb");
	fscanf(localVersion, "1.%d.0", &Lversion);
	fclose(localVersion);
	//check if we are up-to-date.
	if (Lversion == Sversion) {
		//the version is the same.
		puts("Your game is up-to-date!\nJust click mclauncher and enjoy it!");
		system("pause");
		return 0;
	}
	else {
		//we need to update the game, step-by-step accoding to the version.
		printf("We need to update some files to play the game.\n"
			"Local game version:  1.%d.0\n"
			"Server game version: 1.%d.0\n",
			Lversion, Sversion
		);
		for (int i = Lversion; i < Sversion; i++) {
			printf("Updating 1.%d.0 to 1.%d.0... ", i, i + 1);
			char updatePackage[STRINGLENGTH];
			//Download update package.
			sprintf(updatePackage, "http://zh.server309.dimension.moe/minecraft/update-%d.tar", i + 1);
			download(updatePackage, "update.tar");
			//decompress the package.
			system("tools\\tar xf update.tar");
			//call the update script to install the update package.
			system("\"update\\install.bat\"");
			//remove the packages
			system("del update.tar");
			system("del /F /A /Q update");
			localVersion = fopen("version.txt", "rb+");
			fprintf(localVersion, "1.%d.0", i + 1);
			fclose(localVersion);
			puts("finished!");
		}
	}
	system("pause");
	return 0;
}

void download(const char *url, const char *fileName) {
	char command[STRINGLENGTH];
	sprintf(command, "tools\\wget -O %s %s > tools\\logs\\wget.log", fileName, url);
	system(command);
}

bool exist(const char *path) {
	FILE *fp = fopen(path, "r");
	if (!fp)
		return false;
	else {
		fclose(fp);
		return true;
	}
}

C#版本源码:

using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;
using ICSharpCode.SharpZipLib.Tar;
using System.Text;

namespace Updater
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void download(string url, string fileName)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            Stream responseStream = response.GetResponseStream();
            Stream stream = new FileStream(fileName, FileMode.Create);
            byte[] buffer = new byte[1024];
            int size = responseStream.Read(buffer, 0, (int)buffer.Length);
            while (size > 0)
            {
                stream.Write(buffer, 0, size);
                size = responseStream.Read(buffer, 0, (int)buffer.Length);
            }
            stream.Close();
            responseStream.Close();
        }
        public void DeleteFolder(string deleteDirectory)
        {
            if (Directory.Exists(deleteDirectory))
            {
                foreach (string deleteFile in Directory.GetFileSystemEntries(deleteDirectory))
                {
                    if (File.Exists(deleteFile))
                        File.Delete(deleteFile);
                    else
                        DeleteFolder(deleteFile);
                }
                Directory.Delete(deleteDirectory);
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            Thread th = new Thread(main);
            th.IsBackground = true;
            th.Start();
        }
        private void main()
        {
            textBox1.Text = "Minecraft Updater 1.1\r\n";
            textBox1.Text += "检测是否已下载游戏\r\n";
            if (!File.Exists("Version.txt"))
            {
                textBox1.Text += "未找到本地游戏,开始下载。这可能需要一段时间……\r\n";
                try
                {
                    if (File.Exists("base.tar"))
                        textBox1.Text += "找到本地离线安装包,跳过下载\r\n";
                    else
                        download("http://zh.server309.dimension.moe/minecraft/base.tar", "base.tar");
                }
                catch (Exception ex)
                {
                    textBox1.Text += "发生错误:" + ex.Message + "\r\n程序已终止!";
                    MessageBox.Show("发生错误,在下载纯净版客户端:" + ex.Message + "\r\n程序已终止!");
                    Application.Exit();
                }
                textBox1.Text += "下载纯净版完成,开始解压缩……\r\n";
                try
                {
                    TarArchive package = TarArchive.CreateInputTarArchive(File.OpenRead("base.tar"));
                    package.ExtractContents(Environment.CurrentDirectory);
                    package.Close();
                }
                catch (Exception ex)
                {
                    textBox1.Text += "发生错误:" + ex.Message + "\r\n程序已终止!";
                    MessageBox.Show("发生错误,在解压缩纯净版客户端:" + ex.Message + "\r\n程序已终止!");
                    Application.Exit();
                }
                textBox1.Text += "解压缩完成,进入检查更新阶段……\r\n";
                File.Delete("base.tar");
            }
            textBox1.Text += "获取服务器端最新版本号……\r\n";
            string serverVersion, localVersion;
            try
            {
                HttpWebRequest request = WebRequest.Create("http://zh.server309.dimension.moe/minecraft/LastVersion.txt") as HttpWebRequest;
                request.Method = "GET";
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                var reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                serverVersion = reader.ReadToEnd();
                textBox1.Text += "服务器端版本为:" + serverVersion + "\r\n";
                textBox1.Text += "获取本地版本号……\r\n";
                StreamReader sr = new StreamReader("Version.txt", Encoding.Default);
                localVersion = sr.ReadLine();
                textBox1.Text += "本地版本为:" + localVersion + "\r\n";
                if (localVersion == serverVersion)
                {
                    textBox1.Text += "本地游戏已是最新版,无需安装更新。\r\n";
                    return;
                }
                string[] SVersion = serverVersion.Split('.');
                string[] LVersion = localVersion.Split('.');
                for (int i = Convert.ToInt32(LVersion[1]); i != Convert.ToInt32(SVersion[1]); i++)
                {
                    textBox1.Text += "正在下载自1." + i + ".0至1." + (i + 1) + ".0的更新……\r\n";
                    string updatePackageName = "http://zh.server309.dimension.moe/minecraft/update-" + (i + 1) + ".tar";
                    download(updatePackageName, "upgrade.tar");
                    textBox1.Text += "正在解压更新……\r\n";
                    TarArchive package = TarArchive.CreateInputTarArchive(File.OpenRead("upgrade.tar"));
                    package.ExtractContents(Environment.CurrentDirectory);
                    package.Close();
                    textBox1.Text += "正在安装更新\r\n";
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
                    process.StartInfo.CreateNoWindow = false;
                    process.StartInfo.FileName = "update\\install.bat";
                    process.Start();
                    StreamWriter sw = new StreamWriter(File.OpenWrite("Version.txt"), Encoding.Default);
                    sw.WriteLine("1." + (i + 1) + ".0");
                    Thread.Sleep(500);
                    textBox1.Text += "清理更新文件\r\n";
                    DeleteFolder("update");
                    File.Delete("upgrade.tar");
                }
                textBox1.Text += "全部更新安装完成,可以开始游戏了。\r\n";
            }
            catch (Exception ex)
            {
                textBox1.Text += "发生错误:" + ex.Message + "\r\n程序已终止!";
                MessageBox.Show("发生错误,在更新本地客户端:" + ex.Message + "\r\n程序已终止!");
                Application.Exit();
            }
        }
    }
}