MCSI-20 Generate a server starting script #22
@ -2,4 +2,8 @@ import 'dart:typed_data';
|
|||||||
|
|
||||||
abstract interface class InstallationFileStorage {
|
abstract interface class InstallationFileStorage {
|
||||||
Future<void> saveFile(Uint8List fileBytes, String path);
|
Future<void> saveFile(Uint8List fileBytes, String path);
|
||||||
|
|
||||||
|
Future<void> writeFile(String path, String content);
|
||||||
|
|
||||||
|
Future<void> grantFileExecutePermission(String path);
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,16 @@ class InstallationRepositoryImpl implements InstallationRepository {
|
|||||||
InstallationRepositoryImpl(this._apiService, this._fileStorage);
|
InstallationRepositoryImpl(this._apiService, this._fileStorage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> downloadServerFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) async {
|
Future<void> downloadFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) async {
|
||||||
final fileBytes = await _apiService.fetchRemoteFile(url, onProgressChanged: onProgressChanged);
|
final fileBytes = await _apiService.fetchRemoteFile(url, onProgressChanged: onProgressChanged);
|
||||||
await _fileStorage.saveFile(fileBytes, path);
|
await _fileStorage.saveFile(fileBytes, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> writeFile(String path, String content) => _fileStorage.writeFile(path, content);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> grantFileExecutePermission(String path) {
|
||||||
|
return _fileStorage.grantFileExecutePermission(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
||||||
import 'package:minecraft_server_installer/main/adapter/presentation/progress_view_model.dart';
|
import 'package:minecraft_server_installer/main/adapter/presentation/progress_view_model.dart';
|
||||||
import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.dart';
|
import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/application/use_case/grant_file_permission_use_case.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/application/use_case/write_file_use_case.dart';
|
||||||
import 'package:minecraft_server_installer/main/constants.dart';
|
import 'package:minecraft_server_installer/main/constants.dart';
|
||||||
import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart';
|
import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
class InstallationBloc extends Bloc<InstallationEvent, InstallationState> {
|
class InstallationBloc extends Bloc<InstallationEvent, InstallationState> {
|
||||||
InstallationBloc(DownloadFileUseCase downloadFileUseCase) : super(const InstallationState.empty()) {
|
InstallationBloc(
|
||||||
|
DownloadFileUseCase downloadFileUseCase,
|
||||||
|
WriteFileUseCase writeFileUseCase,
|
||||||
|
GrantFilePermissionUseCase grantFilePermissionUseCase,
|
||||||
|
) : super(const InstallationState.empty()) {
|
||||||
on<InstallationStartedEvent>((_, emit) async {
|
on<InstallationStartedEvent>((_, emit) async {
|
||||||
if (!state.canStartToInstall) {
|
if (!state.canStartToInstall) {
|
||||||
return;
|
return;
|
||||||
@ -24,6 +32,13 @@ class InstallationBloc extends Bloc<InstallationEvent, InstallationState> {
|
|||||||
onProgressChanged: (progressValue) => add(_InstallationProgressValueChangedEvent(progressValue)),
|
onProgressChanged: (progressValue) => add(_InstallationProgressValueChangedEvent(progressValue)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final startScriptFilePath = path.join(savePath, Constants.startScriptFileName);
|
||||||
|
final startScriptContent = Platform.isWindows
|
||||||
|
? 'java -jar .\\${Constants.serverFileName}\r\n'
|
||||||
|
: 'java -jar ./${Constants.serverFileName}\n';
|
||||||
|
await writeFileUseCase(startScriptFilePath, startScriptContent);
|
||||||
|
await grantFilePermissionUseCase(startScriptFilePath);
|
||||||
|
|
||||||
emit(state.copyWith(isLocked: false, downloadProgress: const ProgressViewModel.complete()));
|
emit(state.copyWith(isLocked: false, downloadProgress: const ProgressViewModel.complete()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
typedef DownloadProgressCallback = void Function(double progress);
|
typedef DownloadProgressCallback = void Function(double progress);
|
||||||
|
|
||||||
abstract interface class InstallationRepository {
|
abstract interface class InstallationRepository {
|
||||||
Future<void> downloadServerFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged});
|
Future<void> downloadFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged});
|
||||||
|
|
||||||
|
Future<void> writeFile(String path, String content);
|
||||||
|
|
||||||
|
Future<void> grantFileExecutePermission(String path);
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,5 @@ class DownloadFileUseCase {
|
|||||||
DownloadFileUseCase(this._installationRepository);
|
DownloadFileUseCase(this._installationRepository);
|
||||||
|
|
||||||
Future<void> call(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) =>
|
Future<void> call(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) =>
|
||||||
_installationRepository.downloadServerFile(url, path, onProgressChanged: onProgressChanged);
|
_installationRepository.downloadFile(url, path, onProgressChanged: onProgressChanged);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart';
|
||||||
|
|
||||||
|
class GrantFilePermissionUseCase {
|
||||||
|
final InstallationRepository _installationRepository;
|
||||||
|
|
||||||
|
GrantFilePermissionUseCase(this._installationRepository);
|
||||||
|
|
||||||
|
Future<void> call(String path) => _installationRepository.grantFileExecutePermission(path);
|
||||||
|
}
|
9
lib/main/application/use_case/write_file_use_case.dart
Normal file
9
lib/main/application/use_case/write_file_use_case.dart
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart';
|
||||||
|
|
||||||
|
class WriteFileUseCase {
|
||||||
|
final InstallationRepository _installationRepository;
|
||||||
|
|
||||||
|
WriteFileUseCase(this._installationRepository);
|
||||||
|
|
||||||
|
Future<void> call(String path, String content) => _installationRepository.writeFile(path, content);
|
||||||
|
}
|
@ -1,4 +1,8 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
abstract class Constants {
|
abstract class Constants {
|
||||||
static const gameVersionListUrl = 'https://www.dropbox.com/s/mtz3moc9dpjtz7s/GameVersions.txt?dl=1';
|
static const gameVersionListUrl = 'https://www.dropbox.com/s/mtz3moc9dpjtz7s/GameVersions.txt?dl=1';
|
||||||
static const serverFileName = 'server.jar';
|
static const serverFileName = 'server.jar';
|
||||||
|
|
||||||
|
static final startScriptFileName = Platform.isWindows ? 'start.bat' : 'start.sh';
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,26 @@ class InstallationFileStorageImpl implements InstallationFileStorage {
|
|||||||
@override
|
@override
|
||||||
Future<void> saveFile(Uint8List fileBytes, String path) async {
|
Future<void> saveFile(Uint8List fileBytes, String path) async {
|
||||||
final file = File(path);
|
final file = File(path);
|
||||||
|
await file.create(recursive: true, exclusive: false);
|
||||||
if (!await file.parent.exists()) {
|
|
||||||
await file.parent.create(recursive: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
await file.create();
|
|
||||||
await file.writeAsBytes(fileBytes, flush: true);
|
await file.writeAsBytes(fileBytes, flush: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> writeFile(String path, String content) async {
|
||||||
|
File file = File(path);
|
||||||
|
await file.create(recursive: true, exclusive: false);
|
||||||
|
await file.writeAsString(content, flush: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> grantFileExecutePermission(String path) async {
|
||||||
|
File file = File(path);
|
||||||
|
await file.create(recursive: true, exclusive: false);
|
||||||
|
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
await Process.run('icacls', [path, '/grant', '%USERNAME%:(RX)']);
|
||||||
|
} else {
|
||||||
|
await Process.run('chmod', ['+x', path]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import 'package:minecraft_server_installer/main/adapter/gateway/installation_rep
|
|||||||
import 'package:minecraft_server_installer/main/adapter/presentation/installation_bloc.dart';
|
import 'package:minecraft_server_installer/main/adapter/presentation/installation_bloc.dart';
|
||||||
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
||||||
import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.dart';
|
import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/application/use_case/grant_file_permission_use_case.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/application/use_case/write_file_use_case.dart';
|
||||||
import 'package:minecraft_server_installer/main/framework/api/installation_api_service_impl.dart';
|
import 'package:minecraft_server_installer/main/framework/api/installation_api_service_impl.dart';
|
||||||
import 'package:minecraft_server_installer/main/framework/storage/installation_file_storage_impl.dart';
|
import 'package:minecraft_server_installer/main/framework/storage/installation_file_storage_impl.dart';
|
||||||
import 'package:minecraft_server_installer/main/framework/ui/basic_configuration_tab.dart';
|
import 'package:minecraft_server_installer/main/framework/ui/basic_configuration_tab.dart';
|
||||||
@ -28,6 +30,8 @@ class MinecraftServerInstaller extends StatelessWidget {
|
|||||||
final gameVersionRepository = VanillaRepositoryImpl(gameVersionApiService);
|
final gameVersionRepository = VanillaRepositoryImpl(gameVersionApiService);
|
||||||
|
|
||||||
final downloadFileUseCase = DownloadFileUseCase(installationRepository);
|
final downloadFileUseCase = DownloadFileUseCase(installationRepository);
|
||||||
|
final writeFileUseCase = WriteFileUseCase(installationRepository);
|
||||||
|
final grantFilePermissionUseCase = GrantFilePermissionUseCase(installationRepository);
|
||||||
final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository);
|
final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository);
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
@ -35,7 +39,13 @@ class MinecraftServerInstaller extends StatelessWidget {
|
|||||||
theme: ThemeData.light().copyWith(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade900)),
|
theme: ThemeData.light().copyWith(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade900)),
|
||||||
home: MultiBlocProvider(
|
home: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(create: (_) => InstallationBloc(downloadFileUseCase)),
|
BlocProvider(
|
||||||
|
create: (_) => InstallationBloc(
|
||||||
|
downloadFileUseCase,
|
||||||
|
writeFileUseCase,
|
||||||
|
grantFilePermissionUseCase,
|
||||||
|
),
|
||||||
|
),
|
||||||
BlocProvider<VanillaBloc>(
|
BlocProvider<VanillaBloc>(
|
||||||
create: (_) => VanillaBloc(getGameVersionListUseCase)..add(VanillaGameVersionListLoadedEvent()),
|
create: (_) => VanillaBloc(getGameVersionListUseCase)..add(VanillaGameVersionListLoadedEvent()),
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user