5 Commits

Author SHA1 Message Date
Alessandro Autiero
70d83dc1c5 refactor 2025-09-19 18:14:22 +01:00
Alessandro Autiero
d53a577f0b Refactored GUI 2025-08-11 22:53:11 +01:00
Alessandro Autiero
c9ed6a5af3 Refactored GUI 2025-08-10 20:13:18 +01:00
Alessandro Autiero
4ea73d17c7 Refactored GUI 2025-08-10 19:43:57 +01:00
Alessandro Autiero
52abf5eb95 Renamed backend into auth_backend and added server_browser_backend implementation to replace Supabase. 2025-08-09 02:54:48 +01:00
186 changed files with 3596 additions and 2849 deletions

View File

@@ -1,18 +1,21 @@
export 'package:reboot_common/src/constant/backend.dart';
export 'package:reboot_common/src/constant/game.dart';
export 'package:reboot_common/src/constant/supabase.dart';
export 'package:reboot_common/src/model/fortnite_build.dart';
export 'package:reboot_common/src/model/fortnite_version.dart';
export 'package:reboot_common/src/model/game_instance.dart';
export 'package:reboot_common/src/model/server_result.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_timer.dart';
export 'package:reboot_common/src/model/fortnite_server.dart';
export 'package:reboot_common/src/model/dll.dart';
export 'package:reboot_common/src/util/backend.dart';
export 'package:reboot_common/src/util/downloader.dart';
export 'package:reboot_common/src/util/os.dart';
export 'package:reboot_common/src/util/log.dart';
export 'package:reboot_common/src/util/game.dart';
export 'package:reboot_common/src/backend/auth_backend_constants.dart';
export 'package:reboot_common/src/backend/auth_backend_helper.dart';
export 'package:reboot_common/src/backend/auth_backend_result.dart';
export 'package:reboot_common/src/backend/auth_backend_type.dart';
export 'package:reboot_common/src/browser/server_browser_client.dart';
export 'package:reboot_common/src/browser/server_browser_entry.dart';
export 'package:reboot_common/src/browser/server_browser_event.dart';
export 'package:reboot_common/src/browser/server_browser_state.dart';
export 'package:reboot_common/src/game/game_build.dart';
export 'package:reboot_common/src/game/game_constants.dart';
export 'package:reboot_common/src/game/game_dll.dart';
export 'package:reboot_common/src/game/game_downloader.dart';
export 'package:reboot_common/src/game/game_instance.dart';
export 'package:reboot_common/src/game/game_metadata.dart';
export 'package:reboot_common/src/game/game_version.dart';
export 'package:reboot_common/src/util/extensions.dart';
export 'package:reboot_common/src/util/logger.dart';
export 'package:reboot_common/src/util/os.dart';

View File

