Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ tasks.test {
}

tasks.processResources {
filesMatching("**") {
filesMatching("**/*.json") {
expand(
"version" to project.version,
)
}
filesMatching("**/*.mod.json") {
expand(
"version" to project.version,
)
Expand Down
37 changes: 36 additions & 1 deletion src/main/java/i18nupdatemod/I18nUpdateMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import i18nupdatemod.core.ResourcePack;
import i18nupdatemod.core.ResourcePackConverter;
import i18nupdatemod.entity.GameAssetDetail;
import i18nupdatemod.core.LoadDetailUI;
import i18nupdatemod.entity.LoadStage;
import i18nupdatemod.util.FileUtil;
import i18nupdatemod.util.Log;

Expand All @@ -24,10 +26,13 @@
public class I18nUpdateMod {
public static final String MOD_ID = "i18nupdatemod";
public static String MOD_VERSION;

public static volatile boolean shouldShutdown = false;
public static final Gson GSON = new Gson();

public static void init(Path minecraftPath, String minecraftVersion, String loader) {
LoadDetailUI.show();
LoadDetailUI.setStage(LoadStage.INIT);

try (InputStream is = I18nUpdateMod.class.getResourceAsStream("/i18nMetaData.json")) {
MOD_VERSION = GSON.fromJson(new InputStreamReader(is), JsonObject.class).get("version").getAsString();
} catch (Exception e) {
Expand All @@ -47,6 +52,11 @@ public static void init(Path minecraftPath, String minecraftVersion, String load
Log.warning("I18nUpdateMod会从互联网获取内容不可控的资源包。");
Log.warning("这一行为违背了网易我的世界「开发者内容审核制度」:禁止上传与提审内容不一致的游戏内容。");
Log.warning("为了遵循这一制度,I18nUpdateMod不会下载任何内容。");

LoadDetailUI.appendLog("I18nUpdateMod会从互联网获取内容不可控的资源包。");
LoadDetailUI.appendLog("这一行为违背了网易我的世界「开发者内容审核制度」:禁止上传与提审内容不一致的游戏内容。");
LoadDetailUI.appendLog("为了遵循这一制度,I18nUpdateMod不会下载任何内容。");
LoadDetailUI.appendLog("请您手动关闭此窗口");
return;
} catch (ClassNotFoundException ignored) {
}
Expand All @@ -57,36 +67,61 @@ public static void init(Path minecraftPath, String minecraftVersion, String load

try {
//Get asset
if (shouldShutdown) {
return;
}
GameAssetDetail assets = I18nConfig.getAssetDetail(minecraftVersion, loader);

//Update resource pack
LoadDetailUI.setStage(LoadStage.DOWNLOAD_ASSET);
if (shouldShutdown) {
return;
}
List<ResourcePack> languagePacks = new ArrayList<>();
boolean convertNotNeed = assets.downloads.size() == 1 && assets.downloads.get(0).targetVersion.equals(minecraftVersion);
String applyFileName = assets.downloads.get(0).fileName;
for (GameAssetDetail.AssetDownloadDetail it : assets.downloads) {
if (shouldShutdown) {
return;
}
FileUtil.setTemporaryDirPath(Paths.get(localStorage, "." + MOD_ID, it.targetVersion));
ResourcePack languagePack = new ResourcePack(it.fileName, convertNotNeed);
languagePack.checkUpdate(it.fileUrl, it.md5Url);
languagePacks.add(languagePack);
}

//Convert resourcepack
LoadDetailUI.setStage(LoadStage.CONVERT_RESOURCE_PACK);
if (shouldShutdown) {
return;
}
if (!convertNotNeed) {
FileUtil.setTemporaryDirPath(Paths.get(localStorage, "." + MOD_ID, minecraftVersion));
applyFileName = assets.covertFileName;
ResourcePackConverter converter = new ResourcePackConverter(languagePacks, applyFileName);
converter.convert(assets.covertPackFormat, getResourcePackDescription(assets.downloads));
}
LoadDetailUI.appendLog("资源包已转换完成。");

//Apply resource pack
LoadDetailUI.setStage(LoadStage.APPLY_RESOURCE_PACK);
if (shouldShutdown) {
return;
}
GameConfig config = new GameConfig(minecraftPath.resolve("options.txt"));
config.addResourcePack("Minecraft-Mod-Language-Modpack",
(minecraftMajorVersion <= 12 ? "" : "file/") + applyFileName);
config.writeToFile();
LoadDetailUI.appendLog("资源包已应用。");
LoadDetailUI.setStage(LoadStage.FINISH);
} catch (Exception e) {
Log.warning(String.format("Failed to update resource pack: %s", e));
LoadDetailUI.appendLog(String.format("I18n Update Mod 运行失败: %s", e));
LoadDetailUI.appendLog("请您手动关闭此窗口");
return;
// e.printStackTrace();
}
LoadDetailUI.hide();
}

private static String getResourcePackDescription(List<GameAssetDetail.AssetDownloadDetail> downloads) {
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/i18nupdatemod/core/I18nConfig.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package i18nupdatemod.core;

import com.google.gson.Gson;
import i18nupdatemod.entity.AssetMetaData;
import i18nupdatemod.entity.GameAssetDetail;
import i18nupdatemod.entity.GameMetaData;
import i18nupdatemod.entity.I18nMetaData;
import i18nupdatemod.entity.*;
import i18nupdatemod.util.Log;
import i18nupdatemod.util.Version;
import i18nupdatemod.util.VersionRange;
Expand Down Expand Up @@ -62,8 +59,10 @@ public static GameAssetDetail getAssetDetail(String minecraftVersion, String loa
GameMetaData convert = getGameMetaData(minecraftVersion);
GameAssetDetail ret = new GameAssetDetail();

LoadDetailUI.appendLog("正在获取最快的镜像源...");
String assetRoot = getFastestUrl();
Log.debug("Using asset root: " + assetRoot);
LoadDetailUI.appendLog("即将从 " + assetRoot + " 下载资源包");

if (assetRoot.equals("https://raw.githubusercontent.com/")) {
ret.downloads = createDownloadDetailsFromGit(convert, loader);
Expand Down
152 changes: 152 additions & 0 deletions src/main/java/i18nupdatemod/core/LoadDetailUI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package i18nupdatemod.core;

import i18nupdatemod.I18nUpdateMod;
import i18nupdatemod.entity.LoadStage;
import i18nupdatemod.util.Log;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;

public class LoadDetailUI {
private static volatile LoadDetailUI instance;
private final JFrame frame;
private final JProgressBar statusBar;
private final JTextArea logArea;
private final boolean useGUI;

private LoadDetailUI() {
useGUI = !Boolean.parseBoolean(System.getProperty("java.awt.headless", "false"));

if (!useGUI) {
frame = null;
statusBar = null;
logArea = null;
return;
}

frame = new JFrame();
frame.setTitle("I18nUpdateMod-资源包下载进度");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(854, 480);
frame.setLocationRelativeTo(null);
frame.setLayout(new BorderLayout());
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
shutdown();
}
});


URL iconURL = getClass().getResource("/icons/CFPA.png");
if (iconURL != null) {
Image icon = Toolkit.getDefaultToolkit().getImage(iconURL);
frame.setIconImage(icon);
}

// 主面板
JPanel panel = new JPanel();
panel.setBackground(new Color(220, 220, 220));
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

// 状态栏
statusBar = new JProgressBar();
statusBar.setString(LoadStage.getDescription(LoadStage.INIT));
statusBar.setStringPainted(true);
statusBar.setMaximum(LoadStage.values().length - 1);
statusBar.setValue(0);
statusBar.setForeground(new Color(102, 255, 102));
panel.add(statusBar);
panel.add(Box.createVerticalStrut(10));

// 日志输出区
logArea = new JTextArea(6, 30);
logArea.setEditable(false);
logArea.setFont(new Font("Monospaced", Font.PLAIN, 13));
JScrollPane scrollPane = new JScrollPane(logArea);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.GRAY));
panel.add(scrollPane);
panel.add(Box.createVerticalStrut(10));

// 提示文字
JLabel tip = new JLabel("如遇到进度卡住,可以点击下方按钮/关闭此窗口停止此次下载。");
tip.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(tip);
panel.add(Box.createVerticalStrut(10));

// 停止按钮
JButton stopButton = new JButton("停止此次下载");
stopButton.setFocusPainted(false);
stopButton.setBackground(Color.WHITE);
stopButton.setAlignmentX(Component.CENTER_ALIGNMENT);
stopButton.addActionListener((ActionEvent e) -> shutdown());
panel.add(stopButton);

frame.add(panel, BorderLayout.CENTER);
}

public static LoadDetailUI getInstance() {
if (instance == null) {
synchronized (LoadDetailUI.class) {
if (instance == null) {
instance = new LoadDetailUI();
}
}
}
return instance;
}

public static void show() {
LoadDetailUI gui = getInstance();
if (!gui.useGUI || gui.frame == null) {
return;
}
SwingUtilities.invokeLater(() -> gui.frame.setVisible(true));
}

public static void hide() {
LoadDetailUI gui = getInstance();
if (!gui.useGUI || gui.frame == null) {
return;
}
SwingUtilities.invokeLater(() -> gui.frame.setVisible(false));
}

private void shutdown() {
I18nUpdateMod.shouldShutdown = true;
Log.info("User shutdown task");
if (!useGUI) {
return;
}
hide();
}

public static void setStage(LoadStage stage) {
LoadDetailUI gui = getInstance();
if (!gui.useGUI || gui.statusBar == null || gui.logArea == null) {
return;
}
SwingUtilities.invokeLater(() -> {
gui.statusBar.setString(LoadStage.getDescription(stage));
gui.statusBar.setValue(stage.getValue());
gui.logArea.append("当前阶段: " + LoadStage.getDescription(stage) + "\n");
gui.logArea.setCaretPosition(gui.logArea.getDocument().getLength());
});
}

public static void appendLog(String log) {
LoadDetailUI gui = getInstance();
if (!gui.useGUI || gui.logArea == null) {
return;
}
SwingUtilities.invokeLater(() -> {
gui.logArea.append(log + "\n");
gui.logArea.setCaretPosition(gui.logArea.getDocument().getLength());
});
}
}
3 changes: 3 additions & 0 deletions src/main/java/i18nupdatemod/core/ResourcePack.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ public ResourcePack(String filename, boolean saveToGame) {

public void checkUpdate(String fileUrl, String md5Url) throws IOException, URISyntaxException, NoSuchAlgorithmException {
if (isUpToDate(md5Url)) {
LoadDetailUI.appendLog(filename + " 无需更新");
Log.debug("Already up to date.");
return;
}
//In this time, we can only download full file
LoadDetailUI.appendLog("正在下载 " + filename);
downloadFull(fileUrl, md5Url);
LoadDetailUI.appendLog(filename + " 下载完成");
//In the future, we will download patch file and merge local file
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public void convert(int packFormat, String description) throws Exception {
// zos.setMethod(ZipOutputStream.STORED);
for (Path p : sourcePath) {
Log.info("Converting: " + p);
LoadDetailUI.appendLog("正在转换 " + p);
try (ZipFile zf = new ZipFile(p.toFile(), StandardCharsets.UTF_8)) {
for (Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements(); ) {
ZipEntry ze = e.nextElement();
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/i18nupdatemod/entity/LoadStage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package i18nupdatemod.entity;

public enum LoadStage {
INIT(0),
DOWNLOAD_ASSET(1),
CONVERT_RESOURCE_PACK(2),
APPLY_RESOURCE_PACK(3),
FINISH(4);

private final int value;

LoadStage(int value) {
this.value = value;
}

public int getValue() {
return value;
}

public static String getDescription(LoadStage stage) {
switch (stage) {
case INIT:
return "初始化";
case DOWNLOAD_ASSET:
return "更新资源包";
case CONVERT_RESOURCE_PACK:
return "转换资源包";
case APPLY_RESOURCE_PACK:
return "应用资源包";
case FINISH:
return "完成";
default:
return "未知";
}
}
}
Binary file added src/main/resources/icons/CFPA.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/resources/icons/CFPA_with_title.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.