Skip to content

Commit

Permalink
feat: 初步实现jar包自动更新
Browse files Browse the repository at this point in the history
  • Loading branch information
creeper12356 committed Aug 26, 2024
1 parent c7fa3f5 commit 3f23491
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 3 deletions.
2 changes: 2 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.20'
implementation "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
implementation "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
implementation group: 'com.kotcrab.vis', name: 'vis-ui', version: '1.5.1'

}
12 changes: 11 additions & 1 deletion core/src/main/java/io/github/creeper12356/MyGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.kotcrab.vis.ui.VisUI;

import io.github.creeper12356.screen.BasicMenuScreen;
import io.github.creeper12356.screen.BoardScreen;
import io.github.creeper12356.screen.MainMenuScreen;
import io.github.creeper12356.screen.RoundMenuScreen;
import io.github.creeper12356.screen.StoryMenuScreen;
import io.github.creeper12356.utils.Resource;
import io.github.creeper12356.utils.UpdateChecker;

public class MyGame extends Game {
public static final int SCREEN_MAIN_MENU = 0;
Expand All @@ -20,6 +22,9 @@ public class MyGame extends Game {
private BasicMenuScreen[] screens = new BasicMenuScreen[4];
private int lastScreen = -1;
private int currentScreen = -1;

private UpdateChecker updateChecker = new UpdateChecker();

/**
* @brief 切换屏幕
* @details 在外部调用此方法切换屏幕
Expand All @@ -43,20 +48,25 @@ public void navigateBack() {

@Override
public void create() {
VisUI.load();
screens[0] = new MainMenuScreen(this);
screens[1] = new StoryMenuScreen(this);
screens[2] = new RoundMenuScreen(this);
screens[3] = new BoardScreen(this);

updateChecker.checkUpdate();

setScreen(SCREEN_MAIN_MENU);
}

@Override
public void dispose() {
Resource.dispose();

for(Screen screen: screens) {
for (Screen screen : screens) {
screen.dispose();
}
VisUI.dispose();
System.out.println("Game disposed");
super.dispose();
}
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/java/io/github/creeper12356/utils/Resource.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public class Resource {
public static float aniDelayDuration;
public static int pointMgr;


public static String version;
public static String language;
// public static Animation aniTalkButton;

Expand Down Expand Up @@ -753,7 +753,8 @@ public static byte[] loadData(String filename) {
aniDelayDuration = 0.1f;
// pointMgr = new PointMgr();
// aniTalkButton = new Animation();


version = "v1.0.0";
language = "en";

// 启动游戏时加载
Expand Down
169 changes: 169 additions & 0 deletions core/src/main/java/io/github/creeper12356/utils/UpdateChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package io.github.creeper12356.utils;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.File;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net.HttpMethods;
import com.badlogic.gdx.Net.HttpRequest;
import com.badlogic.gdx.Net.HttpResponseListener;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.JsonValue;

import io.github.creeper12356.MyGame;

public class UpdateChecker {
private String latestVersion;
private String downloadUrl;

public void checkUpdate() {
String url = "https://api.github.com/repos/creeper12356/ChineseCheckerPorted/releases/latest";
HttpRequest httpGet = new HttpRequest(HttpMethods.GET);
httpGet.setUrl(url);

Gdx.net.sendHttpRequest(httpGet, new HttpResponseListener() {
@Override
public void handleHttpResponse(com.badlogic.gdx.Net.HttpResponse httpResponse) {
JsonReader json = new JsonReader();
JsonValue latestRelease = json.parse(httpResponse.getResultAsString());

latestVersion = latestRelease.getString("tag_name");

if (latestVersion.equals(Resource.version)) {
System.out.println("No updates available.");
return;
}

JsonValue assets = latestRelease.get("assets");
for (JsonValue asset : assets) {
String assetName = asset.getString("name");
if (assetName.endsWith(Resource.language + ".jar")) {
downloadUrl = asset.getString("browser_download_url");
break;
}
}

if (downloadUrl == null) {
System.out.println("No download URL found.");
return;
}

System.out.println("Latest version: " + latestVersion);
System.out.println("Download URL: " + downloadUrl);

// 下载并替换jar包
setProxy();
downloadFile(downloadUrl, System.getProperty("user.dir"));
unsetProxy();
}

@Override
public void failed(Throwable t) {
t.printStackTrace();
System.out.println("Failed to check for updates.");
}

@Override
public void cancelled() {
System.out.println("Cancelled checking for updates.");
}
});
}

public void downloadFile(String fileURL, String savePath) {
try {
URL url = new URL(fileURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();

// 检查HTTP响应代码
if (responseCode == HttpURLConnection.HTTP_OK) {
String disposition = httpConn.getHeaderField("Content-Disposition");
int contentLength = httpConn.getContentLength();

// 打印文件信息
System.out.println("Content-Type = " + httpConn.getContentType());
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);

// 打开输入流和输出流
InputStream inputStream = httpConn.getInputStream();
String oldJarPath = getCurrentJarPath();
String saveFilePath = oldJarPath + ".new";

try (FileOutputStream outputStream = new FileOutputStream(saveFilePath);
BufferedInputStream in = new BufferedInputStream(inputStream)) {

byte[] buffer = new byte[4096];
int bytesRead = -1;
long totalBytesRead = 0;
int percentCompleted = 0;
long fileSize = contentLength;

while ((bytesRead = in.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
int percent = (int) (totalBytesRead * 100 / fileSize);
if (percent > percentCompleted) {
percentCompleted = percent;
System.out.print("下载进度: " + percentCompleted + "%\r");
}
}
System.out.println("\n文件下载完成,保存到: " + saveFilePath);

ProcessBuilder processBuilder;
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
processBuilder = new ProcessBuilder("cmd", "/c",
"move " + saveFilePath + " " + oldJarPath + " && java -jar " + oldJarPath);
} else {
processBuilder = new ProcessBuilder("sh", "-c",
"mv " + saveFilePath + " " + oldJarPath + " && chmod +x " + oldJarPath
+ " && java -jar " + oldJarPath);
}
processBuilder.start();

System.exit(0);
}
} else {
System.out.println("服务器返回非预期响应代码: " + responseCode);
}
httpConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}

private void setProxy() {
System.setProperty("http.proxyHost", "127.0.0.1");
System.setProperty("http.proxyPort", "7890");
System.setProperty("https.proxyHost", "127.0.0.1");
System.setProperty("https.proxyPort", "7890");
}

private void unsetProxy() {
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
System.clearProperty("https.proxyHost");
System.clearProperty("https.proxyPort");
}

/**
* @brief 获取当前jar包路径
* @return
*/
private String getCurrentJarPath() {
String path = null;
try {
path = new File(MyGame.class.getProtectionDomain().getCodeSource().getLocation()
.toURI()).getPath();
System.out.println(path);
} catch (Exception e) {
e.printStackTrace();
}
return path;
}
}

0 comments on commit 3f23491

Please sign in to comment.