mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 03:02:22 +01:00
Released 9.2.6
This commit is contained in:
@@ -28,7 +28,6 @@ class DllController extends GetxController {
|
||||
late final TextEditingController url;
|
||||
late final RxBool customGameServer;
|
||||
late final RxnInt timestamp;
|
||||
late final Map<String, Future<bool>> _operations;
|
||||
late final Rx<UpdateStatus> status;
|
||||
InfoBarEntry? infoBarEntry;
|
||||
Future<bool>? _updater;
|
||||
@@ -51,20 +50,19 @@ class DllController extends GetxController {
|
||||
customGameServer.listen((value) => _storage?.write("custom_game_server", value));
|
||||
timestamp = RxnInt(_storage?.read("ts"));
|
||||
timestamp.listen((value) => _storage?.write("ts", value));
|
||||
_operations = {};
|
||||
}
|
||||
|
||||
TextEditingController _createController(String key, InjectableDll dll) {
|
||||
final controller = TextEditingController(text: _storage?.read(key) ?? _getDefaultPath(dll));
|
||||
final controller = TextEditingController(text: _storage?.read(key) ?? getDefaultDllPath(dll));
|
||||
controller.addListener(() => _storage?.write(key, controller.text));
|
||||
return controller;
|
||||
}
|
||||
|
||||
void resetGame() {
|
||||
gameServerDll.text = _getDefaultPath(InjectableDll.reboot);
|
||||
unrealEngineConsoleDll.text = _getDefaultPath(InjectableDll.console);
|
||||
backendDll.text = _getDefaultPath(InjectableDll.cobalt);
|
||||
memoryLeakDll.text = _getDefaultPath(InjectableDll.memory);
|
||||
gameServerDll.text = getDefaultDllPath(InjectableDll.reboot);
|
||||
unrealEngineConsoleDll.text = getDefaultDllPath(InjectableDll.console);
|
||||
backendDll.text = getDefaultDllPath(InjectableDll.cobalt);
|
||||
memoryLeakDll.text = getDefaultDllPath(InjectableDll.memory);
|
||||
}
|
||||
|
||||
void resetServer() {
|
||||
@@ -147,7 +145,7 @@ class DllController extends GetxController {
|
||||
}
|
||||
|
||||
(File, bool) getInjectableData(InjectableDll dll) {
|
||||
final defaultPath = canonicalize(_getDefaultPath(dll));
|
||||
final defaultPath = canonicalize(getDefaultDllPath(dll));
|
||||
switch(dll){
|
||||
case InjectableDll.reboot:
|
||||
if(customGameServer.value) {
|
||||
@@ -170,23 +168,10 @@ class DllController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
String _getDefaultPath(InjectableDll dll) => "${dllsDirectory.path}\\${dll.name}.dll";
|
||||
String getDefaultDllPath(InjectableDll dll) => "${dllsDirectory.path}\\${dll.name}.dll";
|
||||
|
||||
Future<bool> downloadCriticalDllInteractive(String filePath, {bool silent = false}) {
|
||||
Future<bool> downloadCriticalDllInteractive(String filePath, {bool silent = false, bool force = false}) async {
|
||||
log("[DLL] Asking for $filePath(silent: $silent)");
|
||||
final old = _operations[filePath];
|
||||
if(old != null) {
|
||||
log("[DLL] Download task already exists");
|
||||
return old;
|
||||
}
|
||||
|
||||
log("[DLL] Creating new download task...");
|
||||
final newRun = _downloadCriticalDllInteractive(filePath, silent);
|
||||
_operations[filePath] = newRun;
|
||||
return newRun;
|
||||
}
|
||||
|
||||
Future<bool> _downloadCriticalDllInteractive(String filePath, bool silent) async {
|
||||
final fileName = basename(filePath).toLowerCase();
|
||||
log("[DLL] File name: $fileName");
|
||||
InfoBarEntry? entry;
|
||||
@@ -198,7 +183,7 @@ class DllController extends GetxController {
|
||||
);
|
||||
}
|
||||
|
||||
if(File(filePath).existsSync()) {
|
||||
if(!force && File(filePath).existsSync()) {
|
||||
log("[DLL] File already exists");
|
||||
return true;
|
||||
}
|
||||
@@ -225,7 +210,8 @@ class DllController extends GetxController {
|
||||
log("[DLL] Error: $message");
|
||||
entry?.close();
|
||||
var error = message.toString();
|
||||
error = error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error;
|
||||
error =
|
||||
error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error;
|
||||
error = error.toLowerCase();
|
||||
final completer = Completer();
|
||||
await showRebootInfoBar(
|
||||
@@ -243,8 +229,6 @@ class DllController extends GetxController {
|
||||
);
|
||||
await completer.future;
|
||||
return false;
|
||||
}finally {
|
||||
_operations.remove(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ class SettingsController extends GetxController {
|
||||
late final RxString language;
|
||||
late final Rx<ThemeMode> themeMode;
|
||||
late final RxBool firstRun;
|
||||
late final RxBool debug;
|
||||
late double width;
|
||||
late double height;
|
||||
late double? offsetX;
|
||||
@@ -38,6 +39,7 @@ class SettingsController extends GetxController {
|
||||
language.listen((value) => _storage?.write("language", value));
|
||||
firstRun = RxBool(_storage?.read("first_run_tutorial") ?? true);
|
||||
firstRun.listen((value) => _storage?.write("first_run_tutorial", value));
|
||||
debug = RxBool(false);
|
||||
}
|
||||
|
||||
void saveWindowSize(Size size) {
|
||||
|
||||
@@ -23,19 +23,18 @@ InfoBarEntry showRebootInfoBar(dynamic text, {
|
||||
|
||||
Widget _buildOverlay(text, Widget? action, bool loading, InfoBarSeverity severity) => ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: double.infinity,
|
||||
minHeight: _height
|
||||
minHeight: _height
|
||||
),
|
||||
child: Mica(
|
||||
elevation: 1,
|
||||
child: InfoBar(
|
||||
title: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if(text is Widget)
|
||||
text,
|
||||
if(text is String)
|
||||
Text(text),
|
||||
Expanded(
|
||||
child: text is Widget ? text : Text(text)
|
||||
),
|
||||
if(action != null)
|
||||
action
|
||||
],
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
|
||||
import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||
import 'package:reboot_launcher/src/messenger/implementation/onboard.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
|
||||
abstract class RebootPage extends StatefulWidget {
|
||||
const RebootPage({super.key});
|
||||
@@ -19,32 +24,110 @@ abstract class RebootPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
abstract class RebootPageState<T extends RebootPage> extends State<T> with AutomaticKeepAliveClientMixin<T> {
|
||||
final SettingsController _settingsController = Get.find<SettingsController>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
var buttonWidget = button;
|
||||
if(buttonWidget == null) {
|
||||
return _listView;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildFirstLaunchInfo(),
|
||||
_buildDebugInfo(),
|
||||
Expanded(
|
||||
child: _listView
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildFirstLaunchInfo(),
|
||||
_buildDebugInfo(),
|
||||
Expanded(
|
||||
child: _listView,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _listView,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 1000
|
||||
),
|
||||
child: buttonWidget
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 1000
|
||||
),
|
||||
child: buttonWidget
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFirstLaunchInfo() => Obx(() {
|
||||
if(!_settingsController.firstRun.value) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0
|
||||
),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: InfoBar(
|
||||
title: Text(translations.welcomeTitle),
|
||||
severity: InfoBarSeverity.warning,
|
||||
isLong: true,
|
||||
content: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Text(translations.welcomeDescription)
|
||||
),
|
||||
action: Button(
|
||||
child: Text(translations.welcomeAction),
|
||||
onPressed: () => startOnboarding(),
|
||||
),
|
||||
onClose: () => _settingsController.firstRun.value = false
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
Widget _buildDebugInfo() => Obx(() {
|
||||
if(!_settingsController.debug.value) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0
|
||||
),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: InfoBar(
|
||||
title: Text("Debug mode is enabled"),
|
||||
severity: InfoBarSeverity.warning,
|
||||
isLong: true,
|
||||
content: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Text( "• Automatic dll injection is disabled\n"
|
||||
"• The game server cannot start automatically\n"
|
||||
"• The game server runs in a normal window")
|
||||
),
|
||||
onClose: () {
|
||||
_settingsController.debug.value = false;
|
||||
},
|
||||
),
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
ListView get _listView => ListView.builder(
|
||||
itemCount: settings.length,
|
||||
itemBuilder: (context, index) => settings[index],
|
||||
|
||||
@@ -221,11 +221,12 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
content: Obx(() => DropDownButton(
|
||||
onOpen: () => inDialog = true,
|
||||
onClose: () => inDialog = false,
|
||||
leading: Text(_hostingController.type.value.translatedName),
|
||||
leading: Text(_settingsController.debug.value ? GameServerType.window.translatedName : _hostingController.type.value.translatedName),
|
||||
items: GameServerType.values.map((entry) => MenuFlyoutItem(
|
||||
text: Text(entry.translatedName),
|
||||
onPressed: () => _hostingController.type.value = entry
|
||||
)).toList()
|
||||
)).toList(),
|
||||
disabled: _settingsController.debug.value
|
||||
)),
|
||||
),
|
||||
SettingTile(
|
||||
@@ -317,7 +318,12 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
return createFileSetting(
|
||||
title: translations.settingsServerFileName,
|
||||
description: translations.settingsServerFileDescription,
|
||||
controller: _dllController.gameServerDll
|
||||
controller: _dllController.gameServerDll,
|
||||
onReset: () {
|
||||
final path = _dllController.getDefaultDllPath(InjectableDll.reboot);
|
||||
_dllController.gameServerDll.text = path;
|
||||
_dllController.downloadCriticalDllInteractive(path);
|
||||
}
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
@@ -331,10 +337,29 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
),
|
||||
title: Text(translations.settingsServerMirrorName),
|
||||
subtitle: Text(translations.settingsServerMirrorDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsServerMirrorPlaceholder,
|
||||
controller: _dllController.url,
|
||||
validator: _checkUpdateUrl
|
||||
content: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormBox(
|
||||
placeholder: translations.settingsServerMirrorPlaceholder,
|
||||
controller: _dllController.url,
|
||||
validator: _checkUpdateUrl
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8.0),
|
||||
Button(
|
||||
style: ButtonStyle(
|
||||
padding: ButtonState.all(EdgeInsets.zero)
|
||||
),
|
||||
onPressed: () => _dllController.url.text = kRebootDownloadUrl,
|
||||
child: SizedBox.square(
|
||||
dimension: 30,
|
||||
child: Icon(
|
||||
FluentIcons.arrow_reset_24_regular
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
}),
|
||||
@@ -343,29 +368,50 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.timer_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerTimerName),
|
||||
subtitle: Text(translations.settingsServerTimerSubtitle),
|
||||
content: Obx(() => DropDownButton(
|
||||
onOpen: () => inDialog = true,
|
||||
onClose: () => inDialog = false,
|
||||
leading: Text(_dllController.timer.value.text),
|
||||
items: UpdateTimer.values.map((entry) => MenuFlyoutItem(
|
||||
text: Text(entry.text),
|
||||
onPressed: () {
|
||||
_dllController.timer.value = entry;
|
||||
_dllController.infoBarEntry?.close();
|
||||
_dllController.updateGameServerDll(
|
||||
force: true
|
||||
);
|
||||
}
|
||||
)).toList()
|
||||
))
|
||||
content: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Obx(() => DropDownButton(
|
||||
onOpen: () => inDialog = true,
|
||||
onClose: () => inDialog = false,
|
||||
leading: Text(_dllController.timer.value.text),
|
||||
items: UpdateTimer.values.map((entry) => MenuFlyoutItem(
|
||||
text: Text(entry.text),
|
||||
onPressed: () {
|
||||
_dllController.timer.value = entry;
|
||||
_dllController.infoBarEntry?.close();
|
||||
_dllController.updateGameServerDll(
|
||||
force: true
|
||||
);
|
||||
}
|
||||
)).toList()
|
||||
)),
|
||||
),
|
||||
const SizedBox(width: 8.0),
|
||||
Button(
|
||||
style: ButtonStyle(
|
||||
padding: ButtonState.all(EdgeInsets.zero)
|
||||
),
|
||||
onPressed: () {
|
||||
_dllController.updateGameServerDll(force: true);
|
||||
},
|
||||
child: SizedBox.square(
|
||||
dimension: 30,
|
||||
child: Icon(
|
||||
FluentIcons.arrow_download_24_regular
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
}),
|
||||
})
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/src/controller/dll_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/game_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||
@@ -40,48 +41,6 @@ class _PlayPageState extends RebootPageState<PlayPage> {
|
||||
final SettingsController _settingsController = Get.find<SettingsController>();
|
||||
final GameController _gameController = Get.find<GameController>();
|
||||
final DllController _dllController = Get.find<DllController>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildFirstLaunchInfo(),
|
||||
Expanded(
|
||||
child: super.build(context),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFirstLaunchInfo() => Obx(() {
|
||||
if(!_settingsController.firstRun.value) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0
|
||||
),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: InfoBar(
|
||||
title: Text(translations.welcomeTitle),
|
||||
severity: InfoBarSeverity.warning,
|
||||
isLong: true,
|
||||
content: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Text(translations.welcomeDescription)
|
||||
),
|
||||
action: Button(
|
||||
child: Text(translations.welcomeAction),
|
||||
onPressed: () => startOnboarding(),
|
||||
),
|
||||
onClose: () => _settingsController.firstRun.value = false
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@override
|
||||
Widget? get button => LaunchButton(
|
||||
@@ -110,17 +69,32 @@ class _PlayPageState extends RebootPageState<PlayPage> {
|
||||
createFileSetting(
|
||||
title: translations.settingsClientConsoleName,
|
||||
description: translations.settingsClientConsoleDescription,
|
||||
controller: _dllController.unrealEngineConsoleDll
|
||||
controller: _dllController.unrealEngineConsoleDll,
|
||||
onReset: () {
|
||||
final path = _dllController.getDefaultDllPath(InjectableDll.console);
|
||||
_dllController.unrealEngineConsoleDll.text = path;
|
||||
_dllController.downloadCriticalDllInteractive(path, force: true);
|
||||
}
|
||||
),
|
||||
createFileSetting(
|
||||
title: translations.settingsClientAuthName,
|
||||
description: translations.settingsClientAuthDescription,
|
||||
controller: _dllController.backendDll
|
||||
controller: _dllController.backendDll,
|
||||
onReset: () {
|
||||
final path = _dllController.getDefaultDllPath(InjectableDll.cobalt);
|
||||
_dllController.backendDll.text = path;
|
||||
_dllController.downloadCriticalDllInteractive(path, force: true);
|
||||
}
|
||||
),
|
||||
createFileSetting(
|
||||
title: translations.settingsClientMemoryName,
|
||||
description: translations.settingsClientMemoryDescription,
|
||||
controller: _dllController.memoryLeakDll
|
||||
controller: _dllController.memoryLeakDll,
|
||||
onReset: () {
|
||||
final path = _dllController.getDefaultDllPath(InjectableDll.memory);
|
||||
_dllController.memoryLeakDll.text = path;
|
||||
_dllController.downloadCriticalDllInteractive(path, force: true);
|
||||
}
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -42,7 +42,8 @@ class _SettingsPageState extends RebootPageState<SettingsPage> {
|
||||
List<Widget> get settings => [
|
||||
_language,
|
||||
_theme,
|
||||
_installationDirectory
|
||||
_debugMode,
|
||||
_installationDirectory,
|
||||
];
|
||||
|
||||
SettingTile get _language => SettingTile(
|
||||
@@ -99,6 +100,29 @@ class _SettingsPageState extends RebootPageState<SettingsPage> {
|
||||
child: Text(translations.settingsUtilsInstallationDirectoryContent),
|
||||
)
|
||||
);
|
||||
|
||||
SettingTile get _debugMode => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.developer_board_24_regular
|
||||
),
|
||||
title: Text("Debug mode"),
|
||||
subtitle: Text("Whether the launcher should disable automatic features for troubleshooting"),
|
||||
contentWidth: null,
|
||||
content: Row(
|
||||
children: [
|
||||
Text(
|
||||
_settingsController.debug.value ? translations.on : translations.off
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16.0
|
||||
),
|
||||
Obx(() => ToggleSwitch(
|
||||
checked: _settingsController.debug.value,
|
||||
onChanged: (value) => _settingsController.debug.value = value
|
||||
))
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
extension _ThemeModeExtension on ThemeMode {
|
||||
|
||||
@@ -36,7 +36,6 @@ Future<bool> pingGameServer(String address, {Duration? timeout}) async {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final start = DateTime.now();
|
||||
var firstTime = true;
|
||||
final split = address.split(":");
|
||||
|
||||
@@ -2,26 +2,55 @@ import 'dart:io';
|
||||
|
||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/file_selector.dart';
|
||||
import 'package:reboot_launcher/src/widget/setting_tile.dart';
|
||||
|
||||
SettingTile createFileSetting({required String title, required String description, required TextEditingController controller}) => SettingTile(
|
||||
SettingTile createFileSetting({required String title, required String description, required TextEditingController controller, required void Function() onReset}) {
|
||||
final obx = RxString(controller.text);
|
||||
controller.addListener(() => obx.value = controller.text);
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.document_24_regular
|
||||
),
|
||||
title: Text(title),
|
||||
subtitle: Text(description),
|
||||
content: FileSelector(
|
||||
placeholder: translations.selectPathPlaceholder,
|
||||
windowTitle: translations.selectPathWindowTitle,
|
||||
controller: controller,
|
||||
validator: _checkDll,
|
||||
extension: "dll",
|
||||
folder: false,
|
||||
validatorMode: AutovalidateMode.always
|
||||
content: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FileSelector(
|
||||
placeholder: translations.selectPathPlaceholder,
|
||||
windowTitle: translations.selectPathWindowTitle,
|
||||
controller: controller,
|
||||
validator: _checkDll,
|
||||
extension: "dll",
|
||||
folder: false,
|
||||
validatorMode: AutovalidateMode.always
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8.0),
|
||||
Obx(() => Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: _checkDll(obx.value) == null ? 0.0 : 20.0
|
||||
),
|
||||
child: Button(
|
||||
style: ButtonStyle(
|
||||
padding: ButtonState.all(EdgeInsets.zero)
|
||||
),
|
||||
onPressed: onReset,
|
||||
child: SizedBox.square(
|
||||
dimension: 30,
|
||||
child: Icon(
|
||||
FluentIcons.arrow_reset_24_regular
|
||||
),
|
||||
)
|
||||
),
|
||||
))
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
String? _checkDll(String? text) {
|
||||
if (text == null || text.isEmpty) {
|
||||
|
||||
@@ -41,10 +41,12 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
final HostingController _hostingController = Get.find<HostingController>();
|
||||
final BackendController _backendController = Get.find<BackendController>();
|
||||
final DllController _dllController = Get.find<DllController>();
|
||||
final SettingsController _settingsController = Get.find<SettingsController>();
|
||||
|
||||
InfoBarEntry? _gameClientInfoBar;
|
||||
InfoBarEntry? _gameServerInfoBar;
|
||||
CancelableOperation? _operation;
|
||||
CancelableOperation? _pingOperation;
|
||||
IVirtualDesktop? _virtualDesktop;
|
||||
|
||||
@override
|
||||
@@ -94,10 +96,6 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
log("[${host ? 'HOST' : 'GAME'}] Checking dlls: ${InjectableDll.values}");
|
||||
for (final injectable in InjectableDll.values) {
|
||||
if(await _getDllFileOrStop(injectable, host) == null) {
|
||||
_onStop(
|
||||
reason: _StopReason.missingCustomDllError,
|
||||
error: injectable.name,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +121,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
return;
|
||||
}
|
||||
log("[${host ? 'HOST' : 'GAME'}] Backend works");
|
||||
final serverType = _hostingController.type.value;
|
||||
final serverType = _settingsController.debug.value ? GameServerType.window : _hostingController.type.value;
|
||||
log("[${host ? 'HOST' : 'GAME'}] Implicit game server metadata: headless($serverType)");
|
||||
final linkedHostingInstance = await _startMatchMakingServer(version, host, serverType, false);
|
||||
log("[${host ? 'HOST' : 'GAME'}] Implicit game server result: $linkedHostingInstance");
|
||||
@@ -139,6 +137,12 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
}else {
|
||||
_showLaunchingGameServerWidget();
|
||||
}
|
||||
} on ProcessException catch (exception, stackTrace) {
|
||||
_onStop(
|
||||
reason: _StopReason.corruptedVersionError,
|
||||
error: exception.toString(),
|
||||
stackTrace: stackTrace
|
||||
);
|
||||
} catch (exception, stackTrace) {
|
||||
_onStop(
|
||||
reason: _StopReason.unknownError,
|
||||
@@ -155,6 +159,11 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(_settingsController.debug.value) {
|
||||
log("[${host ? 'HOST' : 'GAME'}] The user is on debug mode, not asking for auto server");
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!forceLinkedHosting && _backendController.type.value == ServerType.embedded && !isLocalHost(_backendController.gameServerAddress.text)) {
|
||||
log("[${host ? 'HOST' : 'GAME'}] Backend is not set to embedded and/or not pointing to the local game server");
|
||||
return null;
|
||||
@@ -271,9 +280,17 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
line: line,
|
||||
host: host,
|
||||
onShutdown: () => _onStop(reason: _StopReason.normal),
|
||||
onTokenError: () => _onStop(reason: _StopReason.tokenError),
|
||||
onTokenError: () {
|
||||
if(_settingsController.debug.value) {
|
||||
log("[PROCESS] Ignoring token error because debug mode is on");
|
||||
}else {
|
||||
_onStop(reason: _StopReason.tokenError);
|
||||
}
|
||||
},
|
||||
onBuildCorrupted: () {
|
||||
if(instance?.launched == false) {
|
||||
if(instance == null) {
|
||||
return;
|
||||
}else if(!instance.launched) {
|
||||
_onStop(reason: _StopReason.corruptedVersionError);
|
||||
}else {
|
||||
_onStop(reason: _StopReason.crash);
|
||||
@@ -432,10 +449,11 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
duration: null
|
||||
);
|
||||
final gameServerPort = _dllController.gameServerPort.text;
|
||||
final localPingResult = await pingGameServer(
|
||||
this._pingOperation = await CancelableOperation.fromFuture(pingGameServer(
|
||||
"127.0.0.1:$gameServerPort",
|
||||
timeout: const Duration(minutes: 2)
|
||||
);
|
||||
));
|
||||
final localPingResult = (await _pingOperation?.value) ?? false;
|
||||
_gameServerInfoBar?.close();
|
||||
if (!localPingResult) {
|
||||
showRebootInfoBar(
|
||||
@@ -478,16 +496,18 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
duration: null
|
||||
);
|
||||
final publicIp = await Ipify.ipv4();
|
||||
final externalResult = await pingGameServer("$publicIp:$gameServerPort");
|
||||
this._pingOperation = CancelableOperation.fromFuture(pingGameServer("$publicIp:$gameServerPort"));
|
||||
final externalResult = (await _pingOperation?.value) ?? false;
|
||||
if (externalResult) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_gameServerInfoBar?.close();
|
||||
final future = pingGameServer(
|
||||
this._pingOperation = CancelableOperation.fromFuture(pingGameServer(
|
||||
"$publicIp:$gameServerPort",
|
||||
timeout: const Duration(days: 365)
|
||||
);
|
||||
));
|
||||
final future = await _pingOperation?.value ?? false;
|
||||
_gameServerInfoBar = showRebootInfoBar(
|
||||
translations.checkGameServerFixMessage(gameServerPort),
|
||||
action: Button(
|
||||
@@ -506,6 +526,8 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
|
||||
Future<void> _onStop({required _StopReason reason, bool? host, String? error, StackTrace? stackTrace}) async {
|
||||
if(host == null) {
|
||||
await _pingOperation?.cancel();
|
||||
_pingOperation = null;
|
||||
await _operation?.cancel();
|
||||
_operation = null;
|
||||
_backendController.cancelInteractive();
|
||||
@@ -513,6 +535,10 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
|
||||
host = host ?? widget.host;
|
||||
final instance = host ? _hostingController.instance.value : _gameController.instance.value;
|
||||
if(instance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(host){
|
||||
_hostingController.instance.value = null;
|
||||
}else {
|
||||
@@ -534,19 +560,17 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
_hostingController.discardServer();
|
||||
}
|
||||
|
||||
if(instance != null) {
|
||||
if(reason == _StopReason.normal) {
|
||||
instance.launched = true;
|
||||
}
|
||||
if(reason == _StopReason.normal) {
|
||||
instance.launched = true;
|
||||
}
|
||||
|
||||
instance.kill();
|
||||
final child = instance.child;
|
||||
if(child != null) {
|
||||
await _onStop(
|
||||
reason: reason,
|
||||
host: child.serverType != null
|
||||
);
|
||||
}
|
||||
instance.kill();
|
||||
final child = instance.child;
|
||||
if(child != null) {
|
||||
await _onStop(
|
||||
reason: reason,
|
||||
host: child.serverType != null
|
||||
);
|
||||
}
|
||||
|
||||
_setStarted(host, false);
|
||||
@@ -578,7 +602,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
);
|
||||
break;
|
||||
case _StopReason.exitCode:
|
||||
if(instance != null && !instance.launched) {
|
||||
if(!instance.launched) {
|
||||
showRebootInfoBar(
|
||||
translations.corruptedVersionError,
|
||||
severity: InfoBarSeverity.error,
|
||||
@@ -614,7 +638,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
case _StopReason.tokenError:
|
||||
_backendController.stop();
|
||||
showRebootInfoBar(
|
||||
translations.tokenError(instance?.injectedDlls.map((element) => element.name).join(", ") ?? translations.none),
|
||||
translations.tokenError(instance.injectedDlls.map((element) => element.name).join(", ")),
|
||||
severity: InfoBarSeverity.error,
|
||||
duration: infoBarLongDuration,
|
||||
action: Button(
|
||||
@@ -663,6 +687,10 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
}
|
||||
|
||||
log("[${hosting ? 'HOST' : 'GAME'}] Trying to inject ${injectable.name}...");
|
||||
if(_settingsController.debug.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
await injectDll(gameProcess, dllPath);
|
||||
instance.injectedDlls.add(injectable);
|
||||
log("[${hosting ? 'HOST' : 'GAME'}] Injected ${injectable.name}");
|
||||
@@ -687,13 +715,17 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
}
|
||||
|
||||
log("[${host ? 'HOST' : 'GAME'}] Path doesn't exist");
|
||||
if(customDll || isRetry) {
|
||||
if(customDll) {
|
||||
log("[${host ? 'HOST' : 'GAME'}] Custom dll -> no recovery");
|
||||
_onStop(
|
||||
reason: _StopReason.missingCustomDllError,
|
||||
error: injectable.name,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
log("[${host ? 'HOST' : 'GAME'}] Path does not exist, downloading critical dll again...");
|
||||
await _dllController.downloadCriticalDllInteractive(file.path);
|
||||
await _dllController.downloadCriticalDllInteractive(file.path, force: true);
|
||||
log("[${host ? 'HOST' : 'GAME'}] Downloaded dll again, retrying check...");
|
||||
return _getDllFileOrStop(injectable, host, true);
|
||||
}
|
||||
@@ -710,7 +742,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
||||
loading: true,
|
||||
duration: null,
|
||||
action: Obx(() {
|
||||
if(_hostingController.started.value || linkedHosting) {
|
||||
if(_settingsController.debug.value || _hostingController.started.value || linkedHosting) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user