mirror of
https://github.com/ALEZ-DEV/Babylonia-terminal.git
synced 2025-12-15 17:08:51 +00:00
can now install the game from the GUI
This commit is contained in:
parent
ac52edbb4d
commit
9188860db3
@ -79,6 +79,9 @@ impl GameComponent {
|
||||
match v {
|
||||
Some(str) => {
|
||||
if str == "done" {
|
||||
if let Ok(size) = current_size {
|
||||
progress.done();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import './screens/screens.dart';
|
||||
import './screens/setup_screen.dart';
|
||||
import './providers/providers.dart';
|
||||
import './models/error_reporter.dart';
|
||||
import './models/game.dart';
|
||||
|
||||
class BabyloniaLauncher extends StatelessWidget {
|
||||
BabyloniaLauncher(
|
||||
@ -105,17 +106,20 @@ class _MenuState extends State<Menu> {
|
||||
),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
drawer: Drawer(
|
||||
child: ListView(
|
||||
children: items,
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => Game(),
|
||||
child: Scaffold(
|
||||
drawer: Drawer(
|
||||
child: ListView(
|
||||
children: items,
|
||||
),
|
||||
),
|
||||
appBar: AppBar(
|
||||
title: const Text("Babylonia Terminal"),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Screens.getCurrent(_selectedIndex),
|
||||
),
|
||||
appBar: AppBar(
|
||||
title: const Text("Babylonia Terminal"),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Screens.getCurrent(_selectedIndex),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:babylonia_terminal_launcher/models/config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import './../providers/providers.dart';
|
||||
|
||||
58
babylonia_terminal_launcher/lib/models/game.dart
Normal file
58
babylonia_terminal_launcher/lib/models/game.dart
Normal file
@ -0,0 +1,58 @@
|
||||
import 'package:babylonia_terminal_launcher/messages/steps/game.pb.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import './../providers/providers.dart';
|
||||
|
||||
enum GameInstallationState {
|
||||
idle,
|
||||
checkingFile,
|
||||
downloading,
|
||||
patching,
|
||||
}
|
||||
|
||||
class Game with ChangeNotifier {
|
||||
GameInstallationState gameInstallationState = GameInstallationState.idle;
|
||||
|
||||
Int64 currentProgress = Int64(0);
|
||||
Int64 maxProgress = Int64(0);
|
||||
|
||||
Future startInstallation(GameStateProvider gameState) async {
|
||||
StartGameInstallation().sendSignalToRust();
|
||||
gameInstallationState = GameInstallationState.checkingFile;
|
||||
notifyListeners();
|
||||
|
||||
//final downloadStream = NotifyGameStartDownloading.rustSignalStream;
|
||||
//await for (final _ in downloadStream) {
|
||||
// gameInstallationState = GameInstallationState.downloading;
|
||||
// notifyListeners();
|
||||
// break;
|
||||
//}
|
||||
|
||||
final downloadProgresStream = GameInstallationProgress.rustSignalStream;
|
||||
await for (final rustSignal in downloadProgresStream) {
|
||||
if (gameInstallationState == GameInstallationState.checkingFile) {
|
||||
gameInstallationState = GameInstallationState.downloading;
|
||||
}
|
||||
|
||||
currentProgress = rustSignal.message.current;
|
||||
maxProgress = rustSignal.message.max;
|
||||
print("progress current : $currentProgress / $maxProgress");
|
||||
notifyListeners();
|
||||
|
||||
if (currentProgress >= maxProgress) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print("patching game...");
|
||||
gameInstallationState = GameInstallationState.patching;
|
||||
notifyListeners();
|
||||
|
||||
final successStream = NotifyGameSuccessfullyInstalled.rustSignalStream;
|
||||
await for (final _ in successStream) {
|
||||
gameState.updateGameState();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,11 @@
|
||||
import 'package:babylonia_terminal_launcher/messages/game_state.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../widgets/background_widget.dart';
|
||||
import '../widgets/serious_lee_widget.dart';
|
||||
import '../widgets/simple_button.dart';
|
||||
import '../widgets/steps/game_steps_widget.dart';
|
||||
import './../providers/providers.dart';
|
||||
import './../models/settings.dart';
|
||||
import './../models/background.dart';
|
||||
@ -16,44 +18,41 @@ class HomeScreen extends StatelessWidget {
|
||||
return Stack(
|
||||
children: [
|
||||
const ShowBackground(),
|
||||
SizedBox(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(50.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 600,
|
||||
maxHeight: 50,
|
||||
),
|
||||
child: SimpleButton(
|
||||
onPressed: () async {
|
||||
Provider.of<GameStateProvider>(context,
|
||||
listen: false)
|
||||
.updateGameState();
|
||||
},
|
||||
child: const Center(
|
||||
child: Text("Download"),
|
||||
Provider.of<GameStateProvider>(context).gameState !=
|
||||
States.GameInstalled
|
||||
? const GameSteps()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(50.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 600,
|
||||
maxHeight: 50,
|
||||
),
|
||||
child: SimpleButton(
|
||||
onPressed: () async {},
|
||||
child: const Center(
|
||||
child: Text("Play"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,145 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:yaru/yaru.dart';
|
||||
|
||||
import './../../models/game.dart';
|
||||
import './../simple_button.dart';
|
||||
import './../gtk_spinner_widget.dart';
|
||||
import './../../providers/providers.dart';
|
||||
|
||||
class GameSteps extends StatelessWidget {
|
||||
const GameSteps({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(50.0),
|
||||
child: Builder(builder: (context) {
|
||||
switch (Provider.of<Game>(context).gameInstallationState) {
|
||||
case GameInstallationState.idle:
|
||||
return const _InstallGame();
|
||||
case GameInstallationState.checkingFile:
|
||||
return const _CheckingFileGame();
|
||||
case GameInstallationState.downloading:
|
||||
return const _DownloadingGame();
|
||||
case GameInstallationState.patching:
|
||||
return const _PatchingGame();
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _InstallGame extends StatelessWidget {
|
||||
const _InstallGame({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 600,
|
||||
maxHeight: 50,
|
||||
),
|
||||
child: SimpleButton(
|
||||
onPressed: () async {
|
||||
Provider.of<Game>(context, listen: false).startInstallation(
|
||||
Provider.of<GameStateProvider>(context, listen: false),
|
||||
);
|
||||
},
|
||||
child: const Center(
|
||||
child: Text("Download"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CheckingFileGame extends StatelessWidget {
|
||||
const _CheckingFileGame({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(bottom: 40.0),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GtkSpinner(),
|
||||
Text("Checking files... (This can take a while)"),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DownloadingGame extends StatelessWidget {
|
||||
const _DownloadingGame({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final provider = Provider.of<Game>(context);
|
||||
final pourcent =
|
||||
(provider.currentProgress.toInt() / provider.maxProgress.toInt()) * 100;
|
||||
final currentGb = provider.currentProgress.toInt() / 1024 / 1024 / 1024;
|
||||
final maxGb = provider.maxProgress.toInt() / 1024 / 1024 / 1024;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 40.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
"${currentGb.toStringAsFixed(2)} / ${maxGb.toStringAsFixed(2)} Gb (${pourcent.toStringAsFixed(2)}%)",
|
||||
),
|
||||
),
|
||||
YaruLinearProgressIndicator(
|
||||
value: pourcent / 100,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PatchingGame extends StatelessWidget {
|
||||
const _PatchingGame({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(bottom: 40.0),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GtkSpinner(),
|
||||
Text("Patching game"),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
20
babylonia_terminal_launcher/messages/steps/game.proto
Normal file
20
babylonia_terminal_launcher/messages/steps/game.proto
Normal file
@ -0,0 +1,20 @@
|
||||
syntax = "proto3";
|
||||
package game;
|
||||
|
||||
// [RINF:RUST-SIGNAL]
|
||||
message GameInstallationProgress {
|
||||
uint64 current = 1;
|
||||
uint64 max = 2;
|
||||
}
|
||||
|
||||
// [RINF:DART-SIGNAL]
|
||||
message StartGameInstallation {}
|
||||
|
||||
// [RINF:RUST-SIGNAL]
|
||||
message NotifyGameStartDownloading {}
|
||||
|
||||
// [RINF:RUST-SIGNAL]
|
||||
message NotifyGameStartPatching {}
|
||||
|
||||
// [RINF:RUST-SIGNAL]
|
||||
message NotifyGameSuccessfullyInstalled {}
|
||||
103
babylonia_terminal_launcher/native/hub/src/game.rs
Normal file
103
babylonia_terminal_launcher/native/hub/src/game.rs
Normal file
@ -0,0 +1,103 @@
|
||||
use std::thread;
|
||||
|
||||
use babylonia_terminal_sdk::{
|
||||
components::proton_component::ProtonComponent, game_manager::GameManager, game_state::GameState,
|
||||
};
|
||||
use rinf::debug_print;
|
||||
use tokio_with_wasm::tokio;
|
||||
|
||||
use crate::messages::{
|
||||
error::ReportError,
|
||||
steps::game::{
|
||||
GameInstallationProgress, NotifyGameStartDownloading, NotifyGameStartPatching,
|
||||
NotifyGameSuccessfullyInstalled, StartGameInstallation,
|
||||
},
|
||||
};
|
||||
|
||||
pub async fn listen_game_installation() {
|
||||
let mut receiver = StartGameInstallation::get_dart_signal_receiver();
|
||||
while let Some(_) = receiver.recv().await {
|
||||
thread::spawn(move || {
|
||||
debug_print!("start downloading game...");
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let game_dir = GameState::get_config().await.config_dir;
|
||||
|
||||
match GameManager::install_game(
|
||||
game_dir.clone(),
|
||||
InstallationReporter::create(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(e) => ReportError {
|
||||
error_message: format!("Failed to install game : {}", e),
|
||||
}
|
||||
.send_signal_to_dart(),
|
||||
Ok(_) => {
|
||||
NotifyGameStartPatching {}.send_signal_to_dart();
|
||||
debug_print!("start patching game...");
|
||||
match GameManager::patch_game(game_dir).await {
|
||||
Err(e) => ReportError {
|
||||
error_message: format!("Failed to install game : {}", e),
|
||||
}
|
||||
.send_signal_to_dart(),
|
||||
Ok(_) => NotifyGameSuccessfullyInstalled {}.send_signal_to_dart(),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct DownloadReporterPrivate {
|
||||
max_progress: Option<u64>,
|
||||
}
|
||||
|
||||
struct InstallationReporter {
|
||||
private: std::sync::Mutex<Option<DownloadReporterPrivate>>,
|
||||
}
|
||||
|
||||
impl InstallationReporter {
|
||||
pub fn create() -> std::sync::Arc<Self> {
|
||||
std::sync::Arc::new(Self {
|
||||
private: std::sync::Mutex::new(None),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl downloader::progress::Reporter for InstallationReporter {
|
||||
fn setup(&self, max_progress: Option<u64>, _: &str) {
|
||||
let private = DownloadReporterPrivate { max_progress };
|
||||
|
||||
let mut guard = self.private.lock().unwrap();
|
||||
*guard = Some(private);
|
||||
}
|
||||
|
||||
fn progress(&self, current: u64) {
|
||||
if let Some(p) = self.private.lock().unwrap().as_mut() {
|
||||
GameInstallationProgress {
|
||||
current,
|
||||
max: p.max_progress.unwrap(),
|
||||
}
|
||||
.send_signal_to_dart();
|
||||
}
|
||||
}
|
||||
|
||||
fn set_message(&self, _: &str) {}
|
||||
|
||||
fn done(&self) {
|
||||
if let Some(p) = self.private.lock().unwrap().as_mut() {
|
||||
GameInstallationProgress {
|
||||
current: p.max_progress.unwrap(),
|
||||
max: p.max_progress.unwrap(),
|
||||
}
|
||||
.send_signal_to_dart();
|
||||
}
|
||||
let mut guard = self.private.lock().unwrap();
|
||||
*guard = None;
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ mod config;
|
||||
mod dependencies;
|
||||
mod dxvk;
|
||||
mod fonts;
|
||||
mod game;
|
||||
mod game_state;
|
||||
mod github;
|
||||
mod messages;
|
||||
@ -25,4 +26,5 @@ async fn main() {
|
||||
tokio::spawn(dxvk::listen_dxvk_installation());
|
||||
tokio::spawn(fonts::listen_fonts_installation());
|
||||
tokio::spawn(dependencies::listen_dependecies_installation());
|
||||
tokio::spawn(game::listen_game_installation());
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user