minor bug fixes

This commit is contained in:
Alessandro Autiero
2022-09-05 03:08:34 +02:00
parent a773c490cc
commit ddc088e7d4
12 changed files with 181 additions and 101 deletions

View File

@@ -0,0 +1,15 @@
[OnlineSubsystemMcp.Xmpp]
bUseSSL=false
ServerAddr="ws://lawinserverxmpp.herokuapp.com"
ServerPort=80
[OnlineSubsystemMcp.Xmpp Prod]
bUseSSL=false
ServerAddr="ws://lawinserverxmpp.herokuapp.com"
ServerPort=80
[OnlineSubsystemMcp]
bUsePartySystemV2=false
[OnlineSubsystemMcp.OnlinePartySystemMcpAdapter]
bUsePartySystemV2=false

Binary file not shown.

View File

@@ -11,6 +11,7 @@ import 'package:reboot_launcher/src/widget/window_buttons.dart';
import '../model/fortnite_version.dart'; import '../model/fortnite_version.dart';
import '../util/generic_controller.dart'; import '../util/generic_controller.dart';
import '../util/reboot.dart';
import '../util/version_controller.dart'; import '../util/version_controller.dart';
class HomePage extends StatefulWidget { class HomePage extends StatefulWidget {
@@ -31,16 +32,23 @@ class _HomePageState extends State<HomePage> {
late final GenericController<Process?> _serverController; late final GenericController<Process?> _serverController;
late final GenericController<bool> _startedServerController; late final GenericController<bool> _startedServerController;
late final GenericController<bool> _startedGameController; late final GenericController<bool> _startedGameController;
late Future _future;
bool _loaded = false; bool _loaded = false;
int _index = 0; int _index = 0;
@override
void initState(){
_future = _load();
super.initState();
}
Future<bool> _load() async { Future<bool> _load() async {
if (_loaded) { if (_loaded) {
return false; return false;
} }
var preferences = await SharedPreferences.getInstance(); var preferences = await SharedPreferences.getInstance();
await downloadRebootDll(preferences);
Iterable json = jsonDecode(preferences.getString("versions") ?? "[]"); Iterable json = jsonDecode(preferences.getString("versions") ?? "[]");
var versions = var versions =
@@ -103,7 +111,7 @@ class _HomePageState extends State<HomePage> {
], ],
trailing: const WindowTitleBar()), trailing: const WindowTitleBar()),
content: FutureBuilder( content: FutureBuilder(
future: _load(), future: _future,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Center( return Center(

View File

@@ -52,7 +52,7 @@ class LauncherPage extends StatelessWidget {
DeploymentSelector( DeploymentSelector(
controller: rebootController, controller: rebootController,
onSelected: () => _streamController.add(null), onSelected: () => _streamController.add(null),
enabled: false enabled: true
), ),
LaunchButton( LaunchButton(
usernameController: usernameController, usernameController: usernameController,

View File

@@ -8,7 +8,7 @@ import 'package:unrar_file/unrar_file.dart';
Future<Process> downloadManifestBuild(String manifestUrl, String destination, Future<Process> downloadManifestBuild(String manifestUrl, String destination,
Function(double) onProgress) async { Function(double) onProgress) async {
var process = await Process.start(await locateBinary("build.exe"), [manifestUrl, destination]); var process = await Process.start(await locateAndCopyBinary("build.exe"), [manifestUrl, destination]);
process.errLines process.errLines
.where((message) => message.contains("%")) .where((message) => message.contains("%"))

View File

@@ -1,7 +1,7 @@
import 'dart:io'; import 'dart:io';
Future<String> locateBinary(String binary) async{ Future<String> locateAndCopyBinary(String binary) async{
var originalFile = File("$binariesDirectory\\$binary"); var originalFile = locateBinary(binary);
var tempFile = File("${Platform.environment["Temp"]}\\$binary"); var tempFile = File("${Platform.environment["Temp"]}\\$binary");
if(!(await tempFile.exists())){ if(!(await tempFile.exists())){
await originalFile.copy("${Platform.environment["Temp"]}\\$binary"); await originalFile.copy("${Platform.environment["Temp"]}\\$binary");
@@ -10,5 +10,9 @@ Future<String> locateBinary(String binary) async{
return tempFile.path; return tempFile.path;
} }
File locateBinary(String binary){
return File("$binariesDirectory\\$binary");
}
String get binariesDirectory => String get binariesDirectory =>
"${File(Platform.resolvedExecutable).parent.path}\\data\\flutter_assets\\assets\\binaries"; "${File(Platform.resolvedExecutable).parent.path}\\data\\flutter_assets\\assets\\binaries";

44
lib/src/util/reboot.dart Normal file
View File

@@ -0,0 +1,44 @@
import 'dart:io';
import 'package:archive/archive_io.dart';
import 'package:reboot_launcher/src/util/locate_binary.dart';
import 'package:http/http.dart' as http;
import 'package:crypto/crypto.dart';
import 'package:shared_preferences/shared_preferences.dart';
const _rebootUrl =
"https://nightly.link/UWUFN/Universal-Walking-Simulator/workflows/msbuild/master/Release.zip";
Future<DateTime?> _getLastUpdate(SharedPreferences preferences) async {
var timeInMillis = preferences.getInt("last_update");
return timeInMillis != null ? DateTime.fromMillisecondsSinceEpoch(timeInMillis) : null;
}
Future<File> downloadRebootDll(SharedPreferences preferences) async {
var now = DateTime.now();
var oldRebootDll = locateBinary("reboot.dll");
var lastUpdate = await _getLastUpdate(preferences);
var exists = await oldRebootDll.exists();
if(lastUpdate != null && now.difference(lastUpdate).inHours <= 24 && exists){
return oldRebootDll;
}
var response = await http.get(Uri.parse(_rebootUrl));
var tempZip = File("${Platform.environment["Temp"]}/reboot.zip")
..writeAsBytesSync(response.bodyBytes);
await extractFileToDisk(tempZip.path, binariesDirectory);
locateBinary("Project Reboot.pdb").delete();
var rebootDll = locateBinary("Project Reboot.dll");
if (!(await rebootDll.exists())) {
throw Exception("Missing reboot dll");
}
preferences.setInt("last_update", now.millisecondsSinceEpoch);
if (exists && sha1.convert(await oldRebootDll.readAsBytes()) == sha1.convert(await rebootDll.readAsBytes())) {
rebootDll.delete();
return oldRebootDll;
}
await rebootDll.rename(oldRebootDll.path);
return oldRebootDll;
}

View File

@@ -7,20 +7,30 @@ import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:process_run/shell.dart'; import 'package:process_run/shell.dart';
import 'package:reboot_launcher/src/util/locate_binary.dart'; import 'package:reboot_launcher/src/util/locate_binary.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
final serverLocation = Directory("${Platform.environment["UserProfile"]}/.lawin");
const String _serverUrl = const String _serverUrl =
"https://github.com/Lawin0129/LawinServer/archive/refs/heads/main.zip"; "https://github.com/Lawin0129/LawinServer/archive/refs/heads/main.zip";
const String _nodeUrl = const String _nodeUrl =
"https://nodejs.org/dist/v16.16.0/node-v16.16.0-x64.msi"; "https://nodejs.org/dist/v16.16.0/node-v16.16.0-x64.msi";
Future<void> downloadServer(Directory output) async { Future<void> downloadServer() async {
var response = await http.get(Uri.parse(_serverUrl)); var response = await http.get(Uri.parse(_serverUrl));
var tempZip = File("${Platform.environment["Temp"]}/lawin.zip") var tempZip = File("${Platform.environment["Temp"]}/lawin.zip")
..writeAsBytesSync(response.bodyBytes); ..writeAsBytesSync(response.bodyBytes);
await extractFileToDisk(tempZip.path, output.parent.path); await extractFileToDisk(tempZip.path, serverLocation.parent.path);
var result = Directory("${output.parent.path}/LawinServer-main"); var result = Directory("${serverLocation.parent.path}/LawinServer-main");
result.renameSync("${output.parent.path}/${path.basename(output.path)}"); await result.rename("${serverLocation.parent.path}/${path.basename(serverLocation.path)}");
await updateEngineConfig();
}
Future<void> updateEngineConfig() async {
var engine = File("${serverLocation.path}/CloudStorage/DefaultEngine.ini");
await engine.writeAsString(await locateBinary("DefaultEngine.ini").readAsString());
var preferences = await SharedPreferences.getInstance();
preferences.setBool("config_update", true);
} }
Future<File> downloadNode() async { Future<File> downloadNode() async {
@@ -34,7 +44,7 @@ Future<File> downloadNode() async {
} }
Future<bool> isPortFree() async { Future<bool> isPortFree() async {
var process = await Process.run(await locateBinary("port.bat"), []); var process = await Process.run(await locateAndCopyBinary("port.bat"), []);
return !process.outText.contains(" LISTENING "); // Goofy way, best we got return !process.outText.contains(" LISTENING "); // Goofy way, best we got
} }
@@ -87,27 +97,24 @@ Future<bool> _pingAddress(String host, String port) async {
&& process.outText.contains("TcpTestSucceeded : True"); && process.outText.contains("TcpTestSucceeded : True");
} }
Future<Process?> startEmbedded(BuildContext context, bool running, bool askFreePort) async { Future<Process?> startEmbedded(BuildContext context, bool running, bool needsFreePort) async {
if (running) { if (running) {
await Process.run(await locateBinary("release.bat"), []); await Process.run(await locateAndCopyBinary("release.bat"), []);
return null; return null;
} }
var free = await isPortFree(); var free = await isPortFree();
if (!free) { if (!free && needsFreePort) {
if(askFreePort) { var shouldKill = await _showAlreadyBindPortWarning(context);
var shouldKill = await _showAlreadyBindPortWarning(context); if (!shouldKill) {
if (!shouldKill) { return null;
return null;
}
} }
await Process.run(await locateBinary("release.bat"), []); await Process.run(await locateAndCopyBinary("release.bat"), []);
} }
var serverLocation = Directory("${Platform.environment["UserProfile"]}/.lawin");
if (!(await serverLocation.exists())) { if (!(await serverLocation.exists())) {
await downloadServer(serverLocation); await downloadServer();
} }
var serverRunner = File("${serverLocation.path}/start.bat"); var serverRunner = File("${serverLocation.path}/start.bat");
@@ -141,7 +148,7 @@ Future<Process?> startEmbedded(BuildContext context, bool running, bool askFreeP
showSnackbar( showSnackbar(
context, context,
const Snackbar( const Snackbar(
content: Text("Start the server when node is installed"))); // Using a infobr could be nicer content: Text("Start the server when node is installed"))); // Using a infobar could be nicer
return null; return null;
} }
@@ -151,6 +158,11 @@ Future<Process?> startEmbedded(BuildContext context, bool running, bool askFreeP
workingDirectory: serverLocation.path); workingDirectory: serverLocation.path);
} }
var preferences = await SharedPreferences.getInstance();
if(!(preferences.getBool("config_update") ?? false)){
await updateEngineConfig();
}
return await Process.start(serverRunner.path, [], return await Process.start(serverRunner.path, [],
workingDirectory: serverLocation.path); workingDirectory: serverLocation.path);
} }

View File

@@ -31,6 +31,7 @@ class _AddServerVersionState extends State<AddServerVersion> {
late TextEditingController _nameController; late TextEditingController _nameController;
late TextEditingController _pathController; late TextEditingController _pathController;
late DownloadStatus _status; late DownloadStatus _status;
late Future _future;
double _downloadProgress = 0; double _downloadProgress = 0;
String? _error; String? _error;
Process? _process; Process? _process;
@@ -38,6 +39,7 @@ class _AddServerVersionState extends State<AddServerVersion> {
@override @override
void initState() { void initState() {
_future = _fetchBuilds();
_buildController = GenericController(initialValue: null); _buildController = GenericController(initialValue: null);
_nameController = TextEditingController(); _nameController = TextEditingController();
_pathController = TextEditingController(); _pathController = TextEditingController();
@@ -51,7 +53,7 @@ class _AddServerVersionState extends State<AddServerVersion> {
_pathController.dispose(); _pathController.dispose();
_nameController.dispose(); _nameController.dispose();
if (_process != null && _status == DownloadStatus.downloading) { if (_process != null && _status == DownloadStatus.downloading) {
locateBinary("stop.bat") locateAndCopyBinary("stop.bat")
.then((value) => Process.runSync(value, [])); // kill doesn't work :/ .then((value) => Process.runSync(value, [])); // kill doesn't work :/
widget.onCancel(); widget.onCancel();
} }
@@ -79,21 +81,20 @@ class _AddServerVersionState extends State<AddServerVersion> {
style: ButtonStyle(backgroundColor: ButtonState.all(Colors.red)), style: ButtonStyle(backgroundColor: ButtonState.all(Colors.red)),
child: const Text('Close')), child: const Text('Close')),
FilledButton( FilledButton(
onPressed: () => _startDownload(context), onPressed: () => _startDownload(context),
child: const Text('Download'), child: const Text('Download'),
) )
]; ];
case DownloadStatus.error: case DownloadStatus.error:
return [ return [
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
child: FilledButton( child: FilledButton(
onPressed: () => _onClose(), onPressed: () => _onClose(),
style: ButtonStyle(backgroundColor: ButtonState.all(Colors.red)), style:
child: const Text('Close') ButtonStyle(backgroundColor: ButtonState.all(Colors.red)),
) child: const Text('Close')))
)
]; ];
default: default:
return [ return [
@@ -122,12 +123,13 @@ class _AddServerVersionState extends State<AddServerVersion> {
try { try {
setState(() => _status = DownloadStatus.downloading); setState(() => _status = DownloadStatus.downloading);
var build = _buildController.value!; var build = _buildController.value!;
if(build.hasManifest) { if (build.hasManifest) {
_process = await downloadManifestBuild(build.link, _pathController.text, _process = await downloadManifestBuild(
_onDownloadProgress); build.link, _pathController.text, _onDownloadProgress);
_process!.exitCode.then((value) => _onDownloadComplete()); _process!.exitCode.then((value) => _onDownloadComplete());
}else{ } else {
downloadArchiveBuild(build.link, _pathController.text, _onDownloadProgress, _onUnrar) downloadArchiveBuild(
build.link, _pathController.text, _onDownloadProgress, _onUnrar)
.then((value) => _onDownloadComplete()) .then((value) => _onDownloadComplete())
.catchError(_handleError); .catchError(_handleError);
} }
@@ -137,7 +139,7 @@ class _AddServerVersionState extends State<AddServerVersion> {
} }
void _handleError(Object exception) { void _handleError(Object exception) {
var message = exception.toString(); var message = exception.toString();
_onDownloadError(message.contains(":") _onDownloadError(message.contains(":")
? " ${message.substring(message.indexOf(":") + 1)}" ? " ${message.substring(message.indexOf(":") + 1)}"
: message); : message);
@@ -184,7 +186,7 @@ class _AddServerVersionState extends State<AddServerVersion> {
Widget _createDownloadVersionBody() { Widget _createDownloadVersionBody() {
return FutureBuilder( return FutureBuilder(
future: _fetchBuilds(), future: _future,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Text("Cannot fetch builds: ${snapshot.error}", return Text("Cannot fetch builds: ${snapshot.error}",
@@ -199,63 +201,62 @@ class _AddServerVersionState extends State<AddServerVersion> {
); );
} }
switch (_status) { return _buildBody();
case DownloadStatus.none:
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BuildSelector(builds: _builds!, controller: _buildController),
VersionNameInput(
controller: _nameController,
versions: widget.controller.versions,
),
SelectFile(
label: "Destination",
placeholder: "Type the download destination",
windowTitle: "Select download destination",
allowNavigator: false,
controller: _pathController,
validator: _checkDownloadDestination),
],
);
case DownloadStatus.downloading:
return InfoLabel(
label: "Downloading",
child: InfoLabel(
label: "${_downloadProgress.round()}%",
child: SizedBox(
width: double.infinity,
child:
ProgressBar(value: _downloadProgress.toDouble()))),
);
case DownloadStatus.extracting:
return const InfoLabel(
label: "Extracting",
child: InfoLabel(
label: "This might take a while...",
child: SizedBox(
width: double.infinity,
child:
ProgressBar()
),
),
);
case DownloadStatus.done:
return const SizedBox(
width: double.infinity,
child: Text("The download was completed successfully!",
textAlign: TextAlign.center));
case DownloadStatus.error:
return SizedBox(
width: double.infinity,
child: Text(
"An exception was thrown during the download process:$_error",
textAlign: TextAlign.center));
}
}); });
} }
Widget _buildBody() {
switch (_status) {
case DownloadStatus.none:
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BuildSelector(builds: _builds!, controller: _buildController),
VersionNameInput(
controller: _nameController,
versions: widget.controller.versions,
),
SelectFile(
label: "Destination",
placeholder: "Type the download destination",
windowTitle: "Select download destination",
allowNavigator: false,
controller: _pathController,
validator: _checkDownloadDestination),
],
);
case DownloadStatus.downloading:
return InfoLabel(
label: "Downloading",
child: InfoLabel(
label: "${_downloadProgress.round()}%",
child: SizedBox(
width: double.infinity,
child: ProgressBar(value: _downloadProgress.toDouble()))),
);
case DownloadStatus.extracting:
return const InfoLabel(
label: "Extracting",
child: InfoLabel(
label: "This might take a while...",
child: SizedBox(width: double.infinity, child: ProgressBar()),
),
);
case DownloadStatus.done:
return const SizedBox(
width: double.infinity,
child: Text("The download was completed successfully!",
textAlign: TextAlign.center));
case DownloadStatus.error:
return SizedBox(
width: double.infinity,
child: Text(
"An exception was thrown during the download process:$_error",
textAlign: TextAlign.center));
}
}
Future<bool> _fetchBuilds() async { Future<bool> _fetchBuilds() async {
if (_builds != null) { if (_builds != null) {
return false; return false;

View File

@@ -164,7 +164,7 @@ class _LaunchButtonState extends State<LaunchButton> {
} }
try{ try{
var success = await injectDll(gameProcess.pid, await locateBinary(binary)); var success = await injectDll(gameProcess.pid, await locateAndCopyBinary(binary));
if(success){ if(success){
return; return;
} }

View File

@@ -48,12 +48,7 @@ class _SmartInputState extends State<SmartInput> {
return; return;
} }
var decoded = preferences.getString(widget.keyName); widget.controller.text = preferences.getString(widget.keyName) ?? "";
if(decoded == null) {
return;
}
widget.controller.text = decoded;
} }
TextBox _buildTextBox() { TextBox _buildTextBox() {

View File

@@ -25,6 +25,7 @@ dependencies:
win32_suspend_process: ^1.0.0 win32_suspend_process: ^1.0.0
version: ^3.0.2 version: ^3.0.2
unrar_file: ^1.1.0 unrar_file: ^1.1.0
crypto: ^3.0.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: