mirror of
https://github.com/zs-yg/MCSJ.git
synced 2025-12-06 19:00:43 +08:00
Compare commits
2 Commits
ddc6aa4e95
...
v0.0.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3831c0ae0a | ||
|
|
5acb70c5d2 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@ bin/
|
|||||||
obj/
|
obj/
|
||||||
logs/
|
logs/
|
||||||
profiles/
|
profiles/
|
||||||
|
jre/
|
||||||
|
setup/
|
||||||
21
Program.cs
21
Program.cs
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MCSJ.Tools;
|
using MCSJ.Tools;
|
||||||
using MCSJ.Tools.LogSystem;
|
using MCSJ.Tools.LogSystem;
|
||||||
|
using MCSJ.Tools.JreDownload;
|
||||||
|
|
||||||
namespace MCSJ
|
namespace MCSJ
|
||||||
{
|
{
|
||||||
@@ -15,6 +16,10 @@ namespace MCSJ
|
|||||||
LogMain.Debug($"日志文件: {LogCreator.GetLogFilePath()}");
|
LogMain.Debug($"日志文件: {LogCreator.GetLogFilePath()}");
|
||||||
|
|
||||||
LogMain.Info("MC服务器下载工具启动");
|
LogMain.Info("MC服务器下载工具启动");
|
||||||
|
var httpClient = new HttpClient {
|
||||||
|
Timeout = TimeSpan.FromMinutes(5),
|
||||||
|
DefaultRequestHeaders = { { "User-Agent", "MCSJ-JRE-Downloader" } }
|
||||||
|
};
|
||||||
var versionManager = new VersionManager();
|
var versionManager = new VersionManager();
|
||||||
var downloadService = new DownloadService(versionManager);
|
var downloadService = new DownloadService(versionManager);
|
||||||
LogMain.Debug("服务初始化完成");
|
LogMain.Debug("服务初始化完成");
|
||||||
@@ -24,7 +29,8 @@ namespace MCSJ
|
|||||||
Console.WriteLine("MC服务器下载工具");
|
Console.WriteLine("MC服务器下载工具");
|
||||||
Console.WriteLine("1. 显示所有版本");
|
Console.WriteLine("1. 显示所有版本");
|
||||||
Console.WriteLine("2. 下载指定版本");
|
Console.WriteLine("2. 下载指定版本");
|
||||||
Console.WriteLine("3. 退出");
|
Console.WriteLine("3. 下载JRE");
|
||||||
|
Console.WriteLine("4. 退出");
|
||||||
Console.Write("请选择操作: ");
|
Console.Write("请选择操作: ");
|
||||||
|
|
||||||
var input = Console.ReadLine();
|
var input = Console.ReadLine();
|
||||||
@@ -44,6 +50,19 @@ namespace MCSJ
|
|||||||
LogMain.Info($"版本下载完成: {version}");
|
LogMain.Info($"版本下载完成: {version}");
|
||||||
break;
|
break;
|
||||||
case "3":
|
case "3":
|
||||||
|
Console.Write("请输入要下载的JRE版本(如jre8,jre11等): ");
|
||||||
|
var jreVersion = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(jreVersion))
|
||||||
|
{
|
||||||
|
Console.WriteLine("JRE版本不能为空");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LogMain.Info($"开始下载JRE: {jreVersion}");
|
||||||
|
var jreDownloadService = new JreDownloadService(httpClient);
|
||||||
|
await jreDownloadService.DownloadAndSetupJre(jreVersion);
|
||||||
|
LogMain.Info($"JRE下载完成: {jreVersion}");
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
LogMain.Info("程序正常退出");
|
LogMain.Info("程序正常退出");
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -16,10 +16,16 @@ namespace MCSJ.Tools
|
|||||||
_httpClient = new HttpClient();
|
_httpClient = new HttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DownloadVersion(string version)
|
public async Task DownloadVersion(string? version)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(version))
|
||||||
|
{
|
||||||
|
Console.WriteLine("版本名称不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var url = _versionManager.GetDownloadUrl(version);
|
var url = _versionManager.GetDownloadUrl(version);
|
||||||
if (url == null)
|
if (string.IsNullOrEmpty(url))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"版本 {version} 不存在");
|
Console.WriteLine($"版本 {version} 不存在");
|
||||||
return;
|
return;
|
||||||
@@ -30,8 +36,8 @@ namespace MCSJ.Tools
|
|||||||
if (!Directory.Exists(profilesRoot))
|
if (!Directory.Exists(profilesRoot))
|
||||||
Directory.CreateDirectory(profilesRoot);
|
Directory.CreateDirectory(profilesRoot);
|
||||||
|
|
||||||
string targetFolder = null;
|
string? targetFolder = null;
|
||||||
string profilePath = null;
|
string? profilePath = null;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Console.Write($"请输入存放文件夹名称(直接回车默认用版本名 '{version}'):");
|
Console.Write($"请输入存放文件夹名称(直接回车默认用版本名 '{version}'):");
|
||||||
|
|||||||
@@ -71,6 +71,13 @@ namespace MCSJ.Tools
|
|||||||
|
|
||||||
public void DisplayAllVersions()
|
public void DisplayAllVersions()
|
||||||
{
|
{
|
||||||
|
var filePath = Path.Combine("resources", "serverlist.txt");
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
Console.WriteLine("版本列表文件不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Console.WriteLine("可用版本列表:");
|
Console.WriteLine("可用版本列表:");
|
||||||
foreach (var version in _versions.Keys)
|
foreach (var version in _versions.Keys)
|
||||||
{
|
{
|
||||||
@@ -78,7 +85,7 @@ namespace MCSJ.Tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetDownloadUrl(string version)
|
public string? GetDownloadUrl(string version)
|
||||||
{
|
{
|
||||||
return _versions.TryGetValue(version, out var url) ? url : null;
|
return _versions.TryGetValue(version, out var url) ? url : null;
|
||||||
}
|
}
|
||||||
|
|||||||
59
Tools/jredownload/JreDownloadProgress.cs
Normal file
59
Tools/jredownload/JreDownloadProgress.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace MCSJ.Tools.JreDownload
|
||||||
|
{
|
||||||
|
public class JreDownloadProgress : IProgress<(long bytesReceived, long totalBytesToReceive, int progressPercentage)>
|
||||||
|
{
|
||||||
|
public void Report((long bytesReceived, long totalBytesToReceive, int progressPercentage) value)
|
||||||
|
{
|
||||||
|
// 保存当前控制台颜色
|
||||||
|
var originalColor = Console.ForegroundColor;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 计算下载百分比
|
||||||
|
int percentage = value.progressPercentage;
|
||||||
|
|
||||||
|
// 格式化文件大小(使用MB单位)
|
||||||
|
string received = FormatFileSizeMB(value.bytesReceived);
|
||||||
|
string total = FormatFileSizeMB(value.totalBytesToReceive);
|
||||||
|
|
||||||
|
// 创建进度条
|
||||||
|
string progressBar = CreateProgressBar(percentage);
|
||||||
|
|
||||||
|
// 显示进度信息(仅进度条部分为绿色)
|
||||||
|
Console.Write("\r下载进度: ");
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.Write($"{progressBar}");
|
||||||
|
Console.ForegroundColor = originalColor;
|
||||||
|
Console.Write($" {percentage}% [{FormatFileSizeMB(value.bytesReceived)} / {FormatFileSizeMB(value.totalBytesToReceive)}]");
|
||||||
|
|
||||||
|
// 下载完成时换行
|
||||||
|
if (percentage == 100)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// 恢复原始控制台颜色
|
||||||
|
Console.ForegroundColor = originalColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CreateProgressBar(int percentage)
|
||||||
|
{
|
||||||
|
int width = 20; // 进度条宽度
|
||||||
|
int progress = percentage * width / 100;
|
||||||
|
|
||||||
|
return $"[{new string('#', progress)}{new string('-', width - progress)}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatFileSizeMB(long bytes)
|
||||||
|
{
|
||||||
|
double mb = bytes / (1024.0 * 1024.0);
|
||||||
|
return $"{mb:0.##} MB";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
193
Tools/jredownload/JreDownloadService.cs
Normal file
193
Tools/jredownload/JreDownloadService.cs
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
|
namespace MCSJ.Tools.JreDownload
|
||||||
|
{
|
||||||
|
public class JreDownloadService
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private const string JreListPath = "resources/jrelist.txt";
|
||||||
|
private const string JreRootFolder = "jre";
|
||||||
|
private const string SetupFolder = "setup";
|
||||||
|
|
||||||
|
public JreDownloadService(HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DownloadAndSetupJre(string version)
|
||||||
|
{
|
||||||
|
// 1. 读取jrelist.txt获取下载链接
|
||||||
|
var downloadUrl = GetDownloadUrl(version);
|
||||||
|
if (string.IsNullOrEmpty(downloadUrl))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"找不到版本 {version} 的下载链接");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 下载压缩包
|
||||||
|
var progress = new JreDownloadProgress();
|
||||||
|
var tempZipPath = await DownloadJreZip(downloadUrl, version, progress);
|
||||||
|
if (string.IsNullOrEmpty(tempZipPath))
|
||||||
|
{
|
||||||
|
Console.WriteLine("下载失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 解压到jre文件夹
|
||||||
|
var jreFolder = Path.Combine(JreRootFolder, version);
|
||||||
|
if (!ExtractJre(tempZipPath, jreFolder))
|
||||||
|
{
|
||||||
|
Console.WriteLine("解压失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 查找java.exe和javaw.exe
|
||||||
|
var javaExePath = FindJavaExe(jreFolder, "java.exe");
|
||||||
|
var javawExePath = FindJavaExe(jreFolder, "javaw.exe");
|
||||||
|
|
||||||
|
if (javaExePath == null || javawExePath == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("找不到java.exe或javaw.exe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 生成jre.toml
|
||||||
|
CreateJreToml(version, javaExePath, javawExePath);
|
||||||
|
|
||||||
|
// 6. 清理临时文件
|
||||||
|
File.Delete(tempZipPath);
|
||||||
|
|
||||||
|
Console.WriteLine($"JRE {version} 安装完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? GetDownloadUrl(string version)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(version))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!File.Exists(JreListPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var lines = File.ReadAllLines(JreListPath);
|
||||||
|
return lines.FirstOrDefault(l => l.StartsWith(version + ":"))?.Split(':').LastOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string?> DownloadJreZip(string url, string version, IProgress<(long, long, int)>? progress = null)
|
||||||
|
{
|
||||||
|
var tempPath = Path.GetTempFileName();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine($"开始下载 JRE {version}...");
|
||||||
|
// 确保URL是绝对路径,自动补全https协议头
|
||||||
|
if (!url.StartsWith("http:") && !url.StartsWith("https:"))
|
||||||
|
{
|
||||||
|
url = "https:" + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"无效的下载URL: {url}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"正在准备下载 {url}...");
|
||||||
|
var response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var totalBytes = response.Content.Headers.ContentLength ?? 0;
|
||||||
|
Console.WriteLine($"文件总大小: {totalBytes} 字节");
|
||||||
|
long bytesRead = 0;
|
||||||
|
var lastReportTime = DateTime.MinValue;
|
||||||
|
Console.WriteLine("开始下载...");
|
||||||
|
|
||||||
|
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||||
|
using (var fileStream = new FileStream(tempPath, FileMode.Create))
|
||||||
|
{
|
||||||
|
var buffer = new byte[8192];
|
||||||
|
int bytesReadThisPass;
|
||||||
|
|
||||||
|
while ((bytesReadThisPass = await stream.ReadAsync(buffer)) != 0)
|
||||||
|
{
|
||||||
|
await fileStream.WriteAsync(buffer.AsMemory(0, bytesReadThisPass));
|
||||||
|
bytesRead += bytesReadThisPass;
|
||||||
|
|
||||||
|
// 限制进度报告频率,避免过多控制台输出
|
||||||
|
if (DateTime.Now - lastReportTime > TimeSpan.FromMilliseconds(100) || bytesRead == totalBytes)
|
||||||
|
{
|
||||||
|
int progressPercentage = totalBytes > 0 ? (int)(bytesRead * 100 / totalBytes) : 0;
|
||||||
|
Console.WriteLine($"报告进度: {bytesRead}/{totalBytes} ({progressPercentage}%)");
|
||||||
|
progress?.Report((bytesRead, totalBytes, progressPercentage));
|
||||||
|
lastReportTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempPath;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"下载失败: {ex.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ExtractJre(string zipPath, string targetFolder)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(targetFolder))
|
||||||
|
Directory.Delete(targetFolder, true);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(targetFolder);
|
||||||
|
ZipFile.ExtractToDirectory(zipPath, targetFolder);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"解压失败: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? FindJavaExe(string folder, string exeName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(folder) || string.IsNullOrWhiteSpace(exeName))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!Directory.Exists(folder))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Directory.GetFiles(folder, exeName, SearchOption.AllDirectories).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateJreToml(string version, string javaExePath, string javawExePath)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(SetupFolder))
|
||||||
|
Directory.CreateDirectory(SetupFolder);
|
||||||
|
|
||||||
|
var tomlPath = Path.Combine(SetupFolder, "jre.toml");
|
||||||
|
var content = $@"[jre.{version}]
|
||||||
|
java_path = '{javaExePath}'
|
||||||
|
javaw_path = '{javawExePath}'
|
||||||
|
";
|
||||||
|
|
||||||
|
if (File.Exists(tomlPath))
|
||||||
|
{
|
||||||
|
var existingContent = File.ReadAllText(tomlPath);
|
||||||
|
if (!existingContent.Contains($"[jre.{version}]"))
|
||||||
|
{
|
||||||
|
File.AppendAllText(tomlPath, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File.WriteAllText(tomlPath, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user