mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 19:22:22 +01:00
9.0.8
This commit is contained in:
@@ -9,7 +9,6 @@ import 'package:reboot_launcher/src/controller/game_controller.dart';
|
||||
import 'package:reboot_launcher/src/dialog/abstract/info_bar.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
import 'package:reboot_launcher/src/page/pages.dart';
|
||||
import 'package:reboot_launcher/src/util/keyboard.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/server_start_button.dart';
|
||||
@@ -67,12 +66,32 @@ class _BackendPageState extends RebootPageState<BackendPage> {
|
||||
_type,
|
||||
_hostName,
|
||||
_port,
|
||||
_detached,
|
||||
_gameServerAddress,
|
||||
_unrealEngineConsoleKey,
|
||||
_detached,
|
||||
_installationDirectory,
|
||||
_resetDefaults
|
||||
];
|
||||
|
||||
Widget get _gameServerAddress => Obx(() {
|
||||
if(_backendController.type.value != ServerType.embedded) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.stream_input_20_regular
|
||||
),
|
||||
title: Text(translations.matchmakerConfigurationAddressName),
|
||||
subtitle: Text(translations.matchmakerConfigurationAddressDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.matchmakerConfigurationAddressName,
|
||||
controller: _backendController.gameServerAddress,
|
||||
focusNode: _backendController.gameServerAddressFocusNode
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
Widget get _hostName => Obx(() {
|
||||
if(_backendController.type.value != ServerType.remote) {
|
||||
return const SizedBox.shrink();
|
||||
@@ -202,13 +221,9 @@ class _BackendPageState extends RebootPageState<BackendPage> {
|
||||
),
|
||||
title: Text(translations.backendTypeName),
|
||||
subtitle: Text(translations.backendTypeDescription),
|
||||
content: const ServerTypeSelector(
|
||||
backend: true
|
||||
)
|
||||
content: const ServerTypeSelector()
|
||||
);
|
||||
|
||||
@override
|
||||
Widget get button => const ServerButton(
|
||||
backend: true
|
||||
);
|
||||
Widget get button => const ServerButton();
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ class _HomePageState extends State<HomePage> with WindowListener, AutomaticKeepA
|
||||
void initState() {
|
||||
windowManager.addListener(this);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_updateController.update();
|
||||
_updateController.notifyLauncherUpdate();
|
||||
_updateController.updateReboot();
|
||||
watchDlls().listen((filePath) => showDllDeletedDialog(() {
|
||||
downloadCriticalDllInteractive(filePath);
|
||||
}));
|
||||
|
||||
@@ -6,8 +6,8 @@ import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
import 'package:reboot_launcher/src/page/pages.dart';
|
||||
import 'package:reboot_launcher/src/util/info.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/info_tile.dart';
|
||||
|
||||
class InfoPage extends RebootPage {
|
||||
const InfoPage({Key? key}) : super(key: key);
|
||||
@@ -32,153 +32,6 @@ class _InfoPageState extends RebootPageState<InfoPage> {
|
||||
final SettingsController _settingsController = Get.find<SettingsController>();
|
||||
RxInt _counter = RxInt(180);
|
||||
|
||||
static final List<InfoTile> _infoTiles = [
|
||||
InfoTile(
|
||||
title: Text("What is Project Reboot?"),
|
||||
content: Text(
|
||||
"Project Reboot is a game server for Fortnite that aims to support as many seasons as possible.\n"
|
||||
"The project was started on Discord by Milxnor, while the launcher is developed by Auties00.\n"
|
||||
"Both are open source on GitHub, anyone can easily contribute or audit the code!"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("What is a Fortnite game server?"),
|
||||
content: Text(
|
||||
"If you have ever played Minecraft multiplayer, you might know that the servers you join are hosted on a computer running a program, called Minecraft Game Server.\n"
|
||||
"While the Minecraft Game server is written by the creators of Minecraft, Mojang, Epic Games doesn't provide an equivalent for Fortnite.\n"
|
||||
"By exploiting the Fortnite internals, though, it's possible to create a game server just like in Minecraft: this is in easy terms what Project Reboot does.\n"
|
||||
"Some Fortnite versions support running this game server in the background without rendering the game(\"headless\"), while others still require the full game to be open.\n"
|
||||
"Just like in Minecraft, you need a game client to play the game and one to host the server.\n"
|
||||
"By default, a game server is automatically started on your PC when you start a Fortnite version from the \"Play\" section in the launcher.\n"
|
||||
"If you want to play in another way, for example by joining a server hosted by one of your friends instead of running one yourself, you can checkout the \"Multiplayer\" section in the \"Play\" tab of the launcher."
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("Types of Fortnite game server"),
|
||||
content: Text(
|
||||
"Some Fortnite versions support running this game server in the background without rendering the game: this type of server is called \"headless\" as the game is running, but you can't see it on your screen.\n"
|
||||
"If headless is not supported by the Fortnite version you want to play, or if you disabled it manually from the \"Configuration\" section in the \"Host\" tab of the launcher, you will see an instance of Fortnite open on your screen.\n"
|
||||
"For convenience, this window will be opened on a new Virtual Desktop, if your Windows version supports it. This feature can be disabled as well from from the \"Configuration\" section in the \"Host\" tab of the launcher."
|
||||
"Just like in Minecraft, you need a game client to play the game and one to host the server."
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("How can others join my game server?"),
|
||||
content: Text(
|
||||
"For others to join your game server, port 7777 must be accessible on your PC.\n"
|
||||
"One option is to use a private VPN service like Hamachi or Radmin, but all of the players will need to download this software.\n"
|
||||
"The best solution is to use port forwarding:\n"
|
||||
"1. Set a static IP\n"
|
||||
" If you don't have already a static IP set, set one by following any tutorial on Google\n"
|
||||
"2. Log into your router's admin panel\n"
|
||||
" Usually this can be accessed on any web browser by going to http://192.168.1.1/\n"
|
||||
" You might need a username and a password to log in: refer to your router's manual for precise instructions\n"
|
||||
"3. Find the port forwarding section\n"
|
||||
" Once logged in into the admin panel, navigate to the port forwarding section of your router's settings\n"
|
||||
" This location may vary from router to router, but it's typically labelled as \"Port Forwarding,\" \"Port Mapping\" or \"Virtual Server\"\n"
|
||||
" Refer to your router's manual for precise instructions\n"
|
||||
"4. Add a port forwarding rule\n"
|
||||
" Now, you'll need to create a new port forwarding rule. Here's what you'll typically need to specify:\n"
|
||||
" - Service Name: Choose a name for your port forwarding rule (e.g., \"Fortnite Game Server\")\n"
|
||||
" - Port Number: Enter 7777 for both the external and internal ports\n"
|
||||
" - Protocol: Select the UDP protocol\n"
|
||||
" - Internal IP Address: Enter the static IP address you set earlier\n"
|
||||
" - Enable: Make sure the port forwarding rule is enabled\n"
|
||||
"5. Save and apply the changes\n"
|
||||
" After configuring the port forwarding rule, save your changes and apply them\n"
|
||||
" This step may involve clicking a \"Save\" or \"Apply\" button on your router's web interface"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("What is a backend?"),
|
||||
content: Text(
|
||||
"A backend is a piece of software that emulates the Epic Games server responsible for authentication and related features.\n"
|
||||
"By default, the Reboot Launcher ships with a slightly customized version of LawinV1, an open source implementation available on Github.\n"
|
||||
"If you are having any problems with the built in backend, enable the \"Detached\" option in the \"Backend\" tab of the Reboot Laucher to troubleshoot the issue."
|
||||
"LawinV1 was chosen to allow users to log into Fortnite and join games easily, but keep in mind that if you want to use features such as parties, voice chat or skins, you will need to use a custom backend.\n"
|
||||
"Other popular options are LawinV2 and Momentum, both available on Github, but it's not recommended to use them if you are not an advanced user.\n"
|
||||
"You can run these alternatives either either on your PC or on a server by selecting respectively \"Local\" or \"Remote\" from the \"Type\" section in the \"Backend\" tab of the Reboot Launcher."
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("What is the Unreal Engine console?"),
|
||||
content: Text(
|
||||
"Many Fortnite versions don't support entering in game by clicking the \"Play\" button.\n"
|
||||
"Instead, you need to click the key assigned to the Unreal Engine console, by default F8 or the tilde(the button above tab), and type open 127.0.0.1\n"
|
||||
"Keep in mind that the Unreal Engine console key is controlled by the backend, so this is true only if you are using the embedded backend: custom backends might use different keys.\n"
|
||||
"When using the embedded backend, you can customize the key used to open the console in the \"Backend\" tab of the Reboot Launcher."
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("What is a matchmaker?"),
|
||||
content: Text(
|
||||
"A matchmaker is a piece of software that emulates the Epic Games server responsible for putting you in game when you click the \"Play\" button in Fortnite.\n"
|
||||
"By default, the Reboot Launcher ships with a slightly customized version of Lawin's FortMatchmaker, an open source implementation available on Github.\n"
|
||||
"If you are having any problems with the built in matchmaker, enable the \"Detached\" option in the \"Matchmaker\" tab of the Reboot Launcher to troubleshoot the issue.\n"
|
||||
"Lawin's FortMatchmaker is an extremely basic implementation of a matchmaker: it takes the IP you configured in the \"Matchmaker\" tab, by default 127.0.0.1(your local machine) of the Reboot Launcher and send you with no wait to that game server.\n"
|
||||
"Unfortunately right now the play button still doesn't work on many Fortnite versions, you so might need to use the Unreal Engine console.\n"
|
||||
"Just like a backend, you can run a custom matchmaker, either on your PC or on a server with the appropriate configuration."
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("The backend is not working correctly"),
|
||||
content: Text(
|
||||
"To resolve this issue:\n"
|
||||
"- Check that your backend is working correctly from the \"Backend\" tab\n"
|
||||
"- If you are using a custom backend, try to use the embedded one\n"
|
||||
"- Try to run the backend as detached by enabling the \"Detached\" option in the \"Backend\" tab"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("The matchmaker is not working correctly"),
|
||||
content: Text(
|
||||
"To resolve this issue:\n"
|
||||
"- Check that your matchmaker is working correctly from the \"Matchmaker\" tab\n"
|
||||
"- If you are using a custom matchmaker, try to use the embedded one\n"
|
||||
"- Try to run the matchmaker as detached by enabling the \"Detached\" option in the \"Matchmaker\" tab"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("Why do I see two Fortnite versions opened on my PC?"),
|
||||
content: Text(
|
||||
"As explained in the \"What is a Fortnite game server?\" section, one instance of Fortnite is used to host the game server, while the other is used to let you play.\n"
|
||||
"The Fortnite instance used up by the game server is usually frozen, so it should be hard to use the wrong one to try to play.\n"
|
||||
"If you do not want to host a game server yourself, you can:\n"
|
||||
"1. Set a custom IP in the \"Matchmaker\" tab\n"
|
||||
"2. Set a custom matchmaker in the \"Matchmaker\" tab\n"
|
||||
"3. Disable the automatic game server from the \"Configuration\" section in the \"Host\" tab\n"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("I cannot open Fortnite because of an authentication error"),
|
||||
content: Text(
|
||||
"To resolve this issue:\n"
|
||||
"- Check that your backend is working correctly from the \"Backend\" tab\n"
|
||||
"- If you are using a custom backend, try to use the embedded one\n"
|
||||
"- Try to run the backend as detached by enabling the \"Detached\" option in the \"Backend\" tab"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("I cannot enter in a match when I'm in Fortnite"),
|
||||
content: Text(
|
||||
"As explained in the \"What is the Unreal Engine console?\" section, the \"Play\" button doesn't work in many Fortnite versions.\n"
|
||||
"Instead, you need to click the key assigned to the Unreal Engine console, by default F8 or the tilde(the button above tab), and type open 127.0.0.1"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("An error occurred while downloading a build (DioException)"),
|
||||
content: Text(
|
||||
"Unfortunately the servers that host the Fortnite builds are not reliable all the time so it might take a few tries, or downloading another version, to get started"
|
||||
)
|
||||
),
|
||||
InfoTile(
|
||||
title: Text("Failed to open descriptor file / Fortnite crash Reporter / Unreal Engine crash reporter"),
|
||||
content: Text(
|
||||
"Your version of Fortnite is corrupted, download it again from the launcher or use another build."
|
||||
)
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if(_settingsController.firstRun.value) {
|
||||
@@ -195,7 +48,7 @@ class _InfoPageState extends RebootPageState<InfoPage> {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Widget> get settings => _infoTiles;
|
||||
List<Widget> get settings => infoTiles;
|
||||
|
||||
@override
|
||||
Widget? get button => Obx(() {
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart' as fluentUi show FluentIcons;
|
||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/src/controller/matchmaker_controller.dart';
|
||||
import 'package:reboot_launcher/src/dialog/implementation/data.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/server_start_button.dart';
|
||||
import 'package:reboot_launcher/src/widget/server_type_selector.dart';
|
||||
import 'package:reboot_launcher/src/widget/setting_tile.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class MatchmakerPage extends RebootPage {
|
||||
const MatchmakerPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
RebootPageState<MatchmakerPage> createState() => _MatchmakerPageState();
|
||||
|
||||
@override
|
||||
String get name => translations.matchmakerName;
|
||||
|
||||
@override
|
||||
String get iconAsset => "assets/images/matchmaker.png";
|
||||
|
||||
@override
|
||||
bool hasButton(String? pageName) => pageName == null;
|
||||
|
||||
@override
|
||||
RebootPageType get type => RebootPageType.matchmaker;
|
||||
}
|
||||
|
||||
class _MatchmakerPageState extends RebootPageState<MatchmakerPage> {
|
||||
final MatchmakerController _matchmakerController = Get.find<MatchmakerController>();
|
||||
|
||||
@override
|
||||
Widget? get button => const ServerButton(
|
||||
backend: false
|
||||
);
|
||||
|
||||
@override
|
||||
List<Widget> get settings => [
|
||||
_type,
|
||||
_hostName,
|
||||
_port,
|
||||
_gameServerAddress,
|
||||
_installationDirectory,
|
||||
_resetDefaults
|
||||
];
|
||||
|
||||
Widget get _gameServerAddress => Obx(() {
|
||||
if(_matchmakerController.type.value != ServerType.embedded) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.stream_input_20_regular
|
||||
),
|
||||
title: Text(translations.matchmakerConfigurationAddressName),
|
||||
subtitle: Text(translations.matchmakerConfigurationAddressDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.matchmakerConfigurationAddressName,
|
||||
controller: _matchmakerController.gameServerAddress,
|
||||
focusNode: _matchmakerController.gameServerAddressFocusNode
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
Widget get _port => Obx(() {
|
||||
if(_matchmakerController.type.value == ServerType.embedded) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
fluentUi.FluentIcons.number_field
|
||||
),
|
||||
title: Text(translations.matchmakerConfigurationPortName),
|
||||
subtitle: Text(translations.matchmakerConfigurationPortDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.matchmakerConfigurationPortName,
|
||||
controller: _matchmakerController.port,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
]
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
Widget get _hostName => Obx(() {
|
||||
if(_matchmakerController.type.value != ServerType.remote) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.globe_24_regular
|
||||
),
|
||||
title: Text(translations.matchmakerConfigurationHostName),
|
||||
subtitle: Text(translations.matchmakerConfigurationHostDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.matchmakerConfigurationHostName,
|
||||
controller: _matchmakerController.host
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
Widget get _type => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.people_24_regular
|
||||
),
|
||||
title: Text(translations.matchmakerTypeName),
|
||||
subtitle: Text(translations.matchmakerTypeDescription),
|
||||
content: const ServerTypeSelector(
|
||||
backend: false
|
||||
)
|
||||
);
|
||||
|
||||
Widget get _installationDirectory => Obx(() {
|
||||
if(_matchmakerController.type.value != ServerType.embedded) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.folder_24_regular
|
||||
),
|
||||
title: Text(translations.matchmakerInstallationDirectoryName),
|
||||
subtitle: Text(translations.matchmakerInstallationDirectoryDescription),
|
||||
content: Button(
|
||||
onPressed: () => launchUrl(matchmakerDirectory.uri),
|
||||
child: Text(translations.matchmakerInstallationDirectoryContent)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
SettingTile get _resetDefaults => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.arrow_reset_24_regular
|
||||
),
|
||||
title: Text(translations.matchmakerResetDefaultsName),
|
||||
subtitle: Text(translations.matchmakerResetDefaultsDescription),
|
||||
content: Button(
|
||||
onPressed: () => showResetDialog(_matchmakerController.reset),
|
||||
child: Text(translations.matchmakerResetDefaultsContent),
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/src/controller/backend_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/game_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/hosting_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/matchmaker_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||
import 'package:reboot_launcher/src/dialog/abstract/info_bar.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
import 'package:reboot_launcher/src/page/pages.dart';
|
||||
import 'package:reboot_launcher/src/util/keyboard.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/file_setting_tile.dart';
|
||||
import 'package:reboot_launcher/src/widget/game_start_button.dart';
|
||||
@@ -39,9 +34,9 @@ class PlayPage extends RebootPage {
|
||||
}
|
||||
|
||||
class _PlayPageState extends RebootPageState<PlayPage> {
|
||||
final MatchmakerController _matchmakerController = Get.find<MatchmakerController>();
|
||||
final SettingsController _settingsController = Get.find<SettingsController>();
|
||||
final GameController _gameController = Get.find<GameController>();
|
||||
final BackendController _backendController = Get.find<BackendController>();
|
||||
|
||||
@override
|
||||
Widget? get button => LaunchButton(
|
||||
@@ -52,8 +47,9 @@ class _PlayPageState extends RebootPageState<PlayPage> {
|
||||
|
||||
@override
|
||||
List<SettingTile> get settings => [
|
||||
_clientSettings,
|
||||
versionSelectSettingTile,
|
||||
_options,
|
||||
_internalFiles,
|
||||
_multiplayer
|
||||
];
|
||||
|
||||
@@ -70,7 +66,7 @@ class _PlayPageState extends RebootPageState<PlayPage> {
|
||||
],
|
||||
);
|
||||
|
||||
SettingTile get _clientSettings => SettingTile(
|
||||
SettingTile get _internalFiles => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.archive_settings_24_regular
|
||||
),
|
||||
@@ -92,24 +88,34 @@ class _PlayPageState extends RebootPageState<PlayPage> {
|
||||
description: translations.settingsClientMemoryDescription,
|
||||
controller: _settingsController.memoryLeakDll
|
||||
),
|
||||
SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.options_24_regular
|
||||
),
|
||||
title: Text(translations.settingsClientArgsName),
|
||||
subtitle: Text(translations.settingsClientArgsDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsClientArgsPlaceholder,
|
||||
controller: _gameController.customLaunchArgs,
|
||||
)
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
SettingTile get _options => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.options_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerOptionsName),
|
||||
subtitle: Text(translations.settingsServerOptionsSubtitle),
|
||||
children: [
|
||||
SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.options_24_regular
|
||||
),
|
||||
title: Text(translations.settingsClientArgsName),
|
||||
subtitle: Text(translations.settingsClientArgsDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsClientArgsPlaceholder,
|
||||
controller: _gameController.customLaunchArgs,
|
||||
)
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
SettingTile get _matchmakerTile => SettingTile(
|
||||
onPressed: () {
|
||||
pageIndex.value = RebootPageType.matchmaker.index;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _matchmakerController.gameServerAddressFocusNode.requestFocus());
|
||||
pageIndex.value = RebootPageType.backend.index;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _backendController.gameServerAddressFocusNode.requestFocus());
|
||||
},
|
||||
icon: Icon(
|
||||
FluentIcons.globe_24_regular
|
||||
|
||||
@@ -5,8 +5,8 @@ import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/src/controller/backend_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/hosting_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/matchmaker_controller.dart';
|
||||
import 'package:reboot_launcher/src/dialog/implementation/server.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
@@ -34,7 +34,7 @@ class BrowsePage extends RebootPage {
|
||||
|
||||
class _BrowsePageState extends RebootPageState<BrowsePage> {
|
||||
final HostingController _hostingController = Get.find<HostingController>();
|
||||
final MatchmakerController _matchmakerController = Get.find<MatchmakerController>();
|
||||
final BackendController _backendController = Get.find<BackendController>();
|
||||
final TextEditingController _filterController = TextEditingController();
|
||||
final StreamController<String> _filterControllerStream = StreamController.broadcast();
|
||||
|
||||
@@ -98,11 +98,11 @@ class _BrowsePageState extends RebootPageState<BrowsePage> {
|
||||
title: Text("${_formatName(entry)} • ${entry["author"]}"),
|
||||
subtitle: Text("${_formatDescription(entry)} • ${_formatVersion(entry)}"),
|
||||
content: Button(
|
||||
onPressed: () => _matchmakerController.joinServer(_hostingController.uuid, entry),
|
||||
onPressed: () => _backendController.joinServer(_hostingController.uuid, entry),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(_matchmakerController.type.value == ServerType.embedded ? translations.joinServer : translations.copyIp),
|
||||
Text(_backendController.type.value == ServerType.embedded ? translations.joinServer : translations.copyIp),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:clipboard/clipboard.dart';
|
||||
import 'package:dart_ipify/dart_ipify.dart';
|
||||
import 'package:fluent_ui/fluent_ui.dart' as fluentUi show FluentIcons;
|
||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -20,7 +21,6 @@ import 'package:reboot_launcher/src/widget/file_setting_tile.dart';
|
||||
import 'package:reboot_launcher/src/widget/game_start_button.dart';
|
||||
import 'package:reboot_launcher/src/widget/setting_tile.dart';
|
||||
import 'package:reboot_launcher/src/widget/version_selector_tile.dart';
|
||||
import 'package:fluent_ui/fluent_ui.dart' as fluentUi show FluentIcons;
|
||||
|
||||
import '../../util/checks.dart';
|
||||
|
||||
@@ -72,8 +72,9 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
@override
|
||||
List<Widget> get settings => [
|
||||
_information,
|
||||
_configuration,
|
||||
versionSelectSettingTile,
|
||||
_options,
|
||||
_internalFiles,
|
||||
_share,
|
||||
_resetDefaults
|
||||
];
|
||||
@@ -179,63 +180,104 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
]
|
||||
);
|
||||
|
||||
SettingTile get _configuration => SettingTile(
|
||||
SettingTile get _internalFiles => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.archive_settings_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerName),
|
||||
subtitle: Text(translations.settingsServerSubtitle),
|
||||
children: [
|
||||
createFileSetting(
|
||||
title: translations.settingsServerFileName,
|
||||
description: translations.settingsServerFileDescription,
|
||||
controller: _settingsController.gameServerDll
|
||||
),
|
||||
SettingTile(
|
||||
icon: Icon(
|
||||
fluentUi.FluentIcons.number_field
|
||||
),
|
||||
title: Text(translations.settingsServerPortName),
|
||||
subtitle: Text(translations.settingsServerPortDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsServerPortName,
|
||||
controller: _settingsController.gameServerPort,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
]
|
||||
)
|
||||
),
|
||||
SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.globe_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerMirrorName),
|
||||
subtitle: Text(translations.settingsServerMirrorDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsServerMirrorPlaceholder,
|
||||
controller: _updateController.url,
|
||||
validator: checkUpdateUrl
|
||||
)
|
||||
),
|
||||
SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.timer_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerTimerName),
|
||||
subtitle: Text(translations.settingsServerTimerSubtitle),
|
||||
title: Text(translations.settingsServerTypeName),
|
||||
subtitle: Text(translations.settingsServerTypeDescription),
|
||||
content: Obx(() => DropDownButton(
|
||||
leading: Text(_updateController.timer.value.text),
|
||||
items: UpdateTimer.values.map((entry) => MenuFlyoutItem(
|
||||
text: Text(entry.text),
|
||||
leading: Text(_updateController.customGameServer.value ? translations.settingsServerTypeCustomName : translations.settingsServerTypeEmbeddedName),
|
||||
items: {
|
||||
false: translations.settingsServerTypeEmbeddedName,
|
||||
true: translations.settingsServerTypeCustomName
|
||||
}.entries.map((entry) => MenuFlyoutItem(
|
||||
text: Text(entry.value),
|
||||
onPressed: () {
|
||||
_updateController.timer.value = entry;
|
||||
final oldValue = _updateController.customGameServer.value;
|
||||
if(oldValue == entry.key) {
|
||||
return;
|
||||
}
|
||||
|
||||
_updateController.customGameServer.value = entry.key;
|
||||
_updateController.infoBarEntry?.close();
|
||||
_updateController.update(true);
|
||||
if(!entry.key) {
|
||||
_updateController.updateReboot(true);
|
||||
}
|
||||
}
|
||||
)).toList()
|
||||
))
|
||||
),
|
||||
Obx(() {
|
||||
if(!_updateController.customGameServer.value) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return createFileSetting(
|
||||
title: translations.settingsServerFileName,
|
||||
description: translations.settingsServerFileDescription,
|
||||
controller: _settingsController.gameServerDll
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
if(_updateController.customGameServer.value) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.globe_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerMirrorName),
|
||||
subtitle: Text(translations.settingsServerMirrorDescription),
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsServerMirrorPlaceholder,
|
||||
controller: _updateController.url,
|
||||
validator: checkUpdateUrl
|
||||
)
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
if(_updateController.customGameServer.value) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.timer_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerTimerName),
|
||||
subtitle: Text(translations.settingsServerTimerSubtitle),
|
||||
content: Obx(() => DropDownButton(
|
||||
leading: Text(_updateController.timer.value.text),
|
||||
items: UpdateTimer.values.map((entry) => MenuFlyoutItem(
|
||||
text: Text(entry.text),
|
||||
onPressed: () {
|
||||
_updateController.timer.value = entry;
|
||||
_updateController.infoBarEntry?.close();
|
||||
_updateController.updateReboot(true);
|
||||
}
|
||||
)).toList()
|
||||
))
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
SettingTile get _options => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.options_24_regular
|
||||
),
|
||||
title: Text(translations.settingsServerOptionsName),
|
||||
subtitle: Text(translations.settingsServerOptionsSubtitle),
|
||||
children: [
|
||||
Obx(() => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.window_console_20_regular
|
||||
@@ -280,6 +322,45 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
],
|
||||
),
|
||||
)),
|
||||
Obx(() => SettingTile(
|
||||
icon: Icon(
|
||||
FluentIcons.arrow_reset_24_regular
|
||||
),
|
||||
title: Text(translations.hostAutomaticRestartName),
|
||||
subtitle: Text(translations.hostAutomaticRestartDescription),
|
||||
contentWidth: null,
|
||||
content: Row(
|
||||
children: [
|
||||
Text(
|
||||
_hostingController.autoRestart.value ? translations.on : translations.off
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16.0
|
||||
),
|
||||
ToggleSwitch(
|
||||
checked: _hostingController.autoRestart.value,
|
||||
onChanged: (value) => _hostingController.autoRestart.value = value
|
||||
),
|
||||
],
|
||||
),
|
||||
)),
|
||||
SettingTile(
|
||||
icon: Icon(
|
||||
fluentUi.FluentIcons.number_field
|
||||
),
|
||||
title: Text(translations.settingsServerPortName),
|
||||
subtitle: Text(translations.settingsServerPortDescription),
|
||||
contentWidth: 64,
|
||||
content: TextFormBox(
|
||||
placeholder: translations.settingsServerPortName,
|
||||
controller: _settingsController.gameServerPort,
|
||||
keyboardType: TextInputType.number,
|
||||
textAlign: TextAlign.center,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
]
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:archive/archive_io.dart';
|
||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_gen/gen_l10n/reboot_localizations.dart';
|
||||
import 'package:flutter_localized_locales/flutter_localized_locales.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||
import 'package:reboot_launcher/src/dialog/abstract/info_bar.dart';
|
||||
import 'package:reboot_launcher/src/dialog/implementation/data.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page.dart';
|
||||
import 'package:reboot_launcher/src/page/abstract/page_type.dart';
|
||||
import 'package:reboot_launcher/src/util/picker.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/setting_tile.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
Reference in New Issue
Block a user