Added settings tab

This commit is contained in:
Alessandro Autiero
2022-10-07 19:18:19 +02:00
parent 55467152c9
commit 07481c303e
17 changed files with 258 additions and 110 deletions

View File

@@ -20,6 +20,7 @@ import 'package:win32/win32.dart';
import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
// Needed because binaries can't be loaded in any other way
const String _craniumDownload = "https://cdn.discordapp.com/attachments/1001161930599317524/1027684488718860309/cranium.dll"; const String _craniumDownload = "https://cdn.discordapp.com/attachments/1001161930599317524/1027684488718860309/cranium.dll";
const String _consoleDownload = "https://cdn.discordapp.com/attachments/1001161930599317524/1027684489184432188/console.dll"; const String _consoleDownload = "https://cdn.discordapp.com/attachments/1001161930599317524/1027684489184432188/console.dll";
const String _injectorDownload = "https://cdn.discordapp.com/attachments/1001161930599317524/1027686593697435799/injector.exe"; const String _injectorDownload = "https://cdn.discordapp.com/attachments/1001161930599317524/1027686593697435799/injector.exe";
@@ -74,20 +75,23 @@ Future<String?> _getWindowsPath(String folderID) {
Future<void> handleCLI(List<String> args) async { Future<void> handleCLI(List<String> args) async {
stdout.writeln("Reboot Launcher CLI Tool"); stdout.writeln("Reboot Launcher CLI Tool");
stdout.writeln("Wrote by Auties00"); stdout.writeln("Wrote by Auties00");
stdout.writeln("Version 3.10"); stdout.writeln("Version 3.11");
var gameJson = await _getControllerJson("game1"); var gameJson = await _getControllerJson("game");
var serverJson = await _getControllerJson("server1"); var serverJson = await _getControllerJson("server");
var settingsJson = await _getControllerJson("settings");
var versions = _getVersions(gameJson); var versions = _getVersions(gameJson);
var parser = ArgParser() var parser = ArgParser()
..addCommand("list")..addCommand("launch") ..addCommand("list")
..addCommand("launch")
..addOption("version", defaultsTo: gameJson["version"]) ..addOption("version", defaultsTo: gameJson["version"])
..addOption("username") ..addOption("username")
..addOption("server-type", allowed: ["embedded", "remote"], defaultsTo: serverJson["embedded"] ?? true ? "embedded" : "remote") ..addOption("server-type", allowed: ["embedded", "remote"], defaultsTo: serverJson["embedded"] ?? true ? "embedded" : "remote")
..addOption("server-host", defaultsTo: serverJson["host"]) ..addOption("server-host", defaultsTo: serverJson["host"])
..addOption("server-port", defaultsTo: serverJson["port"]) ..addOption("server-port", defaultsTo: serverJson["port"])
..addOption("dll", defaultsTo: settingsJson["reboot"] ?? await loadBinary("reboot.dll", true))
..addOption("type", allowed: ["client", "server", "headless_server"], defaultsTo: _getDefaultType(gameJson)) ..addOption("type", allowed: ["client", "server", "headless_server"], defaultsTo: _getDefaultType(gameJson))
..addFlag("update", defaultsTo: true, negatable: true) ..addFlag("update", defaultsTo: settingsJson["auto_update"] ?? true, negatable: true)
..addFlag("log", defaultsTo: false); ..addFlag("log", defaultsTo: false);
var result = parser.parse(args); var result = parser.parse(args);
if (result.command?.name == "list") { if (result.command?.name == "list") {
@@ -104,7 +108,7 @@ Future<void> handleCLI(List<String> args) async {
var dummyVersion = _createVersion(gameJson["version"], result["version"], versions); var dummyVersion = _createVersion(gameJson["version"], result["version"], versions);
await _updateDLLs(); await _updateDLLs();
if(result["update"]) { if(result["update"]) {
stdout.writeln("Updating DLL..."); stdout.writeln("Updating reboot dll...");
await downloadRebootDll(0); await downloadRebootDll(0);
} }
@@ -121,7 +125,7 @@ Future<void> handleCLI(List<String> args) async {
return; return;
} }
await _startGameProcess(dummyVersion, type != GameType.client, result); await _startGameProcess(dummyVersion, result["dll"], type != GameType.client, result);
await _injectOrShowError("cranium.dll"); await _injectOrShowError("cranium.dll");
} }
@@ -193,7 +197,7 @@ List<FortniteVersion> _getVersions(Map<String, dynamic> gameJson) {
.toList(); .toList();
} }
Future<void> _startGameProcess(FortniteVersion dummyVersion, bool host, ArgResults result) async { Future<void> _startGameProcess(FortniteVersion dummyVersion, String rebootDll, bool host, ArgResults result) async {
var gamePath = dummyVersion.executable?.path; var gamePath = dummyVersion.executable?.path;
if (gamePath == null) { if (gamePath == null) {
throw Exception("${dummyVersion.location throw Exception("${dummyVersion.location
@@ -209,7 +213,7 @@ Future<void> _startGameProcess(FortniteVersion dummyVersion, bool host, ArgResul
var verbose = result["log"]; var verbose = result["log"];
_gameProcess = await Process.start(gamePath, createRebootArgs(username, result["type"] == "headless_server")) _gameProcess = await Process.start(gamePath, createRebootArgs(username, result["type"] == "headless_server"))
..exitCode.then((_) => _onClose()) ..exitCode.then((_) => _onClose())
..outLines.forEach((line) => _onGameOutput(line, host, verbose)); ..outLines.forEach((line) => _onGameOutput(line, rebootDll, host, verbose));
} }
void _onClose() { void _onClose() {
@@ -323,7 +327,7 @@ FortniteVersion _createVersion(String? versionName, String? versionPath, List<Fo
return FortniteVersion(name: "dummy", location: Directory(versionPath)); return FortniteVersion(name: "dummy", location: Directory(versionPath));
} }
void _onGameOutput(String line, bool host, bool verbose) { void _onGameOutput(String line, String rebootDll, bool host, bool verbose) {
if(verbose) { if(verbose) {
stdout.writeln(line); stdout.writeln(line);
} }
@@ -353,18 +357,22 @@ void _onGameOutput(String line, bool host, bool verbose) {
} }
if(line.contains("Region") && host){ if(line.contains("Region") && host){
_injectOrShowError("reboot.dll"); _injectOrShowError(rebootDll, false);
} }
} }
Future<void> _injectOrShowError(String binary) async { Future<void> _injectOrShowError(String binary, [bool locate = true]) async {
if (_gameProcess == null) { if (_gameProcess == null) {
return; return;
} }
try { try {
stdout.writeln("Injecting $binary..."); stdout.writeln("Injecting $binary...");
var dll = await loadBinary(binary, true); var dll = locate ? await loadBinary(binary, true) : File(binary);
if(!dll.existsSync()){
throw Exception("Cannot inject $dll: missing file");
}
var success = await injectDll(_gameProcess!.pid, dll.path, true); var success = await injectDll(_gameProcess!.pid, dll.path, true);
if (success) { if (success) {
return; return;

View File

@@ -10,6 +10,7 @@ import 'package:reboot_launcher/cli.dart';
import 'package:reboot_launcher/src/controller/build_controller.dart'; import 'package:reboot_launcher/src/controller/build_controller.dart';
import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart';
import 'package:reboot_launcher/src/controller/server_controller.dart'; import 'package:reboot_launcher/src/controller/server_controller.dart';
import 'package:reboot_launcher/src/controller/settings_controller.dart';
import 'package:reboot_launcher/src/page/home_page.dart'; import 'package:reboot_launcher/src/page/home_page.dart';
import 'package:reboot_launcher/src/util/binary.dart'; import 'package:reboot_launcher/src/util/binary.dart';
import 'package:reboot_launcher/src/util/os.dart'; import 'package:reboot_launcher/src/util/os.dart';
@@ -28,9 +29,11 @@ void main(List<String> args) async {
await GetStorage.init("game"); await GetStorage.init("game");
await GetStorage.init("server"); await GetStorage.init("server");
await GetStorage.init("update"); await GetStorage.init("update");
await GetStorage.init("settings");
Get.put(GameController()); Get.put(GameController());
Get.put(ServerController()); Get.put(ServerController());
Get.put(BuildController()); Get.put(BuildController());
Get.put(SettingsController());
doWhenWindowReady(() { doWhenWindowReady(() {
const size = Size(600, 365); const size = Size(600, 365);
var window = appWindow as WinDesktopWindow; var window = appWindow as WinDesktopWindow;
@@ -52,6 +55,8 @@ class RebootApplication extends StatefulWidget {
} }
class _RebootApplicationState extends State<RebootApplication> { class _RebootApplicationState extends State<RebootApplication> {
final SettingsController _settingsController = Get.find<SettingsController>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final color = SystemTheme.accentColor.accent.toAccentColor(); final color = SystemTheme.accentColor.accent.toAccentColor();
@@ -60,23 +65,20 @@ class _RebootApplicationState extends State<RebootApplication> {
themeMode: ThemeMode.system, themeMode: ThemeMode.system,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
color: color, color: color,
darkTheme: ThemeData( darkTheme: _createTheme(Brightness.dark),
brightness: Brightness.dark, theme: _createTheme(Brightness.light),
accentColor: color,
visualDensity: VisualDensity.standard,
focusTheme: FocusThemeData(
glowFactor: is10footScreen() ? 2.0 : 0.0,
),
),
theme: ThemeData(
brightness: Brightness.light,
accentColor: color,
visualDensity: VisualDensity.standard,
focusTheme: FocusThemeData(
glowFactor: is10footScreen() ? 2.0 : 0.0,
),
),
home: const HomePage(), home: const HomePage(),
); );
} }
ThemeData _createTheme(Brightness brightness) {
return ThemeData(
brightness: brightness,
accentColor: SystemTheme.accentColor.accent.toAccentColor(),
visualDensity: VisualDensity.standard,
focusTheme: FocusThemeData(
glowFactor: is10footScreen() ? 2.0 : 0.0,
),
);
}
} }

View File

@@ -43,9 +43,7 @@ class GameController extends GetxController {
}); });
username = TextEditingController(text: _storage.read("${type.value == GameType.client ? 'game' : 'host'}_username") ?? ""); username = TextEditingController(text: _storage.read("${type.value == GameType.client ? 'game' : 'host'}_username") ?? "");
username.addListener(() async { username.addListener(() => _storage.write("${type.value == GameType.client ? 'game' : 'host'}_username", username.text));
await _storage.write("${type.value == GameType.client ? 'game' : 'host'}_username", username.text);
});
started = RxBool(false); started = RxBool(false);
} }

View File

@@ -0,0 +1,41 @@
import 'dart:convert';
import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:reboot_launcher/src/model/fortnite_version.dart';
import 'package:reboot_launcher/src/model/game_type.dart';
import 'package:reboot_launcher/src/util/binary.dart';
import 'package:system_theme/system_theme.dart';
class SettingsController extends GetxController {
late final GetStorage _storage;
late final String originalDll;
late final TextEditingController rebootDll;
late final TextEditingController consoleDll;
late final TextEditingController craniumDll;
late final RxBool autoUpdate;
SettingsController() {
_storage = GetStorage("settings");
rebootDll = _createController("reboot", "reboot.dll");
consoleDll = _createController("console", "console.dll");
craniumDll = _createController("cranium", "cranium.dll");
autoUpdate = RxBool(_storage.read("auto_update") ?? true);
autoUpdate.listen((value) => _storage.write("auto_update", value));
}
TextEditingController _createController(String key, String name) {
var controller = TextEditingController(text: _storage.read(key) ?? "$safeBinariesDirectory\\$name");
controller.addListener(() {
if(controller.text.isEmpty || !File(controller.text).existsSync()) {
return;
}
_storage.write(key, controller.text);
});
return controller;
}
}

View File

@@ -1,6 +1,6 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:reboot_launcher/src/page/info_page.dart'; import 'package:reboot_launcher/src/page/settings_page.dart';
import 'package:reboot_launcher/src/page/launcher_page.dart'; import 'package:reboot_launcher/src/page/launcher_page.dart';
import 'package:reboot_launcher/src/page/server_page.dart'; import 'package:reboot_launcher/src/page/server_page.dart';
import 'package:reboot_launcher/src/util/os.dart'; import 'package:reboot_launcher/src/util/os.dart';
@@ -54,7 +54,7 @@ class _HomePageState extends State<HomePage> with WindowListener {
items: [ items: [
_createPane("Home", FluentIcons.game), _createPane("Home", FluentIcons.game),
_createPane("Lawin", FluentIcons.server_enviroment), _createPane("Lawin", FluentIcons.server_enviroment),
_createPane("Info", FluentIcons.info), _createPane("Settings", FluentIcons.settings)
], ],
trailing: WindowTitleBar(focused: _focused)), trailing: WindowTitleBar(focused: _focused)),
content: NavigationBody( content: NavigationBody(
@@ -62,7 +62,7 @@ class _HomePageState extends State<HomePage> with WindowListener {
children: [ children: [
const LauncherPage(), const LauncherPage(),
ServerPage(), ServerPage(),
const InfoPage() SettingsPage()
] ]
) )
), ),

View File

@@ -1,38 +0,0 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:url_launcher/url_launcher.dart';
const String _discordLink = "https://discord.gg/NJU4QjxSMF";
class InfoPage extends StatelessWidget {
const InfoPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
const Expanded(child: SizedBox()),
Column(
children: [
const CircleAvatar(
radius: 48,
backgroundImage: AssetImage("assets/images/auties.png")),
const SizedBox(
height: 16.0,
),
const Text("Made by Auties00"),
const SizedBox(
height: 16.0,
),
Button(
child: const Text("Join the discord"),
onPressed: () => launchUrl(Uri.parse(_discordLink))),
],
),
const Expanded(
child: Align(
alignment: Alignment.bottomLeft, child: Text("Version 3.10${kDebugMode ? '-DEBUG' : ''}")))
],
);
}
}

View File

@@ -13,6 +13,7 @@ import 'package:reboot_launcher/src/widget/username_box.dart';
import 'package:reboot_launcher/src/widget/version_selector.dart'; import 'package:reboot_launcher/src/widget/version_selector.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../controller/settings_controller.dart';
import '../util/binary.dart'; import '../util/binary.dart';
import '../util/reboot.dart'; import '../util/reboot.dart';
import '../widget/warning_info.dart'; import '../widget/warning_info.dart';
@@ -29,10 +30,11 @@ class LauncherPage extends StatefulWidget {
class _LauncherPageState extends State<LauncherPage> { class _LauncherPageState extends State<LauncherPage> {
final GameController _gameController = Get.find<GameController>(); final GameController _gameController = Get.find<GameController>();
final BuildController _buildController = Get.find<BuildController>(); final BuildController _buildController = Get.find<BuildController>();
final SettingsController _settingsController = Get.find<SettingsController>();
@override @override
void initState() { void initState() {
if(_gameController.updater == null) { if(_gameController.updater == null && _settingsController.autoUpdate.value){
_gameController.updater = compute(downloadRebootDll, _updateTime) _gameController.updater = compute(downloadRebootDll, _updateTime)
..then((value) => _updateTime = value) ..then((value) => _updateTime = value)
..onError(_saveError); ..onError(_saveError);

View File

@@ -0,0 +1,86 @@
import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:reboot_launcher/src/controller/settings_controller.dart';
import 'package:reboot_launcher/src/widget/file_selector.dart';
import 'package:reboot_launcher/src/widget/smart_switch.dart';
class SettingsPage extends StatelessWidget {
final SettingsController _settingsController = Get.find<SettingsController>();
SettingsPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: [
Form(
autovalidateMode: AutovalidateMode.always,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FileSelector(
label: "Reboot DLL",
placeholder: "Type the path to the reboot dll",
controller: _settingsController.rebootDll,
windowTitle: "Select a dll",
folder: false,
extension: "dll",
validator: _checkDll
),
FileSelector(
label: "Console DLL",
placeholder: "Type the path to the console dll",
controller: _settingsController.consoleDll,
windowTitle: "Select a dll",
folder: false,
extension: "dll",
validator: _checkDll
),
FileSelector(
label: "Cranium DLL",
placeholder: "Type the path to the cranium dll",
controller: _settingsController.craniumDll,
windowTitle: "Select a dll",
folder: false,
extension: "dll",
validator: _checkDll
),
SmartSwitch(
value: _settingsController.autoUpdate,
label: "Update DLLs"
),
],
)
),
const Align(
alignment: Alignment.bottomRight,
child: Text("Version 3.11${kDebugMode ? '-DEBUG' : ''}")
)
],
);
}
String? _checkDll(String? text) {
if (text == null || text.isEmpty) {
return "Empty dll path";
}
if (!File(text).existsSync()) {
return "This dll doesn't exist";
}
if (!text.endsWith(".dll")) {
return "This file is not a dll";
}
return null;
}
}

View File

@@ -1,7 +1,7 @@
import 'dart:io'; import 'dart:io';
Future<File> loadBinary(String binary, bool safe) async{ Future<File> loadBinary(String binary, bool safe) async{
var safeBinary = File("$safeBinariesDirectory/$binary"); var safeBinary = File("$safeBinariesDirectory\\$binary");
if(await safeBinary.exists()){ if(await safeBinary.exists()){
return safeBinary; return safeBinary;
} }

View File

@@ -16,9 +16,22 @@ bool get isWin11 {
return intBuild != null && intBuild > 22000; return intBuild != null && intBuild > 22000;
} }
Future<String?> openFilePicker(String title) async => Future<String?> openFolderPicker(String title) async =>
await FilePicker.platform.getDirectoryPath(dialogTitle: title); await FilePicker.platform.getDirectoryPath(dialogTitle: title);
Future<String?> openFilePicker(String extension) async {
var result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowMultiple: false,
allowedExtensions: [extension]
);
if(result == null || result.files.isEmpty){
return null;
}
return result.files.first.path;
}
Future<List<Directory>> scanInstallations(String input) => Directory(input) Future<List<Directory>> scanInstallations(String input) => Directory(input)
.list(recursive: true) .list(recursive: true)
.handleError((_) {}, test: (e) => e is FileSystemException) .handleError((_) {}, test: (e) => e is FileSystemException)

View File

@@ -4,7 +4,7 @@ import 'package:fluent_ui/fluent_ui.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart';
import 'package:reboot_launcher/src/model/fortnite_version.dart'; import 'package:reboot_launcher/src/model/fortnite_version.dart';
import 'package:reboot_launcher/src/widget/select_file.dart'; import 'package:reboot_launcher/src/widget/file_selector.dart';
class AddLocalVersion extends StatelessWidget { class AddLocalVersion extends StatelessWidget {
final GameController _gameController = Get.find<GameController>(); final GameController _gameController = Get.find<GameController>();
@@ -76,12 +76,14 @@ class AddLocalVersion extends StatelessWidget {
}, },
), ),
SelectFile( FileSelector(
label: "Location", label: "Location",
placeholder: "Type the game folder", placeholder: "Type the game folder",
windowTitle: "Select game folder", windowTitle: "Select game folder",
controller: _gamePathController, controller: _gamePathController,
validator: _checkGameFolder) validator: _checkGameFolder,
folder: true
)
], ],
); );
} }

