Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
040dceb9ed | ||
|
|
c905b49102 | ||
|
|
23ded32db1 | ||
|
|
9e66c9dbc7 | ||
|
|
07fffc4b01 | ||
|
|
141df8c7b8 | ||
|
|
f5d739711d |
No files matched your search
@@ -138,6 +138,17 @@ jobs:
|
||||
|
||||
def put(name: str, data: bytes):
|
||||
url = upload_root + "/" + urllib.parse.quote(name, safe="")
|
||||
# Gitea refuses to overwrite a generic package file (HTTP 409), so the previous copy of this one
|
||||
# file is deleted right before it is uploaded again (keeps the gap without a file as short as possible).
|
||||
delete = urllib.request.Request(url, method="DELETE")
|
||||
delete.add_header("Authorization", "token " + token)
|
||||
delete.add_header("User-Agent", "tdlm-hmcl-publish")
|
||||
try:
|
||||
with urllib.request.urlopen(delete, timeout=300) as response:
|
||||
response.read()
|
||||
except urllib.error.HTTPError as exc:
|
||||
if exc.code != 404:
|
||||
raise SystemExit("HTTP %s deleting the old %s: %s" % (exc.code, name, exc.read()[:300]))
|
||||
request = urllib.request.Request(url, data=data, method="PUT")
|
||||
request.add_header("Authorization", "token " + token)
|
||||
request.add_header("Content-Type", "application/octet-stream")
|
||||
@@ -204,7 +215,7 @@ jobs:
|
||||
"- %s/HMCL.jar\n\n"
|
||||
"TDLMPack does not Maven-resolve this launcher; point the pack README / install docs at these URLs "
|
||||
"instead of hand-copying exe/jar.\n"
|
||||
"Client pack fileApi default: https://packages.dandanton.com/tdlm-client/latest\n"
|
||||
"Client pack fileApi default: http://159.75.5.225:19527/tdlm-client\n"
|
||||
"(Pack must publish/mirror the same layout; see docs/TDLM_CONSUME.md).\n"
|
||||
) % (package_root, package_root)
|
||||
|
||||
|
||||
@@ -141,9 +141,9 @@ public final class Metadata {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Default client Server Modpack fileApi (CDN mirror of Pack's `tdlm-client/latest` layout).
|
||||
/// Default client Server Modpack fileApi: self-hosted static mirror on the TDLM VPS (nginx, port 19527).
|
||||
public static final String DEFAULT_CLIENT_FILE_API =
|
||||
"https://packages.dandanton.com/tdlm-client/latest";
|
||||
"http://159.75.5.225:19527/tdlm-client";
|
||||
|
||||
/// Stable client update root (`server-manifest.json` and `overrides/` live under this URL).
|
||||
///
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package org.jackhuang.hmcl.download;
|
||||
|
||||
import org.glavo.url.WebURL;
|
||||
import org.jackhuang.hmcl.Metadata;
|
||||
import org.jackhuang.hmcl.download.cleanroom.CleanroomRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.fabric.FabricRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.forge.ForgeRemoteVersion;
|
||||
@@ -183,6 +184,11 @@ public final class HMCLDownloadProvider extends DownloadProvider {
|
||||
new SimpleRule("https://hmcl.glavo.site/metadata/fmllibs", "https://alist.8mi.tech/d/mirror/HMCL-Metadata/Auto/fmllibs"),
|
||||
new SimpleRule("https://zkitefly.github.io/unlisted-versions-of-minecraft", "https://alist.8mi.tech/d/mirror/unlisted-versions-of-minecraft/Auto"),
|
||||
|
||||
// files.prismlauncher.org is unreachable from mainland China (TLS handshake reset) and BMCLAPI
|
||||
// does not mirror its repackaged log4j-fixed artifacts. Serve them from the self-hosted client
|
||||
// mirror (alongside the fileApi root); Prism stays as the fallback for reachable networks.
|
||||
new SimpleRule("https://files.prismlauncher.org/maven", Metadata.getClientFileApi() + "/maven"),
|
||||
|
||||
// https://github.com/mcmod-info-mirror/mcim-rust-api
|
||||
new SimpleRule("https://api.modrinth.com", null, "https://mod.mcimirror.top/modrinth"),
|
||||
new SimpleRule("https://cdn.modrinth.com", null, "https://mod.mcimirror.top"),
|
||||
|
||||
@@ -398,12 +398,22 @@ public final class Controllers {
|
||||
.whenComplete(Schedulers.javafx(), (result, exception) -> {
|
||||
if (exception != null) {
|
||||
LOG.warning("Failed to fetch client Server Modpack manifest", exception);
|
||||
Controllers.dialog(
|
||||
manifestUrl + "\n" + exception.getMessage(),
|
||||
i18n("message.error"),
|
||||
MessageType.ERROR);
|
||||
Instances.importModpack();
|
||||
return;
|
||||
}
|
||||
ServerModpackManifest manifest =
|
||||
JsonUtils.fromMaybeMalformedJson(result, ServerModpackManifest.class);
|
||||
if (manifest == null) {
|
||||
LOG.warning("Malformed client Server Modpack manifest from " + manifestUrl);
|
||||
Controllers.dialog(
|
||||
i18n("modpack.type.server.malformed"),
|
||||
i18n("message.error"),
|
||||
MessageType.ERROR);
|
||||
Instances.importModpack();
|
||||
return;
|
||||
}
|
||||
Controllers.getDecorator().startWizard(
|
||||
|
||||
+18
@@ -25,6 +25,7 @@ import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
|
||||
@@ -37,6 +38,8 @@ public final class MojangJavaDownloadTask extends Task<MojangJavaDownloadTask.Re
|
||||
private final Path tempDir;
|
||||
private final Task<MojangJavaRemoteFiles> javaDownloadsTask;
|
||||
private final List<Task<?>> dependencies = new ArrayList<>();
|
||||
private final AtomicInteger completedFiles = new AtomicInteger();
|
||||
private volatile int totalFiles;
|
||||
|
||||
private volatile MojangJavaDownloads.JavaDownload download;
|
||||
|
||||
@@ -147,6 +150,21 @@ public final class MojangJavaDownloadTask extends Task<MojangJavaDownloadTask.Re
|
||||
Files.createSymbolicLink(dest, Paths.get(link.getTarget()));
|
||||
}
|
||||
}
|
||||
|
||||
// Report per-file progress so the bar advances through the download, LZMA decompress and
|
||||
// cache-copy phases; otherwise it stays indeterminate while files appear on disk and players
|
||||
// assume the install is frozen. The callbacks run after each file completes and never touch
|
||||
// the download/decompress logic above.
|
||||
totalFiles = dependencies.size();
|
||||
if (totalFiles > 0) {
|
||||
List<Task<?>> tracked = new ArrayList<>(totalFiles);
|
||||
for (Task<?> dependency : dependencies) {
|
||||
tracked.add(dependency.thenRunAsync(() -> updateProgress(completedFiles.incrementAndGet(), totalFiles)));
|
||||
}
|
||||
dependencies.clear();
|
||||
dependencies.addAll(tracked);
|
||||
updateProgress(0, totalFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-8
@@ -46,26 +46,33 @@ Assets on each tag: `HMCL.exe`, `HMCL.jar`, plus `.sha256` files.
|
||||
In `TDLM/TDLMPack` README §启动, replace the repo-only “安装 TDLM/HMCL” step with one of the URLs above.
|
||||
**Do not** add HMCL as a Gradle/Maven dependency of the pack — pack CI stays pack-only.
|
||||
|
||||
### 4. Client pack fileApi (CDN)
|
||||
### 4. Client pack fileApi (self-hosted VPS)
|
||||
|
||||
HMCL default (`Metadata.DEFAULT_CLIENT_FILE_API`):
|
||||
|
||||
```text
|
||||
https://packages.dandanton.com/tdlm-client/latest
|
||||
http://159.75.5.225:19527/tdlm-client
|
||||
```
|
||||
|
||||
First install / updates fetch `{fileApi}/server-manifest.json` (and `overrides/**` under that root).
|
||||
Override at runtime: `-Dhmcl.client.fileApi=…` or jar attribute `hmcl.client.fileApi`.
|
||||
|
||||
The fileApi is a read-only nginx static mirror on the TDLM VPS (`159.75.5.225`, port `19527`,
|
||||
root `/var/www/tdlm-dl`). Players read it anonymously; integrity is verified by the SHA-1 hashes
|
||||
in `server-manifest.json`.
|
||||
|
||||
**TDLMPack must use the same URL** so `server-manifest.json` embeds it:
|
||||
|
||||
```text
|
||||
TDLM_CLIENT_FILE_API=https://packages.dandanton.com/tdlm-client/latest
|
||||
TDLM_CLIENT_FILE_API=http://159.75.5.225:19527/tdlm-client
|
||||
```
|
||||
|
||||
Set that as the Gitea Actions **variable** on `TDLM/TDLMPack` (pack.yml already passes `vars.TDLM_CLIENT_FILE_API`).
|
||||
Set that as the Gitea Actions **variable** on `TDLM/TDLMPack` (pack.yml passes `vars.TDLM_CLIENT_FILE_API`;
|
||||
`PackBuild.DEFAULT_FILE_API` is the build-time fallback).
|
||||
|
||||
**Publish caveat:** Pack’s current workflow PUTs the client tree to whatever `TDLM_CLIENT_FILE_API` is (upload root = fileApi). Today that defaults to Gitea generic
|
||||
`https://git.nest.potatolab.uk:8443/api/packages/TDLM/generic/tdlm-client/latest`.
|
||||
If you only change the HMCL default to the CDN and leave Pack publishing to Gitea, players will 404 unless you **mirror/sync** Gitea → `packages.dandanton.com/tdlm-client/latest`.
|
||||
If you set `TDLM_CLIENT_FILE_API` to the CDN URL, Pack CI must be able to PUT to that CDN (or you must split “upload origin” from “public fileApi” in Pack — not implemented today). Do not point HMCL at the CDN without one of those two ops paths.
|
||||
**Publish path (upload origin split from public fileApi):** Pack CI no longer PUTs to the read URL.
|
||||
The `pack.yml` "Publish the client Server Modpack to fileApi" step rsyncs `build/pack/client/overrides/`
|
||||
then `server-manifest.json` (manifest last) over SSH to `ubuntu@159.75.5.225:/var/www/tdlm-dl/tdlm-client`.
|
||||
Auth is the repo secret `TDLM_VPS_SSH_KEY`, an ed25519 deploy key confined on the VPS by
|
||||
`command="/usr/bin/rrsync /var/www/tdlm-dl/tdlm-client"` (rsync-only, no shell, no forwarding).
|
||||
The public port 19527 serves GET/HEAD only — there is no public write surface.
|
||||
Reference in new issue
Block a user