@@ -15,93 +15,95 @@ final Semaphore _semaphore = Semaphore();
String? _lastIp;
String? _lastPort;
Stream<ServerResult> startBackend({
required ServerType type,
typedef BackendErrorHandler = void Function(String);
Stream<AuthBackendEvent> startAuthBackend({
required AuthBackendType type,
required String host,
required String port,
required bool detached,
required void Function(String) onError
required BackendErrorHandler? onError
}) async* {
Process? process;
HttpServer? server;
try {
host = host.trim();
port = port.trim();
if(type != ServerType.local || port != kDefaultBackendPort.toString()) {
yield ServerResult(ServerResultType.starting);
if(type != AuthBackendType.local || port != kDefaultBackendPort.toString()) {
yield AuthBackendEvent(AuthBackendEventType.starting);
}
if (host.isEmpty) {
yield ServerResult(ServerResultType.startMissingHostError);
yield AuthBackendEvent(AuthBackendEventType.startMissingHostError);
return;
}
if (port.isEmpty) {
yield ServerResult(ServerResultType.startMissingPortError);
yield AuthBackendEvent(AuthBackendEventType.startMissingPortError);
return;
}
final portNumber = int.tryParse(port);
if (portNumber == null) {
yield ServerResult(ServerResultType.startIllegalPortError);
yield AuthBackendEvent(AuthBackendEventType.startIllegalPortError);
return;
}
if ((type != ServerType.local || port != kDefaultBackendPort.toString()) && !(await isBackendPortFree())) {
yield ServerResult(ServerResultType.startFreeingPort);
final result = await freeBackendPort();
if ((type != AuthBackendType.local || port != kDefaultBackendPort.toString()) && !(await isAuthBackendPortFree())) {
yield AuthBackendEvent(AuthBackendEventType.startFreeingPort);
final result = await freeAuthBackendPort();
if(!result) {
yield ServerResult(ServerResultType.startFreePortError);
yield AuthBackendEvent(AuthBackendEventType.startFreePortError);
return;
}
yield ServerResult(ServerResultType.startFreePortSuccess);
yield AuthBackendEvent(AuthBackendEventType.startFreePortSuccess);
}
switch(type){
case ServerType.embedded:
process = await startEmbeddedBackend(detached, onError: onError);
yield ServerResult(ServerResultType.startedImplementation, implementation: ServerImplementation(process: process));
case AuthBackendType.embedded:
process = await _startEmbedded(detached, onError: onError);
yield AuthBackendEvent(AuthBackendEventType.startedImplementation, implementation: AuthBackendImplementation(process: process));
break;
case ServerType.remote:
yield ServerResult(ServerResultType.startPingingRemote);
final uriResult = await pingBackend(host, portNumber);
case AuthBackendType.remote:
yield AuthBackendEvent(AuthBackendEventType.startPingingRemote);
final uriResult = await _ping(host, portNumber);
if(uriResult == null) {
yield ServerResult(ServerResultType.startPingError);
yield AuthBackendEvent(AuthBackendEventType.startPingError);
return;
}
server = await startRemoteBackendProxy(uriResult);
yield ServerResult(ServerResultType.startedImplementation, implementation: ServerImplementation(server: server));
server = await _startRemote(uriResult);
yield AuthBackendEvent(AuthBackendEventType.startedImplementation, implementation: AuthBackendImplementation(server: server));
break;
case ServerType.local:
case AuthBackendType.local:
if(portNumber != kDefaultBackendPort) {
yield ServerResult(ServerResultType.startPingingLocal);
final uriResult = await pingBackend(kDefaultBackendHost, portNumber);
yield AuthBackendEvent(AuthBackendEventType.startPingingLocal);
final uriResult = await _ping(kDefaultBackendHost, portNumber);
if(uriResult == null) {
yield ServerResult(ServerResultType.startPingError);
yield AuthBackendEvent(AuthBackendEventType.startPingError);
return;
}
server = await startRemoteBackendProxy(Uri.parse("http://$kDefaultBackendHost:$port"));
yield ServerResult(ServerResultType.startedImplementation, implementation: ServerImplementation(server: server));
server = await _startRemote(Uri.parse("http://$kDefaultBackendHost:$port"));
yield AuthBackendEvent(AuthBackendEventType.startedImplementation, implementation: AuthBackendImplementation(server: server));
}
break;
}
yield ServerResult(ServerResultType.startPingingLocal);
final uriResult = await pingBackend(kDefaultBackendHost, kDefaultBackendPort);
yield AuthBackendEvent(AuthBackendEventType.startPingingLocal);
final uriResult = await _ping(kDefaultBackendHost, kDefaultBackendPort);
if(uriResult == null) {
yield ServerResult(ServerResultType.startPingError);
yield AuthBackendEvent(AuthBackendEventType.startPingError);
process?.kill(ProcessSignal.sigterm);
server?.close(force: true);
return;
}
yield ServerResult(ServerResultType.startSuccess);
yield AuthBackendEvent(AuthBackendEventType.startSuccess);
}catch(error, stackTrace) {
yield ServerResult(
ServerResultType.startError,
yield AuthBackendEvent(
AuthBackendEventType.startError,
error: error,
stackTrace: stackTrace
);
@@ -110,34 +112,7 @@ Stream<ServerResult> startBackend({
}
}
Stream<ServerResult> stopBackend({required ServerType type, required ServerImplementation? implementation}) async* {
yield ServerResult(ServerResultType.stopping);
try{
switch(type){
case ServerType.embedded:
final process = implementation?.process;
if(process != null) {
Process.killPid(process.pid, ProcessSignal.sigterm);
}
break;
case ServerType.remote:
await implementation?.server?.close(force: true);
break;
case ServerType.local:
await implementation?.server?.close(force: true);
break;
}
yield ServerResult(ServerResultType.stopSuccess);
}catch(error, stackTrace){
yield ServerResult(
ServerResultType.stopError,
error: error,
stackTrace: stackTrace
);
}
}
Future<Process> startEmbeddedBackend(bool detached, {void Function(String)? onError}) async {
Future<Process> _startEmbedded(bool detached, {BackendErrorHandler? onError}) async {
final process = await startProcess(
executable: backendStartExecutable,
window: detached,
@@ -164,22 +139,38 @@ Future<Process> startEmbeddedBackend(bool detached, {void Function(String)? onEr
return process;
}
Future<HttpServer> startRemoteBackendProxy(Uri uri) async => await serve(proxyHandler(uri), kDefaultBackendHost, kDefaultBackendPort);
Future<HttpServer> _startRemote(Uri uri) async => await serve(proxyHandler(uri), kDefaultBackendHost, kDefaultBackendPort);
Future<bool> isBackendPortFree() async => await pingBackend(kDefaultBackendHost, kDefaultBackendPort) == null;
Future<bool> freeBackendPort() async {
await killProcessByPort(kDefaultBackendPort);
await killProcessByPort(kDefaultXmppPort);
final standardResult = await isBackendPortFree();
if(standardResult) {
return true;
Stream<AuthBackendEvent> stopAuthBackend({required AuthBackendType type, required AuthBackendImplementation? implementation}) async* {
yield AuthBackendEvent(AuthBackendEventType.stopping);
try{
switch(type){
case AuthBackendType.embedded:
final process = implementation?.process;
if(process != null) {
Process.killPid(process.pid, ProcessSignal.sigterm);
}
break;
case AuthBackendType.remote:
await implementation?.server?.close(force: true);
break;
case AuthBackendType.local:
await implementation?.server?.close(force: true);
break;
}
yield AuthBackendEvent(AuthBackendEventType.stopSuccess);
}catch(error, stackTrace){
yield AuthBackendEvent(
AuthBackendEventType.stopError,
error: error,
stackTrace: stackTrace
);
}
return false;
}
Future<Uri?> pingBackend(String host, int port, [bool https=false]) async {
Future<bool> isAuthBackendPortFree() async => await _ping(kDefaultBackendHost, kDefaultBackendPort) == null;
Future<Uri?> _ping(String host, int port, [bool https=false]) async {
final hostName = host.replaceFirst("http://", "").replaceFirst("https://", "");
final declaredScheme = host.startsWith("http://") ? "http" : host.startsWith("https://") ? "https" : null;
try{
@@ -198,7 +189,7 @@ Future<Uri?> pingBackend(String host, int port, [bool https=false]) async {
return uri;
}catch(error) {
log("[BACKEND] Cannot ping backend: $error");
return https || declaredScheme != null || isLocalHost(host) ? null : await pingBackend(host, port, true);
return https || declaredScheme != null || isLocalHost(host) ? null : await _ping(host, port, true);
}
}
@@ -236,7 +227,18 @@ Stream<String?> watchMatchmakingIp() async* {
});
}
Future<void> writeMatchmakingIp(String text) async {
Future<bool> freeAuthBackendPort() async {
await killProcessByPort(kDefaultBackendPort);
await killProcessByPort(kDefaultXmppPort);
final standardResult = await isAuthBackendPortFree();
if(standardResult) {
return true;
}
return false;
}
Future<void> writeAuthBackendMatchmakingIp(String text) async {
final exists = await matchmakerConfigFile.exists();
if(!exists) {
return;

View File

@@ -1,12 +1,12 @@
import 'dart:io';
class ServerResult {
final ServerResultType type;
final ServerImplementation? implementation;
class AuthBackendEvent {
final AuthBackendEventType type;
final AuthBackendImplementation? implementation;
final Object? error;
final StackTrace? stackTrace;
ServerResult(this.type, {this.implementation, this.error, this.stackTrace});
AuthBackendEvent(this.type, {this.implementation, this.error, this.stackTrace});
@override
String toString() {
@@ -14,14 +14,7 @@ class ServerResult {
}
}
class ServerImplementation {
final Process? process;
final HttpServer? server;
ServerImplementation({this.process, this.server});
}
enum ServerResultType {
enum AuthBackendEventType {
starting,
startMissingHostError,
startMissingPortError,
@@ -39,9 +32,16 @@ enum ServerResultType {
stopSuccess,
stopError;
bool get isStart => name.contains("start");
bool get isStart => name.startsWith("start");
bool get isError => name.contains("Error");
bool get isError => name.endsWith("Error");
bool get isSuccess => this == ServerResultType.startSuccess || this == ServerResultType.stopSuccess;
bool get isSuccess => this == AuthBackendEventType.startSuccess || this == AuthBackendEventType.stopSuccess;
}
class AuthBackendImplementation {
final Process? process;
final HttpServer? server;
AuthBackendImplementation({this.process, this.server});
}

View File

@@ -1,4 +1,4 @@
enum ServerType {
enum AuthBackendType {
embedded,
remote,
local

View File

@@ -0,0 +1,209 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:reboot_common/common.dart';
class ServerBrowserClient {
static const String _pingEvent = 'ping';
static const String _addEvent = 'add';
static const String _removeEvent = 'remove';
static const Duration _pingInterval = const Duration(seconds: 30);
static const Duration _reconnectDelay = const Duration(seconds: 10);
static const Duration _timeout = const Duration(seconds: 10);
final String _serverUrl;
final StreamController<ServerBrowserEvent> _eventsController = StreamController.broadcast();
WebSocket? _socket;
Timer? _reconnectTimer;
Timer? _pingTimer;
Completer _pingCompleter = Completer();
ServerBrowserState _state = ServerBrowserState.disconnected;
ServerBrowserClient({required String serverUrl})
: _serverUrl = serverUrl;
Future<void> connect() async {
if (_state != ServerBrowserState.disconnected) {
return;
}
_setState(ServerBrowserState.connecting);
_reconnectTimer?.cancel();
try {
final socket = await WebSocket.connect(_serverUrl)
.timeout(_timeout);
_socket = socket;
_setState(ServerBrowserState.connected);
socket.listen(
_handleMessage,
onDone: () => _handleDisconnection(_state == ServerBrowserState.connected),
onError: (error) {
_eventsController.add(new ServerBrowserErrorEvent(
error: 'An unhandled error was thrown: $error'
));
_handleDisconnection(true);
}
);
_startHeartbeat();
} catch (e) {
_eventsController.add(new ServerBrowserErrorEvent(
error: 'Cannot connect: $e'
));
_handleDisconnection(true);
}
}
void _handleMessage(dynamic data) {
try {
final message = jsonDecode(data);
final type = message['type'];
final payload = message['data'];
switch (type) {
case _pingEvent:
if(!_pingCompleter.isCompleted) {
_pingCompleter.complete(null);
}
break;
case _addEvent:
if (payload is List) {
final entries = payload
.map((entry) => ServerBrowserEntry.fromJson(entry))
.toList(growable: false);
_eventsController.add(new ServerBrowserAddEvent(
entries: entries,
));
}else {
_eventsController.add(new ServerBrowserErrorEvent(
error: 'Invalid add event payload: ${payload?.runtimeType}'
));
}
break;
case _removeEvent:
if (payload is List) {
final entries = payload
.map((entry) => entry['id'] as String?)
.whereType<String>()
.toList(growable: false);
_eventsController.add(new ServerBrowserRemoveEvent(
entries: entries
));
}else {
_eventsController.add(new ServerBrowserErrorEvent(
error: 'Invalid remove event payload: ${payload?.runtimeType}'
));
}
break;
default:
_eventsController.add(new ServerBrowserErrorEvent(
error: 'Invalid event type: $type'
));
break;
}
} catch (error) {
_eventsController.add(new ServerBrowserErrorEvent(
error: 'An error occurred while processing an event: $error'
));
}
}
void _handleDisconnection(bool reconnect) {
_setState(ServerBrowserState.disconnected);
_cleanup();
if (reconnect) {
_reconnectTimer = Timer(_reconnectDelay, () => connect());
}
}
void _startHeartbeat() {
_pingTimer?.cancel();
_pingTimer = Timer.periodic(_pingInterval, (timer) async {
final socket = _socket;
if(socket == null || _state != ServerBrowserState.connected) {
return;
}
try {
socket.add(jsonEncode({'type': _pingEvent}));
await _pingCompleter.future
.timeout(_timeout);
_pingCompleter = Completer();
} catch (error) {
_pingCompleter = Completer();
_handleDisconnection(true);
}
});
}
void _cleanup() {
_socket?.close();
_socket = null;
_pingTimer?.cancel();
_pingTimer = null;
}
void _setState(ServerBrowserState newState) {
if (_state != newState) {
_state = newState;
_eventsController.add(ServerBrowserStateEvent(
state: newState
));
}
}
Future<bool> addEntry(ServerBrowserEntry entry) async {
if (_state != ServerBrowserState.connected) {
return false;
}
final socket = _socket;
if(socket == null) {
return false;
}
final message = {
'type': _addEvent,
'data': entry.toJson()
};
socket.add(jsonEncode(message));
return true;
}
Future<bool> removeEntry(String id) async {
if (_state != ServerBrowserState.connected) {
return false;
}
final socket = _socket;
if(socket == null) {
return false;
}
final message = {
'type': _removeEvent,
'data': id
};
socket.add(jsonEncode(message));
return true;
}
StreamSubscription<ServerBrowserEvent> addListener(void Function(ServerBrowserEvent) onData) {
return _eventsController.stream.listen(onData);
}
Future<void> disconnect() async {
_reconnectTimer?.cancel();
_cleanup();
_setState(ServerBrowserState.disconnected);
}
void dispose() {
disconnect();
_eventsController.close();
}
}

View File

@@ -1,15 +1,14 @@
class FortniteServer {
class ServerBrowserEntry {
final String id;
final String name;
final String description;
final String author;
final String ip;
final String version;
final String? password;
final String password;
final DateTime timestamp;
final bool discoverable;
FortniteServer({
ServerBrowserEntry({
required this.id,
required this.name,
required this.description,
@@ -18,10 +17,9 @@ class FortniteServer {
required this.version,
required this.password,
required this.timestamp,
required this.discoverable
});
factory FortniteServer.fromJson(json) => FortniteServer(
factory ServerBrowserEntry.fromJson(json) => ServerBrowserEntry(
id: json["id"],
name: json["name"],
description: json["description"],
@@ -29,8 +27,7 @@ class FortniteServer {
ip: json["ip"],
version: json["version"],
password: json["password"],
timestamp: json.containsKey("json") ? DateTime.parse(json["timestamp"]) : DateTime.now(),
discoverable: json["discoverable"] ?? false
timestamp: json.containsKey("json") ? DateTime.parse(json["timestamp"]) : DateTime.now()
);
Map<String, dynamic> toJson() => {
@@ -41,7 +38,6 @@ class FortniteServer {
"ip": ip,
"version": version,
"password": password,
"timestamp": timestamp.toString(),
"discoverable": discoverable
"timestamp": timestamp.toString()
};
}

View File

@@ -0,0 +1,30 @@
import 'package:reboot_common/common.dart';
import 'package:reboot_common/src/browser/server_browser_state.dart';
sealed class ServerBrowserEvent {
}
final class ServerBrowserStateEvent extends ServerBrowserEvent {
final ServerBrowserState state;
ServerBrowserStateEvent({required this.state});
}
final class ServerBrowserAddEvent extends ServerBrowserEvent {
final List<ServerBrowserEntry> entries;
ServerBrowserAddEvent({required this.entries});
}
final class ServerBrowserRemoveEvent extends ServerBrowserEvent {
final List<String> entries;
ServerBrowserRemoveEvent({required this.entries});
}
final class ServerBrowserErrorEvent extends ServerBrowserEvent {
final String error;
ServerBrowserErrorEvent({required this.error});
}

View File

@@ -0,0 +1,5 @@
enum ServerBrowserState {
disconnected,
connecting,
connected
}

View File

@@ -1,2 +0,0 @@
const String supabaseUrl = 'https://drxuhdtyigthmjfhjgfl.supabase.co';
const String supabaseAnonKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImRyeHVoZHR5aWd0aG1qZmhqZ2ZsIiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODUzMDU4NjYsImV4cCI6MjAwMDg4MTg2Nn0.unuO67xf9CZgHi-3aXmC5p3RAktUfW7WwqDY-ccFN1M';

View File

@@ -0,0 +1,64 @@
import 'dart:io';
import 'dart:isolate';
class GameBuild {
final String gameVersion;
final String link;
final bool available;
GameBuild({
required this.gameVersion,
required this.link,
required this.available
});
}
class GameBuildDownloadProgress {
final double progress;
final int? timeLeft;
final bool extracting;
final int speed;
GameBuildDownloadProgress({
required this.progress,
required this.extracting,
required this.timeLeft,
required this.speed
});
}
class GameBuildDownloadOptions {
GameBuild build;
Directory destination;
SendPort port;
GameBuildDownloadOptions(this.build, this.destination, this.port);
}
class GameBuildManifestChunk {
List<int> chunksIds;
String file;
int fileSize;
GameBuildManifestChunk._internal(this.chunksIds, this.file, this.fileSize);
factory GameBuildManifestChunk.fromJson(json) => GameBuildManifestChunk._internal(
List<int>.from(json["ChunksIds"] as List),
json["File"],
json["FileSize"]
);
}
class GameBuildManifestFile {
String name;
List<GameBuildManifestChunk> chunks;
int size;
GameBuildManifestFile._internal(this.name, this.chunks, this.size);
factory GameBuildManifestFile.fromJson(json) => GameBuildManifestFile._internal(
json["Name"],
List<GameBuildManifestChunk>.from(json["Chunks"].map((chunk) => GameBuildManifestChunk.fromJson(chunk))),
json["Size"]
);
}

View File

@@ -0,0 +1,10 @@
enum GameDll {
console,
auth,
gameServer,
memoryLeak
}
extension InjectableDllVersionAware on GameDll {
bool get isVersionDependent => this == GameDll.gameServer;
}

View File

@@ -19,107 +19,103 @@ const String kRebootBelowS20DownloadUrl =
const String kRebootAboveS20DownloadUrl =
"https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/RebootS20.zip";
const String _kRebootBelowS20FallbackDownloadUrl =
"https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootFallback.zip";
const String _kRebootAboveS20FallbackDownloadUrl =
"https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootS20Fallback.zip";
const String kStopBuildDownloadSignal = "kill";
final int _ariaPort = 6800;
final Uri _ariaEndpoint = Uri.parse('http://localhost:$_ariaPort/jsonrpc');
final Duration _ariaMaxSpawnTime = const Duration(seconds: 10);
final RegExp _rarProgressRegex = RegExp("^((100)|(\\d{1,2}(.\\d*)?))%\$");
final List<FortniteBuild> downloadableBuilds = [
FortniteBuild(gameVersion: "1.7.2", link: "https://public.simplyblk.xyz/1.7.2.zip", available: true),
FortniteBuild(gameVersion: "1.8", link: "https://public.simplyblk.xyz/1.8.rar", available: true),
FortniteBuild(gameVersion: "1.8.1", link: "https://public.simplyblk.xyz/1.8.1.rar", available: true),
FortniteBuild(gameVersion: "1.8.2", link: "https://public.simplyblk.xyz/1.8.2.rar", available: true),
FortniteBuild(gameVersion: "1.9", link: "https://public.simplyblk.xyz/1.9.rar", available: true),
FortniteBuild(gameVersion: "1.9.1", link: "https://public.simplyblk.xyz/1.9.1.rar", available: true),
FortniteBuild(gameVersion: "1.10", link: "https://public.simplyblk.xyz/1.10.rar", available: true),
FortniteBuild(gameVersion: "1.11", link: "https://public.simplyblk.xyz/1.11.zip", available: true),
FortniteBuild(gameVersion: "2.1.0", link: "https://public.simplyblk.xyz/2.1.0.zip", available: true),
FortniteBuild(gameVersion: "2.2.0", link: "https://public.simplyblk.xyz/2.2.0.rar", available: true),
FortniteBuild(gameVersion: "2.3", link: "https://public.simplyblk.xyz/2.3.rar", available: true),
FortniteBuild(gameVersion: "2.4.0", link: "https://public.simplyblk.xyz/2.4.0.zip", available: true),
FortniteBuild(gameVersion: "2.4.2", link: "https://public.simplyblk.xyz/2.4.2.zip", available: true),
FortniteBuild(gameVersion: "2.5.0", link: "https://public.simplyblk.xyz/2.5.0.rar", available: true),
FortniteBuild(gameVersion: "3.0", link: "https://public.simplyblk.xyz/3.0.zip", available: true),
FortniteBuild(gameVersion: "3.1", link: "https://public.simplyblk.xyz/3.1.rar", available: true),
FortniteBuild(gameVersion: "3.1.1", link: "https://public.simplyblk.xyz/3.1.1.zip", available: true),
FortniteBuild(gameVersion: "3.2", link: "https://public.simplyblk.xyz/3.2.zip", available: true),
FortniteBuild(gameVersion: "3.3", link: "https://public.simplyblk.xyz/3.3.rar", available: true),
FortniteBuild(gameVersion: "3.5", link: "https://public.simplyblk.xyz/3.5.rar", available: true),
FortniteBuild(gameVersion: "3.6", link: "https://public.simplyblk.xyz/3.6.zip", available: true),
FortniteBuild(gameVersion: "4.0", link: "https://public.simplyblk.xyz/4.0.zip", available: true),
FortniteBuild(gameVersion: "4.1", link: "https://public.simplyblk.xyz/4.1.zip", available: true),
FortniteBuild(gameVersion: "4.2", link: "https://public.simplyblk.xyz/4.2.zip", available: true),
FortniteBuild(gameVersion: "4.4", link: "https://public.simplyblk.xyz/4.4.rar", available: true),
FortniteBuild(gameVersion: "4.5", link: "https://public.simplyblk.xyz/4.5.rar", available: true),
FortniteBuild(gameVersion: "5.00", link: "https://public.simplyblk.xyz/5.00.rar", available: true),
FortniteBuild(gameVersion: "5.0.1", link: "https://public.simplyblk.xyz/5.0.1.rar", available: true),
FortniteBuild(gameVersion: "5.10", link: "https://public.simplyblk.xyz/5.10.rar", available: true),
FortniteBuild(gameVersion: "5.21", link: "https://public.simplyblk.xyz/5.21.rar", available: true),
FortniteBuild(gameVersion: "5.30", link: "https://public.simplyblk.xyz/5.30.rar", available: true),
FortniteBuild(gameVersion: "5.40", link: "https://public.simplyblk.xyz/5.40.rar", available: true),
FortniteBuild(gameVersion: "6.00", link: "https://public.simplyblk.xyz/6.00.rar", available: true),
FortniteBuild(gameVersion: "6.01", link: "https://public.simplyblk.xyz/6.01.rar", available: true),
FortniteBuild(gameVersion: "6.1.1", link: "https://public.simplyblk.xyz/6.1.1.rar", available: true),
FortniteBuild(gameVersion: "6.02", link: "https://public.simplyblk.xyz/6.02.rar", available: true),
FortniteBuild(gameVersion: "6.2.1", link: "https://public.simplyblk.xyz/6.2.1.rar", available: true),
FortniteBuild(gameVersion: "6.10", link: "https://public.simplyblk.xyz/6.10.rar", available: true),
FortniteBuild(gameVersion: "6.10.1", link: "https://public.simplyblk.xyz/6.10.1.rar", available: true),
FortniteBuild(gameVersion: "6.10.2", link: "https://public.simplyblk.xyz/6.10.2.rar", available: true),
FortniteBuild(gameVersion: "6.21", link: "https://public.simplyblk.xyz/6.21.rar", available: true),
FortniteBuild(gameVersion: "6.22", link: "https://public.simplyblk.xyz/6.22.rar", available: true),
FortniteBuild(gameVersion: "6.30", link: "https://public.simplyblk.xyz/6.30.rar", available: true),
FortniteBuild(gameVersion: "6.31", link: "https://public.simplyblk.xyz/6.31.rar", available: true),
FortniteBuild(gameVersion: "7.00", link: "https://public.simplyblk.xyz/7.00.rar", available: true),
FortniteBuild(gameVersion: "7.10", link: "https://public.simplyblk.xyz/7.10.rar", available: true),
FortniteBuild(gameVersion: "7.20", link: "https://public.simplyblk.xyz/7.20.rar", available: true),
FortniteBuild(gameVersion: "7.30", link: "https://public.simplyblk.xyz/7.30.zip", available: true),
FortniteBuild(gameVersion: "7.40", link: "https://public.simplyblk.xyz/7.40.rar", available: true),
FortniteBuild(gameVersion: "8.00", link: "https://public.simplyblk.xyz/8.00.zip", available: true),
FortniteBuild(gameVersion: "8.20", link: "https://public.simplyblk.xyz/8.20.rar", available: true),
FortniteBuild(gameVersion: "8.30", link: "https://public.simplyblk.xyz/8.30.rar", available: true),
FortniteBuild(gameVersion: "8.40", link: "https://public.simplyblk.xyz/8.40.zip", available: true),
FortniteBuild(gameVersion: "8.50", link: "https://public.simplyblk.xyz/8.50.zip", available: true),
FortniteBuild(gameVersion: "8.51", link: "https://public.simplyblk.xyz/8.51.rar", available: true),
FortniteBuild(gameVersion: "9.00", link: "https://public.simplyblk.xyz/9.00.zip", available: true),
FortniteBuild(gameVersion: "9.01", link: "https://public.simplyblk.xyz/9.01.zip", available: true),
FortniteBuild(gameVersion: "9.10", link: "https://public.simplyblk.xyz/9.10.rar", available: true),
FortniteBuild(gameVersion: "9.21", link: "https://public.simplyblk.xyz/9.21.zip", available: true),
FortniteBuild(gameVersion: "9.30", link: "https://public.simplyblk.xyz/9.30.zip", available: true),
FortniteBuild(gameVersion: "9.40", link: "https://public.simplyblk.xyz/9.40.zip", available: true),
FortniteBuild(gameVersion: "9.41", link: "https://public.simplyblk.xyz/9.41.rar", available: true),
FortniteBuild(gameVersion: "10.00", link: "https://public.simplyblk.xyz/10.00.zip", available: true),
FortniteBuild(gameVersion: "10.10", link: "https://public.simplyblk.xyz/10.10.zip", available: true),
FortniteBuild(gameVersion: "10.20", link: "https://public.simplyblk.xyz/10.20.zip", available: true),
FortniteBuild(gameVersion: "10.31", link: "https://public.simplyblk.xyz/10.31.zip", available: true),
FortniteBuild(gameVersion: "10.40", link: "https://public.simplyblk.xyz/10.40.rar", available: true),
FortniteBuild(gameVersion: "11.00", link: "https://public.simplyblk.xyz/11.00.zip", available: true),
FortniteBuild(gameVersion: "11.31", link: "https://public.simplyblk.xyz/11.31.rar", available: true),
FortniteBuild(gameVersion: "12.00", link: "https://public.simplyblk.xyz/12.00.rar", available: true),
FortniteBuild(gameVersion: "12.21", link: "https://public.simplyblk.xyz/12.21.zip", available: true),
FortniteBuild(gameVersion: "12.50", link: "https://public.simplyblk.xyz/12.50.zip", available: true),
FortniteBuild(gameVersion: "12.61", link: "https://public.simplyblk.xyz/12.61.zip", available: true),
FortniteBuild(gameVersion: "13.00", link: "https://public.simplyblk.xyz/13.00.rar", available: true),
FortniteBuild(gameVersion: "13.40", link: "https://public.simplyblk.xyz/13.40.zip", available: true),
FortniteBuild(gameVersion: "14.00", link: "https://public.simplyblk.xyz/14.00.rar", available: true),
FortniteBuild(gameVersion: "14.40", link: "https://public.simplyblk.xyz/14.40.rar", available: true),
FortniteBuild(gameVersion: "14.60", link: "https://public.simplyblk.xyz/14.60.rar", available: true),
FortniteBuild(gameVersion: "15.30", link: "https://public.simplyblk.xyz/15.30.rar", available: true),
FortniteBuild(gameVersion: "16.40", link: "https://public.simplyblk.xyz/16.40.rar", available: true),
FortniteBuild(gameVersion: "17.30", link: "https://public.simplyblk.xyz/17.30.zip", available: true),
FortniteBuild(gameVersion: "17.50", link: "https://public.simplyblk.xyz/17.50.zip", available: true),
FortniteBuild(gameVersion: "18.40", link: "https://public.simplyblk.xyz/18.40.zip", available: true),
FortniteBuild(gameVersion: "19.10", link: "https://public.simplyblk.xyz/19.10.rar", available: true),
FortniteBuild(gameVersion: "20.40", link: "https://public.simplyblk.xyz/20.40.zip", available: true),
final List<GameBuild> downloadableBuilds = [
GameBuild(gameVersion: "1.7.2", link: "https://builds.rebootfn.org/1.7.2.zip", available: true),
GameBuild(gameVersion: "1.8", link: "https://builds.rebootfn.org/1.8.rar", available: true),
GameBuild(gameVersion: "1.8.1", link: "https://builds.rebootfn.org/1.8.1.rar", available: true),
GameBuild(gameVersion: "1.8.2", link: "https://builds.rebootfn.org/1.8.2.rar", available: true),
GameBuild(gameVersion: "1.9", link: "https://builds.rebootfn.org/1.9.rar", available: true),
GameBuild(gameVersion: "1.9.1", link: "https://builds.rebootfn.org/1.9.1.rar", available: true),
GameBuild(gameVersion: "1.10", link: "https://builds.rebootfn.org/1.10.rar", available: true),
GameBuild(gameVersion: "1.11", link: "https://builds.rebootfn.org/1.11.zip", available: true),
GameBuild(gameVersion: "2.1.0", link: "https://builds.rebootfn.org/2.1.0.zip", available: true),
GameBuild(gameVersion: "2.2.0", link: "https://builds.rebootfn.org/2.2.0.rar", available: true),
GameBuild(gameVersion: "2.3", link: "https://builds.rebootfn.org/2.3.rar", available: true),
GameBuild(gameVersion: "2.4.0", link: "https://builds.rebootfn.org/2.4.0.zip", available: true),
GameBuild(gameVersion: "2.4.2", link: "https://builds.rebootfn.org/2.4.2.zip", available: true),
GameBuild(gameVersion: "2.5.0", link: "https://builds.rebootfn.org/2.5.0.rar", available: true),
GameBuild(gameVersion: "3.0", link: "https://builds.rebootfn.org/3.0.zip", available: true),
GameBuild(gameVersion: "3.1", link: "https://builds.rebootfn.org/3.1.rar", available: true),
GameBuild(gameVersion: "3.1.1", link: "https://builds.rebootfn.org/3.1.1.zip", available: true),
GameBuild(gameVersion: "3.2", link: "https://builds.rebootfn.org/3.2.zip", available: true),
GameBuild(gameVersion: "3.3", link: "https://builds.rebootfn.org/3.3.rar", available: true),
GameBuild(gameVersion: "3.5", link: "https://builds.rebootfn.org/3.5.rar", available: true),
GameBuild(gameVersion: "3.6", link: "https://builds.rebootfn.org/3.6.zip", available: true),
GameBuild(gameVersion: "4.0", link: "https://builds.rebootfn.org/4.0.zip", available: true),
GameBuild(gameVersion: "4.1", link: "https://builds.rebootfn.org/4.1.zip", available: true),
GameBuild(gameVersion: "4.2", link: "https://builds.rebootfn.org/4.2.zip", available: true),
GameBuild(gameVersion: "4.4", link: "https://builds.rebootfn.org/4.4.rar", available: true),
GameBuild(gameVersion: "4.5", link: "https://builds.rebootfn.org/4.5.rar", available: true),
GameBuild(gameVersion: "5.00", link: "https://builds.rebootfn.org/5.00.rar", available: true),
GameBuild(gameVersion: "5.0.1", link: "https://builds.rebootfn.org/5.0.1.rar", available: true),
GameBuild(gameVersion: "5.10", link: "https://builds.rebootfn.org/5.10.rar", available: true),
GameBuild(gameVersion: "5.21", link: "https://builds.rebootfn.org/5.21.rar", available: true),
GameBuild(gameVersion: "5.30", link: "https://builds.rebootfn.org/5.30.rar", available: true),
GameBuild(gameVersion: "5.40", link: "https://builds.rebootfn.org/5.40.rar", available: true),
GameBuild(gameVersion: "6.00", link: "https://builds.rebootfn.org/6.00.rar", available: true),
GameBuild(gameVersion: "6.01", link: "https://builds.rebootfn.org/6.01.rar", available: true),
GameBuild(gameVersion: "6.1.1", link: "https://builds.rebootfn.org/6.1.1.rar", available: true),
GameBuild(gameVersion: "6.02", link: "https://builds.rebootfn.org/6.02.rar", available: true),
GameBuild(gameVersion: "6.2.1", link: "https://builds.rebootfn.org/6.2.1.rar", available: true),
GameBuild(gameVersion: "6.10", link: "https://builds.rebootfn.org/6.10.rar", available: true),
GameBuild(gameVersion: "6.10.1", link: "https://builds.rebootfn.org/6.10.1.rar", available: true),
GameBuild(gameVersion: "6.10.2", link: "https://builds.rebootfn.org/6.10.2.rar", available: true),
GameBuild(gameVersion: "6.21", link: "https://builds.rebootfn.org/6.21.rar", available: true),
GameBuild(gameVersion: "6.22", link: "https://builds.rebootfn.org/6.22.rar", available: true),
GameBuild(gameVersion: "6.30", link: "https://builds.rebootfn.org/6.30.rar", available: true),
GameBuild(gameVersion: "6.31", link: "https://builds.rebootfn.org/6.31.rar", available: true),
GameBuild(gameVersion: "7.00", link: "https://builds.rebootfn.org/7.00.rar", available: true),
GameBuild(gameVersion: "7.10", link: "https://builds.rebootfn.org/7.10.rar", available: true),
GameBuild(gameVersion: "7.20", link: "https://builds.rebootfn.org/7.20.rar", available: true),
GameBuild(gameVersion: "7.30", link: "https://builds.rebootfn.org/7.30.zip", available: true),
GameBuild(gameVersion: "7.40", link: "https://builds.rebootfn.org/7.40.rar", available: true),
GameBuild(gameVersion: "8.00", link: "https://builds.rebootfn.org/8.00.zip", available: true),
GameBuild(gameVersion: "8.20", link: "https://builds.rebootfn.org/8.20.rar", available: true),
GameBuild(gameVersion: "8.30", link: "https://builds.rebootfn.org/8.30.rar", available: true),
GameBuild(gameVersion: "8.40", link: "https://builds.rebootfn.org/8.40.zip", available: true),
GameBuild(gameVersion: "8.50", link: "https://builds.rebootfn.org/8.50.zip", available: true),
GameBuild(gameVersion: "8.51", link: "https://builds.rebootfn.org/8.51.rar", available: true),
GameBuild(gameVersion: "9.00", link: "https://builds.rebootfn.org/9.00.zip", available: true),
GameBuild(gameVersion: "9.01", link: "https://builds.rebootfn.org/9.01.zip", available: true),
GameBuild(gameVersion: "9.10", link: "https://builds.rebootfn.org/9.10.rar", available: true),
GameBuild(gameVersion: "9.21", link: "https://builds.rebootfn.org/9.21.zip", available: true),
GameBuild(gameVersion: "9.30", link: "https://builds.rebootfn.org/9.30.zip", available: true),
GameBuild(gameVersion: "9.40", link: "https://builds.rebootfn.org/9.40.zip", available: true),
GameBuild(gameVersion: "9.41", link: "https://builds.rebootfn.org/9.41.rar", available: true),
GameBuild(gameVersion: "10.00", link: "https://builds.rebootfn.org/10.00.zip", available: true),
GameBuild(gameVersion: "10.10", link: "https://builds.rebootfn.org/10.10.zip", available: true),
GameBuild(gameVersion: "10.20", link: "https://builds.rebootfn.org/10.20.zip", available: true),
GameBuild(gameVersion: "10.31", link: "https://builds.rebootfn.org/10.31.zip", available: true),
GameBuild(gameVersion: "10.40", link: "https://builds.rebootfn.org/10.40.rar", available: false),
GameBuild(gameVersion: "11.00", link: "https://builds.rebootfn.org/11.00.zip", available: false),
GameBuild(gameVersion: "11.31", link: "https://builds.rebootfn.org/11.31.rar", available: false),
GameBuild(gameVersion: "12.00", link: "https://builds.rebootfn.org/12.00.rar", available: false),
GameBuild(gameVersion: "12.21", link: "https://builds.rebootfn.org/12.21.zip", available: false),
GameBuild(gameVersion: "Fortnite 12.41", link: "https://builds.rebootfn.org/Fortnite%2012.41.zip", available: false),
GameBuild(gameVersion: "12.50", link: "https://builds.rebootfn.org/12.50.zip", available: false),
GameBuild(gameVersion: "12.61", link: "https://builds.rebootfn.org/12.61.zip", available: false),
GameBuild(gameVersion: "13.00", link: "https://builds.rebootfn.org/13.00.rar", available: false),
GameBuild(gameVersion: "13.40", link: "https://builds.rebootfn.org/13.40.zip", available: false),
GameBuild(gameVersion: "14.00", link: "https://builds.rebootfn.org/14.00.rar", available: false),
GameBuild(gameVersion: "14.40", link: "https://builds.rebootfn.org/14.40.rar", available: false),
GameBuild(gameVersion: "14.60", link: "https://builds.rebootfn.org/14.60.rar", available: false),
GameBuild(gameVersion: "15.30", link: "https://builds.rebootfn.org/15.30.rar", available: false),
GameBuild(gameVersion: "16.40", link: "https://builds.rebootfn.org/16.40.rar", available: false),
GameBuild(gameVersion: "17.30", link: "https://builds.rebootfn.org/17.30.zip", available: false),
GameBuild(gameVersion: "17.50", link: "https://builds.rebootfn.org/17.50.zip", available: false),
GameBuild(gameVersion: "18.40", link: "https://builds.rebootfn.org/18.40.zip", available: false),
GameBuild(gameVersion: "19.10", link: "https://builds.rebootfn.org/19.10.rar", available: false),
GameBuild(gameVersion: "20.40", link: "https://builds.rebootfn.org/20.40.zip", available: false)
];
Future<void> downloadArchiveBuild(FortniteBuildDownloadOptions options) async {
Future<void> downloadArchiveBuild(GameBuildDownloadOptions options) async {
final fileName = options.build.link.substring(options.build.link.lastIndexOf("/") + 1);
final outputFile = File("${options.destination.path}\\.build\\$fileName");
Timer? timer;
@@ -259,7 +255,7 @@ Future<bool> _isAriaRunning() async {
}
}
Future<String> _startAriaDownload(FortniteBuildDownloadOptions options, File outputFile) async {
Future<String> _startAriaDownload(GameBuildDownloadOptions options, File outputFile) async {
http.Response? addDownloadResponse;
try {
final addDownloadRequestId = Uuid().toString().replaceAll("-", "");
@@ -311,7 +307,7 @@ Future<void> stopDownloadServer() async {
}
Future<void> _extractArchive(Completer<dynamic> stopped, String extension, File tempFile, FortniteBuildDownloadOptions options) async {
Future<void> _extractArchive(Completer<dynamic> stopped, String extension, File tempFile, GameBuildDownloadOptions options) async {
Process? process;
switch (extension.toLowerCase()) {
case ".zip":
@@ -437,7 +433,7 @@ Future<void> _extractArchive(Completer<dynamic> stopped, String extension, File
void _onProgress(SendPort port, double percentage, int speed, int minutesLeft, bool extracting) {
if(percentage == 0) {
port.send(FortniteBuildDownloadProgress(
port.send(GameBuildDownloadProgress(
progress: percentage,
extracting: extracting,
timeLeft: null,
@@ -446,7 +442,7 @@ void _onProgress(SendPort port, double percentage, int speed, int minutesLeft, b
return;
}
port.send(FortniteBuildDownloadProgress(
port.send(GameBuildDownloadProgress(
progress: percentage,
extracting: extracting,
timeLeft: minutesLeft,
@@ -454,13 +450,13 @@ void _onProgress(SendPort port, double percentage, int speed, int minutesLeft, b
));
}
void _onError(Object? error, FortniteBuildDownloadOptions options) {
void _onError(Object? error, GameBuildDownloadOptions options) {
if(error != null) {
options.port.send(error.toString());
}
}
Completer<dynamic> _setupLifecycle(FortniteBuildDownloadOptions options) {
Completer<dynamic> _setupLifecycle(GameBuildDownloadOptions options) {
var stopped = Completer();
var lifecyclePort = ReceivePort();
lifecyclePort.listen((message) {
@@ -473,8 +469,6 @@ Completer<dynamic> _setupLifecycle(FortniteBuildDownloadOptions options) {
return stopped;
}
Future<bool> hasRebootDllUpdate(int? lastUpdateMs, {int hours = 24, bool force = false}) async {
final lastUpdate = await _getLastUpdate(lastUpdateMs);
final exists = await rebootBeforeS20DllFile.exists() && await rebootAboveS20DllFile.exists();
@@ -482,16 +476,16 @@ Future<bool> hasRebootDllUpdate(int? lastUpdateMs, {int hours = 24, bool force =
return force || !exists || (hours > 0 && lastUpdate != null && now.difference(lastUpdate).inHours > hours);
}
Future<bool> downloadDependency(InjectableDll dll, String outputPath) async {
Future<bool> downloadDependency(GameDll dll, String outputPath) async {
String? name;
switch(dll) {
case InjectableDll.console:
case GameDll.console:
name = "console.dll";
case InjectableDll.auth:
name = "cobalt.dll";
case InjectableDll.memoryLeak:
case GameDll.auth:
name = "sinum.dll";
case GameDll.memoryLeak:
name = "memory.dll";
case InjectableDll.gameServer:
case GameDll.gameServer:
name = null;
}
if(name == null) {

View File

@@ -9,7 +9,7 @@ class GameInstance {
final int gamePid;
final int? launcherPid;
final int? eacPid;
final List<InjectableDll> injectedDlls;
final List<GameDll> injectedDlls;
final bool headless;
bool launched;
bool tokenError;

Some files were not shown because too many files have changed in this diff Show More