View File

@@ -10,7 +10,7 @@ import 'package:reboot_launcher/src/controller/game_controller.dart';
import 'package:reboot_launcher/src/model/fortnite_version.dart'; import 'package:reboot_launcher/src/model/fortnite_version.dart';
import 'package:reboot_launcher/src/util/binary.dart'; import 'package:reboot_launcher/src/util/binary.dart';
import 'package:reboot_launcher/src/util/build.dart'; import 'package:reboot_launcher/src/util/build.dart';
import 'package:reboot_launcher/src/widget/select_file.dart'; import 'package:reboot_launcher/src/widget/file_selector.dart';
import 'package:reboot_launcher/src/widget/version_name_input.dart'; import 'package:reboot_launcher/src/widget/version_name_input.dart';
import 'build_selector.dart'; import 'build_selector.dart';
@@ -242,12 +242,13 @@ class _AddServerVersionState extends State<AddServerVersion> {
VersionNameInput(controller: _nameController), VersionNameInput(controller: _nameController),
SelectFile( FileSelector(
label: "Destination", label: "Destination",
placeholder: "Type the download destination", placeholder: "Type the download destination",
windowTitle: "Select download destination", windowTitle: "Select download destination",
controller: _pathController, controller: _pathController,
validator: _checkDownloadDestination validator: _checkDownloadDestination,
folder: true
), ),
], ],
); );

