Compare commits

...

12 Commits

Author SHA1 Message Date
NotThorny
fafec01fe3 Fix not loading old configs from correct dir 2025-11-14 02:45:24 -07:00
NotThorny
0c910b7317 Update langs 2025-11-14 02:38:22 -07:00
NotThorny
6f2be3c5a5 Add profiles 2025-11-14 02:37:37 -07:00
NotThorny
d2b8124877 Update AIO to 6.1 2025-10-31 21:17:31 -06:00
NotThorny
247150c62a Update patch 2025-10-25 16:18:44 -06:00
NotThorny
1599c37100 Update AIO 6.0 2025-10-17 00:48:37 -06:00
NotThorny
ecb7936a8f Add 6.0 patch from @pmagixc
Bump version
2025-10-15 21:36:14 -06:00
Thoronium
a40080cca2 Merge pull request #255 from GID0317/main
Update launch_args, Fix login timeout and transparency support
2025-07-01 14:32:09 -06:00
GID
364d138779 Update launch_args and fix login timeout to use the options OptionSection for better UX and easier for theming 2025-07-01 19:35:14 +07:00
GID
f03cc0a09f Update to make the transparency enabled to make easier to support rounded corners windows 2025-07-01 19:31:39 +07:00
Thoronium
7750266a3d Bump version 2025-03-27 01:19:00 -06:00
Thoronium
028ee380f2 Replace 5.x+ individual patch files with universal 2025-03-27 01:17:24 -06:00
38 changed files with 370 additions and 91 deletions

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@
# production
/build
/target
# misc
.DS_Store

View File

@@ -1,6 +1,6 @@
{
"name": "cultivation",
"version": "1.5.7",
"version": "1.7.0",
"private": true,
"dependencies": {
"@tauri-apps/api": "^1.0.0-rc.5",

2
src-tauri/Cargo.lock generated
View File

@@ -959,7 +959,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]]
name = "cultivation"
version = "1.5.7"
version = "1.6.3"
dependencies = [
"anime-launcher-sdk",
"anyhow",

View File

@@ -1,13 +1,13 @@
[package]
name = "cultivation"
version = "1.5.7"
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

View File

@@ -1,7 +1,7 @@
{
"lang_name": "简体中文",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "启动",
"gc_enable": "以 Grasscutter 模式连接",
"https_enable": "使用 HTTPS",
@@ -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.4 一体化",
"grasscutter_fullquest": "下载 6.1 一体化",
"grasscutter_stable_data": "下载 Grasscutter 稳定版数据",
"grasscutter_latest_data": "下载 Grasscutter 开发版数据",
"grasscutter_stable_data_update": "更新 Grasscutter 稳定版数据",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "繁體中文",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "啟動",
"gc_enable": "以Grasscutter模式連接",
"https_enable": "使用 HTTPS",
@@ -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.4 一体化",
"grasscutter_fullquest": "下载 6.1 一体化",
"grasscutter_stable_data": "下載Grasscutter穩定版數據Data",
"grasscutter_latest_data": "下載Grasscutter開發板數據Data",
"grasscutter_stable_data_update": "更新Grasscutter穩定版數據Data",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Deutsch",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Starten",
"gc_enable": "Mit Grasscutter verbinden",
"https_enable": "HTTPS verwenden",
@@ -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.4 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",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "English",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Launch",
"gc_enable": "Connect to Grasscutter",
"https_enable": "Use HTTPS",
@@ -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.4 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",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Español",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Launch",
"gc_enable": "Conectar Via Grasscutter",
"https_enable": "Usar HTTPS",
@@ -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.4",
"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",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Francais",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Lancer",
"gc_enable": "Se connecter avec Grasscutter",
"https_enable": "Utiliser HTTPS",
@@ -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.4 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)",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Indonesia",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Luncurkan",
"gc_enable": "Terhubung Melalui GrassCutter",
"ip_placeholder": "Alamat Server...",
@@ -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.4 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",

View File

@@ -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.4 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",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "日本語",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "起動",
"gc_enable": "Grasscutterに接続",
"https_enable": "HTTPS接続を使用",
@@ -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.4 All-in-Oneをダウンロード",
"grasscutter_fullquest": "6.1 All-in-Oneをダウンロード",
"grasscutter_stable_data": "Grasscutter安定版データファイルをダウンロード",
"grasscutter_latest_data": "Grasscutter最新版データファイルをダウンロード",
"grasscutter_stable_data_update": "Grasscutter安定版データファイルをアップデート",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "한국어",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "게임 시작",
"gc_enable": "Grasscutter 연결",
"https_enable": "HTTPS 사용",
@@ -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.4 올인원 다운로드",
"grasscutter_fullquest": "6.1 올인원 다운로드",
"grasscutter_stable_data": "안정적인 데이터 다운로드",
"grasscutter_latest_data": "최신 데이터 다운로드",
"grasscutter_stable_data_update": "안정적 데이터 업데이트",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Latviešu",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Palaist",
"gc_enable": "Savienot ar Grasscutter",
"https_enable": "Izm. HTTPS",
@@ -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.4 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",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Nederlands",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Start",
"gc_enable": "Verbind Met Grasscutter",
"https_enable": "Gebruik HTTPS",
@@ -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.4 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",

View File

@@ -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.4 (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",

View File

@@ -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.4 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",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Русский",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Запустить",
"gc_enable": "Подключиться с Grasscutter",
"https_enable": "Исп. HTTPS",
@@ -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.4 все в одном",
"grasscutter_fullquest": "Скачать 6.1 все в одном",
"grasscutter_stable_data": "Скачать стабильные данные Grasscutter",
"grasscutter_latest_data": "Скачать последние данные Grasscutter",
"grasscutter_stable_data_update": "Обновить стабильные данные Grasscutter",

View File

@@ -1,7 +1,7 @@
{
"lang_name": "Tiếng Việt",
"main": {
"title": "Cultivation",
"title": "Cultivation: Thorny Edition",
"launch_button": "Khởi Chạy",
"gc_enable": "Kết nối qua Grasscutter",
"https_enable": "Dùng HTTPS",
@@ -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.4 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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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("profile");
path.push(profile);
}
path
}
pub fn get_config() -> Configuration {
let path = config_path();
pub fn get_config(profile_name: String) -> Configuration {
let path = config_path(profile_name);
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.as_ref().unwrap_or(&default);
if *prof != String::from("default") {
get_config(prof.clone());
}
config
}

View File

@@ -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
}

View File

@@ -153,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(),
@@ -343,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()?;

View File

@@ -7,7 +7,7 @@
},
"package": {
"productName": "Cultivation",
"version": "1.5.7"
"version": "1.7.0"
},
"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
}
]
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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()
@@ -393,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">
@@ -403,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 && (

View File

@@ -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/GrasscutterLunaGC54.zip' // https://github.com/pmagixc/LunaGC_5.4.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'

View File

@@ -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;
}

View File

@@ -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,19 +777,14 @@ 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> */}
</div>
<Divider />
@@ -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>
)

View File

@@ -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.7
version: Grasscutter 1.7.4 (4.0) / Forks (6.1) - Cultivation 1.7.0
</td>
</tr>
)

View File

@@ -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,69 @@ 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'
}
// 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)
@@ -157,6 +223,12 @@ async function readConfigFile() {
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({