mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 19:22:22 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93c5d6c56b | ||
|
|
46034aa1fa | ||
|
|
3069f3aa05 |
@@ -70,7 +70,7 @@ void _onGameOutput(String line, String dll, bool hosting, bool verbose) {
|
|||||||
_injectOrShowError("console.dll");
|
_injectOrShowError("console.dll");
|
||||||
}
|
}
|
||||||
|
|
||||||
_injectOrShowError("memoryleak.dll");
|
_injectOrShowError("memory.dll");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,12 +87,12 @@ Future<void> _injectOrShowError(String binary, [bool locate = true]) async {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
stdout.writeln("Injecting $binary...");
|
stdout.writeln("Injecting $binary...");
|
||||||
var dll = locate ? File("${assetsDirectory.path}\\dlls\\$binary") : File(binary);
|
var dll = locate ? File("${dllsDirectory.path}\\$binary") : File(binary);
|
||||||
if(!dll.existsSync()){
|
if(!dll.existsSync()){
|
||||||
throw Exception("Cannot inject $dll: missing file");
|
throw Exception("Cannot inject $dll: missing file");
|
||||||
}
|
}
|
||||||
|
|
||||||
await injectDll(_gameProcess!.pid, dll.path);
|
await injectDll(_gameProcess!.pid, dll);
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
throw Exception("Cannot inject binary: $binary");
|
throw Exception("Cannot inject binary: $binary");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import 'package:reboot_common/common.dart';
|
|||||||
// TODO: Use github
|
// TODO: Use github
|
||||||
const String _baseDownload = "https://cdn.discordapp.com/attachments/1095351875961901057/1110968021373169674/cobalt.dll";
|
const String _baseDownload = "https://cdn.discordapp.com/attachments/1095351875961901057/1110968021373169674/cobalt.dll";
|
||||||
const String _consoleDownload = "https://cdn.discordapp.com/attachments/1095351875961901057/1110968095033524234/console.dll";
|
const String _consoleDownload = "https://cdn.discordapp.com/attachments/1095351875961901057/1110968095033524234/console.dll";
|
||||||
const String _memoryFixDownload = "https://cdn.discordapp.com/attachments/1095351875961901057/1110968141556756581/memoryleak.dll";
|
const String _memoryFixDownload = "https://cdn.discordapp.com/attachments/1095351875961901057/1110968141556756581/memory.dll";
|
||||||
const String _embeddedConfigDownload = "https://cdn.discordapp.com/attachments/1026121175878881290/1040679319351066644/embedded.zip";
|
const String _embeddedConfigDownload = "https://cdn.discordapp.com/attachments/1026121175878881290/1040679319351066644/embedded.zip";
|
||||||
|
|
||||||
Future<void> downloadRequiredDLLs() async {
|
Future<void> downloadRequiredDLLs() async {
|
||||||
stdout.writeln("Downloading necessary components...");
|
stdout.writeln("Downloading necessary components...");
|
||||||
var consoleDll = File("${assetsDirectory.path}\\dlls\\console.dll");
|
var consoleDll = File("${dllsDirectory.path}\\console.dll");
|
||||||
if(!consoleDll.existsSync()){
|
if(!consoleDll.existsSync()){
|
||||||
var response = await http.get(Uri.parse(_consoleDownload));
|
var response = await http.get(Uri.parse(_consoleDownload));
|
||||||
if(response.statusCode != 200){
|
if(response.statusCode != 200){
|
||||||
@@ -22,7 +22,7 @@ Future<void> downloadRequiredDLLs() async {
|
|||||||
await consoleDll.writeAsBytes(response.bodyBytes);
|
await consoleDll.writeAsBytes(response.bodyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
var craniumDll = File("${assetsDirectory.path}\\dlls\\cobalt.dll");
|
var craniumDll = File("${dllsDirectory.path}\\cobalt.dll");
|
||||||
if(!craniumDll.existsSync()){
|
if(!craniumDll.existsSync()){
|
||||||
var response = await http.get(Uri.parse(_baseDownload));
|
var response = await http.get(Uri.parse(_baseDownload));
|
||||||
if(response.statusCode != 200){
|
if(response.statusCode != 200){
|
||||||
@@ -32,11 +32,11 @@ Future<void> downloadRequiredDLLs() async {
|
|||||||
await craniumDll.writeAsBytes(response.bodyBytes);
|
await craniumDll.writeAsBytes(response.bodyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
var memoryFixDll = File("${assetsDirectory.path}\\dlls\\memoryleak.dll");
|
var memoryFixDll = File("${dllsDirectory.path}\\memory.dll");
|
||||||
if(!memoryFixDll.existsSync()){
|
if(!memoryFixDll.existsSync()){
|
||||||
var response = await http.get(Uri.parse(_memoryFixDownload));
|
var response = await http.get(Uri.parse(_memoryFixDownload));
|
||||||
if(response.statusCode != 200){
|
if(response.statusCode != 200){
|
||||||
throw Exception("Cannot download memoryleak.dll");
|
throw Exception("Cannot download memory.dll");
|
||||||
}
|
}
|
||||||
|
|
||||||
await memoryFixDll.writeAsBytes(response.bodyBytes);
|
await memoryFixDll.writeAsBytes(response.bodyBytes);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export 'package:reboot_common/src/model/server_result.dart';
|
|||||||
export 'package:reboot_common/src/model/server_type.dart';
|
export 'package:reboot_common/src/model/server_type.dart';
|
||||||
export 'package:reboot_common/src/model/update_status.dart';
|
export 'package:reboot_common/src/model/update_status.dart';
|
||||||
export 'package:reboot_common/src/model/update_timer.dart';
|
export 'package:reboot_common/src/model/update_timer.dart';
|
||||||
|
export 'package:reboot_common/src/model/dll.dart';
|
||||||
export 'package:reboot_common/src/util/backend.dart';
|
export 'package:reboot_common/src/util/backend.dart';
|
||||||
export 'package:reboot_common/src/util/build.dart';
|
export 'package:reboot_common/src/util/build.dart';
|
||||||
export 'package:reboot_common/src/util/dll.dart';
|
export 'package:reboot_common/src/util/dll.dart';
|
||||||
|
|||||||
@@ -21,3 +21,4 @@ const List<String> kCannotConnectErrors = [
|
|||||||
"UOnlineAccountCommon::ForceLogout"
|
"UOnlineAccountCommon::ForceLogout"
|
||||||
];
|
];
|
||||||
const String kGameFinishedLine = "PlayersLeft: 1";
|
const String kGameFinishedLine = "PlayersLeft: 1";
|
||||||
|
const String kDisplayInitializedLine = "Display";
|
||||||
|
|||||||
6
common/lib/src/model/dll.dart
Normal file
6
common/lib/src/model/dll.dart
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
enum InjectableDll {
|
||||||
|
console,
|
||||||
|
cobalt,
|
||||||
|
reboot,
|
||||||
|
memory
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import 'package:path/path.dart' as path;
|
|||||||
import 'package:reboot_common/common.dart';
|
import 'package:reboot_common/common.dart';
|
||||||
|
|
||||||
bool _watcher = false;
|
bool _watcher = false;
|
||||||
final File rebootDllFile = File("${assetsDirectory.path}\\dlls\\reboot.dll");
|
final File rebootDllFile = File("${dllsDirectory.path}\\reboot.dll");
|
||||||
const String kRebootDownloadUrl =
|
const String kRebootDownloadUrl =
|
||||||
"http://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/Release.zip";
|
"http://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/Release.zip";
|
||||||
|
|
||||||
@@ -18,7 +18,8 @@ Future<bool> hasRebootDllUpdate(int? lastUpdateMs, {int hours = 24, bool force =
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> downloadCriticalDll(String name, String outputPath) async {
|
Future<void> downloadCriticalDll(String name, String outputPath) async {
|
||||||
final response = await http.get(Uri.parse("https://github.com/Auties00/reboot_launcher/raw/master/gui/assets/dlls/$name"));
|
print("https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/$name");
|
||||||
|
final response = await http.get(Uri.parse("https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/$name"));
|
||||||
if(response.statusCode != 200) {
|
if(response.statusCode != 200) {
|
||||||
throw Exception("Cannot download $name: status code ${response.statusCode}");
|
throw Exception("Cannot download $name: status code ${response.statusCode}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,11 @@ final class _MIB_TCPTABLE_OWNER_PID extends Struct {
|
|||||||
@Uint32()
|
@Uint32()
|
||||||
external int dwNumEntries;
|
external int dwNumEntries;
|
||||||
|
|
||||||
@Array(1)
|
@Array(512)
|
||||||
external Array<_MIB_TCPROW_OWNER_PID> table;
|
external Array<_MIB_TCPROW_OWNER_PID> table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool isLocalHost(String host) => host.trim() == "127.0.0.1"
|
bool isLocalHost(String host) => host.trim() == "127.0.0.1"
|
||||||
|| host.trim().toLowerCase() == "localhost"
|
|| host.trim().toLowerCase() == "localhost"
|
||||||
|| host.trim() == "0.0.0.0";
|
|| host.trim() == "0.0.0.0";
|
||||||
@@ -46,7 +47,6 @@ bool killProcessByPort(int port) {
|
|||||||
var pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>();
|
var pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>();
|
||||||
final dwSize = calloc<DWORD>();
|
final dwSize = calloc<DWORD>();
|
||||||
dwSize.value = 0;
|
dwSize.value = 0;
|
||||||
|
|
||||||
int result = _getExtendedTcpTable(
|
int result = _getExtendedTcpTable(
|
||||||
nullptr,
|
nullptr,
|
||||||
dwSize,
|
dwSize,
|
||||||
@@ -56,6 +56,7 @@ bool killProcessByPort(int port) {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
if (result == ERROR_INSUFFICIENT_BUFFER) {
|
if (result == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
free(pTcpTable);
|
||||||
pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>(dwSize.value);
|
pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>(dwSize.value);
|
||||||
result = _getExtendedTcpTable(
|
result = _getExtendedTcpTable(
|
||||||
pTcpTable,
|
pTcpTable,
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import 'dart:io';
|
|||||||
Directory get installationDirectory =>
|
Directory get installationDirectory =>
|
||||||
File(Platform.resolvedExecutable).parent;
|
File(Platform.resolvedExecutable).parent;
|
||||||
|
|
||||||
|
Directory get dllsDirectory => Directory("${installationDirectory.path}\\dlls");
|
||||||
|
|
||||||
Directory get assetsDirectory {
|
Directory get assetsDirectory {
|
||||||
var directory = Directory("${installationDirectory.path}\\data\\flutter_assets\\assets");
|
var directory = Directory("${installationDirectory.path}\\data\\flutter_assets\\assets");
|
||||||
if(directory.existsSync()) {
|
if(directory.existsSync()) {
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ final _CreateRemoteThread = _kernel32.lookupFunction<
|
|||||||
Pointer<Uint32> lpThreadId)>('CreateRemoteThread');
|
Pointer<Uint32> lpThreadId)>('CreateRemoteThread');
|
||||||
const chunkSize = 1024;
|
const chunkSize = 1024;
|
||||||
|
|
||||||
Future<void> injectDll(int pid, String dll) async {
|
Future<void> injectDll(int pid, File dll) async {
|
||||||
|
// Get the path to the file
|
||||||
|
final dllPath = dll.path;
|
||||||
|
|
||||||
final process = OpenProcess(
|
final process = OpenProcess(
|
||||||
0x43A,
|
0x43A,
|
||||||
0,
|
0,
|
||||||
@@ -52,7 +55,7 @@ Future<void> injectDll(int pid, String dll) async {
|
|||||||
final dllAddress = VirtualAllocEx(
|
final dllAddress = VirtualAllocEx(
|
||||||
process,
|
process,
|
||||||
nullptr,
|
nullptr,
|
||||||
dll.length + 1,
|
dllPath.length + 1,
|
||||||
0x3000,
|
0x3000,
|
||||||
0x4
|
0x4
|
||||||
);
|
);
|
||||||
@@ -60,8 +63,8 @@ Future<void> injectDll(int pid, String dll) async {
|
|||||||
final writeMemoryResult = WriteProcessMemory(
|
final writeMemoryResult = WriteProcessMemory(
|
||||||
process,
|
process,
|
||||||
dllAddress,
|
dllAddress,
|
||||||
dll.toNativeUtf8(),
|
dllPath.toNativeUtf8(),
|
||||||
dll.length,
|
dllPath.length,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -89,6 +92,18 @@ Future<void> injectDll(int pid, String dll) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> startElevatedProcess({required String executable, required String args, bool window = false}) async {
|
||||||
|
var shellInput = calloc<SHELLEXECUTEINFO>();
|
||||||
|
shellInput.ref.lpFile = executable.toNativeUtf16();
|
||||||
|
shellInput.ref.lpParameters = args.toNativeUtf16();
|
||||||
|
shellInput.ref.nShow = window ? SW_SHOWNORMAL : SW_HIDE;
|
||||||
|
shellInput.ref.fMask = ES_AWAYMODE_REQUIRED;
|
||||||
|
shellInput.ref.lpVerb = "runas".toNativeUtf16();
|
||||||
|
shellInput.ref.cbSize = sizeOf<SHELLEXECUTEINFO>();
|
||||||
|
var shellResult = ShellExecuteEx(shellInput);
|
||||||
|
return shellResult == 1;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Process> startProcess({required File executable, List<String>? args, bool wrapProcess = true, bool window = false, String? name}) async {
|
Future<Process> startProcess({required File executable, List<String>? args, bool wrapProcess = true, bool window = false, String? name}) async {
|
||||||
final argsOrEmpty = args ?? [];
|
final argsOrEmpty = args ?? [];
|
||||||
if(wrapProcess) {
|
if(wrapProcess) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
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.
|
Project Reboot is a game server for Fortnite that aims to support as many seasons as possible.
|
||||||
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.
|
The project was started on Discord by Milxnor, while the launcher is developed by Auties00.
|
||||||
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.
|
Both are open source on GitHub, anyone can easily contribute or audit the code!"
|
||||||
Just like in Minecraft, you need a game client to play the game and one to host the server."
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
A backend is a piece of software that emulates the Epic Games server responsible for authentication and related features.
|
A backend is a piece of software that emulates the Epic Games server responsible for authentication and related features.
|
||||||
By default, the Reboot Launcher ships with a slightly customized version of LawinV1, an open source implementation available on Github.
|
By default, the Reboot Launcher ships with a slightly customized version of LawinV1, an open source implementation available on Github.
|
||||||
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."
|
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.
|
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.
|
||||||
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.
|
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.
|
||||||
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.
|
You can run these alternatives 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.
|
||||||
BIN
gui/dependencies/InnoDependencyInstaller/netcorecheck.exe
Normal file
BIN
gui/dependencies/InnoDependencyInstaller/netcorecheck.exe
Normal file
Binary file not shown.
BIN
gui/dependencies/InnoDependencyInstaller/netcorecheck_x64.exe
Normal file
BIN
gui/dependencies/InnoDependencyInstaller/netcorecheck_x64.exe
Normal file
Binary file not shown.
@@ -24,7 +24,7 @@ import 'package:reboot_launcher/src/dialog/abstract/info_bar.dart';
|
|||||||
import 'package:reboot_launcher/src/dialog/implementation/error.dart';
|
import 'package:reboot_launcher/src/dialog/implementation/error.dart';
|
||||||
import 'package:reboot_launcher/src/dialog/implementation/server.dart';
|
import 'package:reboot_launcher/src/dialog/implementation/server.dart';
|
||||||
import 'package:reboot_launcher/src/page/implementation/home_page.dart';
|
import 'package:reboot_launcher/src/page/implementation/home_page.dart';
|
||||||
import 'package:reboot_launcher/src/util/info.dart';
|
import 'package:reboot_launcher/src/page/implementation/info_page.dart';
|
||||||
import 'package:reboot_launcher/src/util/matchmaker.dart';
|
import 'package:reboot_launcher/src/util/matchmaker.dart';
|
||||||
import 'package:reboot_launcher/src/util/os.dart';
|
import 'package:reboot_launcher/src/util/os.dart';
|
||||||
import 'package:reboot_launcher/src/util/translations.dart';
|
import 'package:reboot_launcher/src/util/translations.dart';
|
||||||
@@ -35,37 +35,46 @@ import 'package:version/version.dart';
|
|||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
const double kDefaultWindowWidth = 1536;
|
const double kDefaultWindowWidth = 1536;
|
||||||
const double kDefaultWindowHeight = 1024;
|
const double kDefaultWindowHeight = 1224;
|
||||||
const String kCustomUrlSchema = "Reboot";
|
const String kCustomUrlSchema = "Reboot";
|
||||||
|
|
||||||
Version? appVersion;
|
Version? appVersion;
|
||||||
|
|
||||||
class _MyHttpOverrides extends HttpOverrides {
|
|
||||||
@override
|
|
||||||
HttpClient createHttpClient(SecurityContext? context){
|
|
||||||
return super.createHttpClient(context)
|
|
||||||
..badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() => runZonedGuarded(
|
void main() => runZonedGuarded(
|
||||||
() async {
|
() => _startApp(),
|
||||||
HttpOverrides.global = _MyHttpOverrides();
|
(error, stack) => onError(error, stack, false),
|
||||||
|
zoneSpecification: ZoneSpecification(
|
||||||
|
handleUncaughtError: (self, parent, zone, error, stacktrace) => onError(error, stacktrace, false)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> _startApp() async {
|
||||||
final errors = <Object>[];
|
final errors = <Object>[];
|
||||||
try {
|
try {
|
||||||
await installationDirectory.create(recursive: true);
|
final pathError = await _initPath();
|
||||||
await Supabase.initialize(
|
if(pathError != null) {
|
||||||
url: supabaseUrl,
|
errors.add(pathError);
|
||||||
anonKey: supabaseAnonKey
|
}
|
||||||
);
|
|
||||||
await localNotifier.setup(
|
final databaseError = await _initDatabase();
|
||||||
appName: 'Reboot Launcher',
|
if(databaseError != null) {
|
||||||
shortcutPolicy: ShortcutPolicy.ignore
|
errors.add(databaseError);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
final notificationsError = await _initNotifications();
|
||||||
|
if(notificationsError != null) {
|
||||||
|
errors.add(notificationsError);
|
||||||
|
}
|
||||||
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await SystemTheme.accentColor.load();
|
|
||||||
_initWindow();
|
_initWindow();
|
||||||
initInfoTiles();
|
|
||||||
|
final tilesError = InfoPage.initInfoTiles();
|
||||||
|
if(tilesError != null) {
|
||||||
|
errors.add(tilesError);
|
||||||
|
}
|
||||||
|
|
||||||
final versionError = await _initVersion();
|
final versionError = await _initVersion();
|
||||||
if(versionError != null) {
|
if(versionError != null) {
|
||||||
errors.add(versionError);
|
errors.add(versionError);
|
||||||
@@ -88,12 +97,40 @@ void main() => runZonedGuarded(
|
|||||||
runApp(const RebootApplication());
|
runApp(const RebootApplication());
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) => _handleErrors(errors));
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) => _handleErrors(errors));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
(error, stack) => onError(error, stack, false),
|
|
||||||
zoneSpecification: ZoneSpecification(
|
Future<Object?> _initNotifications() async {
|
||||||
handleUncaughtError: (self, parent, zone, error, stacktrace) => onError(error, stacktrace, false)
|
try {
|
||||||
)
|
await localNotifier.setup(
|
||||||
|
appName: 'Reboot Launcher',
|
||||||
|
shortcutPolicy: ShortcutPolicy.ignore
|
||||||
);
|
);
|
||||||
|
return null;
|
||||||
|
}catch(error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Object?> _initDatabase() async {
|
||||||
|
try {
|
||||||
|
await Supabase.initialize(
|
||||||
|
url: supabaseUrl,
|
||||||
|
anonKey: supabaseAnonKey
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}catch(error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Object?> _initPath() async {
|
||||||
|
try {
|
||||||
|
await installationDirectory.create(recursive: true);
|
||||||
|
return null;
|
||||||
|
}catch(error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _handleErrors(List<Object?> errors) {
|
void _handleErrors(List<Object?> errors) {
|
||||||
errors.where((element) => element != null).forEach((element) => onError(element!, null, false));
|
errors.where((element) => element != null).forEach((element) => onError(element!, null, false));
|
||||||
@@ -170,6 +207,7 @@ void _joinServer(Uri uri) {
|
|||||||
String _parseCustomUrl(Uri uri) => uri.host;
|
String _parseCustomUrl(Uri uri) => uri.host;
|
||||||
|
|
||||||
void _initWindow() => doWhenWindowReady(() async {
|
void _initWindow() => doWhenWindowReady(() async {
|
||||||
|
await SystemTheme.accentColor.load();
|
||||||
await windowManager.ensureInitialized();
|
await windowManager.ensureInitialized();
|
||||||
await Window.initialize();
|
await Window.initialize();
|
||||||
var settingsController = Get.find<SettingsController>();
|
var settingsController = Get.find<SettingsController>();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class SettingsController extends GetxController {
|
|||||||
gameServerDll = _createController("game_server", "reboot.dll");
|
gameServerDll = _createController("game_server", "reboot.dll");
|
||||||
unrealEngineConsoleDll = _createController("unreal_engine_console", "console.dll");
|
unrealEngineConsoleDll = _createController("unreal_engine_console", "console.dll");
|
||||||
backendDll = _createController("backend", "cobalt.dll");
|
backendDll = _createController("backend", "cobalt.dll");
|
||||||
memoryLeakDll = _createController("memory_leak", "memoryleak.dll");
|
memoryLeakDll = _createController("memory_leak", "memory.dll");
|
||||||
gameServerPort = TextEditingController(text: _storage.read("game_server_port") ?? kDefaultGameServerPort);
|
gameServerPort = TextEditingController(text: _storage.read("game_server_port") ?? kDefaultGameServerPort);
|
||||||
gameServerPort.addListener(() => _storage.write("game_server_port", gameServerPort.text));
|
gameServerPort.addListener(() => _storage.write("game_server_port", gameServerPort.text));
|
||||||
width = _storage.read("width") ?? kDefaultWindowWidth;
|
width = _storage.read("width") ?? kDefaultWindowWidth;
|
||||||
@@ -67,5 +67,5 @@ class SettingsController extends GetxController {
|
|||||||
firstRun.value = true;
|
firstRun.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _controllerDefaultPath(String name) => "${assetsDirectory.path}\\dlls\\$name";
|
String _controllerDefaultPath(String name) => "${dllsDirectory.path}\\$name";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ extension ServerControllerDialog on BackendController {
|
|||||||
severity: InfoBarSeverity.success
|
severity: InfoBarSeverity.success
|
||||||
);
|
);
|
||||||
case ServerResultType.startError:
|
case ServerResultType.startError:
|
||||||
|
print(event.stackTrace);
|
||||||
return showInfoBar(
|
return showInfoBar(
|
||||||
type.value == ServerType.local ? translations.localServerError(event.error ?? translations.unknownError) : translations.startServerError(event.error ?? translations.unknownError),
|
type.value == ServerType.local ? translations.localServerError(event.error ?? translations.unknownError) : translations.startServerError(event.error ?? translations.unknownError),
|
||||||
severity: InfoBarSeverity.error,
|
severity: InfoBarSeverity.error,
|
||||||
|
|||||||
@@ -46,14 +46,24 @@ class _HomePageState extends State<HomePage> with WindowListener, AutomaticKeepA
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
windowManager.addListener(this);
|
windowManager.addListener(this);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) => _checkUpdates());
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkUpdates() {
|
||||||
_updateController.notifyLauncherUpdate();
|
_updateController.notifyLauncherUpdate();
|
||||||
_updateController.updateReboot();
|
|
||||||
|
if(!dllsDirectory.existsSync()) {
|
||||||
|
dllsDirectory.createSync(recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(final injectable in InjectableDll.values) {
|
||||||
|
downloadCriticalDllInteractive("${injectable.name}.dll");
|
||||||
|
}
|
||||||
|
|
||||||
watchDlls().listen((filePath) => showDllDeletedDialog(() {
|
watchDlls().listen((filePath) => showDllDeletedDialog(() {
|
||||||
downloadCriticalDllInteractive(filePath);
|
downloadCriticalDllInteractive(filePath);
|
||||||
}));
|
}));
|
||||||
});
|
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,15 +1,53 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:collection';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons;
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:get/get.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/controller/settings_controller.dart';
|
||||||
import 'package:reboot_launcher/src/page/abstract/page.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/abstract/page_type.dart';
|
||||||
import 'package:reboot_launcher/src/page/pages.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/util/translations.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:reboot_launcher/src/widget/info_tile.dart';
|
||||||
|
|
||||||
class InfoPage extends RebootPage {
|
class InfoPage extends RebootPage {
|
||||||
|
static late final List<InfoTile> _infoTiles;
|
||||||
|
static Object? initInfoTiles() {
|
||||||
|
try {
|
||||||
|
final directory = Directory("${assetsDirectory.path}\\info\\$currentLocale");
|
||||||
|
final map = SplayTreeMap<int, InfoTile>();
|
||||||
|
for(final entry in directory.listSync()) {
|
||||||
|
if(entry is File) {
|
||||||
|
final name = Uri.decodeQueryComponent(path.basename(entry.path));
|
||||||
|
final splitter = name.indexOf(".");
|
||||||
|
if(splitter == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final index = int.tryParse(name.substring(0, splitter));
|
||||||
|
if(index == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final questionName = Uri.decodeQueryComponent(name.substring(splitter + 2));
|
||||||
|
map[index] = InfoTile(
|
||||||
|
title: Text(questionName),
|
||||||
|
content: Text(entry.readAsStringSync())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_infoTiles = map.values.toList(growable: false);
|
||||||
|
return null;
|
||||||
|
}catch(error) {
|
||||||
|
_infoTiles = [];
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const InfoPage({Key? key}) : super(key: key);
|
const InfoPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -30,7 +68,7 @@ class InfoPage extends RebootPage {
|
|||||||
|
|
||||||
class _InfoPageState extends RebootPageState<InfoPage> {
|
class _InfoPageState extends RebootPageState<InfoPage> {
|
||||||
final SettingsController _settingsController = Get.find<SettingsController>();
|
final SettingsController _settingsController = Get.find<SettingsController>();
|
||||||
RxInt _counter = RxInt(180);
|
RxInt _counter = RxInt(kDebugMode ? 0 : 180);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -48,7 +86,7 @@ class _InfoPageState extends RebootPageState<InfoPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Widget> get settings => infoTiles;
|
List<Widget> get settings => InfoPage._infoTiles;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget? get button => Obx(() {
|
Widget? get button => Obx(() {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
import 'package:fluent_ui/fluent_ui.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
import 'package:reboot_common/common.dart';
|
import 'package:reboot_common/common.dart';
|
||||||
|
import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||||
import 'package:reboot_launcher/src/controller/update_controller.dart';
|
import 'package:reboot_launcher/src/controller/update_controller.dart';
|
||||||
import 'package:reboot_launcher/src/dialog/abstract/info_bar.dart';
|
import 'package:reboot_launcher/src/dialog/abstract/info_bar.dart';
|
||||||
import 'package:reboot_launcher/src/util/translations.dart';
|
import 'package:reboot_launcher/src/util/translations.dart';
|
||||||
@@ -68,3 +70,26 @@ Future<void> _downloadCriticalDllInteractive(String filePath) async {
|
|||||||
_operations.remove(fileName);
|
_operations.remove(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension InjectableDllExtension on InjectableDll {
|
||||||
|
String get path {
|
||||||
|
final SettingsController settingsController = Get.find<SettingsController>();
|
||||||
|
switch(this){
|
||||||
|
case InjectableDll.reboot:
|
||||||
|
if(_updateController.customGameServer.value) {
|
||||||
|
final file = File(settingsController.gameServerDll.text);
|
||||||
|
if(file.existsSync()) {
|
||||||
|
return file.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rebootDllFile.path;
|
||||||
|
case InjectableDll.console:
|
||||||
|
return settingsController.unrealEngineConsoleDll.text;
|
||||||
|
case InjectableDll.cobalt:
|
||||||
|
return settingsController.backendDll.text;
|
||||||
|
case InjectableDll.memory:
|
||||||
|
return settingsController.memoryLeakDll.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
import 'dart:collection';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
import 'package:reboot_common/common.dart';
|
|
||||||
import 'package:reboot_launcher/src/util/log.dart';
|
|
||||||
import 'package:reboot_launcher/src/util/translations.dart';
|
|
||||||
import 'package:reboot_launcher/src/widget/info_tile.dart';
|
|
||||||
|
|
||||||
final _entries = SplayTreeMap<int, InfoTile>();
|
|
||||||
|
|
||||||
void initInfoTiles() {
|
|
||||||
try {
|
|
||||||
final directory = Directory("${assetsDirectory.path}\\info\\$currentLocale");
|
|
||||||
for(final entry in directory.listSync()) {
|
|
||||||
if(entry is File) {
|
|
||||||
final name = Uri.decodeQueryComponent(path.basename(entry.path));
|
|
||||||
final splitter = name.indexOf(".");
|
|
||||||
if(splitter == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final index = int.tryParse(name.substring(0, splitter));
|
|
||||||
if(index == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final questionName = Uri.decodeQueryComponent(name.substring(splitter + 2));
|
|
||||||
_entries[index] = InfoTile(
|
|
||||||
title: Text(questionName),
|
|
||||||
content: Text(entry.readAsStringSync())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}catch(error) {
|
|
||||||
log("[INFO] Error occurred while initializing info tiles: $error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<InfoTile> get infoTiles => _entries.values.toList(growable: false);
|
|
||||||
@@ -103,8 +103,8 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
log("[${widget.host ? 'HOST' : 'GAME'}] Setting started...");
|
log("[${widget.host ? 'HOST' : 'GAME'}] Setting started...");
|
||||||
_setStarted(widget.host, true);
|
_setStarted(widget.host, true);
|
||||||
log("[${widget.host ? 'HOST' : 'GAME'}] Set started");
|
log("[${widget.host ? 'HOST' : 'GAME'}] Set started");
|
||||||
log("[${widget.host ? 'HOST' : 'GAME'}] Checking dlls: ${_Injectable.values}");
|
log("[${widget.host ? 'HOST' : 'GAME'}] Checking dlls: ${InjectableDll.values}");
|
||||||
for (final injectable in _Injectable.values) {
|
for (final injectable in InjectableDll.values) {
|
||||||
if(await _getDllFileOrStop(injectable, widget.host) == null) {
|
if(await _getDllFileOrStop(injectable, widget.host) == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
}else{
|
}else{
|
||||||
_gameController.instance.value = instance;
|
_gameController.instance.value = instance;
|
||||||
}
|
}
|
||||||
await _injectOrShowError(_Injectable.sslBypassV2, host);
|
await _injectOrShowError(InjectableDll.cobalt, host);
|
||||||
log("[${host ? 'HOST' : 'GAME'}] Finished creating game instance");
|
log("[${host ? 'HOST' : 'GAME'}] Finished creating game instance");
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@@ -319,46 +319,33 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
_onStop(
|
_onStop(
|
||||||
reason: _StopReason.normal
|
reason: _StopReason.normal
|
||||||
);
|
);
|
||||||
return;
|
}else if(kCorruptedBuildErrors.any((element) => line.contains(element))){
|
||||||
}
|
|
||||||
|
|
||||||
if(kCorruptedBuildErrors.any((element) => line.contains(element))){
|
|
||||||
_onStop(
|
_onStop(
|
||||||
reason: _StopReason.corruptedVersionError
|
reason: _StopReason.corruptedVersionError
|
||||||
);
|
);
|
||||||
return;
|
}else if(kCannotConnectErrors.any((element) => line.contains(element))){
|
||||||
}
|
|
||||||
|
|
||||||
if(kCannotConnectErrors.any((element) => line.contains(element))){
|
|
||||||
_onStop(
|
_onStop(
|
||||||
reason: _StopReason.tokenError
|
reason: _StopReason.tokenError
|
||||||
);
|
);
|
||||||
return;
|
}else if(kLoggedInLines.every((entry) => line.contains(entry))) {
|
||||||
}
|
|
||||||
|
|
||||||
if(kLoggedInLines.every((entry) => line.contains(entry))) {
|
|
||||||
final instance = host ? _hostingController.instance.value : _gameController.instance.value;
|
final instance = host ? _hostingController.instance.value : _gameController.instance.value;
|
||||||
if(instance != null && !instance.launched) {
|
if(instance != null && !instance.launched) {
|
||||||
instance.launched = true;
|
instance.launched = true;
|
||||||
instance.tokenError = false;
|
instance.tokenError = false;
|
||||||
await _injectOrShowError(_Injectable.memoryFix, host);
|
await _injectOrShowError(InjectableDll.memory, host);
|
||||||
if(!host){
|
if(!host){
|
||||||
await _injectOrShowError(_Injectable.console, host);
|
await _injectOrShowError(InjectableDll.console, host);
|
||||||
_onGameClientInjected();
|
_onGameClientInjected();
|
||||||
}else {
|
}else {
|
||||||
final gameServerPort = int.tryParse(_settingsController.gameServerPort.text);
|
final gameServerPort = int.tryParse(_settingsController.gameServerPort.text);
|
||||||
if(gameServerPort != null) {
|
if(gameServerPort != null) {
|
||||||
await killProcessByPort(gameServerPort);
|
await killProcessByPort(gameServerPort);
|
||||||
}
|
}
|
||||||
await _injectOrShowError(_Injectable.reboot, host);
|
await _injectOrShowError(InjectableDll.reboot, host);
|
||||||
_onGameServerInjected();
|
_onGameServerInjected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else if(line.contains(kGameFinishedLine) && host) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(line.contains(kGameFinishedLine) && host) {
|
|
||||||
if(_hostingController.autoRestart.value) {
|
if(_hostingController.autoRestart.value) {
|
||||||
final notification = LocalNotification(
|
final notification = LocalNotification(
|
||||||
title: translations.gameServerEnd,
|
title: translations.gameServerEnd,
|
||||||
@@ -378,10 +365,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
_onStop(reason: _StopReason.normal, host: true);
|
_onStop(reason: _StopReason.normal, host: true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
}else if(line.contains(kDisplayInitializedLine) && host && virtualDesktop) {
|
||||||
}
|
|
||||||
|
|
||||||
if(line.contains("Display") && host && virtualDesktop) {
|
|
||||||
final hostingInstance = _hostingController.instance.value;
|
final hostingInstance = _hostingController.instance.value;
|
||||||
if(hostingInstance != null && !hostingInstance.movedToVirtualDesktop) {
|
if(hostingInstance != null && !hostingInstance.movedToVirtualDesktop) {
|
||||||
hostingInstance.movedToVirtualDesktop = true;
|
hostingInstance.movedToVirtualDesktop = true;
|
||||||
@@ -615,7 +599,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _injectOrShowError(_Injectable injectable, bool hosting) async {
|
Future<void> _injectOrShowError(InjectableDll injectable, bool hosting) async {
|
||||||
final instance = hosting ? _hostingController.instance.value : _gameController.instance.value;
|
final instance = hosting ? _hostingController.instance.value : _gameController.instance.value;
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
log("[${hosting ? 'HOST' : 'GAME'}] No instance found to inject ${injectable.name}");
|
log("[${hosting ? 'HOST' : 'GAME'}] No instance found to inject ${injectable.name}");
|
||||||
@@ -637,7 +621,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log("[${hosting ? 'HOST' : 'GAME'}] Trying to inject ${injectable.name}...");
|
log("[${hosting ? 'HOST' : 'GAME'}] Trying to inject ${injectable.name}...");
|
||||||
await injectDll(gameProcess, dllPath.path);
|
await injectDll(gameProcess, dllPath);
|
||||||
log("[${hosting ? 'HOST' : 'GAME'}] Injected ${injectable.name}");
|
log("[${hosting ? 'HOST' : 'GAME'}] Injected ${injectable.name}");
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
log("[${hosting ? 'HOST' : 'GAME'}] Cannot inject ${injectable.name}: $error $stackTrace");
|
log("[${hosting ? 'HOST' : 'GAME'}] Cannot inject ${injectable.name}: $error $stackTrace");
|
||||||
@@ -650,29 +634,9 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getDllPath(_Injectable injectable) {
|
Future<File?> _getDllFileOrStop(InjectableDll injectable, bool host) async {
|
||||||
switch(injectable){
|
|
||||||
case _Injectable.reboot:
|
|
||||||
if(_updateController.customGameServer.value) {
|
|
||||||
final file = File(_settingsController.gameServerDll.text);
|
|
||||||
if(file.existsSync()) {
|
|
||||||
return file.path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rebootDllFile.path;
|
|
||||||
case _Injectable.console:
|
|
||||||
return _settingsController.unrealEngineConsoleDll.text;
|
|
||||||
case _Injectable.sslBypassV2:
|
|
||||||
return _settingsController.backendDll.text;
|
|
||||||
case _Injectable.memoryFix:
|
|
||||||
return _settingsController.memoryLeakDll.text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<File?> _getDllFileOrStop(_Injectable injectable, bool host) async {
|
|
||||||
log("[${host ? 'HOST' : 'GAME'}] Checking dll ${injectable}...");
|
log("[${host ? 'HOST' : 'GAME'}] Checking dll ${injectable}...");
|
||||||
final path = _getDllPath(injectable);
|
final path = injectable.path;
|
||||||
log("[${host ? 'HOST' : 'GAME'}] Path: $path");
|
log("[${host ? 'HOST' : 'GAME'}] Path: $path");
|
||||||
final file = File(path);
|
final file = File(path);
|
||||||
if(await file.exists()) {
|
if(await file.exists()) {
|
||||||
@@ -713,10 +677,3 @@ enum _StopReason {
|
|||||||
|
|
||||||
bool get isError => name.contains("Error");
|
bool get isError => name.contains("Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _Injectable {
|
|
||||||
console,
|
|
||||||
sslBypassV2,
|
|
||||||
reboot,
|
|
||||||
memoryFix,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ flutter:
|
|||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
generate: true
|
generate: true
|
||||||
assets:
|
assets:
|
||||||
- assets/dlls/
|
|
||||||
- assets/icons/
|
- assets/icons/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
- assets/backend/
|
- assets/backend/
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ AppPublisher={{PUBLISHER_NAME}}
|
|||||||
AppPublisherURL={{PUBLISHER_URL}}
|
AppPublisherURL={{PUBLISHER_URL}}
|
||||||
AppSupportURL={{PUBLISHER_URL}}
|
AppSupportURL={{PUBLISHER_URL}}
|
||||||
AppUpdatesURL={{PUBLISHER_URL}}
|
AppUpdatesURL={{PUBLISHER_URL}}
|
||||||
DefaultDirName={{INSTALL_DIR_NAME}}
|
DefaultDirName={autopf}\{{DISPLAY_NAME}};
|
||||||
DisableProgramGroupPage=yes
|
DisableProgramGroupPage=yes
|
||||||
OutputBaseFilename={{OUTPUT_BASE_FILENAME}}
|
OutputBaseFilename={{OUTPUT_BASE_FILENAME}}
|
||||||
Compression=lzma
|
Compression=zip
|
||||||
SolidCompression=yes
|
SolidCompression=yes
|
||||||
SetupIconFile={{SETUP_ICON_FILE}}
|
SetupIconFile={{SETUP_ICON_FILE}}
|
||||||
WizardStyle=modern
|
WizardStyle=modern
|
||||||
@@ -32,7 +32,8 @@ Name: "launchAtStartup"; Description: "{cm:AutoStartProgram,{{DISPLAY_NAME}}}";
|
|||||||
Source: "{{SOURCE_DIR}}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "{{SOURCE_DIR}}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
Filename: "{app}\\{{EXECUTABLE_NAME}}"; Description: "{cm:LaunchProgram,{{DISPLAY_NAME}}}"; Flags: runascurrentuser nowait postinstall skipifsilent
|
Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -Command ""Add-MpPreference -ExclusionPath '{app}'"""; Flags: runhidden
|
||||||
|
Filename: "{app}\{{EXECUTABLE_NAME}}"; Description: "{cm:LaunchProgram,{{DISPLAY_NAME}}}"; Flags: runascurrentuser nowait postinstall skipifsilent
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{autoprograms}\{{DISPLAY_NAME}}"; Filename: "{app}\{{EXECUTABLE_NAME}}"
|
Name: "{autoprograms}\{{DISPLAY_NAME}}"; Filename: "{app}\{{EXECUTABLE_NAME}}"
|
||||||
|
|||||||
Reference in New Issue
Block a user