View File

@@ -3,29 +3,34 @@ import 'package:flutter/foundation.dart';
import '../util/os.dart'; import '../util/os.dart';
class SelectFile extends StatefulWidget { class FileSelector extends StatefulWidget {
final String label; final String label;
final String placeholder; final String placeholder;
final String windowTitle; final String windowTitle;
final bool allowNavigator; final bool allowNavigator;
final TextEditingController controller; final TextEditingController controller;
final String? Function(String?) validator; final String? Function(String?) validator;
final String? extension;
final bool folder;
const SelectFile( const FileSelector(
{required this.label, {required this.label,
required this.placeholder, required this.placeholder,
required this.windowTitle, required this.windowTitle,
required this.controller, required this.controller,
required this.validator, required this.validator,
required this.folder,
this.extension,
this.allowNavigator = true, this.allowNavigator = true,
Key? key}) Key? key})
: super(key: key); : assert(folder || extension != null, "Missing extension for file selector"),
super(key: key);
@override @override
State<SelectFile> createState() => _SelectFileState(); State<FileSelector> createState() => _FileSelectorState();
} }
class _SelectFileState extends State<SelectFile> { class _FileSelectorState extends State<FileSelector> {
bool _selecting = false; bool _selecting = false;
@override @override
@@ -47,7 +52,7 @@ class _SelectFileState extends State<SelectFile> {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 21.0), padding: const EdgeInsets.only(bottom: 21.0),
child: Tooltip( child: Tooltip(
message: "Select a folder", message: "Select a ${widget.folder ? 'folder' : 'file'}",
child: Button( child: Button(
onPressed: _onPressed, onPressed: _onPressed,
child: const Icon(FluentIcons.open_folder_horizontal) child: const Icon(FluentIcons.open_folder_horizontal)
@@ -66,7 +71,14 @@ class _SelectFileState extends State<SelectFile> {
} }
_selecting = true; _selecting = true;
compute(openFilePicker, "Select the game folder") if(widget.folder) {
compute(openFolderPicker, widget.windowTitle)
.then((value) => widget.controller.text = value ?? "")
.then((_) => _selecting = false);
return;
}
compute(openFilePicker, widget.extension!)
.then((value) => widget.controller.text = value ?? "") .then((value) => widget.controller.text = value ?? "")
.then((_) => _selecting = false); .then((_) => _selecting = false);
} }

View File

@@ -15,6 +15,7 @@ import 'package:reboot_launcher/src/util/server.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:win32_suspend_process/win32_suspend_process.dart'; import 'package:win32_suspend_process/win32_suspend_process.dart';
import '../controller/settings_controller.dart';
import '../util/server_standalone.dart'; import '../util/server_standalone.dart';
class LaunchButton extends StatefulWidget { class LaunchButton extends StatefulWidget {
@@ -29,6 +30,7 @@ class LaunchButton extends StatefulWidget {
class _LaunchButtonState extends State<LaunchButton> { class _LaunchButtonState extends State<LaunchButton> {
final GameController _gameController = Get.find<GameController>(); final GameController _gameController = Get.find<GameController>();
final ServerController _serverController = Get.find<ServerController>(); final ServerController _serverController = Get.find<ServerController>();
final SettingsController _settingsController = Get.find<SettingsController>();
File? _logFile; File? _logFile;
bool _fail = false; bool _fail = false;
@@ -114,7 +116,7 @@ class _LaunchButtonState extends State<LaunchButton> {
_gameController.gameProcess = await Process.start(gamePath, createRebootArgs(_gameController.username.text, hosting)) _gameController.gameProcess = await Process.start(gamePath, createRebootArgs(_gameController.username.text, hosting))
..exitCode.then((_) => _onEnd()) ..exitCode.then((_) => _onEnd())
..outLines.forEach(_onGameOutput); ..outLines.forEach(_onGameOutput);
await _injectOrShowError("cranium.dll"); await _injectOrShowError(Injectable.cranium);
if(hosting){ if(hosting){
await _showServerLaunchingWarning(); await _showServerLaunchingWarning();
@@ -333,12 +335,12 @@ class _LaunchButtonState extends State<LaunchButton> {
} }
if (line.contains("Game Engine Initialized") && _gameController.type.value == GameType.client) { if (line.contains("Game Engine Initialized") && _gameController.type.value == GameType.client) {
_injectOrShowError("console.dll"); _injectOrShowError(Injectable.console);
return; return;
} }
if(line.contains("Region") && _gameController.type.value != GameType.client){ if(line.contains("Region") && _gameController.type.value != GameType.client){
_injectOrShowError("reboot.dll") _injectOrShowError(Injectable.reboot)
.then((value) => _closeDialogIfOpen(true)); .then((value) => _closeDialogIfOpen(true));
} }
} }
@@ -374,22 +376,33 @@ class _LaunchButtonState extends State<LaunchButton> {
_gameController.kill(); _gameController.kill();
} }
Future<void> _injectOrShowError(String binary) async { Future<void> _injectOrShowError(Injectable injectable) async {
var gameProcess = _gameController.gameProcess; var gameProcess = _gameController.gameProcess;
if (gameProcess == null) { if (gameProcess == null) {
return; return;
} }
try { try {
var dll = await loadBinary(binary, true); var dllPath = _getDllPath(injectable);
var success = await injectDll(gameProcess.pid, dll.path); var success = await injectDll(gameProcess.pid, dllPath);
if (success) { if (success) {
return; return;
} }
_onInjectError(binary); _onInjectError(injectable.name);
} catch (exception) { } catch (exception) {
_onInjectError(binary); _onInjectError(injectable.name);
}
}
String _getDllPath(Injectable injectable){
switch(injectable){
case Injectable.reboot:
return _settingsController.rebootDll.text;
case Injectable.console:
return _settingsController.consoleDll.text;
case Injectable.cranium:
return _settingsController.craniumDll.text;
} }
} }
@@ -398,3 +411,9 @@ class _LaunchButtonState extends State<LaunchButton> {
launchUrl(injectLogFile.uri); launchUrl(injectLogFile.uri);
} }
} }
enum Injectable {
console,
cranium,
reboot
}

View File

@@ -4,7 +4,7 @@ import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:reboot_launcher/src/util/os.dart'; import 'package:reboot_launcher/src/util/os.dart';
import 'package:reboot_launcher/src/widget/select_file.dart'; import 'package:reboot_launcher/src/widget/file_selector.dart';
class ScanLocalVersion extends StatefulWidget { class ScanLocalVersion extends StatefulWidget {
@@ -83,12 +83,14 @@ class _ScanLocalVersionState extends State<ScanLocalVersion> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SelectFile( FileSelector(
label: "Location", label: "Location",
placeholder: "Type the folder to scan", placeholder: "Type the folder to scan",
windowTitle: "Select the folder to scan", windowTitle: "Select the folder to scan",
controller: _folderController, controller: _folderController,
validator: _checkScanFolder) validator: _checkScanFolder,
folder: true
)
], ],
); );
} }

