mirror of
https://github.com/Bluemangoo/sekai-unpacker.git
synced 2026-05-06 20:44:47 +08:00
Compare commits
4 Commits
2f1c7eb9d8
...
e019948017
| Author | SHA1 | Date | |
|---|---|---|---|
| e019948017 | |||
| e00b25b6c7 | |||
| 59c50d5e08 | |||
| b892c3b46f |
20
.dockerignore
Normal file
20
.dockerignore
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Git files
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Data
|
||||||
|
data/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
20
client.DOCKERFILE
Normal file
20
client.DOCKERFILE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM rust:slim-bookworm AS builder
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y musl-tools pkg-config libssl-dev
|
||||||
|
RUN rustup target add x86_64-unknown-linux-musl
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN cargo build --target x86_64-unknown-linux-musl --release --bin client
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN apk add --no-cache ca-certificates
|
||||||
|
RUN update-ca-certificates
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /usr/src/app/target/x86_64-unknown-linux-musl/release/client .
|
||||||
|
|
||||||
|
# Copy config file
|
||||||
|
COPY sekai-unpacker-client.yaml .
|
||||||
|
|
||||||
|
CMD ["./client", "-p", "cn", "-p", "jp"]
|
||||||
|
EXPOSE 3000
|
||||||
@ -67,6 +67,7 @@ impl Profile {
|
|||||||
from obj;
|
from obj;
|
||||||
self.sync_context.asset_version = asset_version as String;
|
self.sync_context.asset_version = asset_version as String;
|
||||||
self.sync_context.asset_hash = asset_hash as String;
|
self.sync_context.asset_hash = asset_hash as String;
|
||||||
|
self.sync_context.app_version = app_version as String;
|
||||||
self.concurrent = concurrent as Number.as_u64().ok_or(anyhow::Error::msg("concurrent is not usize"))? as usize;
|
self.concurrent = concurrent as Number.as_u64().ok_or(anyhow::Error::msg("concurrent is not usize"))? as usize;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -200,6 +200,16 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
if error.to_string().contains(REGION_NOT_FOUND) {
|
if error.to_string().contains(REGION_NOT_FOUND) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if error
|
||||||
|
.to_string()
|
||||||
|
.contains("Session did not reconnect within 15s")
|
||||||
|
{
|
||||||
|
error!(
|
||||||
|
"Session lost for profile {}. Waiting for a fresh tunnel endpoint...",
|
||||||
|
profile.0
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
error!("{}", error);
|
error!("{}", error);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -251,6 +261,16 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
if error
|
||||||
|
.to_string()
|
||||||
|
.contains("Session did not reconnect within 15s")
|
||||||
|
{
|
||||||
|
error!(
|
||||||
|
"Session lost for profile {}. Reconnecting tunnel...",
|
||||||
|
profile.0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
error!("{}", error);
|
error!("{}", error);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use crate::config::Profile;
|
|||||||
use crate::http::{close, download, sync};
|
use crate::http::{close, download, sync};
|
||||||
use common::http::{CloseRequest, DownloadRequest};
|
use common::http::{CloseRequest, DownloadRequest};
|
||||||
use communicator::ClientManager;
|
use communicator::ClientManager;
|
||||||
|
use anyhow::anyhow;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -64,30 +65,42 @@ pub async fn run(
|
|||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
task: task.clone(),
|
task: task.clone(),
|
||||||
};
|
};
|
||||||
let result = download(&mut client.get_client().await.unwrap(), &req, &p1).await;
|
let mut conn = client.get_client().await?;
|
||||||
if let Err(e) = result
|
let mut result = download(&mut conn, &req, &p1).await;
|
||||||
&& let Some(_) = e.downcast_ref::<h2::Error>()
|
if let Err(e) = &result
|
||||||
|
&& e.downcast_ref::<h2::Error>().is_some()
|
||||||
{
|
{
|
||||||
download(&mut client.get_client().await.unwrap(), &req, &p1)
|
let mut retry_conn = client.get_client().await?;
|
||||||
.await
|
result = download(&mut retry_conn, &req, &p1).await;
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
result?;
|
||||||
|
|
||||||
local_manifest
|
local_manifest
|
||||||
.add_bundle(task.bundle_path.clone(), task.bundle_hash.clone())
|
.add_bundle(task.bundle_path.clone(), task.bundle_hash.clone())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
?;
|
||||||
drop(permit);
|
drop(permit);
|
||||||
|
Ok::<(), anyhow::Error>(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let mut succeed = 0;
|
let mut succeed = 0;
|
||||||
let mut failed = 0;
|
let mut failed = 0;
|
||||||
while let Some(r) = join_set.join_next().await {
|
while let Some(r) = join_set.join_next().await {
|
||||||
if let Err(e) = r {
|
match r {
|
||||||
error!("{}", e);
|
Ok(Ok(())) => {
|
||||||
failed += 1;
|
succeed += 1;
|
||||||
} else {
|
}
|
||||||
succeed += 1;
|
Ok(Err(e)) => {
|
||||||
|
if e.to_string().contains("Session did not reconnect within 15s") {
|
||||||
|
return Err(anyhow!(e));
|
||||||
|
}
|
||||||
|
error!("{}", e);
|
||||||
|
failed += 1;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("{}", e);
|
||||||
|
failed += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_manifest.save().await?;
|
local_manifest.save().await?;
|
||||||
|
|||||||
@ -18,7 +18,8 @@ pub async fn server_send_files<P: AsRef<Path>, S: AsRef<str>>(
|
|||||||
let metadata = file.metadata().await?;
|
let metadata = file.metadata().await?;
|
||||||
|
|
||||||
let file_name = &path_ref.1;
|
let file_name = &path_ref.1;
|
||||||
let name_bytes = file_name.as_ref().as_bytes();
|
let file_name = file_name.as_ref().replace('\\', "/");
|
||||||
|
let name_bytes = file_name.as_bytes();
|
||||||
let file_size = metadata.len();
|
let file_size = metadata.len();
|
||||||
|
|
||||||
let mut meta_buf = BytesMut::with_capacity(2 + name_bytes.len() + 8);
|
let mut meta_buf = BytesMut::with_capacity(2 + name_bytes.len() + 8);
|
||||||
@ -62,6 +63,7 @@ pub async fn client_receive(
|
|||||||
let mut name_buf = vec![0u8; name_len as usize];
|
let mut name_buf = vec![0u8; name_len as usize];
|
||||||
response_body_reader.read_exact(&mut name_buf).await?;
|
response_body_reader.read_exact(&mut name_buf).await?;
|
||||||
let file_name = String::from_utf8(name_buf)?;
|
let file_name = String::from_utf8(name_buf)?;
|
||||||
|
let file_name = file_name.replace('\\', "/");
|
||||||
|
|
||||||
let data_len = response_body_reader.read_u64().await?;
|
let data_len = response_body_reader.read_u64().await?;
|
||||||
|
|
||||||
|
|||||||
249
sekai-unpacker-client.example.yaml
Normal file
249
sekai-unpacker-client.example.yaml
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
# ==========================================
|
||||||
|
# Sekai Unpacker 客户端配置示例
|
||||||
|
# sekai-unpacker-client.example.yaml
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# 日志级别: DEBUG, INFO, WARN, ERROR
|
||||||
|
log_level: "INFO"
|
||||||
|
|
||||||
|
# 说明:`client`/`server` 是 TCP 连接方向,不是进程身份。
|
||||||
|
# - `client`: 主动连出到远端
|
||||||
|
# - `server`: 本地监听并接受远端连入
|
||||||
|
# 当前文件默认展示“client 进程常用连出模式”,也可同时/单独启用 `server`。
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 服务器连接配置
|
||||||
|
# ==========================================
|
||||||
|
# 可配置多个服务器,客户端会依次尝试连接
|
||||||
|
client:
|
||||||
|
# 第一个服务器配置
|
||||||
|
- url: "127.0.0.1:3333" # 服务器地址和端口
|
||||||
|
token: "your_auth_token_here" # 认证令牌,必须与服务器配置相同
|
||||||
|
# host: "example.com" # [可选] TLS SNI 主机名
|
||||||
|
# 仅在需要 TLS 加密到 Identity 交换为止时配置
|
||||||
|
# 如不配置,则使用明文握手
|
||||||
|
# 加密范围:Identity 交换之前的握手,H2 通信不加密
|
||||||
|
|
||||||
|
# 可以配置多个服务器
|
||||||
|
# - url: "backup.example.com:3333"
|
||||||
|
# token: "backup_token"
|
||||||
|
# host: "backup.example.com"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 可选:反向连接场景(本进程作为监听端)
|
||||||
|
# ==========================================
|
||||||
|
# server:
|
||||||
|
# - url: "0.0.0.0:3334" # 本地监听地址和端口
|
||||||
|
# token: "reverse_link_token" # 需与对端 client.token 一致
|
||||||
|
# # cert: "/path/to/certificate.pem" # [可选] 启用 TLS 握手
|
||||||
|
# # key: "/path/to/private.key"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 同步配置文件(Profiles)
|
||||||
|
# ==========================================
|
||||||
|
# 每个配置文件对应一个地区的同步任务
|
||||||
|
profiles:
|
||||||
|
# ==========================================
|
||||||
|
# 国服配置示例
|
||||||
|
# ==========================================
|
||||||
|
cn:
|
||||||
|
# [必需] 地区标识,必须与服务器配置中的 regions 一致
|
||||||
|
region: cn
|
||||||
|
|
||||||
|
# ========== 版本信息配置(可选) ==========
|
||||||
|
# 以下三个字段会被 dynamic_load 中的值覆盖
|
||||||
|
|
||||||
|
# 应用版本
|
||||||
|
# app_version: "6.0.0"
|
||||||
|
|
||||||
|
# 资源版本
|
||||||
|
# asset_version: "1.0.0"
|
||||||
|
|
||||||
|
# 资源哈希值
|
||||||
|
# asset_hash: "abc123def456"
|
||||||
|
|
||||||
|
# ========== 动态加载配置(可选) ==========
|
||||||
|
# 从指定 URL 动态加载版本和哈希信息
|
||||||
|
# 用于获取最新版本而无需更新配置文件
|
||||||
|
dynamic_load:
|
||||||
|
url: "https://api.example.com/versions/cn"
|
||||||
|
# 映射关系:本地字段名 -> 远程 JSON 字段名
|
||||||
|
map:
|
||||||
|
app_version: appVersion
|
||||||
|
asset_version: assetVersion
|
||||||
|
asset_hash: assetHash
|
||||||
|
# concurrent: concurrent # [可选] 远程并发数,需为数字
|
||||||
|
|
||||||
|
# ========== 下载配置 ==========
|
||||||
|
# 更新间隔(秒,可选)
|
||||||
|
# 如设置,则每隔指定秒数自动检查更新
|
||||||
|
# interval: 3600
|
||||||
|
|
||||||
|
# 并发下载数(单个资源包的同时下载线程数)
|
||||||
|
concurrent: 50
|
||||||
|
|
||||||
|
# 精确匹配单文件包
|
||||||
|
exact_single_file_bundle: true
|
||||||
|
|
||||||
|
# 导出基础路径
|
||||||
|
path: "./data/cn"
|
||||||
|
|
||||||
|
# ========== 资源过滤配置 ==========
|
||||||
|
filters:
|
||||||
|
# 启动应用时必须下载的资源类型
|
||||||
|
start_app:
|
||||||
|
- "thumbnail" # 缩略图
|
||||||
|
- "stamp" # 邮票/表情
|
||||||
|
# - "area" # 地图
|
||||||
|
# - "home" # 主页背景
|
||||||
|
|
||||||
|
# 按需下载(用户请求时才下载)的资源类型
|
||||||
|
on_demand:
|
||||||
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
|
# - "event" # 活动资源
|
||||||
|
# - "mysekai" # 我的SEKAI资源
|
||||||
|
|
||||||
|
# 跳过下载的资源标识
|
||||||
|
# 完全不下载这些资源
|
||||||
|
skip: []
|
||||||
|
|
||||||
|
# 按文件扩展名过滤
|
||||||
|
# 仅下载指定扩展名的文件
|
||||||
|
file_ext: []
|
||||||
|
|
||||||
|
# ========== 导出和处理配置 ==========
|
||||||
|
export:
|
||||||
|
# 是否按分类导出(按资源类别分文件夹)
|
||||||
|
by_category: false
|
||||||
|
|
||||||
|
# ---- USM 视频文件处理 ----
|
||||||
|
usm:
|
||||||
|
export: true # 是否导出 USM 文件
|
||||||
|
decode: true # 是否解码为视频格式(需要 FFmpeg)
|
||||||
|
|
||||||
|
# ---- ACB 音频包处理 ----
|
||||||
|
acb:
|
||||||
|
export: true # 是否导出 ACB 文件
|
||||||
|
decode: true # 是否解包并解码(需要 cri_ware_decoder)
|
||||||
|
|
||||||
|
# ---- HCA 音频文件处理 ----
|
||||||
|
hca:
|
||||||
|
decode: true # 是否解码为 MP3/FLAC(需要 FFmpeg)
|
||||||
|
|
||||||
|
# ---- 图片处理 ----
|
||||||
|
images:
|
||||||
|
convert_to_webp: false # 是否转换为 WebP 格式(需要 FFmpeg)
|
||||||
|
remove_png: false # 转换后是否删除原 PNG 文件
|
||||||
|
|
||||||
|
# ---- 视频处理 ----
|
||||||
|
video:
|
||||||
|
convert_to_mp4: false # 是否转换为 MP4 格式(需要 FFmpeg)
|
||||||
|
direct_usm_to_mp4_with_ffmpeg: false # 直接用 FFmpeg 转换 USM 为 MP4(不先转M2V)
|
||||||
|
remove_m2v: false # 转换后是否删除原 M2V 文件
|
||||||
|
|
||||||
|
# ---- 音频处理 ----
|
||||||
|
audio:
|
||||||
|
convert_to_mp3: false # 是否转换为 MP3 格式(需要 FFmpeg)
|
||||||
|
convert_to_flac: false # 是否转换为 FLAC 格式(需要 FFmpeg)
|
||||||
|
remove_wav: false # 转换后是否删除原 WAV 文件
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 日服配置示例
|
||||||
|
# ==========================================
|
||||||
|
jp:
|
||||||
|
# [必需] 地区标识
|
||||||
|
region: jp
|
||||||
|
|
||||||
|
# 并发下载数
|
||||||
|
concurrent: 50
|
||||||
|
|
||||||
|
# 精确匹配单文件包
|
||||||
|
exact_single_file_bundle: true
|
||||||
|
|
||||||
|
# 导出路径
|
||||||
|
path: "./data/jp"
|
||||||
|
|
||||||
|
# 动态加载配置(使用 GitHub 作为版本源)
|
||||||
|
dynamic_load:
|
||||||
|
url: "https://github.com/Team-Haruki/haruki-sekai-master/raw/refs/heads/main/versions/current_version.json"
|
||||||
|
map:
|
||||||
|
# app_version: appVersion
|
||||||
|
asset_version: assetVersion
|
||||||
|
asset_hash: assetHash
|
||||||
|
# concurrent: concurrent # [可选] 远程并发数,需为数字
|
||||||
|
|
||||||
|
# 过滤配置
|
||||||
|
filters:
|
||||||
|
start_app:
|
||||||
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
|
on_demand:
|
||||||
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
|
skip: []
|
||||||
|
file_ext: []
|
||||||
|
|
||||||
|
# 导出配置
|
||||||
|
export:
|
||||||
|
by_category: false
|
||||||
|
usm:
|
||||||
|
export: true
|
||||||
|
decode: true
|
||||||
|
acb:
|
||||||
|
export: true
|
||||||
|
decode: true
|
||||||
|
hca:
|
||||||
|
decode: true
|
||||||
|
images:
|
||||||
|
convert_to_webp: false
|
||||||
|
remove_png: false
|
||||||
|
video:
|
||||||
|
convert_to_mp4: false
|
||||||
|
direct_usm_to_mp4_with_ffmpeg: false
|
||||||
|
remove_m2v: false
|
||||||
|
audio:
|
||||||
|
convert_to_mp3: false
|
||||||
|
convert_to_flac: false
|
||||||
|
remove_wav: false
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 配置说明
|
||||||
|
# ==========================================
|
||||||
|
#
|
||||||
|
# 【基本配置】
|
||||||
|
# - log_level: 日志输出级别,建议生产环境设为 INFO
|
||||||
|
# - client: 主动连出配置,支持故障转移
|
||||||
|
# - server: 本地监听配置(可选,反向连接时使用)
|
||||||
|
#
|
||||||
|
# 【版本管理】
|
||||||
|
# - 优先级:直接配置(app_version等)> dynamic_load > 默认值
|
||||||
|
# - 建议使用 dynamic_load 保持版本自动更新
|
||||||
|
#
|
||||||
|
# 【资源过滤】
|
||||||
|
# - start_app: 影响初始化和启动时的下载
|
||||||
|
# - on_demand: 需要时才下载的资源
|
||||||
|
# - skip: 完全忽略的资源,不会被下载
|
||||||
|
# - file_ext: 为空表示下载所有文件,指定则仅下载这些扩展名
|
||||||
|
#
|
||||||
|
# 【导出处理】
|
||||||
|
# - export:true 必须为 true,资源才会被导出
|
||||||
|
# - decode:true 表示对导出的资源进行解码/转换
|
||||||
|
# - 各转换功能均需要对应的外部工具(FFmpeg 等)
|
||||||
|
#
|
||||||
|
# 【多地区配置】
|
||||||
|
# - 可在 profiles 中定义多个地区
|
||||||
|
# - 每个地区独立管理下载和导出配置
|
||||||
|
# - region 名称必须与服务器配置一致
|
||||||
|
#
|
||||||
|
# 【TLS 加密】
|
||||||
|
# - 仅在需要加密握手时配置 host 字段
|
||||||
|
# - 加密仅到 Identity 交换,之后 H2 通信不加密
|
||||||
|
# - 留空或不配置则使用明文握手
|
||||||
|
#
|
||||||
|
# 【角色说明】
|
||||||
|
# - 角色由连接方向决定,不由可执行文件名称决定
|
||||||
|
# - 同一进程可只开 `client`、只开 `server`,或两者同时开启
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
283
sekai-unpacker-server.example.yaml
Normal file
283
sekai-unpacker-server.example.yaml
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
# ==========================================
|
||||||
|
# Sekai Unpacker 服务器配置示例
|
||||||
|
# sekai-unpacker-server.example.yaml
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# 日志级别: DEBUG, INFO, WARN, ERROR
|
||||||
|
log_level: "INFO"
|
||||||
|
|
||||||
|
# 说明:`server`/`client` 是 TCP 连接方向,不是进程身份。
|
||||||
|
# - `server`: 本地监听并接受远端连入
|
||||||
|
# - `client`: 主动连出到远端
|
||||||
|
# 当前文件默认展示“server 进程常用监听模式”,也可同时/单独启用 `client`。
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 服务器监听配置
|
||||||
|
# ==========================================
|
||||||
|
# 可配置多个监听地址和端口
|
||||||
|
server:
|
||||||
|
# 主服务器配置
|
||||||
|
- url: "127.0.0.1:3333" # 监听地址和端口
|
||||||
|
token: "your_secure_token_here" # 认证令牌,对端必须提供相同的令牌
|
||||||
|
|
||||||
|
# ========== TLS 证书配置(可选) ==========
|
||||||
|
# 如配置证书和密钥,服务器将支持 TLS 加密握手
|
||||||
|
# 如未配置,服务器仅接受明文握手
|
||||||
|
# 注意:加密仅应用于 Identity 交换阶段,H2 通信保持明文
|
||||||
|
|
||||||
|
# cert: "/path/to/certificate.pem" # TLS 证书文件路径
|
||||||
|
# key: "/path/to/private.key" # TLS 私钥文件路径
|
||||||
|
|
||||||
|
# 例子:
|
||||||
|
# cert: "D:\\certs\\_.example.com-chain.pem"
|
||||||
|
# key: "D:\\certs\\_.example.com-key.pem"
|
||||||
|
|
||||||
|
# 可配置多个监听地址和端口
|
||||||
|
# - url: "0.0.0.0:3334"
|
||||||
|
# token: "alternative_token"
|
||||||
|
# cert: "/path/to/another-cert.pem"
|
||||||
|
# key: "/path/to/another-key.pem"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 可选:反向连接场景(本进程主动连出)
|
||||||
|
# ==========================================
|
||||||
|
# client:
|
||||||
|
# - url: "upstream.example.com:3333" # 远端监听地址和端口
|
||||||
|
# token: "reverse_link_token" # 需与对端 server.token 一致
|
||||||
|
# # host: "upstream.example.com" # [可选] 启用 TLS 握手时填写
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 资源执行配置
|
||||||
|
# ==========================================
|
||||||
|
execution:
|
||||||
|
# HTTP 代理设置(可选)
|
||||||
|
# 如需通过代理服务器访问资源源,配置此项
|
||||||
|
# proxy: "http://proxy.example.com:8080"
|
||||||
|
# proxy: "socks5://proxy.example.com:1080"
|
||||||
|
|
||||||
|
# 资源下载和处理的超时时间(秒)
|
||||||
|
timeout_seconds: 300
|
||||||
|
|
||||||
|
# 是否允许客户端取消正在执行的任务
|
||||||
|
allow_cancel: true
|
||||||
|
|
||||||
|
# ========== 重试策略 ==========
|
||||||
|
retry:
|
||||||
|
# 最大重试次数(网络错误时)
|
||||||
|
attempts: 4
|
||||||
|
|
||||||
|
# 初始退避时间(毫秒)
|
||||||
|
# 首次失败后等待 1000ms 再重试
|
||||||
|
initial_backoff_ms: 1000
|
||||||
|
|
||||||
|
# 最大退避时间(毫秒)
|
||||||
|
# 后续每次重试的等待时间翻倍,但不超过此值
|
||||||
|
max_backoff_ms: 4000
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 工具配置
|
||||||
|
# ==========================================
|
||||||
|
tools:
|
||||||
|
# ========== FFmpeg 工具 ==========
|
||||||
|
# 用于视频和音频的转换和处理
|
||||||
|
# 留空或 "ffmpeg" 表示使用系统 PATH 中的 ffmpeg
|
||||||
|
# 如 FFmpeg 未在 PATH 中,请指定完整路径
|
||||||
|
ffmpeg_path: "ffmpeg"
|
||||||
|
# 例子:
|
||||||
|
# ffmpeg_path: "C:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe"
|
||||||
|
# ffmpeg_path: "/usr/bin/ffmpeg"
|
||||||
|
|
||||||
|
# ========== AssetStudio CLI 工具(可选) ==========
|
||||||
|
# 用于解析 Unity AssetBundle 文件
|
||||||
|
# 如不配置,某些资源的精细解析功能可能不可用
|
||||||
|
# asset_studio_cli_path: "D:\\Workspace\\AssetStudio\\AssetStudioCLI\\bin\\Release\\net9.0\\AssetStudioModCLI.exe"
|
||||||
|
# asset_studio_cli_path: "/opt/AssetStudioCLI"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 并发配置
|
||||||
|
# ==========================================
|
||||||
|
# 各处理阶段的并发数量配置
|
||||||
|
# 数值越大,处理速度越快,但对系统资源占用也越大
|
||||||
|
concurrency:
|
||||||
|
# 同时下载的资源文件数(好像没用到)
|
||||||
|
download: 4
|
||||||
|
|
||||||
|
# 同时上传/传输的资源文件数(好像没用到)
|
||||||
|
upload: 4
|
||||||
|
|
||||||
|
# ACB 音频包解析的并发数
|
||||||
|
acb: 8
|
||||||
|
|
||||||
|
# USM 视频解析的并发数
|
||||||
|
usm: 4
|
||||||
|
|
||||||
|
# HCA 音频解码的并发数(通常可设置较大值)
|
||||||
|
hca: 16
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 地区配置
|
||||||
|
# ==========================================
|
||||||
|
# 定义支持的资源地区及其对应的数据源
|
||||||
|
regions:
|
||||||
|
# ==========================================
|
||||||
|
# 日本服务器配置
|
||||||
|
# ==========================================
|
||||||
|
jp:
|
||||||
|
# 是否启用该地区
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# ========== 资源提供者配置 ==========
|
||||||
|
provider:
|
||||||
|
# 提供者类型:colorful_palette 或 nuverse
|
||||||
|
kind: colorful_palette
|
||||||
|
|
||||||
|
# 资源包元信息 API 地址模板
|
||||||
|
# {env}:环境标识(production/staging 等)
|
||||||
|
# {hash}:配置哈希值
|
||||||
|
# {asset_version}:资源版本
|
||||||
|
# {asset_hash}:资源包哈希
|
||||||
|
asset_info_url_template: "https://{env}-{hash}-assetbundle-info.sekai.colorfulpalette.org/api/version/{asset_version}/{asset_hash}/os/ios"
|
||||||
|
|
||||||
|
# 资源包下载地址模板
|
||||||
|
# {bundle_path}:资源包路径
|
||||||
|
asset_bundle_url_template: "https://{env}-{hash}-assetbundle.sekai.colorfulpalette.org/{asset_version}/{asset_hash}/ios/{bundle_path}"
|
||||||
|
|
||||||
|
# 配置文件名(如 production)
|
||||||
|
profile: "production"
|
||||||
|
|
||||||
|
# 配置对应的哈希值映射表
|
||||||
|
profile_hashes:
|
||||||
|
production: "cf2d2388"
|
||||||
|
# staging: "12345678"
|
||||||
|
|
||||||
|
# 是否需要 Cookie
|
||||||
|
# 某些源需要 Cookie 才能访问(防盗链)
|
||||||
|
required_cookies: true
|
||||||
|
|
||||||
|
# 获取 Cookie 的 Bootstrap URL(可选)
|
||||||
|
# 如配置,服务器会先访问此 URL 获取 Cookie
|
||||||
|
# cookie_bootstrap_url: "https://example.com/bootstrap"
|
||||||
|
|
||||||
|
# ========== 加密配置 ==========
|
||||||
|
# 资源包的 AES 加密参数
|
||||||
|
crypto:
|
||||||
|
# AES 密钥(十六进制字符串)
|
||||||
|
aes_key_hex: "6732666343305a637a4e394d544a3631"
|
||||||
|
|
||||||
|
# AES 初始向量(十六进制字符串)
|
||||||
|
aes_iv_hex: "6d737833495630693958453575595a31"
|
||||||
|
|
||||||
|
# ========== 运行时配置 ==========
|
||||||
|
runtime:
|
||||||
|
# 资源对应的 Unity 版本
|
||||||
|
# 用于正确解析 AssetBundle
|
||||||
|
unity_version: "2022.3.21f1"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 中国服务器配置
|
||||||
|
# ==========================================
|
||||||
|
cn:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
provider:
|
||||||
|
# Nuverse 提供者(国服使用)
|
||||||
|
kind: nuverse
|
||||||
|
|
||||||
|
# 获取资源版本的 API 地址
|
||||||
|
# {app_version}:应用版本
|
||||||
|
asset_version_url: "https://lf3-mkcncdn-tos.dailygn.com/obj/rt-game-lf/gdl_app_5236/Mainland/{app_version}/Release/cn_online/ios/version"
|
||||||
|
|
||||||
|
# 资源包元信息 API 地址模板
|
||||||
|
# {asset_version}:资源版本
|
||||||
|
asset_info_url_template: "https://lf3-mkcncdn-tos.dailygn.com/obj/sf-game-lf/gdl_app_5236/AssetBundle/{app_version}/Release/cn_online/ios{asset_version}/AssetBundleInfoNew.json"
|
||||||
|
|
||||||
|
# 资源包下载地址模板
|
||||||
|
# {app_version}:应用版本
|
||||||
|
# {bundle_path}:资源包路径
|
||||||
|
asset_bundle_url_template: "https://lf3-mkcncdn-tos.dailygn.com/obj/sf-game-lf/gdl_app_5236/AssetBundle/{app_version}/Release/cn_online/{bundle_path}"
|
||||||
|
|
||||||
|
# 是否需要 Cookie
|
||||||
|
required_cookies: false
|
||||||
|
|
||||||
|
# cookie_bootstrap_url: null
|
||||||
|
|
||||||
|
crypto:
|
||||||
|
aes_key_hex: "6732666343305a637a4e394d544a3631"
|
||||||
|
aes_iv_hex: "6d737833495630693958453575595a31"
|
||||||
|
|
||||||
|
runtime:
|
||||||
|
unity_version: "2022.3.21f1"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 其他地区配置示例(禁用)
|
||||||
|
# ==========================================
|
||||||
|
# tw:
|
||||||
|
# enabled: false
|
||||||
|
# provider:
|
||||||
|
# kind: colorful_palette
|
||||||
|
# asset_info_url_template: "https://{env}-{hash}-assetbundle-info.sekai.colorfulpalette.org/api/version/{asset_version}/{asset_hash}/os/ios"
|
||||||
|
# asset_bundle_url_template: "https://{env}-{hash}-assetbundle.sekai.colorfulpalette.org/{asset_version}/{asset_hash}/ios/{bundle_path}"
|
||||||
|
# profile: "production"
|
||||||
|
# profile_hashes:
|
||||||
|
# production: "cf2d2388"
|
||||||
|
# required_cookies: true
|
||||||
|
# crypto:
|
||||||
|
# aes_key_hex: "6732666343305a637a4e394d544a3631"
|
||||||
|
# aes_iv_hex: "6d737833495630693958453575595a31"
|
||||||
|
# runtime:
|
||||||
|
# unity_version: "2022.3.21f1"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 配置说明
|
||||||
|
# ==========================================
|
||||||
|
#
|
||||||
|
# 【服务器配置】
|
||||||
|
# - 可配置多个监听地址,支持多个客户端连接
|
||||||
|
# - 每个监听配置需要不同的 token 来区分认证
|
||||||
|
# - cert 和 key 配置是可选的:
|
||||||
|
# * 配置了:支持 TLS 加密握手 + 明文握手(双模式)
|
||||||
|
# * 未配置:仅支持明文握手
|
||||||
|
# - 如需主动连出,可额外配置 `client` 区块
|
||||||
|
#
|
||||||
|
# 【认证机制】
|
||||||
|
# - client 中的 token 必须与某个 server 配置中的 token 匹配
|
||||||
|
# - 握手时会验证 token,不匹配则拒绝连接
|
||||||
|
#
|
||||||
|
# 【TLS 加密】
|
||||||
|
# - 加密范围:Identity 交换(身份验证)阶段
|
||||||
|
# - H2 通信(实际数据传输)始终不加密,基于 TCP 流
|
||||||
|
# - 证书应该是 X.509 格式的 PEM 编码文件
|
||||||
|
#
|
||||||
|
# 【资源源配置】
|
||||||
|
# - 支持两种提供者:
|
||||||
|
# * colorful_palette:日服资源源
|
||||||
|
# * nuverse:国服资源源
|
||||||
|
# - 每个提供者有不同的 API 地址格式
|
||||||
|
#
|
||||||
|
# 【并发控制】
|
||||||
|
# - 合理设置并发数可提升处理速度
|
||||||
|
# - 过高可能导致网络压力或系统资源不足
|
||||||
|
# - 建议:download/upload 4-8,hca 16,其他 4-8
|
||||||
|
#
|
||||||
|
# 【版本信息】
|
||||||
|
# - 客户端会根据 region 字段从服务器获取该地区的配置
|
||||||
|
# - 确保客户端 profiles 中的 region 值与服务器的地区名称一致
|
||||||
|
#
|
||||||
|
# 【禁用地区】
|
||||||
|
# - 将 enabled 设为 false 可禁用某个地区
|
||||||
|
# - 禁用的地区客户端无法同步
|
||||||
|
#
|
||||||
|
# 【代理配置】
|
||||||
|
# - 如果服务器需要通过代理访问资源源,在 execution.proxy 中配置
|
||||||
|
# - 支持 HTTP、HTTPS、SOCKS5 代理
|
||||||
|
#
|
||||||
|
# 【工具路径】
|
||||||
|
# - 确保 ffmpeg 和 AssetStudioCLI 可从配置的路径访问
|
||||||
|
# - 如在 PATH 中,可直接写命令名称
|
||||||
|
# - 否则需要提供完整的绝对路径
|
||||||
|
#
|
||||||
|
# 【角色说明】
|
||||||
|
# - 角色由连接方向决定,不由可执行文件名称决定
|
||||||
|
# - 同一进程可只开 `client`、只开 `server`,或两者同时开启
|
||||||
|
|
||||||
|
|
||||||
43
server.DOCKERFILE
Normal file
43
server.DOCKERFILE
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
FROM rust:slim-bookworm AS builder
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
RUN cargo build --release
|
||||||
|
RUN apt-get update && apt-get install -y musl-tools pkg-config libssl-dev
|
||||||
|
RUN rustup target add x86_64-unknown-linux-musl
|
||||||
|
COPY . .
|
||||||
|
RUN cargo build --target x86_64-unknown-linux-musl --release --bin client
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim AS assetstudio-builder
|
||||||
|
WORKDIR /src
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN git clone --depth 1 --single-branch --branch sekai-modify https://github.com/Team-Haruki/AssetStudio.git
|
||||||
|
RUN cd AssetStudio/AssetStudioCLI && \
|
||||||
|
dotnet publish -c Release -r linux-x64 -f net9.0 --self-contained true -o /app/assetstudio \
|
||||||
|
-p:PublishTrimmed=false \
|
||||||
|
-p:PublishSingleFile=true \
|
||||||
|
-p:IncludeNativeLibrariesForSelfExtract=true
|
||||||
|
|
||||||
|
FROM mwader/static-ffmpeg:7.1.1 AS ffmpeg-builder
|
||||||
|
|
||||||
|
FROM debian:trixie-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
libicu76 \
|
||||||
|
libxml2 && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/target/release/server /app/server
|
||||||
|
COPY --from=assetstudio-builder /app/assetstudio /app/server
|
||||||
|
COPY --from=ffmpeg-builder /ffmpeg /usr/local/bin/ffmpeg
|
||||||
|
RUN ln -sf /app/assetstudio/AssetStudioModCLI /app/assetstudio/AssetStudioCLI && \
|
||||||
|
mkdir -p logs
|
||||||
|
|
||||||
|
ENV TZ=Asia/Shanghai \
|
||||||
|
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["./server"]
|
||||||
Loading…
x
Reference in New Issue
Block a user