Merge branch 'next' into feat/i18n/pl

This commit is contained in:
Dominik Opyd 2023-08-19 22:33:30 +02:00 committed by GitHub
commit 8ed27fbdeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 776 additions and 708 deletions

View file

@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Added feature to map wine drives
- Added Portuguese
- Added `%launch_args%` magic word for game launching command.
Now you can use `%bash_command% <script> %launch_args%` to run custom script
- Added 4.0.0 voiceovers sizes
- Added `--session <name>` flag to switch active session
### Fixed
- Fixed logo size in the first run window
### Changed
- Updated Turkish
- Updated Italian
- Updated Japanese
- Updated Swedish
- Improved files migration code. In the best case scenarios, it will work immediately now
### Removed
- Removed patch integration
## [3.8.0] - 02.08.2023
### Added

16
Cargo.lock generated
View file

@ -39,8 +39,8 @@ dependencies = [
[[package]]
name = "anime-game-core"
version = "1.13.5"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.13.5#11e48e47563acf97a6885d3cc369875031dc5f61"
version = "1.15.0"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.15.0#e34a35e04dd97d8268e47769f82591100b3354ae"
dependencies = [
"anyhow",
"bzip2",
@ -88,8 +88,8 @@ dependencies = [
[[package]]
name = "anime-launcher-sdk"
version = "1.8.13"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.8.13#1669dceafce3eaa3e9332fb4ac6ff78ea9fb1639"
version = "1.11.0"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.11.0#b858205ca74d3ce930d0d6cd36eb0b9dc749a7a7"
dependencies = [
"anime-game-core",
"anyhow",
@ -1288,9 +1288,9 @@ dependencies = [
[[package]]
name = "glib-build-tools"
version = "0.17.10"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a65d79efe318ef2cbbbb37032b125866fd82c34ea44c816132621bbc552e716"
checksum = "3431c56f463443cba9bc3600248bc6d680cb614c2ee1cdd39dab5415bd12ac5c"
[[package]]
name = "glib-macros"
@ -1971,9 +1971,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "open"
version = "4.2.0"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a083c0c7e5e4a8ec4176346cf61f67ac674e8bfb059d9226e1c54a96b377c12"
checksum = "cfabf1927dce4d6fdf563d63328a0a506101ced3ec780ca2135747336c98cef8"
dependencies = [
"is-wsl",
"libc",

View file

@ -15,12 +15,12 @@ lto = true
opt-level = "s"
[build-dependencies]
glib-build-tools = "0.17"
glib-build-tools = "0.18"
[dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/anime-launcher-sdk"
tag = "1.8.13"
features = ["all", "genshin", "genshin-patch"]
tag = "1.11.0"
features = ["all", "genshin"]
# path = "../anime-launcher-sdk" # ! for dev purposes only
@ -30,7 +30,7 @@ gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] }
adw = { package = "libadwaita", version = "0.4", features = ["v1_2"] }
rfd = { version = "0.11", features = ["xdg-portal"], default-features = false }
open = "4.0"
open = "5.0.0"
whatadistro = "0.1.0"
serde_json = "1.0"

View file

@ -16,24 +16,6 @@
<br>
# ⚠️ Please don't link to this repository
We understand you want to help people run An Anime Game on Linux. The issue is, the more people know
of the tools involved in it, the higher the chances The Anime Game Company will notice them, and then
fix the flaws that let us do the needful.
While sharing in your self-managed chat services and through private messaging is fine, we humbly ask
that you refrain from publically sharing links to this repository, or to any of the tools involved.
Or share them and ruin it for the dozens of Linux players. It's up to you.
## If you're going to share it anyway
Do what you must, but we would respectfully request that you try to label the game as "An Anime Game"
instead of the actual name of the game, to avoid search engine parsing.
<br>
# ♥️ Useful links and thanks
* Original patch project without which this project wouldn't be possible. Link is omitted for "privacy" purposes

View file

@ -26,4 +26,5 @@ zh-cn = 简体中文
ja-jp = 日本語
hu-hu = Magyar
sv-se = Svenska
pl-pl = Polski
pt-br = Português
pl-pl = Polski

View file

@ -14,6 +14,12 @@ system = System
borderless-window = Randloses Fenster
virtual-desktop = Virtueller Desktop
map-drive-c = Laufwerk C: abbilden
map-drive-c-description = Symlink den drive_c ordner vom Wine-Prefix automatisch zu den DOS-Geräten
map-game-folder = Spielordner abbilden
map-game-folder-description = Symlink den Spielordner automatisch zu den DOS-Geräten
game = Spiel
hud = HUD

View file

@ -14,6 +14,12 @@ system = System
borderless-window = Borderless window
virtual-desktop = Virtual desktop
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = Game
hud = HUD

View file

@ -14,6 +14,12 @@ system = Sistema
borderless-window = Ventana sin bordes
virtual-desktop = Escritorio virtual
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = Juego
hud = HUD

View file

@ -14,6 +14,12 @@ system = Système
borderless-window = Utiliser une fenêtre sans bordure
virtual-desktop = Bureau virtuel
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = Jeu
hud = HUD

View file

@ -14,6 +14,12 @@ system = Rendszer
borderless-window = Kerettelen ablak(borderless)
virtual-desktop = Virtuális asztal
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = Játék
hud = HUD

View file

@ -14,6 +14,12 @@ system = Sistem
borderless-window = window tanpa border
virtual-desktop = Desktop virtual
map-drive-c = Petakan drive C:
map-drive-c-description = Otomatis menghubungkan folder drive_c secara simbolik dari prefiks wine ke dosdevices
map-game-folder = Petakan folder game
map-game-folder-description = Otomatis menghubungkan folder game secara simbolik ke dosdevices
game = Game
hud = HUD

View file

@ -14,6 +14,12 @@ system = Sistema
borderless-window = Finestra senza bordi
virtual-desktop = Desktop virtuale
map-drive-c = Mappa disco C:
map-drive-c-description = Crea automaticamente un collegamento simbolico dalla cartella drive_c del prefisso di Wine a dosdevices
map-game-folder = Mappa cartella del gioco
map-game-folder-description = Crea automaticamente un collegamento simbolico dalla cartella del gioco a dosdevices
game = Gioco
hud = HUD

View file

@ -13,7 +13,7 @@ failed-get-selected-wine = Ottenimento della versione selezionata di wine non ri
downloading-failed = Scaricamento non riuscito
unpacking-failed = Unpacking non riuscito
kill-game-process-failed = Failed to kill the game's process
kill-game-process-failed = Terminazione del processo del gioco non riuscita
game-file-repairing-error = Riparazione del file di gioco non riuscita
integrity-files-getting-error = Ottenimento dei file di integrità non riuscito

View file

@ -58,8 +58,8 @@ disable-mhypbase-description = Sperimentale. Se abiliata, il launcher disabilite
ask-superuser-permissions = Chiedi permessi di amministratore
ask-superuser-permissions-description = Il launcher li userà per aggiornare automaticamente il tuo file hosts. Questo non è necessario nell'edizione flatpak
launcher-behavior = Launcher behavior
launcher-behavior-description = What should launcher window do when it starts the game
launcher-behavior = Comportamento del launcher
launcher-behavior-description = Cosa dovrebbe fare il launcher quando fa partire il gioco
wine-tools = Strumenti di Wine
command-line = Linea di comando

View file

@ -17,9 +17,18 @@ wish-url = Apri i desideri
about = Informazioni
close = Chiudi
hide = Hide
nothing = Nothing
close = { $commandType ->
[verb] Chiudersi
*[noun] Chiudi
}
hide = { $commandType ->
[verb] Nascondersi
*[noun] Nascondi
}
nothing = Nulla
save = Salva
continue = Continua
resume = Riprendi
@ -64,7 +73,7 @@ update = Aggiorna
download = Scarica
predownload-update = Prescarica {$version} aggiornamento ({$size})
kill-game-process = Kill game process
kill-game-process = Termina il processo del gioco
main-window--patch-unavailable-tooltip = I server delle patch non sono disponibili e il launcher non può verificare lo stato del patching del gioco. Hai la possibilità di eseguire il gioco a tuo rischio
main-window--patch-outdated-tooltip = La patch non è aggiornata o è in stato di preparazione, quindi non disponibile per l'utilizzo. Torna più tardi per vederne lo stato

View file

@ -14,6 +14,12 @@ system = システム
borderless-window = ボーダーレスウィンドウ
virtual-desktop = 仮想デスクトップ
map-drive-c = Cドライブを作成する
map-drive-c-description = DOSデバイスに、WineプレフィックスのCドライブのソフトリンクを自動的に作成します
map-game-folder = ゲームフォルダを作成する。
map-game-folder-description = DOSデバイスにゲームフォルダのソフトリンクを自動的に作成します
game = ゲーム
hud = HUD

View file

@ -13,7 +13,7 @@ failed-get-selected-wine = 選択されたwineバージョンを入手できま
downloading-failed = ダウンロードに失敗。
unpacking-failed = 展開失敗
kill-game-process-failed = Failed to kill the game's process
kill-game-process-failed = ゲームの停止に失敗しました。
game-file-repairing-error = ゲームファイルの修正に失敗しました。
integrity-files-getting-error = 整合性ファイルの取得に失敗しました

View file

@ -58,8 +58,8 @@ disable-mhypbase-description = 試験的です。有効にすると、ランチ
ask-superuser-permissions = スーパーユーザーを尋ねる。
ask-superuser-permissions-description = あなたのホストのファイルを自動更新するために、 これらを利用します。flatpak版では必要ありません。
launcher-behavior = Launcher behavior
launcher-behavior-description = What should launcher window do when it starts the game
launcher-behavior = 起動時のランチャーの挙動
launcher-behavior-description = ゲーム起動時にランチャーを非表示にしますか?
wine-tools = ワインツール
command-line = コマンドライン

View file

@ -17,9 +17,17 @@ wish-url = 祈願履歴を開く
about = "An anime Game launcher"について
close = 閉じる
hide = Hide
nothing = Nothing
close = { $form ->
[verb] 閉じる
*[noun] 閉じる
}
hide = { $form ->
[verb] 隠す
*[noun] 非表示
}
nothing = 何もしない
save = 保存
continue = 続行
resume = 一時停止
@ -64,7 +72,7 @@ update = 更新
download = ダウンロード
predownload-update = {$version} の早期アップデート({$size})
kill-game-process = Kill game process
kill-game-process = ゲームを停止させる
main-window--patch-unavailable-tooltip = パッチサーバーが利用できないため、パッチの状態を確認することができません。リスクを理解した上で実行することができます。
main-window--patch-outdated-tooltip = パッチは期限切れか準備中のため利用できません。しばらく立ってからパッチステータスを確認してください。

View file

@ -0,0 +1,20 @@
components = Componentes
components-description = Configure suas versões Wine e DXVK
selected-version = Versão selecionada
recommended-only = Exclusivamente recomendada
wine-version = Versão Wine
wine-recommended-description = Mostrar somente versões wine recomendadas
wine-options = Opções Wine
wine-use-shared-libraries = Use libraries wine compartilhadas
wine-use-shared-libraries-description = sete variável LD_LIBRARY_PATH para carregar libraries do sistema da build wine selecionada
gstreamer-use-shared-libraries = Use libraries gstreamer compartilhadas
gstreamer-use-shared-libraries-description = Sete variável GST_PLUGIN_PATH para carregar libraries do gstreamer da build wine selecionada
dxvk-version = Versão DXVK
dxvk-selection-disabled = Seleção DXVK está desativada pelas suas preferências de grupo wine
dxvk-recommended-description = Mostrar somente versões dxvk recomendadas

View file

@ -0,0 +1,69 @@
game-settings-description = Configure opções de jogo e sessão de conta
sandbox-settings-description = Rode o jogo em uma sandbox, similar ao que Flatpak faz
environment-settings-description = Especifique variáveis de contexto e comandos de inicialização do jogo
wine = Wine
synchronization = Sincronização
wine-sync-description = Tecnologia usada para sincronizar eventos internos wine
language = Idioma
wine-lang-description = Idioma usado no contexto wine. Pode consertar problemas no layout do teclado
system = Sistema
borderless-window = Janela sem borda
virtual-desktop = Área de trabalho virtual
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = Jogo
hud = HUD
fsr = FSR
fsr-description = Upscales game to your monitor size. To use select lower resolution in the game's settings and press Alt+Enter
ultra-quality = Ultra qualidade
quality = Qualidade
balanced = Balanceado
performance = Desempenho
gamemode = Gamemode
gamemode-description = Priorize o jogo sobre o resto dos processos
gamescope = Gamescope
gamescope-description = Gamescope é uma feramenta da Valve que permite jogos rodarem em uma instância isolada Xwayland e suporta GPUs AMD, Intel e Nvidia
discord-rpc = Discord RPC
discord-rpc-description = Discord RPC permite que tu providencie ao Discord a informação que está jogando para seus amigos saberem
icon = Ícone
title = Título
description = Descrição
fps-unlocker = Desbloqueador de FPS
enabled = Habilitado
fps-unlocker-description = Remove a limitação de renderização de frames modificando a memória do jogo. Pode ser detectado pelo anti-cheat
power-saving = Economia de energia
power-saving-description = Automaticamente seta o FPS limite para 10 e diminui prioridade do processo ao perder o foco do jogo (e.g. trocando janelas)
monitor = Monitor
monitor-description = Número do monitor que tu quer rodar o jogo
window-mode = Modo janela
borderless = Sem borda
popup = Popup
fullscreen = Tela cheia
priority = Prioridade
priority-description = Prioridade do processo do jogo
realtime = Tempo real
high = Alta
above-normal = Acima do normal
normal = Normal
below-normal = Abaixo do normal
low = Baixa

View file

@ -0,0 +1,7 @@
environment = Contexto
game-command = Comando de jogo
game-command-description = Comando usado para iniciar o jogo. %command% é gerado automaticamente pelo launcher. Por exemplo: gamemoderun '%command%'
new-variable = Nova variável
name = Nome
value = Valor
add = Adicionar

View file

@ -0,0 +1,66 @@
launcher-folder-opening-error = Falha ao abrir pasta do launcher
game-folder-opening-error = Falha ao abrir pasta do jogo
config-file-opening-error = Falha ao abrir arquivo de configuração
debug-file-opening-error = Falha ao abrir arquivo de debug
wish-url-search-failed = Nenhuma url de desejos encontrada
wish-url-opening-error = Erro ao abrir url de desejos
wine-run-error = Falha ao rodar {$executable} executável usando wine
game-launching-failed = Falha ao iniciar jogo
failed-get-selected-wine = Falha ao pegar versão wine selecionada
downloading-failed = Falha ao baixar
unpacking-failed = Falha na extração
kill-game-process-failed = Falha ao terminar o processo do jogo
game-file-repairing-error = Falha ao reparar os arquivos do jogo
integrity-files-getting-error = Falha ao pegar os arquivos de integridade
background-downloading-failed = Falha ao baixar a imagem de fundo
components-index-sync-failed = Falha ao sincronizar o índice de componentes
components-index-verify-failed = Falha ao verificar o índice de componentes
config-update-error = Falha ao salvar configurações
wine-prefix-update-failed = Falha ao atualizar o prefixo wine
dxvk-install-failed = Falha ao instalar DXVK
voice-package-deletion-error = Falha ao deletar o pacote de vozes
game-diff-finding-error = Falha ao encontrar diff do jogo
patch-info-fetching-error = Falha ao pegar info do patch
launcher-state-updating-error = Falha ao atualizar estado do launcher
package-not-available = Pacote não está disponível: {$package}
wine-download-error = Falha ao baixar wine
wine-unpack-errror = Falha ao extrair wine
wine-install-failed = Falha ao instalar wine
dxvk-download-error = Falha ao baixar DXVK
dxvk-unpack-error = Falha ao extrair DXVK
dxvk-apply-error = Falha ao aplicar DXVK
downloaded-wine-list-failed = Falha ao listar versões wine
patch-sync-failed = Falha ao sincronizar pasta do patch
patch-state-check-failed = Falha ao checar estado da pasta do patch
game-patching-error = Falha ao patchear jogo
# Desativar telemetria
telemetry-servers-disabling-error = Falha ao desativar os servidores de telemetria
# Sandbox
documentation-url-open-failed = Falha ao abrir o url da documentação
# Jogo
game-session-add-failed = Falha ao adicionar sessão do jogo
game-session-update-failed = Falha ao atualizar sessão do jogo
game-session-remove-failed = Falha ao remover sessão do jogo
game-session-set-current-failed = Falha ao setar sessão atual do jogo
game-session-apply-failed = Falha ao aplicar sessão do jogo
# Melhorias
discord-rpc-icons-fetch-failed = Falha ao pegar ícones do Discord RPC
discord-rpc-icon-download-failed = Falha ao baixar ícones do Discord RPC

View file

@ -0,0 +1,65 @@
welcome = Bem-vindo
welcome-page-message =
Olá! Seja bem-vindo An Anime Game Launcher
Precisamos preparar algumas coisas e baixar componentes padrões antes de poder rodar o jogo
tos-violation-warning = Aviso de violação dos TdS
tos-violation-warning-message =
Esse launcher é uma ferramenta não oficial, de nenhuma forma relacionada à {company-name} nem {company-alter-name}.
Essa ferramenta foi feita para facilitar jogar {game-name} no Linux, e foi construida com o único propósito de instalar e rodar o jogo com menos complicação.
Fazemos isso usando componentes existentes e fazendo a experiência mais simples para o usuário.
Porém, alguns componentes usados aqui provavelmente quebram os Termos de Serviço da {company-name} para {game-name}.
Se está usando esse launcher, sua conta de jogador pode ser identificada como desconforme pela {company-name}/{company-alter-name}.
Se isso acontecer, como sua conta estaria desobedecendo os Termos de Serviço, {company-name}/{company-alter-name} são livres para fazerem o que quiserem. Incluindo banir.
Se entende o risco de tentar jogar o jogo em capacidade não oficial, aperte OK para continuar
tos-dialog-title = Tem certeza que entende o que queremos dizer?
tos-dialog-message =
1. Não publique informação sobre esse projeto
2. Não abuse usando clientes modados
3. Pergunte somente em nossos servidores discord ou matrix
dependencies = Dependências
missing-dependencies-title = Algumas dependências estão faltando!
missing-dependencies-message = Instale alguns pacotes no seu sistema antes de continuar o processo de instalação
default-paths = Caminho padrão
choose-default-paths = escolha caminho padrão
show-all-folders = Eu sei o que estou fazendo
show-all-folders-subtitle = Mostre configuração de seleção de caminho adicional. Faça como eu digo...
runners-folder = Pasta dos Runners
dxvks-folder = Pasta dos DXVKs
wine-prefix-folder = Pasta dos prefixos Wine
global-game-installation-folder = Pasta de instalação da versão global
chinese-game-installation-folder = Pasta de instalação da versão chinesa
fps-unlocker-folder = Pasta do desbloqueador de FPS
components-index = Índice de componentes
patch-folder = Pasta do patch
temp-folder = Pasta do temp
migrate = Migrar
select-voice-packages = Selecione pacotes de voz
download-components = Baixar componentes
download-dxvk = Baixar DXVK
apply-dxvk = Aplicar DXVK
finish = Feito
finish-title = Está tudo feito!
finish-message = Todos os componentes base foram baixados. Pode agora reiniciar o launcher e baixar o jogo. Bem-vindo ao clube!

View file

@ -0,0 +1,7 @@
game-sessions = Sessões de jogo
active-sessions = Sessão ativa
active-session-description = Sessão de jogo atualmente selecionada. Atualizar após todo início de jogo
update-session = Atualizar sesssão usando versão atual dos valores de registor do prefixo wine
delete-session = Deletar sessão

View file

@ -0,0 +1,13 @@
game-resolution = Resolução de jogo
gamescope-resolution = Resolução gamescope
upscaling = Upscaling
integer-scaling = Escalamento inteiro
integer-scaling-description = Torna cada pixel em um grupo de números inteiros de mesma cor em forma de quadrado ou retângulo. Previne a perda de nitidez quando escalando Full HD para 4K
gamescope-fsr-description = Uma técnica de upscaling de código aberto desenvolvida pela AMD para melhor qualidade
nis-description = Uma técnica de upscaling de código aberto desenvolvida pela Nvidia como uma alternativa á solução DLSS proprietária, significa que funciona em GPUs AMD, Intel e Nvidia
other-settings = Outras configuraões
framerate-limit = Limite de taxa de quadros
unfocused-framerate-limit = Limite de taxa de quadros desfocado

View file

@ -0,0 +1,69 @@
appearance = Aparência
modern = Moderna
classic = Classica
update-background = Atualizar imagem de fundo
update-background-description = Baixar foto oficial de fundo para o launcher. Pode desativar para usar sua própria imagem personalizada
launcher-language = Idioma do launcher
launcher-language-description = Aplicado após reiniciar
game-edition = Edição do jogo
global = Global
china = China
game-environment = Contexto de jogo
game-environment-description = Acesse funcionalidades específicas como métodos de pagamento adicionais
game-voiceovers = Pacotes de voz do jogo
game-voiceovers-description = Lista de pacotes de voz baixados. Pode acessá-los nas configurações do jogo
english = Inglês
japanese = Japonês
korean = Coreano
chinese = Chinês
migrate-installation = Migrar instalação
migrate-installation-description = Abra janela especial onde pide mudar a pasta de instalação
repair-game = Reparar jogo
status = Status
game-version = Versão de jogo
game-not-installed = Não instalado
game-predownload-available = Pré-baixa da atualização do jogo disponível: {$old} -> {$new}
game-update-available = Atualização de jogo disponível: {$old} -> {$new}
game-outdated = Jogo está muito ultrapassado e não pode ser atualizado. Última versão: {$latest}
player-patch-version = Versão do patch do jogador
player-patch-version-description = Patch principal que permite jogar no linux
patch-not-available = Não disponível
patch-not-available-tooltip = Servidores do patch estão inalcançáveis
patch-outdated = Ultrapassado ({$current})
patch-outdated-tooltip = Patch está ultrapassado: {$current} -> {$latest}
patch-preparation = preparação
patch-preparation-tooltip = Patch está em desenvolvimento
patch-testing-tooltip = Patch teste está disponível
patch-not-applied-tooltip = Patch não está aplicado
apply-main-patch = Aplicar patch principal
apply-main-patch-description = Experimental. Desativar isso permite jogar o jogo sem aplicar o patch. Isso pode não funcionar, ou requer modificações de arquivo manuais. Use se sabe o que está fazendo
disable-mhypbase = Desative mhypbase
disable-mhypbase-description = Experimental. Se ativado, o launcher ira desativar mhypbase.dll durante a aplicação do patch principal, que é atualmente equivalente ao patch xlua. melhora performance e reduz uso da CPU
ask-superuser-permissions = Pede permissão de superusuário
ask-superuser-permissions-description = Launcher irá usa-lo para atualizar automaticamente os arquivos. Isso não é necessário na edição flatpak
launcher-behavior = Comportamento do launcher
launcher-behavior-description = O que a janela do launcher deve fazer ao abrir o jogo
wine-tools = Ferramentas wine
command-line = Linha de comando
registry-editor = Editor de registro
explorer = Explorador
task-manager = Gerenciador de tarefas
configuration = Configuração
debugger = Debugador

View file

@ -0,0 +1,75 @@
custom = Customizado
none = Nenhum
default = Padrão
details = Detalhes
options = Opções
width = Largura
height = Altura
# Menu items
launcher-folder = Pasta do launcher
game-folder = Pasta do jogo
config-file = Arquivo de configuração
debug-file = Arquivo de debugação
wish-url = Abrir desejos
about = Sobre
close = Fechar
hide = Esconder
nothing = Nada
save = Salvar
continue = Continuar
resume = Resumir
exit = Sair
check = Checar
restart = Reiniciar
agree = Concordar
loading-data = Carregando dados
downloading-background-picture = Baixando imagem de fundo
updating-components-index = Atualizando índice de componentes
loading-game-version = Carregando versão do jogo
loading-patch-status = Carregando status do patch
loading-launcher-state = Carregando status do launcher
loading-launcher-state--game = Loading launcher state: verificando versão do jogo
loading-launcher-state--voice = Loading launcher state: verificando pacote de voz {$locale}
loading-launcher-state--patch = Loading launcher state: verificando patch instalado
checking-free-space = Checando espaço livre
downloading = Baixando
unpacking = Extraindo
verifying-files = Verificando arquivos
repairing-files = Reparando arquivos
migrating-folders = Migrando pastas
applying-hdiff = Aplicando patches hdiff
removing-outdated = Removendo arquivos velhos
components-index-updated = Índice de componentes foi atualizado
launch = Iniciar
migrate-folders = Migrar pastas
migrate-folders-tooltip = Atualizar estrutura dos arquivos de jogo
apply-patch = Aplicar patch
disable-telemetry = Desativar telemetria
download-wine = Baixar wine
create-prefix = Criar prefixo
update = Atualizar
download = Baixar
predownload-update = Pre-baixar {$version} atualização ({$size})
kill-game-process = Terminar processo de jogo
main-window--patch-unavailable-tooltip = Servidores do patch estão indisponíveis e launcher não pode verificar o estado do patch de jogo. Pode jogar o jogo por sua conta e risco
main-window--patch-outdated-tooltip = Patch é antigo ou em estado de preparação, então indisponível para uso. Volte depois para checar seu estado
main-window--version-outdated-tooltip = Versão é antiga e não pode ser atualizada
preferences = Preferências
general = Geral
enhancements = Melhorias

View file

@ -0,0 +1,28 @@
sandbox = Sandbox
sandbox-description = Rode o jogo em um ambiente isolado, prevenindo-o de acessar seus dados
enable-sandboxing = Habilitar sandboxing
enable-sandboxing-description = Rode o jogo em uma cópia somente leitura do seu sistema de arquivo root
hide-home-directory = Esconder pasta home
hide-home-directory-description = Isolar as suas pastas /home, /var/home/$USER e $HOME do jogo
hostname = Hostname
additional-arguments = Argumentos adicionais
private-directories = Pastas privadas
private-directories-description = Essas pastas serão substituidas por um sistema virtual (tmpfs), e seu conteúdo original não será disponível ao jogo
path = Caminho
shared-directories = Pastas compartilhadas
shared-directories-description = Essas pastas serão symlinkadas à pastas nos seu sistema host
original-path = Caminho original
new-path = Novo caminho
read-only = Apenas leitura
read-only-description = Proibir o jogo de escrever qualquer dado nessa pasta
symlinks = Symlinks
symlinks-description = Symlink o caminho original para o novo dentro da sandbox

View file

@ -14,6 +14,12 @@ system = Системный
borderless-window = Окно без рамок
virtual-desktop = Виртуальный рабочий стол
map-drive-c = Создавать диск C:
map-drive-c-description = Автоматически создавать ссылку на папку drive_c из префикса Wine в dosdevices
map-game-folder = Создавать диск с папкой игры
map-game-folder-description = Автоматически создавать ссылку на папку с игрой в dosdevices
game = Игра
hud = HUD

View file

@ -4,7 +4,7 @@ environment-settings-description = Ange miljövariabler och kommando för att st
wine = Wine
synchronization = Synkronisation
synchronization = Synkronisering
wine-sync-description = Teknik som används för att synkronisera inre händelser i Wine
language = Språk
@ -14,6 +14,12 @@ system = System
borderless-window = Kantlöst fönster
virtual-desktop = Virtuellt skrivbord
map-drive-c = Mappa hårddisk C:
map-drive-c-description = Symlänka automatiskt mappen drive_c från Wine-prefixet till dosdevices
map-game-folder = Mappa spelets mapp
map-game-folder-description = Symlänka automatiskt spelets mapp till dosdevices
game = Spel
hud = HUD

View file

@ -1,5 +1,5 @@
environment = Miljö
game-command = Spel-kommando
game-command = Spelkommandon
game-command-description = Kommando som används för att starta spelet. Platshållaren %command% genereras automatiskt av startprogrammet. Exempelvis: gamemoderun '%command%'
new-variable = Ny variabel
name = Namn

View file

@ -4,4 +4,4 @@ active-sessions = Aktiv session
active-session-description = För närvarande vald spelsession. Uppdateras efter varje spelstart
update-session = Uppdatera sessionen med aktuella registervärden för Wine-prefix
delete-session = Ta bort sessionen
delete-session = Radera sessionen

View file

@ -43,10 +43,10 @@ loading-launcher-state--patch = Laddar starthanterarens tillstånd: verifierar i
checking-free-space = Kontrollerar ledigt utrymme
downloading = Laddar ner
unpacking = Packar upp
verifying-files = Verifierar filerna
repairing-files = Reparerar filerna
migrating-folders = Migrerar mapparna
applying-hdiff = Applicerar hdiff-patcharna
verifying-files = Verifierar filer
repairing-files = Reparerar filer
migrating-folders = Migrerar mappar
applying-hdiff = Applicerar hdiff-patchar
removing-outdated = Tar bort utdaterade filer
@ -71,5 +71,5 @@ main-window--patch-outdated-tooltip = Patchen är utdaterad eller i förberedels
main-window--version-outdated-tooltip = Versionen är för utdaterad och kan inte uppdateras
preferences = Preferenser
general = Allmän
general = Allmänt
enhancements = Förbättringar

View file

@ -14,6 +14,12 @@ system = Sistem
borderless-window = Köşesiz Pencere
virtual-desktop = Sanal Masaüstü
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = Oyun
hud = HUD

View file

@ -13,7 +13,7 @@ failed-get-selected-wine = Seçilen Wine versiyonunu alma başarısız oldu
downloading-failed = İndirme başarısız oldu
unpacking-failed = Oyun dosyalarını çıkarma başarısız oldu
kill-game-process-failed = Failed to kill the game's process
kill-game-process-failed = Oyunu zorla kapatma başarısız oldu
game-file-repairing-error = Oyun dosyaları tamir edilemedi
integrity-files-getting-error = Dosyaların bütünlüğü kontrol edilemedi

View file

@ -58,8 +58,8 @@ disable-mhypbase-description = Deneysel. Etkinleştirilirse, istemci ana yamayı
ask-superuser-permissions = Yönetici izinlerini sor
ask-superuser-permissions-description = İstemci yönetici iznini hostunuzun dosyalarını güncellemek için otomatik olarak kullanacaktır. Buna flatpak versiyonunda gerek yoktur
launcher-behavior = Launcher behavior
launcher-behavior-description = What should launcher window do when it starts the game
launcher-behavior = İstemci davranışı
launcher-behavior-description = İstemci penceresinin oyun başlatıldığında davranışı
wine-tools = Wine araçları
command-line = Komut istemi

View file

@ -17,9 +17,17 @@ wish-url = Dilekleri aç
about = Hakkında
close = Kapat
hide = Hide
nothing = Nothing
close = { $form ->
[verb] Kapat
*[noun] Kapalı
}
hide = { $form ->
[verb] Gizle
*[noun] Gizli
}
nothing = Hiçbir şey
save = Kaydet
continue = Devam et
resume = Sürdürmek
@ -64,7 +72,7 @@ update = Güncelle
download = İndir
predownload-update = Güncellemeyi önceden indir{$version} ({$size})
kill-game-process = Kill game process
kill-game-process = Oyunu zorla kapat
main-window--patch-unavailable-tooltip = Yama sunucuları kullanılamıyor ve istemci, oyunun yama durumunu doğrulayamıyor. Oyunu kendi sorumluluğunuzda çalıştırabilirsiniz
main-window--patch-outdated-tooltip = Yama güncel değil veya hazırlık aşamasında, bu nedenle kullanım için uygun değil. Durumunu görmek için daha sonra geri dönün

View file

@ -14,6 +14,12 @@ system = 系统
borderless-window = 无边框窗口
virtual-desktop = 虚拟桌面
map-drive-c = Map drive C:
map-drive-c-description = Automatically symlink drive_c folder from the wine prefix to the dosdevices
map-game-folder = Map game folder
map-game-folder-description = Automatically symlink game folder to the dosdevices
game = 游戏
hud = HUD

View file

@ -22,6 +22,7 @@ pub const SUPPORTED_LANGUAGES: &[LanguageIdentifier] = &[
langid!("ja-jp"),
langid!("hu-hu"),
langid!("sv-se"),
langid!("pt-br"),
langid!("pl-pl")
];

View file

@ -12,10 +12,13 @@ use anime_launcher_sdk::genshin::consts::*;
use anime_launcher_sdk::anime_game_core::prelude::*;
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
use anime_launcher_sdk::sessions::SessionsExt;
use anime_launcher_sdk::genshin::sessions::Sessions;
use tracing_subscriber::prelude::*;
use tracing_subscriber::filter::*;
pub mod move_folder;
pub mod move_files;
pub mod i18n;
pub mod background;
pub mod ui;
@ -69,7 +72,7 @@ lazy_static::lazy_static! {
pub static ref FIRST_RUN_FILE: PathBuf = LAUNCHER_FOLDER.join(".first-run");
}
fn main() {
fn main() -> anyhow::Result<()> {
// Setup custom panic handler
human_panic::setup_panic!(human_panic::metadata!());
@ -90,16 +93,36 @@ fn main() {
}
// Force debug output
let force_debug = std::env::args().any(|arg| &arg == "--debug");
let mut force_debug = false;
// Run the game
let run_game = std::env::args().any(|arg| &arg == "--run-game");
let mut run_game = false;
// Forcely run the game
let just_run_game = std::env::args().any(|arg| &arg == "--just-run-game");
let mut just_run_game = false;
// Forcely disable verbode tracing output in stdout
let no_verbose_tracing = std::env::args().any(|arg| &arg == "--no-verbose-tracing");
let mut no_verbose_tracing = false;
let args = std::env::args().collect::<Vec<_>>();
// Parse arguments
for i in 0..args.len() {
if args[i] == "--debug" {
force_debug = true;
} else if args[i] == "--run-game" {
run_game = true;
} else if args[i] == "--just-run-game" {
just_run_game = true;
} else if args[i] == "--no-verbose-tracing" {
no_verbose_tracing = true;
} else if args[i] == "--session" {
// Switch active session prior running the app
if let Some(session) = args.get(i + 1) {
Sessions::set_current(session.to_owned())?;
}
}
}
// Prepare stdout logger
let stdout = tracing_subscriber::fmt::layer()
@ -116,10 +139,7 @@ fn main() {
}));
// Prepare debug file logger
let file = match std::fs::File::create(DEBUG_FILE.as_path()) {
Ok(file) => file,
Err(error) => panic!("Failed to create debug.log file: {:?}", error)
};
let file = std::fs::File::create(DEBUG_FILE.as_path())?;
let debug_log = tracing_subscriber::fmt::layer()
.pretty()
@ -206,16 +226,13 @@ fn main() {
LauncherState::Launch => {
anime_launcher_sdk::genshin::game::run().expect("Failed to run the game");
return;
return Ok(());
}
LauncherState::PredownloadAvailable { .. } |
LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status: PatchStatus::NotAvailable, .. }, .. } => {
if just_run_game {
anime_launcher_sdk::genshin::game::run().expect("Failed to run the game");
LauncherState::PredownloadAvailable { .. } if just_run_game => {
anime_launcher_sdk::genshin::game::run().expect("Failed to run the game");
return;
}
return Ok(());
}
_ => ()
@ -228,4 +245,6 @@ fn main() {
// Show main window
app.run::<App>(());
}
Ok(())
}

31
src/move_files.rs Normal file
View file

@ -0,0 +1,31 @@
use std::path::Path;
use std::io::Result;
/// Move files from one folder to another
pub fn move_files(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
for entry in from.as_ref().read_dir()?.flatten() {
let source = entry.path();
let target = to.as_ref().join(entry.file_name());
if std::fs::rename(&source, &target).is_err() {
if source.is_dir() {
std::fs::create_dir_all(&target)
.and_then(|_| move_files(&source, &target))
.and_then(|_| std::fs::remove_dir_all(&source))?;
}
else if source.is_symlink() {
std::fs::read_link(&source)
.and_then(|link_target| std::os::unix::fs::symlink(link_target, &target))
.and_then(|_| std::fs::remove_file(&source))?;
}
else {
std::fs::copy(&source, &target)
.and_then(|_| std::fs::remove_file(&source))?;
}
}
}
Ok(())
}

View file

@ -1,26 +0,0 @@
use std::path::Path;
pub fn move_folder(from: &Path, to: &Path) -> std::io::Result<()> {
if !to.exists() {
std::fs::create_dir_all(to)?;
}
for entry in from.read_dir()?.flatten() {
let to_path = to.join(entry.file_name());
if entry.metadata()?.is_dir() {
move_folder(&entry.path(), &to_path)?;
}
else if entry.metadata()?.is_file() {
std::fs::copy(entry.path(), to_path)?;
std::fs::remove_file(entry.path())?;
}
// TODO: symlinks?
}
std::fs::remove_dir_all(from)?;
Ok(())
}

View file

@ -46,25 +46,6 @@ impl SimpleComponent for AboutDialog {
"Nikita Podvirnyy https://github.com/krypt0nn"
],
// Took patch credits from the CREDITS.md;
// If you want to change your name, link, or have any other questions - contact me
add_credit_section: (Some("Patch credits"), &[
"@Krock https://notabug.org/Krock",
"@y0soro https://notabug.org/y0soro",
"@3Shain https://notabug.org/3Shain",
"@timbuntu https://www.playonlinux.com/de/profil-95714.html",
"@geearf2",
"@SeppNel https://www.playonlinux.com/en/profil-95643.html",
"@0x90 https://www.playonlinux.com/en/profil-96196.html",
"@Th1nkCh3ck https://notabug.org/Th1nkCh3ck",
"@humanik12",
"@Makksim https://notabug.org/Makksim",
"@Kowalski https://notabug.org/Kowalski",
"@WerWolv",
"@Various"
]),
add_credit_section: (Some("An Anime Team"), &[
"Nikita Podvirnyy https://github.com/krypt0nn",
"Marie Piontek https://github.com/Mar0xy",
@ -81,6 +62,7 @@ impl SimpleComponent for AboutDialog {
set_translator_credits: &[
"Русский, English — Nikita Podvirnyy https://github.com/krypt0nn",
"Deutsch — Marie Piontek https://github.com/Mar0xy",
"Deutsch — @caem",
"Français — @zeGolem https://github.com/zeGolem",
"Español — Lautaro Garavano https://github.com/Rattlehead15",
"Türkçe — @Kaozix https://github.com/Kaozix1776",
@ -91,6 +73,7 @@ impl SimpleComponent for AboutDialog {
"日本語 — @zozonteq https://github.com/zozonteq",
// Hungarian?
"Svenska — Jakob Fridesjö https://github.com/jakobfridesjo",
"Português — @kafushy"
].join("\n"),
set_debug_info: &[
@ -108,27 +91,33 @@ impl SimpleComponent for AboutDialog {
"<p>Added</p>",
"<ul>",
"<li>Added new gamescope version compatibility</li>",
"<li>Added \"launcher behavior\" option</li>",
"<li>Added \"kill game process\" button when chosen behavior keeps launcher window open</li>",
"<li>Bundled some icons into the app for consistency across the systems</li>",
"<li>Added better panics handler</li>",
"<li>Added Swedish</li>",
"<li>Added feature to map wine drives</li>",
"<li>Added Portuguese</li>",
"<li>Added `%launch_args%` magic word for game launching command</li>",
"<li>Added 4.0.0 voiceovers sizes</li>",
"<li>Added `--session <name>` flag to switch active session</li>",
"</ul>",
"<p>Fixed</p>",
"<ul>",
"<li>Fixed predownload button sensitivity</li>",
"<li>Fixed logo size in the first run window</li>",
"</ul>",
"<p>Changed</p>",
"<ul>",
"<li>Improved pre-downloads state checking</li>",
"<li>Replaced translation functions by `tr!` macro</li>",
"<li>Reworked app resources structure</li>",
"<li>Improved game running status check (wasn't working properly with Chinese client)</li>",
"<li>Updated Turkish</li>",
"<li>Updated Italian</li>",
"<li>Updated Japanese</li>",
"<li>Updated Swedish</li>",
"<li>Improved files migration code</li>",
"</ul>",
"<p>Removed</p>",
"<ul>",
"<li>Removed patch integration</li>",
"</ul>",
].join("\n"),

View file

@ -25,7 +25,6 @@ pub struct DefaultPathsApp {
game_china: PathBuf,
fps_unlocker: PathBuf,
components: PathBuf,
patch: PathBuf,
temp: PathBuf
}
@ -39,7 +38,6 @@ pub enum Folders {
GameChina,
FpsUnlocker,
Components,
Patch,
Temp
}
@ -194,17 +192,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::Components)
},
adw::ActionRow {
set_title: &tr!("patch-folder"),
set_icon_name: Some("folder-symbolic"),
set_activatable: true,
#[watch]
set_subtitle: model.patch.to_str().unwrap(),
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::Patch)
},
adw::ActionRow {
set_title: &tr!("temp-folder"),
set_icon_name: Some("folder-symbolic"),
@ -302,7 +289,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
game_china: CONFIG.game.path.china.clone(),
fps_unlocker: CONFIG.game.enhancements.fps_unlocker.path.clone(),
components: CONFIG.components.path.clone(),
patch: CONFIG.patch.path.clone(),
#[allow(clippy::or_fun_call)]
temp: CONFIG.launcher.temp.clone().unwrap_or(std::env::temp_dir())
@ -337,7 +323,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
self.game_china = result.join(concat!("Yu", "anS", "hen"));
self.fps_unlocker = result.join("fps-unlocker");
self.components = result.join("components");
self.patch = result.join("patch");
self.temp = result.clone();
self.launcher = result;
@ -350,7 +335,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
Folders::GameChina => self.game_china = result,
Folders::FpsUnlocker => self.fps_unlocker = result,
Folders::Components => self.components = result,
Folders::Patch => self.patch = result,
Folders::Temp => self.temp = result
}
}
@ -374,7 +358,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
(old_config.game.path.global, &self.game_global),
(old_config.game.path.china, &self.game_china),
(old_config.components.path, &self.components),
(old_config.patch.path, &self.patch),
(old_config.game.enhancements.fps_unlocker.path, &self.fps_unlocker)
];
@ -386,7 +369,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
)));
if &from != to && from.exists() {
move_folder::move_folder(from, to).expect(&format!("Failed to move folder: {:?} -> {:?}", from, to));
move_files::move_files(from, to).expect(&format!("Failed to move folder: {:?} -> {:?}", from, to));
}
self.progress_bar.sender().send(ProgressBarMsg::UpdateProgress(i as u64 + 1, folders.len() as u64));
@ -437,7 +420,6 @@ impl DefaultPathsApp {
config.game.path.global = self.game_global.clone();
config.game.path.china = self.game_china.clone();
config.components.path = self.components.clone();
config.patch.path = self.patch.clone();
config.launcher.temp = Some(self.temp.clone());
config.game.enhancements.fps_unlocker.path = self.fps_unlocker.clone();

View file

@ -9,7 +9,6 @@ use anime_launcher_sdk::components::loader::ComponentsLoader;
use crate::*;
use super::welcome::*;
use super::tos_warning::*;
use super::dependencies::*;
use super::default_paths::*;
use super::select_voiceovers::*;
@ -22,7 +21,6 @@ pub static mut MAIN_WINDOW: Option<adw::ApplicationWindow> = None;
pub struct FirstRunApp {
welcome: AsyncController<WelcomeApp>,
tos_warning: AsyncController<TosWarningApp>,
dependencies: AsyncController<DependenciesApp>,
default_paths: AsyncController<DefaultPathsApp>,
select_voiceovers: AsyncController<SelectVoiceoversApp>,
@ -40,7 +38,6 @@ pub struct FirstRunApp {
pub enum FirstRunAppMsg {
SetLoadingStatus(Option<Option<String>>),
ScrollToTosWarning,
ScrollToDependencies,
ScrollToDefaultPaths,
ScrollToSelectVoiceovers,
@ -100,7 +97,6 @@ impl SimpleComponent for FirstRunApp {
set_allow_scroll_wheel: false,
append = model.welcome.widget(),
append = model.tos_warning.widget(),
append = model.dependencies.widget(),
append = model.default_paths.widget(),
append = model.select_voiceovers.widget(),
@ -135,10 +131,6 @@ impl SimpleComponent for FirstRunApp {
.launch(())
.forward(sender.input_sender(), std::convert::identity),
tos_warning: TosWarningApp::builder()
.launch(())
.forward(sender.input_sender(), std::convert::identity),
dependencies: DependenciesApp::builder()
.launch(())
.forward(sender.input_sender(), std::convert::identity),
@ -190,12 +182,6 @@ impl SimpleComponent for FirstRunApp {
self.loading = status;
}
FirstRunAppMsg::ScrollToTosWarning => {
self.title = tr!("tos-violation-warning");
self.carousel.scroll_to(self.tos_warning.widget(), true);
}
FirstRunAppMsg::ScrollToDependencies => {
self.title = tr!("dependencies");

View file

@ -1,6 +1,5 @@
pub mod main;
pub mod welcome;
pub mod tos_warning;
pub mod dependencies;
pub mod default_paths;
pub mod select_voiceovers;

View file

@ -1,125 +0,0 @@
use relm4::prelude::*;
use relm4::component::*;
use adw::prelude::*;
use anime_launcher_sdk::is_available;
use crate::*;
use super::main::FirstRunAppMsg;
use super::main::MAIN_WINDOW;
pub struct TosWarningApp;
#[derive(Debug, Clone)]
pub enum TosWarningAppMsg {
Continue,
Exit
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for TosWarningApp {
type Init = ();
type Input = TosWarningAppMsg;
type Output = FirstRunAppMsg;
view! {
adw::PreferencesPage {
set_hexpand: true,
add = &adw::PreferencesGroup {
set_valign: gtk::Align::Center,
set_vexpand: true,
gtk::Label {
set_label: &tr!("tos-violation-warning"),
add_css_class: "title-1"
}
},
add = &adw::PreferencesGroup {
gtk::Label {
set_label: &tr!("tos-violation-warning-message"),
set_wrap: true,
set_selectable: true
}
},
add = &adw::PreferencesGroup {
set_valign: gtk::Align::Center,
set_vexpand: true,
gtk::Box {
set_orientation: gtk::Orientation::Horizontal,
set_halign: gtk::Align::Center,
set_spacing: 8,
gtk::Button {
set_label: &tr!("continue"),
set_css_classes: &["suggested-action", "pill"],
connect_clicked => TosWarningAppMsg::Continue
},
gtk::Button {
set_label: &tr!("exit"),
add_css_class: "pill",
connect_clicked => TosWarningAppMsg::Exit
}
}
}
}
}
async fn init(
_init: Self::Init,
root: Self::Root,
_sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
let model = Self;
let widgets = view_output!();
AsyncComponentParts { model, widgets }
}
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
match msg {
#[allow(unused_must_use)]
TosWarningAppMsg::Continue => {
let dialog = adw::MessageDialog::new(
unsafe { MAIN_WINDOW.as_ref() },
Some(&tr!("tos-dialog-title")),
Some(&tr!("tos-dialog-message"))
);
dialog.add_responses(&[
("exit", &tr!("exit")),
("continue", &tr!("agree"))
]);
dialog.connect_response(None, move |_, response| {
match response {
"exit" => relm4::main_application().quit(),
"continue" => {
if is_available("git") && is_available("xdelta3") {
sender.output(Self::Output::ScrollToDefaultPaths);
} else {
sender.output(Self::Output::ScrollToDependencies);
}
}
_ => unreachable!()
}
});
dialog.show();
}
TosWarningAppMsg::Exit => relm4::main_application().quit()
}
}
}

View file

@ -3,6 +3,8 @@ use relm4::component::*;
use adw::prelude::*;
use anime_launcher_sdk::is_available;
use crate::*;
use super::main::FirstRunAppMsg;
@ -28,8 +30,8 @@ impl SimpleAsyncComponent for WelcomeApp {
set_valign: gtk::Align::Center,
set_vexpand: true,
gtk::Image {
set_icon_name: Some(APP_ID),
gtk::Picture {
set_resource: Some(&format!("{APP_RESOURCE_PATH}/icons/hicolor/scalable/apps/{APP_ID}.png")),
set_height_request: 128
},
@ -83,7 +85,11 @@ impl SimpleAsyncComponent for WelcomeApp {
match msg {
#[allow(unused_must_use)]
WelcomeAppMsg::Continue => {
sender.output(Self::Output::ScrollToTosWarning);
if is_available("git") && is_available("xdelta3") {
sender.output(Self::Output::ScrollToDefaultPaths);
} else {
sender.output(Self::Output::ScrollToDependencies);
}
}
}
}

View file

@ -1,55 +0,0 @@
use relm4::prelude::*;
use crate::*;
use super::{App, AppMsg};
pub fn apply_patch(sender: ComponentSender<App>, patch: PlayerPatch, rename_mhypbase: bool) {
match patch.status() {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => unreachable!(),
PatchStatus::Testing { .. } |
PatchStatus::Available { .. } => {
sender.input(AppMsg::DisableButtons(true));
let config = Config::get().unwrap();
std::thread::spawn(move || {
if let Err(err) = patch.apply(config.game.path.for_edition(config.launcher.edition), config.patch.root) {
tracing::error!("Failed to patch the game");
sender.input(AppMsg::Toast {
title: tr!("game-patching-error"),
description: Some(err.to_string())
});
}
else if rename_mhypbase {
let game_folder = config.game.path.for_edition(patch.edition);
let mhypbase = game_folder.join("mhypbase.dll");
let mhypbase_bak = game_folder.join("mhypbase.dll.bak");
if mhypbase.exists() {
if let Err(err) = std::fs::rename(mhypbase, mhypbase_bak) {
tracing::error!("Failed to rename mhypbase file");
sender.input(AppMsg::Toast {
title: tr!("game-patching-error"),
description: Some(err.to_string())
});
}
}
}
sender.input(AppMsg::DisableButtons(false));
sender.input(AppMsg::UpdateLauncherState {
perform_on_download_needed: false,
show_status_page: true
});
});
}
}
}

View file

@ -1,4 +1,5 @@
use std::process::Command;
use std::path::PathBuf;
use relm4::prelude::*;
@ -19,7 +20,12 @@ pub fn disable_telemetry(sender: ComponentSender<App>) {
.collect::<Vec<String>>()
.join(" ; ");
let output = if config.patch.root {
// TODO: perhaps find some another way? Or doesn't matter?
let use_root = std::env::var("LAUNCHER_USE_ROOT")
.map(|var| var == "1")
.unwrap_or_else(|_| !PathBuf::from("/.flatpak-info").exists());
let output = if use_root {
Command::new("pkexec")
.arg("bash")
.arg("-c")

View file

@ -10,7 +10,7 @@ pub fn migrate_folder(sender: ComponentSender<App>, from: PathBuf, to: PathBuf,
sender.input(AppMsg::DisableButtons(true));
std::thread::spawn(move || {
move_folder::move_folder(&from, &to).expect("Failed to perform migration");
move_files::move_files(&from, &to).expect("Failed to perform migration");
if let Some(cleanup_folder) = cleanup_folder {
std::fs::remove_dir_all(cleanup_folder).expect("Failed to remove cleanup folder");

View file

@ -11,7 +11,6 @@ use adw::prelude::*;
use gtk::glib::clone;
mod repair_game;
mod apply_patch;
mod download_wine;
mod create_prefix;
mod download_diff;
@ -79,10 +78,6 @@ pub enum AppMsg {
/// was retrieved from the API
SetGameDiff(Option<VersionDiff>),
/// Supposed to be called automatically on app's run when the latest UnityPlayer patch version
/// was retrieved from remote repos
SetPlayerPatch(Option<PlayerPatch>),
/// Supposed to be called automatically on app's run when the launcher state was chosen
SetLauncherState(Option<LauncherState>),
@ -418,15 +413,6 @@ impl SimpleComponent for App {
Some(LauncherState::VoiceUpdateAvailable(_)) |
Some(LauncherState::VoiceNotInstalled(_)) => "document-save-symbolic",
Some(LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status, .. }, .. }) => match status {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => "window-close-symbolic",
PatchStatus::Testing { .. } |
PatchStatus::Available { .. } => "document-save-symbolic"
}
Some(LauncherState::TelemetryNotDisabled) => "security-high-symbolic",
Some(LauncherState::VoiceOutdated(_)) |
@ -440,8 +426,6 @@ impl SimpleComponent for App {
Some(LauncherState::PredownloadAvailable { .. }) => tr!("launch"),
Some(LauncherState::FolderMigrationRequired { .. }) => tr!("migrate-folders"),
Some(LauncherState::PlayerPatchAvailable { .. }) => tr!("apply-patch"),
Some(LauncherState::TelemetryNotDisabled) => tr!("disable-telemetry"),
Some(LauncherState::WineNotInstalled) => tr!("download-wine"),
@ -480,17 +464,7 @@ impl SimpleComponent for App {
Some(LauncherState::GameOutdated { .. }) |
Some(LauncherState::VoiceOutdated(_)) => false,
Some(LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status, .. }, .. }) => match status {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => false,
PatchStatus::Testing { .. } |
PatchStatus::Available { .. } => true
},
Some(_) => true,
None => false
},
@ -499,17 +473,7 @@ impl SimpleComponent for App {
Some(LauncherState::GameOutdated { .. }) |
Some(LauncherState::VoiceOutdated(_)) => &["warning", "pill"],
Some(LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status, .. }, .. }) => match status {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => &["error", "pill"],
PatchStatus::Testing { .. } => &["warning", "pill"],
PatchStatus::Available { .. } => &["suggested-action", "pill"]
},
Some(_) => &["suggested-action", "pill"],
None => &["pill"]
},
@ -520,15 +484,6 @@ impl SimpleComponent for App {
Some(LauncherState::FolderMigrationRequired { .. }) => tr!("migrate-folders-tooltip"),
Some(LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status, .. }, .. }) => match status {
PatchStatus::NotAvailable => tr!("main-window--patch-unavailable-tooltip"),
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => tr!("main-window--patch-outdated-tooltip"),
_ => String::new()
},
_ => String::new()
}),
@ -551,9 +506,6 @@ impl SimpleComponent for App {
set_label: &tr!("kill-game-process")
},
#[watch]
set_visible: model.kill_game_button,
#[watch]
set_sensitive: !model.disabled_kill_game_button,
@ -929,61 +881,6 @@ impl SimpleComponent for App {
}
})));
// Update initial patch status
tasks.push(std::thread::spawn(clone!(@strong sender => move || {
// Sync local patch repo
let patch = Patch::new(&CONFIG.patch.path, CONFIG.launcher.edition);
match patch.is_sync(&CONFIG.patch.servers) {
Ok(Some(_)) => (),
Ok(None) => {
for server in &CONFIG.patch.servers {
match patch.sync(server) {
Ok(_) => break,
Err(err) => {
tracing::error!("Failed to sync patch folder with remote: {server}: {err}");
sender.input(AppMsg::Toast {
title: tr!("patch-sync-failed"),
description: Some(err.to_string())
});
}
}
}
}
Err(err) => {
tracing::error!("Failed to compare local patch folder with remote: {err}");
sender.input(AppMsg::Toast {
title: tr!("patch-state-check-failed"),
description: Some(err.to_string())
});
}
}
// Get main UnityPlayer patch status
sender.input(AppMsg::SetPlayerPatch(match patch.player_patch() {
Ok(patch) => Some(patch),
Err(err) => {
tracing::error!("Failed to fetch player patch info: {err}");
sender.input(AppMsg::Toast {
title: tr!("patch-info-fetching-error"),
description: Some(err.to_string())
});
None
}
}));
tracing::info!("Updated patch status");
})));
// Update initial game version status
tasks.push(std::thread::spawn(clone!(@strong sender => move || {
@ -1048,10 +945,6 @@ impl SimpleComponent for App {
"locale" = locale.to_name()
})))));
}
StateUpdating::Patch => {
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--patch")))));
}
}
}
});
@ -1094,11 +987,6 @@ impl SimpleComponent for App {
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().sender().send(PreferencesAppMsg::SetGameDiff(diff));
}
#[allow(unused_must_use)]
AppMsg::SetPlayerPatch(patch) => unsafe {
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().sender().send(PreferencesAppMsg::SetPlayerPatch(patch));
}
AppMsg::SetLauncherState(state) => {
self.state = state;
}
@ -1177,16 +1065,12 @@ impl SimpleComponent for App {
AppMsg::PerformAction => unsafe {
match self.state.as_ref().unwrap_unchecked() {
LauncherState::PlayerPatchAvailable { patch: PlayerPatch { status: PatchStatus::NotAvailable, .. }, .. } |
LauncherState::PredownloadAvailable { .. } |
LauncherState::Launch => launch::launch(sender),
LauncherState::FolderMigrationRequired { from, to, cleanup_folder } =>
migrate_folder::migrate_folder(sender, from.to_owned(), to.to_owned(), cleanup_folder.to_owned()),
LauncherState::PlayerPatchAvailable { patch, disable_mhypbase } =>
apply_patch::apply_patch(sender, patch.to_owned(), *disable_mhypbase),
LauncherState::TelemetryNotDisabled => disable_telemetry::disable_telemetry(sender),
LauncherState::WineNotInstalled => download_wine::download_wine(sender, self.progress_bar.sender().to_owned()),

View file

@ -1,5 +1,3 @@
use std::path::Path;
use relm4::{
prelude::*,
Sender
@ -105,59 +103,16 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
tracing::warn!("Found broken files:\n{}", broken.iter().fold(String::new(), |acc, file| acc + &format!("- {}\n", file.path.to_string_lossy())));
// Get main patch status
let player_patch = PlayerPatch::from_folder(&config.patch.path, config.launcher.edition)
.and_then(|patch| patch.is_applied(&game_path))
.unwrap_or_else(|err| {
tracing::warn!("Failed to get player patch status: {err}. Used config value instead: {}", config.patch.apply);
config.patch.apply
});
tracing::debug!("Patch status: {player_patch}. Disable mhypbase: {}", config.patch.disable_mhypbase);
fn should_ignore(path: &Path, player_patch: bool, disable_mhypbase: bool) -> bool {
// Files managed by launch.bat file
for part in ["crashreport.exe", "upload_crash.exe"] {
if path.ends_with(part) {
return true;
}
}
// UnityPlayer patch related files
if player_patch {
for part in ["UnityPlayer.dll", "vulkan-1.dll"] {
if path.ends_with(part) {
return true;
}
}
}
// If mhypbase should be disabled
if disable_mhypbase && path.ends_with("mhypbase.dll") {
return true;
}
false
}
for (i, file) in broken.into_iter().enumerate() {
if !should_ignore(&file.path, player_patch, config.patch.disable_mhypbase) {
tracing::debug!("Repairing file: {}", file.path.to_string_lossy());
tracing::debug!("Repairing file: {}", file.path.to_string_lossy());
if let Err(err) = file.repair(&game_path) {
sender.input(AppMsg::Toast {
title: tr!("game-file-repairing-error"),
description: Some(err.to_string())
});
if let Err(err) = file.repair(&game_path) {
sender.input(AppMsg::Toast {
title: tr!("game-file-repairing-error"),
description: Some(err.to_string())
});
tracing::error!("Failed to repair game file: {err}");
}
}
else {
tracing::debug!("Skipped file: {}", file.path.to_string_lossy());
tracing::error!("Failed to repair game file: {err}");
}
progress_bar_input.send(ProgressBarMsg::UpdateProgress(i as u64 + 1, total));

View file

@ -1,6 +1,11 @@
use relm4::prelude::*;
use relm4::component::*;
use relm4::factory::*;
use relm4::factory::{
AsyncFactoryComponent,
AsyncFactorySender,
AsyncFactoryVecDeque
};
use adw::prelude::*;
@ -285,6 +290,76 @@ impl SimpleAsyncComponent for EnhancementsApp {
if let Ok(mut config) = Config::get() {
config.game.wine.virtual_desktop.enabled = switch.state();
Config::update(config);
}
}
}
}
},
adw::ActionRow {
set_title: &tr!("map-drive-c"),
set_subtitle: &tr!("map-drive-c-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.wine.drives.drive_c,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = Config::get() {
config.game.wine.drives.drive_c = switch.state();
Config::update(config);
}
}
}
}
},
#[name = "map_game_folder_row"]
adw::ComboRow {
set_title: &tr!("map-game-folder"),
set_subtitle: &tr!("map-game-folder-description"),
#[wrap(Some)]
set_model = &gtk::StringList::new(&AllowedDrives::list().iter()
.map(|drive| drive.to_drive())
.collect::<Vec<_>>()),
set_selected: match CONFIG.game.wine.drives.game_folder {
Some(drive) => AllowedDrives::list().iter()
.position(|allowed| *allowed == drive)
.unwrap_or(8) as u32,
None => 8 // G:
},
connect_selected_notify => |row| {
if is_ready() {
if let Ok(mut config) = Config::get() {
config.game.wine.drives.game_folder = Some(AllowedDrives::list()[row.selected() as usize]);
Config::update(config);
}
}
},
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.game.wine.drives.game_folder.is_some(),
connect_state_notify[map_game_folder_row] => move |switch| {
if is_ready() {
if let Ok(mut config) = Config::get() {
if switch.state() {
config.game.wine.drives.game_folder = Some(AllowedDrives::list()[map_game_folder_row.selected() as usize]);
} else {
config.game.wine.drives.game_folder = None;
}
Config::update(config);
}
}

View file

@ -111,10 +111,7 @@ pub struct GeneralApp {
components_page: AsyncController<ComponentsPage>,
game_diff: Option<VersionDiff>,
player_patch: Option<PlayerPatch>,
style: LauncherStyle,
languages: Vec<String>
}
@ -124,10 +121,6 @@ pub enum GeneralAppMsg {
/// was retrieved from the API
SetGameDiff(Option<VersionDiff>),
/// Supposed to be called automatically on app's run when the latest UnityPlayer patch version
/// was retrieved from remote repos
SetPlayerPatch(Option<PlayerPatch>),
// If one ever wish to change it to accept VoiceLocale
// I'd recommend to use clone!(@strong self.locale as locale => move |_| { .. })
// in the VoicePackage component
@ -291,21 +284,15 @@ impl SimpleAsyncComponent for GeneralApp {
&tr!("china")
])),
set_selected: match CONFIG.launcher.edition {
GameEdition::Global => 0,
GameEdition::China => 1
},
set_selected: GameEdition::list().iter()
.position(|edition| edition == &CONFIG.launcher.edition)
.unwrap() as u32,
connect_selected_notify[sender] => move |row| {
if is_ready() {
#[allow(unused_must_use)]
if let Ok(mut config) = Config::get() {
config.launcher.edition = match row.selected() {
0 => GameEdition::Global,
1 => GameEdition::China,
_ => unreachable!()
};
config.launcher.edition = GameEdition::list()[row.selected() as usize];
Config::update(config);
@ -432,158 +419,6 @@ impl SimpleAsyncComponent for GeneralApp {
None => String::new()
})
}
},
adw::ActionRow {
set_title: &tr!("player-patch-version"),
set_subtitle: &tr!("player-patch-version-description"),
add_suffix = &gtk::Label {
#[watch]
set_text: &match model.player_patch.as_ref() {
Some(patch) => match patch.status() {
PatchStatus::NotAvailable => tr!("patch-not-available"),
PatchStatus::Outdated { current, .. } => tr!("patch-outdated", {
"current" = current.to_string()
}),
PatchStatus::Preparation { .. } => tr!("patch-preparation"),
PatchStatus::Testing { version, .. } |
PatchStatus::Available { version, .. } => version.to_string()
}
None => String::from("?")
},
#[watch]
set_css_classes: match model.player_patch.as_ref() {
Some(patch) => match patch.status() {
PatchStatus::NotAvailable => &["error"],
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } |
PatchStatus::Testing { .. } => &["warning"],
PatchStatus::Available { .. } => unsafe {
let path = match Config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Ok(true) = model.player_patch.as_ref().unwrap_unchecked().is_applied(path) {
&["success"]
} else {
&["warning"]
}
}
}
None => &[]
},
#[watch]
set_tooltip_text: Some(&match model.player_patch.as_ref() {
Some(patch) => match patch.status() {
PatchStatus::NotAvailable => tr!("patch-not-available-tooltip"),
PatchStatus::Outdated { current, latest, .. } => tr!("patch-outdated-tooltip", {
"current" = current.to_string(),
"latest" = latest.to_string()
}),
PatchStatus::Preparation { .. } => tr!("patch-preparation-tooltip"),
PatchStatus::Testing { .. } => tr!("patch-testing-tooltip"),
PatchStatus::Available { .. } => unsafe {
let path = match Config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Ok(true) = model.player_patch.as_ref().unwrap_unchecked().is_applied(path) {
String::new()
} else {
tr!("patch-not-applied-tooltip")
}
}
}
None => String::new()
})
}
}
},
add = &adw::PreferencesGroup {
adw::ActionRow {
set_title: &tr!("apply-main-patch"),
set_subtitle: &tr!("apply-main-patch-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.patch.apply,
connect_state_notify[sender] => move |switch| {
if is_ready() {
#[allow(unused_must_use)]
if let Ok(mut config) = Config::get() {
config.patch.apply = switch.state();
Config::update(config);
sender.output(PreferencesAppMsg::UpdateLauncherState);
}
}
}
}
},
adw::ActionRow {
set_title: &tr!("disable-mhypbase"),
set_subtitle: &tr!("disable-mhypbase-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.patch.disable_mhypbase,
connect_state_notify[sender] => move |switch| {
if is_ready() {
#[allow(unused_must_use)]
if let Ok(mut config) = Config::get() {
config.patch.disable_mhypbase = switch.state();
Config::update(config);
sender.output(PreferencesAppMsg::UpdateLauncherState);
}
}
}
}
},
adw::ActionRow {
set_title: &tr!("ask-superuser-permissions"),
set_subtitle: &tr!("ask-superuser-permissions-description"),
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: CONFIG.patch.root,
connect_state_notify => |switch| {
if is_ready() {
if let Ok(mut config) = Config::get() {
config.patch.root = switch.state();
Config::update(config);
}
}
}
}
}
},
@ -719,10 +554,7 @@ impl SimpleAsyncComponent for GeneralApp {
.forward(sender.input_sender(), std::convert::identity),
game_diff: None,
player_patch: None,
style: CONFIG.launcher.style,
languages: SUPPORTED_LANGUAGES.iter().map(|lang| tr!(format_lang(lang).as_str())).collect()
};
@ -749,10 +581,6 @@ impl SimpleAsyncComponent for GeneralApp {
self.game_diff = diff;
}
GeneralAppMsg::SetPlayerPatch(patch) => {
self.player_patch = patch;
}
#[allow(unused_must_use)]
GeneralAppMsg::AddVoicePackage(index) => {
if let Some(package) = self.voice_packages.get(index.current_index()) {

View file

@ -4,7 +4,6 @@ use relm4::component::*;
use gtk::prelude::*;
use adw::prelude::*;
use anime_launcher_sdk::anime_game_core::prelude::*;
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
use anime_launcher_sdk::config::ConfigExt;
@ -28,11 +27,6 @@ pub enum PreferencesAppMsg {
/// Supposed to be called automatically on app's run when the latest game version
/// was retrieved from the API
SetGameDiff(Option<VersionDiff>),
/// Supposed to be called automatically on app's run when the latest UnityPlayer patch version
/// was retrieved from remote repos
SetPlayerPatch(Option<PlayerPatch>),
SetLauncherStyle(LauncherStyle),
UpdateLauncherState,
@ -119,11 +113,6 @@ impl SimpleAsyncComponent for PreferencesApp {
self.general.sender().send(GeneralAppMsg::SetGameDiff(diff));
}
#[allow(unused_must_use)]
PreferencesAppMsg::SetPlayerPatch(patch) => {
self.general.sender().send(GeneralAppMsg::SetPlayerPatch(patch));
}
#[allow(unused_must_use)]
PreferencesAppMsg::SetLauncherStyle(style) => {
sender.output(Self::Output::SetLauncherStyle(style));