View File

@@ -1,7 +1,7 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
class SmartInput extends StatelessWidget { class SmartInput extends StatelessWidget {
final String label; final String? label;
final String placeholder; final String placeholder;
final TextEditingController controller; final TextEditingController controller;
final TextInputType type; final TextInputType type;
@@ -11,9 +11,9 @@ class SmartInput extends StatelessWidget {
const SmartInput( const SmartInput(
{Key? key, {Key? key,
required this.label,
required this.placeholder, required this.placeholder,
required this.controller, required this.controller,
this.label,
this.onTap, this.onTap,
this.enabled = true, this.enabled = true,
this.populate = false, this.populate = false,

View File

@@ -1,6 +1,6 @@
name: reboot_launcher name: reboot_launcher
description: Launcher for project reboot description: Launcher for project reboot
version: "3.10.0" version: "3.11.0"
publish_to: 'none' publish_to: 'none'
@@ -56,7 +56,7 @@ msix_config:
display_name: Reboot Launcher display_name: Reboot Launcher
publisher_display_name: Auties00 publisher_display_name: Auties00
identity_name: 31868Auties00.RebootLauncher identity_name: 31868Auties00.RebootLauncher
msix_version: 3.10.0.0 msix_version: 3.11.0.0
publisher: CN=E6CD08C6-DECF-4034-A3EB-2D5FA2CA8029 publisher: CN=E6CD08C6-DECF-4034-A3EB-2D5FA2CA8029
logo_path: ./assets/icons/reboot.ico logo_path: ./assets/icons/reboot.ico
architecture: x64 architecture: x64