mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 03:02:22 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70d83dc1c5 | ||
|
|
d53a577f0b | ||
|
|
c9ed6a5af3 | ||
|
|
4ea73d17c7 | ||
|
|
52abf5eb95 |
@@ -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/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';
|
||||
export 'package:reboot_common/src/util/log.dart';
|
||||
export 'package:reboot_common/src/util/game.dart';
|
||||
export 'package:reboot_common/src/util/extensions.dart';
|
||||
@@ -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;
|
||||
@@ -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});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
enum ServerType {
|
||||
enum AuthBackendType {
|
||||
embedded,
|
||||
remote,
|
||||
local
|
||||
209
common/lib/src/browser/server_browser_client.dart
Normal file
209
common/lib/src/browser/server_browser_client.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
}
|
||||
30
common/lib/src/browser/server_browser_event.dart
Normal file
30
common/lib/src/browser/server_browser_event.dart
Normal 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});
|
||||
}
|
||||
5
common/lib/src/browser/server_browser_state.dart
Normal file
5
common/lib/src/browser/server_browser_state.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
enum ServerBrowserState {
|
||||
disconnected,
|
||||
connecting,
|
||||
connected
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
const String supabaseUrl = 'https://drxuhdtyigthmjfhjgfl.supabase.co';
|
||||
const String supabaseAnonKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImRyeHVoZHR5aWd0aG1qZmhqZ2ZsIiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODUzMDU4NjYsImV4cCI6MjAwMDg4MTg2Nn0.unuO67xf9CZgHi-3aXmC5p3RAktUfW7WwqDY-ccFN1M';
|
||||
64
common/lib/src/game/game_build.dart
Normal file
64
common/lib/src/game/game_build.dart
Normal 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"]
|
||||
);
|
||||
}
|
||||
10
common/lib/src/game/game_dll.dart
Normal file
10
common/lib/src/game/game_dll.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
enum GameDll {
|
||||
console,
|
||||
auth,
|
||||
gameServer,
|
||||
memoryLeak
|
||||
}
|
||||
|
||||
extension InjectableDllVersionAware on GameDll {
|
||||
bool get isVersionDependent => this == GameDll.gameServer;
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -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
Reference in New Issue
Block a user