mirror of
https://github.com/Grasscutters/Cultivation.git
synced 2025-12-12 15:14:35 +01:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ef50b889b | ||
|
|
d9b820c842 | ||
|
|
986259d96b | ||
|
|
97454de75e | ||
|
|
f61f4eed51 | ||
|
|
99b45ddf52 | ||
|
|
fafec01fe3 | ||
|
|
0c910b7317 | ||
|
|
6f2be3c5a5 | ||
|
|
d2b8124877 | ||
|
|
247150c62a | ||
|
|
1599c37100 | ||
|
|
ecb7936a8f | ||
|
|
a40080cca2 | ||
|
|
364d138779 | ||
|
|
f03cc0a09f | ||
|
|
7750266a3d | ||
|
|
028ee380f2 | ||
|
|
fcd08cace5 | ||
|
|
0258aa006a | ||
|
|
0370576c11 | ||
|
|
8c10c00b53 | ||
|
|
fe094c952b | ||
|
|
63a883cf1d | ||
|
|
8207260968 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@
|
||||
|
||||
# production
|
||||
/build
|
||||
/target
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cultivation",
|
||||
"version": "1.5.5",
|
||||
"version": "1.7.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.0.0-rc.5",
|
||||
|
||||
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -959,7 +959,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "cultivation"
|
||||
version = "1.5.5"
|
||||
version = "1.6.3"
|
||||
dependencies = [
|
||||
"anime-launcher-sdk",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "cultivation"
|
||||
version = "1.5.5"
|
||||
version = "1.6.3"
|
||||
description = "A custom launcher for anime game."
|
||||
authors = ["KingRainbow44", "SpikeHD"]
|
||||
license = ""
|
||||
repository = "https://github.com/Grasscutters/Cultivation.git"
|
||||
default-run = "cultivation"
|
||||
edition = "2021"
|
||||
rust-version = "1.58"
|
||||
rust-version = "1.57"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "删除 webCaches 文件夹",
|
||||
"launch_args": "启动参数",
|
||||
"offline_mode": "离线模式",
|
||||
"fix_res": "修复登录超时"
|
||||
"fix_res": "修复登录超时",
|
||||
"show_version": "在按钮上显示游戏版本",
|
||||
"save_profile": "保存配置配置文件"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "下载 Grasscutter 一体化",
|
||||
"grasscutter_fullquest": "下载 5.3 一体化",
|
||||
"grasscutter_fullquest": "下载 6.1 一体化",
|
||||
"grasscutter_stable_data": "下载 Grasscutter 稳定版数据",
|
||||
"grasscutter_latest_data": "下载 Grasscutter 开发版数据",
|
||||
"grasscutter_stable_data_update": "更新 Grasscutter 稳定版数据",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "刪除 webCaches 文件夾",
|
||||
"launch_args": "啟動參數",
|
||||
"offline_mode": "離線模式",
|
||||
"fix_res": "修復登入逾時"
|
||||
"fix_res": "修復登入逾時",
|
||||
"show_version": "在按鈕上顯示遊戲版本",
|
||||
"save_profile": "儲存配置設定檔"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "下載Grasscutter多合一下載",
|
||||
"grasscutter_fullquest": "下载 5.3 一体化",
|
||||
"grasscutter_fullquest": "下载 6.1 一体化",
|
||||
"grasscutter_stable_data": "下載Grasscutter穩定版數據(Data)",
|
||||
"grasscutter_latest_data": "下載Grasscutter開發板數據(Data)",
|
||||
"grasscutter_stable_data_update": "更新Grasscutter穩定版數據(Data)",
|
||||
|
||||
@@ -39,11 +39,13 @@
|
||||
"web_cache": "WebCaches-Ordner löschen",
|
||||
"launch_args": "Start-Argumente",
|
||||
"offline_mode": "Offline-Modus",
|
||||
"fix_res": "Login-Zeitüberschreitung beheben"
|
||||
"fix_res": "Login-Zeitüberschreitung beheben",
|
||||
"show_version": "Spielversion in Schaltflächen anzeigen",
|
||||
"save_profile": "Profil speichern"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Grasscutter All-in-One herunterladen",
|
||||
"grasscutter_fullquest": "5.3 All-in-One herunterladen",
|
||||
"grasscutter_fullquest": "6.1 All-in-One herunterladen",
|
||||
"grasscutter_stable_data": "Stabile Grasscutter-Daten herunterladen",
|
||||
"grasscutter_latest_data": "Neueste Grasscutter-Daten herunterladen",
|
||||
"grasscutter_stable_data_update": "Stabile Grasscutter-Daten aktualisieren",
|
||||
|
||||
@@ -39,11 +39,13 @@
|
||||
"web_cache": "Delete webCaches folder",
|
||||
"launch_args": "Launch Args",
|
||||
"offline_mode": "Offline Mode",
|
||||
"fix_res": "Fix Login Timeout"
|
||||
"fix_res": "Fix Login Timeout",
|
||||
"show_version": "Show game version in buttons",
|
||||
"save_profile": "Save profile"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Download Grasscutter All-in-One",
|
||||
"grasscutter_fullquest": "Download 5.3 All-in-One",
|
||||
"grasscutter_fullbuild": "Download Grasscutter 4.0 All-in-One",
|
||||
"grasscutter_fullquest": "Download 6.1 All-in-One",
|
||||
"grasscutter_stable_data": "Download Grasscutter Stable Data",
|
||||
"grasscutter_latest_data": "Download Grasscutter Latest Data",
|
||||
"grasscutter_stable_data_update": "Update Grasscutter Stable Data",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "Eliminar la carpeta webCaches",
|
||||
"launch_args": "Args de lanzamiento",
|
||||
"offline_mode": "Modo sin conexión",
|
||||
"fix_res": "Reparar el tiempo de espera"
|
||||
"fix_res": "Reparar el tiempo de espera",
|
||||
"show_version": "Mostrar versión del juego en botones",
|
||||
"save_profile": "Guardar perfil"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Descargar datos todo en uno de Grasscutter",
|
||||
"grasscutter_fullquest": "Descargar datos todo en uno de 5.3",
|
||||
"grasscutter_fullquest": "Descargar datos todo en uno de 6.1",
|
||||
"grasscutter_stable_data": "Descargar datos Estables de Grasscutter",
|
||||
"grasscutter_latest_data": "Descargar datos más Recientes de Grasscutter",
|
||||
"grasscutter_stable_data_update": "Actualizar datos estables de Grasscutter",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "Supprimer le dossier webCaches",
|
||||
"launch_args": "Arguments de lancement",
|
||||
"offline_mode": "Mode hors ligne",
|
||||
"fix_res": "Réparation du login"
|
||||
"fix_res": "Réparation du login",
|
||||
"show_version": "Afficher la version du jeu sur les boutons",
|
||||
"save_profile": "Enregistrer le profil"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Telecharger Grasscutter tout-en-un",
|
||||
"grasscutter_fullquest": "Télécharger les 5.3 tout-en-un",
|
||||
"grasscutter_fullquest": "Télécharger les 6.1 tout-en-un",
|
||||
"grasscutter_stable_data": "Télécharger les donnees de Grasscutter (version stable)",
|
||||
"grasscutter_latest_data": "Télécharger les donnees de Grasscutter (derniere version)",
|
||||
"grasscutter_stable_data_update": "Mettre à jour les données de Grasscutter (version stable)",
|
||||
|
||||
@@ -36,11 +36,13 @@
|
||||
"web_cache": "Hapus folder webCaches",
|
||||
"launch_args": "Luncurkan Args",
|
||||
"offline_mode": "Mode Offline",
|
||||
"fix_res": "Perbaiki batas waktu login"
|
||||
"fix_res": "Perbaiki batas waktu login",
|
||||
"show_version": "Tampilkan versi game pada tombol",
|
||||
"save_profile": "Simpan profil"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Sedang Mendownload Grasscutter Semua Dalam Satu",
|
||||
"grasscutter_fullquest": "Unduh 5.3 semua dalam satu",
|
||||
"grasscutter_fullquest": "Unduh 6.1 semua dalam satu",
|
||||
"grasscutter_stable_data": "Sedang Mendownload Grasscutter Versi Stabil",
|
||||
"grasscutter_latest_data": "Sedang Mendownload Grasscutter Data Terbaru",
|
||||
"grasscutter_stable_data_update": "Memperbaharui Grasscutter Data Stabil",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "Elimina la cartella webCaches",
|
||||
"launch_args": "Argomenti di lancio",
|
||||
"offline_mode": "Modalità Offline",
|
||||
"fix_res": "Correggere il timeout dell'accesso"
|
||||
"fix_res": "Correggere il timeout dell'accesso",
|
||||
"show_version": "Mostra la versione del gioco sui pulsanti",
|
||||
"save_profile": "Salva il profilo"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Scarica Grasscutter Tutto-in-Uno",
|
||||
"grasscutter_fullquest": "Scarica 5.3 Tutto-in-Uno",
|
||||
"grasscutter_fullquest": "Scarica 6.1 Tutto-in-Uno",
|
||||
"grasscutter_stable_data": "Scarica i dati di Grasscutter Stabili",
|
||||
"grasscutter_latest_data": "Scarica i dati di Grasscutter Più Recenti",
|
||||
"grasscutter_stable_data_update": "Aggiorna i dati di Grasscutter Stabili",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"check_aagl": "その他のオプションは、他のランチャーをチェックしてください",
|
||||
"grasscutter_elevation": "制限されたポートでのGCの実行方法",
|
||||
"web_cache": "webCachesフォルダを削除",
|
||||
"launch_args": "Launch Args"
|
||||
"launch_args": "Launch Args",
|
||||
"show_version": "ボタンにゲームバージョンを表示",
|
||||
"save_profile": "プロフィールを保存"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Grasscutter All-in-Oneをダウンロード",
|
||||
"grasscutter_fullquest": "5.3 All-in-Oneをダウンロード",
|
||||
"grasscutter_fullquest": "6.1 All-in-Oneをダウンロード",
|
||||
"grasscutter_stable_data": "Grasscutter安定版データファイルをダウンロード",
|
||||
"grasscutter_latest_data": "Grasscutter最新版データファイルをダウンロード",
|
||||
"grasscutter_stable_data_update": "Grasscutter安定版データファイルをアップデート",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "webCaches 폴더 삭제",
|
||||
"launch_args": "실행 인수",
|
||||
"offline_mode": "오프라인 모드",
|
||||
"fix_res": "로그인 시간 초과 수정"
|
||||
"fix_res": "로그인 시간 초과 수정",
|
||||
"show_version": "버튼에 게임 버전 표시",
|
||||
"save_profile": "프로필 저장"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "올인원 Grasscutter 다운로드",
|
||||
"grasscutter_fullquest": "5.3 올인원 다운로드",
|
||||
"grasscutter_fullquest": "6.1 올인원 다운로드",
|
||||
"grasscutter_stable_data": "안정적인 데이터 다운로드",
|
||||
"grasscutter_latest_data": "최신 데이터 다운로드",
|
||||
"grasscutter_stable_data_update": "안정적 데이터 업데이트",
|
||||
|
||||
@@ -35,11 +35,13 @@
|
||||
"web_cache": "Dzēsiet mapi WebCaches",
|
||||
"launch_args": "Palaišanas args",
|
||||
"offline_mode": "Bezsaistes režīms",
|
||||
"fix_res": "Fiksēt pieteikšanās laika"
|
||||
"fix_res": "Fiksēt pieteikšanās laika",
|
||||
"show_version": "Pogās redzamā spēles versija",
|
||||
"save_profile": "Saglabāt profilu"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Lejupielādējiet Grasscutter viss vienā",
|
||||
"grasscutter_fullquest": "Lejupielādēt 5.3 viss vienā",
|
||||
"grasscutter_fullquest": "Lejupielādēt 6.1 viss vienā",
|
||||
"grasscutter_stable_data": "Lejupielādējiet Grasscutter stabilos datus",
|
||||
"grasscutter_latest_data": "Lejupielādējiet Grasscutter jaunākos datus",
|
||||
"grasscutter_stable_data_update": "Atjauniniet Grasscutter stabilos datus",
|
||||
|
||||
@@ -36,11 +36,13 @@
|
||||
"web_cache": "Verwijder de webCaches-map",
|
||||
"launch_args": "Args starten",
|
||||
"offline_mode": "Offline Modus",
|
||||
"fix_res": "Time-out inloggen verhelpen"
|
||||
"fix_res": "Time-out inloggen verhelpen",
|
||||
"show_version": "Spelversie weergegeven op knoppen",
|
||||
"save_profile": "Profiel opslaan"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Grasscutter Alles-in-één Downloaden",
|
||||
"grasscutter_fullquest": "Alles-in-één 5.3 downloaden",
|
||||
"grasscutter_fullquest": "Alles-in-één 6.1 downloaden",
|
||||
"grasscutter_stable_data": "Download Stabiele Gegevens Van Grasscutter",
|
||||
"grasscutter_latest_data": "Download De Nieuwste Gegevens Van Grasscutter",
|
||||
"grasscutter_stable_data_update": "Stabiele gegevens Van Grasscutter bijwerken",
|
||||
|
||||
@@ -39,11 +39,13 @@
|
||||
"web_cache": "Usuń folder webCaches",
|
||||
"launch_args": "Argumenty uruchamiania",
|
||||
"offline_mode": "Tryb offline",
|
||||
"fix_res": "Napraw limit czasu logowania"
|
||||
"fix_res": "Napraw limit czasu logowania",
|
||||
"show_version": "Wersja gry wyświetlana na przyciskach",
|
||||
"save_profile": "Zapisz profil"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Pobierz Grasscutter (wszystko w jednym)",
|
||||
"grasscutter_fullquest": "Pobierz 5.3 (wszystko w jednym)",
|
||||
"grasscutter_fullquest": "Pobierz 6.1 (wszystko w jednym)",
|
||||
"grasscutter_stable_data": "Pobierz stabilne dane Grasscuttera",
|
||||
"grasscutter_latest_data": "Pobierz najnowsze dane Grasscuttera",
|
||||
"grasscutter_stable_data_update": "Zaaktualizuj stabilne dane Grasscuttera",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "Excluir pasta webCaches",
|
||||
"launch_args": "Argumentos de lançamento",
|
||||
"offline_mode": "Modo offline",
|
||||
"fix_res": "Corrigir o tempo limite de login"
|
||||
"fix_res": "Corrigir o tempo limite de login",
|
||||
"show_version": "Versão do jogo exibida nos botões",
|
||||
"save_profile": "Salvar perfil"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Baixar o Grasscutter Tudo-em-Um",
|
||||
"grasscutter_fullquest": "Baixar de 5.3 em um só lugar",
|
||||
"grasscutter_fullquest": "Baixar de 6.1 em um só lugar",
|
||||
"grasscutter_stable_data": "Baixar os Dados do Grasscutter Estável",
|
||||
"grasscutter_latest_data": "Baixar os Dados do Grasscutter Mais Recente",
|
||||
"grasscutter_stable_data_update": "Atualizar os Dados do Grasscutter Estável",
|
||||
|
||||
@@ -36,11 +36,13 @@
|
||||
"web_cache": "Удалить папку webCaches",
|
||||
"launch_args": "Параметры запуска",
|
||||
"offline_mode": "Автономный режим",
|
||||
"fix_res": "Исправить таймаут входа в систему"
|
||||
"fix_res": "Исправить таймаут входа в систему",
|
||||
"show_version": "Версия игры отображается на кнопках",
|
||||
"save_profile": "Сохранить профиль"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Скачать все в одном Grasscutter",
|
||||
"grasscutter_fullquest": "Скачать 5.3 все в одном",
|
||||
"grasscutter_fullquest": "Скачать 6.1 все в одном",
|
||||
"grasscutter_stable_data": "Скачать стабильные данные Grasscutter",
|
||||
"grasscutter_latest_data": "Скачать последние данные Grasscutter",
|
||||
"grasscutter_stable_data_update": "Обновить стабильные данные Grasscutter",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"web_cache": "Xóa thư mục webCaches",
|
||||
"launch_args": "Khởi chạy đối số",
|
||||
"offline_mode": "Chế độ ngoại tuyến",
|
||||
"fix_res": "Sửa lỗi hết thời gian đăng nhập"
|
||||
"fix_res": "Sửa lỗi hết thời gian đăng nhập",
|
||||
"show_version": "Hiển thị phiên bản trò chơi trên các nút",
|
||||
"save_profile": "Lưu hồ sơ"
|
||||
},
|
||||
"downloads": {
|
||||
"grasscutter_fullbuild": "Tải Grasscutter tất cả trong một",
|
||||
"grasscutter_fullquest": "Tải 5.3 tất cả trong một",
|
||||
"grasscutter_fullquest": "Tải 6.1 tất cả trong một",
|
||||
"grasscutter_stable_data": "Tải dữ liệu Grasscutter bản ổn định",
|
||||
"grasscutter_latest_data": "Tải dữ liệu Grasscutter bản mới nhất",
|
||||
"grasscutter_stable_data_update": "Cập nhật dữ liệu Grasscutter bản ổn định",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src-tauri/patch/5version.dll
Normal file
BIN
src-tauri/patch/5version.dll
Normal file
Binary file not shown.
BIN
src-tauri/patch/6version.dll
Normal file
BIN
src-tauri/patch/6version.dll
Normal file
Binary file not shown.
@@ -30,20 +30,33 @@ pub struct Configuration {
|
||||
pub redirect_more: Option<bool>,
|
||||
pub launch_args: Option<String>,
|
||||
pub offline_mode: Option<bool>,
|
||||
pub show_version: Option<bool>,
|
||||
pub profile: Option<String>,
|
||||
}
|
||||
|
||||
pub fn config_path() -> PathBuf {
|
||||
pub fn config_path(profile: String) -> PathBuf {
|
||||
let mut path = tauri::api::path::data_dir().unwrap();
|
||||
path.push("cultivation");
|
||||
path.push("configuration.json");
|
||||
if profile.as_str() == "default" {
|
||||
path.push("configuration.json");
|
||||
} else {
|
||||
path.push("profiles");
|
||||
path.push(profile + ".json");
|
||||
}
|
||||
|
||||
path
|
||||
}
|
||||
|
||||
pub fn get_config() -> Configuration {
|
||||
let path = config_path();
|
||||
pub fn get_config(profile_name: String) -> Configuration {
|
||||
let path = config_path(profile_name.clone());
|
||||
let config = std::fs::read_to_string(path).unwrap_or("{}".to_string());
|
||||
let config: Configuration = serde_json::from_str(&config).unwrap_or_default();
|
||||
|
||||
//let default = String::from("default");
|
||||
let prof = config.profile.clone().unwrap_or_default();
|
||||
if prof != String::from("default") && prof != profile_name.clone() {
|
||||
return get_config(prof.clone());
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ async fn parse_args(inp: &Vec<String>) -> Result<Args, ArgsError> {
|
||||
|
||||
args.parse(inp).unwrap();
|
||||
|
||||
let config = config::get_config();
|
||||
let config = config::get_config(String::from("default"));
|
||||
|
||||
if args.value_of("help")? {
|
||||
println!("{}", args.full_usage());
|
||||
@@ -207,6 +207,7 @@ fn main() -> Result<(), ArgsError> {
|
||||
is_grasscutter_running,
|
||||
restart_grasscutter,
|
||||
get_theme_list,
|
||||
get_profile_list,
|
||||
system_helpers::run_command,
|
||||
system_helpers::run_program,
|
||||
system_helpers::run_program_args,
|
||||
@@ -536,3 +537,20 @@ async fn get_theme_list(data_dir: String) -> Vec<HashMap<String, String>> {
|
||||
|
||||
themes
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_profile_list(data_dir: String) -> Vec<String> {
|
||||
let profile_loc = format!("{}/profiles", data_dir);
|
||||
|
||||
// Ensure folder exists
|
||||
if !std::path::Path::new(&profile_loc).exists() {
|
||||
std::fs::create_dir_all(&profile_loc).unwrap();
|
||||
}
|
||||
|
||||
let mut p_list = Vec::new();
|
||||
for entry in std::fs::read_dir(&profile_loc).unwrap() {
|
||||
p_list.push(entry.unwrap().file_name().into_string().unwrap());
|
||||
}
|
||||
|
||||
p_list
|
||||
}
|
||||
|
||||
@@ -50,79 +50,80 @@ struct WhatToUnpach {
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tauri::command]
|
||||
pub async fn patch_game(newer_game: bool, version: String) -> bool {
|
||||
pub async fn patch_game(_newer_game: bool, version: String) -> bool {
|
||||
let mut patch_path;
|
||||
// Altpatch first - Now using as hoyonet switch
|
||||
if newer_game {
|
||||
let alt_patch_path = PathBuf::from(system_helpers::install_location()).join("altpatch");
|
||||
// People keep using this when they shouldn't, 99.8% of people will never need it. Just remove for now.
|
||||
// if newer_game {
|
||||
// let alt_patch_path = PathBuf::from(system_helpers::install_location()).join("altpatch");
|
||||
|
||||
// Should handle overwriting backup with new version backup later
|
||||
let backup_path = PathBuf::from(system_helpers::install_location())
|
||||
.join("altpatch/original-mihoyonet.dll")
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let backup_exists = file_helpers::does_file_exist(&backup_path);
|
||||
// // Should handle overwriting backup with new version backup later
|
||||
// let backup_path = PathBuf::from(system_helpers::install_location())
|
||||
// .join("altpatch/original-mihoyonet.dll")
|
||||
// .to_str()
|
||||
// .unwrap()
|
||||
// .to_string();
|
||||
// let backup_exists = file_helpers::does_file_exist(&backup_path);
|
||||
|
||||
if !backup_exists {
|
||||
let backup = file_helpers::copy_file_with_new_name(
|
||||
get_game_rsa_path().await.unwrap()
|
||||
+ &String::from("/GenshinImpact_Data/Plugins/mihoyonet.dll"),
|
||||
alt_patch_path.clone().to_str().unwrap().to_string(),
|
||||
String::from("original-mihoyonet.dll"),
|
||||
);
|
||||
// if !backup_exists {
|
||||
// let backup = file_helpers::copy_file_with_new_name(
|
||||
// get_game_rsa_path().await.unwrap()
|
||||
// + &String::from("/GenshinImpact_Data/Plugins/mihoyonet.dll"),
|
||||
// alt_patch_path.clone().to_str().unwrap().to_string(),
|
||||
// String::from("original-mihoyonet.dll"),
|
||||
// );
|
||||
|
||||
if !backup {
|
||||
println!("Unable to backup file!");
|
||||
}
|
||||
}
|
||||
// if !backup {
|
||||
// println!("Unable to backup file!");
|
||||
// }
|
||||
// }
|
||||
|
||||
patch_path = PathBuf::from(system_helpers::install_location()).join("altpatch/mihoyonet.dll");
|
||||
// Copy the other part of patch to game files
|
||||
let alt_replaced = file_helpers::copy_file_with_new_name(
|
||||
patch_path.clone().to_str().unwrap().to_string(),
|
||||
get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins"),
|
||||
String::from("mihoyonet.dll"),
|
||||
);
|
||||
// patch_path = PathBuf::from(system_helpers::install_location()).join("altpatch/mihoyonet.dll");
|
||||
// // Copy the other part of patch to game files
|
||||
// let alt_replaced = file_helpers::copy_file_with_new_name(
|
||||
// patch_path.clone().to_str().unwrap().to_string(),
|
||||
// get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins"),
|
||||
// String::from("mihoyonet.dll"),
|
||||
// );
|
||||
|
||||
if !alt_replaced {
|
||||
return false;
|
||||
}
|
||||
// if !alt_replaced {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/*** For replacing old backup file with new one, for example when version changes
|
||||
* Currently replaces when it shouldn't. Will figure it out when it matters
|
||||
* ***/
|
||||
// else {
|
||||
// // Check if game file matches backup
|
||||
// let matching_alt_backup = file_helpers::are_files_identical(
|
||||
// &backup_path.clone(),
|
||||
// PathBuf::from(get_game_rsa_path().await.unwrap())
|
||||
// .join("/GenshinImpact_Data/Plugins/mihoyonet.dll")
|
||||
// .to_str()
|
||||
// .unwrap(),
|
||||
// );
|
||||
/*** For replacing old backup file with new one, for example when version changes
|
||||
* Currently replaces when it shouldn't. Will figure it out when it matters
|
||||
* ***/
|
||||
// else {
|
||||
// // Check if game file matches backup
|
||||
// let matching_alt_backup = file_helpers::are_files_identical(
|
||||
// &backup_path.clone(),
|
||||
// PathBuf::from(get_game_rsa_path().await.unwrap())
|
||||
// .join("/GenshinImpact_Data/Plugins/mihoyonet.dll")
|
||||
// .to_str()
|
||||
// .unwrap(),
|
||||
// );
|
||||
|
||||
// let is_alt_patched = file_helpers::are_files_identical(
|
||||
// PathBuf::from(system_helpers::install_location()).join("altpatch/mihoyonet.dll").to_str().unwrap(),
|
||||
// PathBuf::from(get_game_rsa_path().await.unwrap())
|
||||
// .join("/GenshinImpact_Data/Plugins/mihoyonet.dll")
|
||||
// .to_str()
|
||||
// .unwrap(),
|
||||
// );
|
||||
// let is_alt_patched = file_helpers::are_files_identical(
|
||||
// PathBuf::from(system_helpers::install_location()).join("altpatch/mihoyonet.dll").to_str().unwrap(),
|
||||
// PathBuf::from(get_game_rsa_path().await.unwrap())
|
||||
// .join("/GenshinImpact_Data/Plugins/mihoyonet.dll")
|
||||
// .to_str()
|
||||
// .unwrap(),
|
||||
// );
|
||||
|
||||
// // Check if already alt patched
|
||||
// if !matching_alt_backup {
|
||||
// // Copy new backup if it is not patched
|
||||
// if !is_alt_patched {
|
||||
// file_helpers::copy_file_with_new_name(
|
||||
// get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins/mihoyonet.dll"),
|
||||
// alt_patch_path.clone().to_str().unwrap().to_string(),
|
||||
// String::from("original-mihoyonet.dll"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// // Check if already alt patched
|
||||
// if !matching_alt_backup {
|
||||
// // Copy new backup if it is not patched
|
||||
// if !is_alt_patched {
|
||||
// file_helpers::copy_file_with_new_name(
|
||||
// get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins/mihoyonet.dll"),
|
||||
// alt_patch_path.clone().to_str().unwrap().to_string(),
|
||||
// String::from("original-mihoyonet.dll"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Standard patch
|
||||
patch_path = PathBuf::from(system_helpers::install_location()).join("patch/version.dll");
|
||||
@@ -152,8 +153,14 @@ pub async fn patch_game(newer_game: bool, version: String) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
// For 5.0 and up
|
||||
// For 5.0 and up use universal
|
||||
if i_ver > 49 {
|
||||
if i_ver < 59 {
|
||||
patch_path = PathBuf::from(system_helpers::install_location()).join("patch/5version.dll");
|
||||
} else {
|
||||
// 6.0 patch not checked/tested if works for old vers, so separate
|
||||
patch_path = PathBuf::from(system_helpers::install_location()).join("patch/6version.dll");
|
||||
}
|
||||
let replaced50 = file_helpers::copy_file_with_new_name(
|
||||
patch_path.clone().to_str().unwrap().to_string(),
|
||||
get_game_rsa_path().await.unwrap(),
|
||||
@@ -342,7 +349,7 @@ pub async fn unpatch_game() -> bool {
|
||||
}
|
||||
|
||||
pub async fn get_game_rsa_path() -> Option<String> {
|
||||
let config = config::get_config();
|
||||
let config = config::get_config(String::from("default"));
|
||||
|
||||
config.game_install_path.as_ref()?;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "Cultivation",
|
||||
"version": "1.5.5"
|
||||
"version": "1.7.2"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
@@ -67,11 +67,13 @@
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
"transparent": true,
|
||||
"height": 730,
|
||||
"resizable": true,
|
||||
"title": "Cultivation",
|
||||
"width": 1280,
|
||||
"decorations": false
|
||||
"decorations": false,
|
||||
"center": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -170,6 +170,8 @@ export class Main extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
// Ensure old configs are updated to use RSA
|
||||
const updatedProfile = await getConfigOption('profile')
|
||||
await setConfigOption('profile', updatedProfile)
|
||||
const updatedConfig = await getConfigOption('patch_rsa')
|
||||
await setConfigOption('patch_rsa', updatedConfig)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
}
|
||||
|
||||
#playButton > div {
|
||||
margin-bottom: 6px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
#playButton .BigButton {
|
||||
@@ -26,10 +26,27 @@
|
||||
|
||||
#serverControls {
|
||||
color: white;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
text-shadow: 1px 1px 8px black;
|
||||
}
|
||||
|
||||
#menuOptionsContainerProfiles {
|
||||
justify-self: right;
|
||||
align-self: right;
|
||||
padding-left: 8px;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
#serverControls select {
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
border: none;
|
||||
border-bottom: 2px solid #cecece;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.BottomSection .CheckboxDisplay {
|
||||
border-color: #c5c5c5;
|
||||
background: #fff;
|
||||
|
||||
@@ -3,7 +3,7 @@ import Checkbox from './common/Checkbox'
|
||||
import BigButton from './common/BigButton'
|
||||
import TextInput from './common/TextInput'
|
||||
import HelpButton from './common/HelpButton'
|
||||
import { getConfig, saveConfig, setConfigOption } from '../../utils/configuration'
|
||||
import { getConfig, saveConfig, setConfigOption, setProfileOption } from '../../utils/configuration'
|
||||
import { translate } from '../../utils/language'
|
||||
import { invoke } from '@tauri-apps/api/tauri'
|
||||
|
||||
@@ -43,6 +43,8 @@ interface IState {
|
||||
migotoSet: boolean
|
||||
|
||||
unElevated: boolean
|
||||
profile: string
|
||||
profiles: string[]
|
||||
}
|
||||
|
||||
export default class ServerLaunchSection extends React.Component<IProps, IState> {
|
||||
@@ -66,6 +68,8 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
akebiSet: false,
|
||||
migotoSet: false,
|
||||
unElevated: false,
|
||||
profile: 'default',
|
||||
profiles: ['default'],
|
||||
}
|
||||
|
||||
this.toggleGrasscutter = this.toggleGrasscutter.bind(this)
|
||||
@@ -75,6 +79,7 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
this.toggleHttps = this.toggleHttps.bind(this)
|
||||
this.launchServer = this.launchServer.bind(this)
|
||||
this.setButtonLabel = this.setButtonLabel.bind(this)
|
||||
this.setProfile = this.setProfile.bind(this)
|
||||
|
||||
listen('start_grasscutter', async () => {
|
||||
this.launchServer()
|
||||
@@ -102,6 +107,8 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
akebiSet: config.akebi_path !== '',
|
||||
migotoSet: config.migoto_path !== '',
|
||||
unElevated: config.un_elevated || false,
|
||||
profile: config.profile || 'default',
|
||||
profiles: (await this.getProfileList()).map((t) => t),
|
||||
})
|
||||
|
||||
this.setButtonLabel()
|
||||
@@ -149,7 +156,7 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
// Connect to proxy
|
||||
if (config.toggle_grasscutter) {
|
||||
const game_exe = await getGameExecutable()
|
||||
let newerGame = false
|
||||
const newerGame = false
|
||||
|
||||
const patchable = game_exe?.toLowerCase().includes('yuanshen') || game_exe?.toLowerCase().includes('genshin')
|
||||
|
||||
@@ -183,35 +190,36 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
|
||||
const versionString = gameVersion?.major.toString() + gameVersion?.minor.toString()
|
||||
|
||||
if ((gameVersion?.major == 4 && gameVersion?.minor > 5) || config.newer_game) {
|
||||
newerGame = true
|
||||
// Keeps being misused, remove for now.
|
||||
// if ((gameVersion?.major == 4 && gameVersion?.minor > 5) || config.newer_game) {
|
||||
// newerGame = true
|
||||
|
||||
const path = (await invoke('install_location')) as string
|
||||
// const path = (await invoke('install_location')) as string
|
||||
|
||||
const patchstring = '\\altpatch\\'
|
||||
const altPatch = path + patchstring
|
||||
// const patchstring = '\\altpatch\\'
|
||||
// const altPatch = path + patchstring
|
||||
|
||||
const ALT_PATCH =
|
||||
'https://autopatchhk.yuanshen.com/client_app/download/pc_zip/20231030132335_iOEfPMcbrXpiA8Ca/ScatteredFiles/GenshinImpact_Data/Plugins/mihoyonet.dll'
|
||||
const pExists = (await invoke('dir_exists', {
|
||||
path: altPatch,
|
||||
})) as boolean
|
||||
// const ALT_PATCH =
|
||||
// 'https://autopatchhk.yuanshen.com/client_app/download/pc_zip/20231030132335_iOEfPMcbrXpiA8Ca/ScatteredFiles/GenshinImpact_Data/Plugins/mihoyonet.dll'
|
||||
// const pExists = (await invoke('dir_exists', {
|
||||
// path: altPatch,
|
||||
// })) as boolean
|
||||
|
||||
if (!pExists) {
|
||||
await invoke('dir_create', {
|
||||
path: altPatch,
|
||||
})
|
||||
this.props.downloadHandler.addDownload(ALT_PATCH, path + '/altpatch/mihoyonet.dll')
|
||||
await confirm('Please wait for the download in the bottom left to disappear, then click yes')
|
||||
}
|
||||
// if (!pExists) {
|
||||
// await invoke('dir_create', {
|
||||
// path: altPatch,
|
||||
// })
|
||||
// this.props.downloadHandler.addDownload(ALT_PATCH, path + '/altpatch/mihoyonet.dll')
|
||||
// await confirm('Please wait for the download in the bottom left to disappear, then click yes')
|
||||
// }
|
||||
|
||||
/* For custom address patch only, used in 4.5 */
|
||||
// let httpString = 'http://'
|
||||
// if (this.state.httpsEnabled) {
|
||||
// httpString = 'https://'
|
||||
// }
|
||||
// config.launch_args = '-server=' + httpString + this.state.ip + ':' + this.state.port
|
||||
}
|
||||
// /* For custom address patch only, used in 4.5 */
|
||||
// // let httpString = 'http://'
|
||||
// // if (this.state.httpsEnabled) {
|
||||
// // httpString = 'https://'
|
||||
// // }
|
||||
// // config.launch_args = '-server=' + httpString + this.state.ip + ':' + this.state.port
|
||||
// }
|
||||
|
||||
const patched = await patchGame(newerGame, versionString)
|
||||
|
||||
@@ -392,6 +400,25 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
}
|
||||
}
|
||||
|
||||
async setProfile(value: string) {
|
||||
this.setState({ profile: value })
|
||||
await setProfileOption('profile', value)
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
async getProfileList() {
|
||||
const profiles: string[] = await invoke('get_profile_list', {
|
||||
dataDir: `${await dataDir()}/cultivation`,
|
||||
})
|
||||
const list = ['default']
|
||||
|
||||
profiles.forEach((t) => {
|
||||
list.push(t.split('.json')[0])
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div id="playButton">
|
||||
@@ -402,6 +429,23 @@ export default class ServerLaunchSection extends React.Component<IProps, IState>
|
||||
onChange={this.toggleGrasscutter}
|
||||
checked={this.state.grasscutterEnabled}
|
||||
/>
|
||||
<div className="OptionSection" id="menuOptionsContainerProfiles">
|
||||
<div className="OptionValue" id="menuOptionsSelectProfiles">
|
||||
<select
|
||||
value={this.state.profile}
|
||||
id="menuOptionsSelectMenuProfiles"
|
||||
onChange={(event) => {
|
||||
this.setProfile(event.target.value)
|
||||
}}
|
||||
>
|
||||
{this.state.profiles.map((t) => (
|
||||
<option key={t} value={t}>
|
||||
{t}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{this.state.grasscutterEnabled && (
|
||||
|
||||
@@ -16,7 +16,7 @@ import { ask } from '@tauri-apps/api/dialog'
|
||||
|
||||
const FULL_BUILD_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterCulti.zip' // Change to link that can be updated without modifying here
|
||||
const FULL_QUEST_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterQuests.zip'
|
||||
const FULL_50_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterLunaGC53.zip' // https://github.com/Kei-Luna/LunaGC_5.3.0
|
||||
const FULL_50_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterLunaGC61.zip' // https://github.com/pmagixc/LunaGC_6.0.0
|
||||
const STABLE_REPO_DOWNLOAD = 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/stable.zip'
|
||||
const DEV_REPO_DOWNLOAD = 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/development.zip'
|
||||
const UNSTABLE_DOWNLOAD = 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/unstable/Grasscutter.zip'
|
||||
|
||||
@@ -20,3 +20,8 @@
|
||||
.OptionSection .HelpButton img {
|
||||
filter: invert(0%) sepia(91%) saturate(7464%) hue-rotate(101deg) brightness(0%) contrast(107%);
|
||||
}
|
||||
|
||||
input#profile_name {
|
||||
height: 25px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@ import { dataDir } from '@tauri-apps/api/path'
|
||||
import DirInput from '../common/DirInput'
|
||||
import Menu from './Menu'
|
||||
import Tr, { getLanguages } from '../../../utils/language'
|
||||
import { setConfigOption, getConfig, getConfigOption, Configuration } from '../../../utils/configuration'
|
||||
import {
|
||||
setConfigOption,
|
||||
getConfig,
|
||||
getConfigOption,
|
||||
Configuration,
|
||||
saveNewProfileConfig,
|
||||
setProfileOption,
|
||||
} from '../../../utils/configuration'
|
||||
import Checkbox from '../common/Checkbox'
|
||||
import Divider from './Divider'
|
||||
import { getThemeList } from '../../../utils/themes'
|
||||
@@ -57,6 +64,8 @@ interface IState {
|
||||
launch_args: string
|
||||
offline_mode: boolean
|
||||
newer_game: boolean
|
||||
show_version: boolean
|
||||
profile_name: string
|
||||
|
||||
// Linux stuff
|
||||
grasscutter_elevation: string
|
||||
@@ -95,6 +104,8 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
launch_args: '',
|
||||
offline_mode: false,
|
||||
newer_game: false,
|
||||
show_version: true,
|
||||
profile_name: '',
|
||||
|
||||
// Linux stuff
|
||||
grasscutter_elevation: GrasscutterElevation.None,
|
||||
@@ -118,6 +129,9 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
this.addMigotoDelay = this.addMigotoDelay.bind(this)
|
||||
this.toggleUnElevatedGame = this.toggleUnElevatedGame.bind(this)
|
||||
this.setLaunchArgs = this.setLaunchArgs.bind(this)
|
||||
this.toggleShowVersion = this.toggleShowVersion.bind(this)
|
||||
this.setProfileName = this.setProfileName.bind(this)
|
||||
this.saveProfile = this.saveProfile.bind(this)
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
@@ -156,6 +170,7 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
launch_args: config.launch_args,
|
||||
offline_mode: config.offline_mode || false,
|
||||
newer_game: config.newer_game || false,
|
||||
show_version: config.show_version || false,
|
||||
|
||||
// Linux stuff
|
||||
grasscutter_elevation: config.grasscutter_elevation || GrasscutterElevation.None,
|
||||
@@ -350,6 +365,17 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
})
|
||||
}
|
||||
|
||||
async toggleShowVersion() {
|
||||
const changedVal = !(await getConfigOption('show_version'))
|
||||
await setConfigOption('show_version', changedVal)
|
||||
|
||||
this.setState({
|
||||
show_version: changedVal,
|
||||
})
|
||||
|
||||
emit('set_config', { show_version: changedVal })
|
||||
}
|
||||
|
||||
async setGCElevation(value: string) {
|
||||
setConfigOption('grasscutter_elevation', value)
|
||||
|
||||
@@ -487,6 +513,28 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
})
|
||||
}
|
||||
|
||||
setProfileName(text: string) {
|
||||
this.setState({
|
||||
profile_name: text,
|
||||
})
|
||||
}
|
||||
|
||||
async saveProfile() {
|
||||
if (this.state.profile_name == '') {
|
||||
alert('No name set')
|
||||
return
|
||||
}
|
||||
|
||||
const config = await getConfig()
|
||||
await saveNewProfileConfig(config, this.state.profile_name)
|
||||
await setProfileOption('profile', this.state.profile_name)
|
||||
this.setState({
|
||||
profile_name: '',
|
||||
})
|
||||
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Menu closeFn={this.props.closeFn} className="Options" heading="Options">
|
||||
@@ -659,6 +707,24 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
|
||||
<Divider />
|
||||
|
||||
<div className="OptionSection" id="profileConfigContainer">
|
||||
<div className="OptionLabel" id="menuOptionsLabelProfile">
|
||||
<Tr text="options.save_profile" />
|
||||
</div>
|
||||
<TextInput
|
||||
id="profile_name"
|
||||
key="profile_name"
|
||||
placeholder={'Profile name...'}
|
||||
onChange={this.setProfileName}
|
||||
initalValue={''}
|
||||
/>
|
||||
<BigButton onClick={this.saveProfile} id="saveProfile">
|
||||
{'Save'}
|
||||
</BigButton>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<div className="OptionSection" id="menuOptionsContainerGCWGame">
|
||||
<div className="OptionLabel" id="menuOptionsLabelGCWDame">
|
||||
<Tr text="options.grasscutter_with_game" />
|
||||
@@ -711,17 +777,12 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="OptionSection" id="menuOptionsContainerNewerGame">
|
||||
<div className="OptionLabel" id="menuOptionsLabelNewerGame">
|
||||
<Tr text="Patch Mihoyonet" />
|
||||
<div className="OptionSection" id="menuOptionsContainerShowVer">
|
||||
<div className="OptionLabel" id="menuOptionsLabelShowVer">
|
||||
<Tr text="options.show_version" />
|
||||
</div>
|
||||
<div className="OptionValue" id="menuOptionsCheckboxNewerGame">
|
||||
<Checkbox
|
||||
onChange={() => this.toggleOption('newer_game')}
|
||||
checked={this.state?.newer_game}
|
||||
id="newerGame"
|
||||
/>
|
||||
<div className="OptionValue" id="menuOptionsButtonShowVer">
|
||||
<Checkbox onChange={() => this.toggleShowVersion()} checked={this.state.show_version} id="showVer" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -823,25 +884,32 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
<Tr text="components.delete" />
|
||||
</BigButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="OptionSection" id="menuOptionsContainerLaunchArgs">
|
||||
<div className="OptionLabel" id="menuOptionsLaunchArgs">
|
||||
<Tr text="options.launch_args" />
|
||||
</div>
|
||||
<TextInput
|
||||
id="launch_args"
|
||||
key="launch_args"
|
||||
placeholder={'-arg=value'}
|
||||
onChange={this.setLaunchArgs}
|
||||
value={this.state.launch_args}
|
||||
/>
|
||||
<div className="OptionValue" id="menuOptionsValueLaunchArgs">
|
||||
<TextInput
|
||||
id="launch_args"
|
||||
key="launch_args"
|
||||
placeholder={'-arg=value'}
|
||||
onChange={this.setLaunchArgs}
|
||||
value={this.state.launch_args}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="OptionLabel" id="menuOptionsLabelFixRes">
|
||||
<Tr text="options.fix_res" />
|
||||
</div>
|
||||
<div className="OptionValue" id="menuOptionsButtonfixRes">
|
||||
<BigButton onClick={this.fixRes} id="fixRes">
|
||||
<Tr text="components.fix" />
|
||||
</BigButton>
|
||||
<div className="OptionSection" id="menuOptionsContainerFixRes">
|
||||
<div className="OptionLabel" id="menuOptionsLabelFixRes">
|
||||
<Tr text="options.fix_res" />
|
||||
</div>
|
||||
<div className="OptionValue" id="menuOptionsButtonfixRes">
|
||||
<BigButton onClick={this.fixRes} id="fixRes">
|
||||
<Tr text="components.fix" />
|
||||
</BigButton>
|
||||
</div>
|
||||
</div>
|
||||
</Menu>
|
||||
)
|
||||
|
||||
@@ -143,7 +143,7 @@ export default class NewsSection extends React.Component<IProps, IState> {
|
||||
<tr>
|
||||
<td>
|
||||
Work in progress area! These numbers may be outdated, so please do not use them as reference. Latest
|
||||
version: Grasscutter 1.7.4 - Cultivation 1.5.5
|
||||
version: Grasscutter 1.7.4 (4.0) / Forks (6.1) - Cultivation 1.7.2
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
|
||||
@@ -31,6 +31,8 @@ let defaultConfig: Configuration
|
||||
launch_args: '',
|
||||
offline_mode: false,
|
||||
newer_game: false,
|
||||
show_version: true,
|
||||
profile: 'default',
|
||||
|
||||
// Linux stuff
|
||||
grasscutter_elevation: 'None',
|
||||
@@ -68,6 +70,8 @@ export interface Configuration {
|
||||
launch_args: string
|
||||
offline_mode: boolean
|
||||
newer_game: boolean
|
||||
show_version: boolean
|
||||
profile: string
|
||||
|
||||
// Linux stuff
|
||||
grasscutter_elevation: string
|
||||
@@ -90,6 +94,15 @@ export async function setConfigOption<K extends keyof Configuration>(key: K, val
|
||||
await saveConfig(<Configuration>config)
|
||||
}
|
||||
|
||||
export async function setProfileOption<K extends keyof Configuration>(key: K, value: Configuration[K]): Promise<void> {
|
||||
const config = await getConfig()
|
||||
config[key] = value
|
||||
const defaultConfig = await getDefaultConfig()
|
||||
defaultConfig[key] = value
|
||||
|
||||
await saveProfileConfig(<Configuration>defaultConfig)
|
||||
}
|
||||
|
||||
export async function getConfigOption<K extends keyof Configuration>(key: K): Promise<Configuration[K]> {
|
||||
const config = await getConfig()
|
||||
const defaults = defaultConfig
|
||||
@@ -113,16 +126,82 @@ export async function getConfig() {
|
||||
return parsed
|
||||
}
|
||||
|
||||
export async function getDefaultConfig() {
|
||||
const raw = await readDefaultConfigFile()
|
||||
let parsed: Configuration = defaultConfig
|
||||
|
||||
try {
|
||||
parsed = <Configuration>JSON.parse(raw)
|
||||
} catch (e) {
|
||||
// We could not open the file
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
return parsed
|
||||
}
|
||||
|
||||
export async function saveConfig(obj: Configuration) {
|
||||
const raw = JSON.stringify(obj)
|
||||
|
||||
await writeConfigFile(raw)
|
||||
}
|
||||
|
||||
export async function saveProfileConfig(obj: Configuration) {
|
||||
const local = await dataDir()
|
||||
const raw = JSON.stringify(obj)
|
||||
const prevPath = configFilePath
|
||||
configFilePath = local + 'cultivation/configuration.json'
|
||||
await writeConfigFile(raw)
|
||||
|
||||
configFilePath = prevPath
|
||||
}
|
||||
|
||||
export async function saveNewProfileConfig(obj: Configuration, prof: string) {
|
||||
obj['profile'] = prof
|
||||
const local = await dataDir()
|
||||
const raw = JSON.stringify(obj)
|
||||
configFilePath = local + 'cultivation/profiles/' + obj['profile'] + '.json'
|
||||
|
||||
const file: fs.FsTextFileOption = {
|
||||
path: configFilePath,
|
||||
contents: raw,
|
||||
}
|
||||
|
||||
await fs.writeFile(file)
|
||||
}
|
||||
|
||||
async function readConfigFile() {
|
||||
const local = await dataDir()
|
||||
|
||||
if (!configFilePath) configFilePath = local + 'cultivation/configuration.json'
|
||||
if (!configFilePath) {
|
||||
configFilePath = local + 'cultivation/configuration.json'
|
||||
}
|
||||
|
||||
const dataFiles = await fs.readDir(local + 'cultivation')
|
||||
|
||||
// Ensure config exists
|
||||
if (!dataFiles.find((fileOrDir) => fileOrDir?.name === 'configuration.json')) {
|
||||
// Create config file
|
||||
const file: fs.FsTextFileOption = {
|
||||
path: configFilePath,
|
||||
contents: JSON.stringify(defaultConfig),
|
||||
}
|
||||
|
||||
await fs.writeFile(file)
|
||||
}
|
||||
|
||||
// Read existing config to get profile name
|
||||
const raw = await fs.readTextFile(configFilePath)
|
||||
const cfg = <Configuration>JSON.parse(raw)
|
||||
// Switch file to config-specified profile
|
||||
let pf = cfg['profile']
|
||||
if (pf && pf != 'default') {
|
||||
const pff = pf
|
||||
pf = 'profiles/' + pff + '.json'
|
||||
} else {
|
||||
pf = 'configuration.json'
|
||||
}
|
||||
configFilePath = local + 'cultivation/' + pf
|
||||
|
||||
// Ensure Cultivation dir exists
|
||||
const dirs = await fs.readDir(local)
|
||||
@@ -140,23 +219,16 @@ async function readConfigFile() {
|
||||
await fs.createDir(local + 'cultivation/grasscutter').catch((e) => console.log(e))
|
||||
}
|
||||
|
||||
const dataFiles = await fs.readDir(local + 'cultivation')
|
||||
|
||||
// Ensure config exists
|
||||
if (!dataFiles.find((fileOrDir) => fileOrDir?.name === 'configuration.json')) {
|
||||
// Create config file
|
||||
const file: fs.FsTextFileOption = {
|
||||
path: configFilePath,
|
||||
contents: JSON.stringify(defaultConfig),
|
||||
}
|
||||
|
||||
await fs.writeFile(file)
|
||||
}
|
||||
|
||||
// Finally, read the file
|
||||
return await fs.readTextFile(configFilePath)
|
||||
}
|
||||
|
||||
async function readDefaultConfigFile() {
|
||||
const local = await dataDir()
|
||||
configFilePath = local + 'cultivation/configuration.json'
|
||||
return await fs.readTextFile(configFilePath)
|
||||
}
|
||||
|
||||
async function writeConfigFile(raw: string) {
|
||||
// All external config functions call readConfigFile, which ensure files exists
|
||||
await fs.writeFile({
|
||||
|
||||
@@ -1,110 +1,34 @@
|
||||
import { invoke } from '@tauri-apps/api'
|
||||
import { getConfig } from './configuration'
|
||||
import { basename, dirname, join } from '@tauri-apps/api/path'
|
||||
import { getConfigOption } from './configuration'
|
||||
|
||||
export const getGrasscutterJar = () => getConfigOption('grasscutter_path')
|
||||
|
||||
export async function getGameExecutable() {
|
||||
const config = await getConfig()
|
||||
|
||||
if (!config.game_install_path) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pathArr = config.game_install_path.replace(/\\/g, '/').split('/')
|
||||
return pathArr[pathArr.length - 1]
|
||||
}
|
||||
|
||||
export async function getGrasscutterJar() {
|
||||
const config = await getConfig()
|
||||
|
||||
if (!config.grasscutter_path) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pathArr = config.grasscutter_path.replace(/\\/g, '/').split('/')
|
||||
return pathArr[pathArr.length - 1]
|
||||
}
|
||||
|
||||
export async function getGameFolder() {
|
||||
const config = await getConfig()
|
||||
|
||||
if (!config.game_install_path) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pathArr = config.game_install_path.replace(/\\/g, '/').split('/')
|
||||
pathArr.pop()
|
||||
|
||||
const path = pathArr.join('/')
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
export async function getGameDataFolder() {
|
||||
const gameExec = await getGameExecutable()
|
||||
|
||||
if (!gameExec) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (await getGameFolder()) + '\\' + gameExec.replace('.exe', '_Data')
|
||||
}
|
||||
const exe_path = await getConfigOption('game_install_path')
|
||||
return await basename(exe_path)
|
||||
}
|
||||
|
||||
export async function getGameVersion() {
|
||||
const GameData = await getGameDataFolder()
|
||||
const platform = await invoke('get_platform')
|
||||
|
||||
if (!GameData) {
|
||||
return null
|
||||
}
|
||||
|
||||
let hasAsb = await invoke('dir_exists', {
|
||||
path: GameData + '\\StreamingAssets\\asb_settings.json',
|
||||
})
|
||||
|
||||
if (platform != 'windows') {
|
||||
hasAsb = await invoke('dir_exists', {
|
||||
path: GameData + '/StreamingAssets/asb_settings.json',
|
||||
})
|
||||
}
|
||||
const execPath = await getConfigOption('game_install_path')
|
||||
const rootPath = await dirname(execPath)
|
||||
const baseName = (await basename(execPath, ".exe"))
|
||||
const datapath = await join(rootPath, `${baseName}_Data`)
|
||||
const asbPath = await join(datapath, 'StreamingAssets', 'asb_settings.json')
|
||||
const hasAsb = await invoke<boolean>('dir_exists', { path: asbPath })
|
||||
|
||||
if (!hasAsb) {
|
||||
// For games that cannot determine game version
|
||||
let otherGameVer: string = await invoke('read_file', {
|
||||
path: GameData + '\\StreamingAssets\\BinaryVersion.bytes',
|
||||
})
|
||||
const versionFile = await join(datapath, 'StreamingAssets', 'BinaryVersion.bytes')
|
||||
const rawVersion = await invoke<string>('read_file', { path: versionFile })
|
||||
if (!rawVersion) return null
|
||||
|
||||
if (platform != 'windows') {
|
||||
otherGameVer = await invoke('read_file', {
|
||||
path: GameData + '/StreamingAssets/BinaryVersion.bytes',
|
||||
})
|
||||
}
|
||||
|
||||
const versionRaw = otherGameVer.split('.')
|
||||
const version = {
|
||||
major: parseInt(versionRaw[0]),
|
||||
minor: parseInt(versionRaw[1]),
|
||||
// This will probably never matter, just use major/minor. If needed, full version values are near EOF
|
||||
release: 0,
|
||||
}
|
||||
|
||||
if (otherGameVer == null || otherGameVer.length < 1) {
|
||||
return null
|
||||
}
|
||||
|
||||
return version
|
||||
const [major, minor] = rawVersion.split('.').map(Number)
|
||||
return { major, minor, release: 0 }
|
||||
}
|
||||
|
||||
const settings = JSON.parse(
|
||||
await invoke('read_file', {
|
||||
path: GameData + '\\StreamingAssets\\asb_settings.json',
|
||||
})
|
||||
)
|
||||
const settings = JSON.parse(await invoke<string>('read_file', { path: asbPath }))
|
||||
const [major, minorRelease] = settings.variance.split('.')
|
||||
const [minor, release] = minorRelease.split('_').map(Number)
|
||||
|
||||
const versionRaw = settings.variance.split('.')
|
||||
const version = {
|
||||
major: parseInt(versionRaw[0]),
|
||||
minor: parseInt(versionRaw[1].split('_')[0]),
|
||||
release: parseInt(versionRaw[1].split('_')[1]),
|
||||
}
|
||||
|
||||
return version
|
||||
return { major: parseInt(major), minor, release }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user