MCSI-20 feat: write the start script

This commit is contained in:
SquidSpirit 2025-07-10 23:07:05 +08:00
parent 23871c8206
commit d590e033c1
9 changed files with 44 additions and 11 deletions

View File

@ -2,4 +2,6 @@ import 'dart:typed_data';
abstract interface class InstallationFileStorage {
Future<void> saveFile(Uint8List fileBytes, String path);
Future<void> writeFile(String path, String content);
}

View File

@ -9,8 +9,11 @@ class InstallationRepositoryImpl implements InstallationRepository {
InstallationRepositoryImpl(this._apiService, this._fileStorage);
@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);
await _fileStorage.saveFile(fileBytes, path);
}
@override
Future<void> writeFile(String path, String content) => _fileStorage.writeFile(path, content);
}

View File

@ -2,12 +2,16 @@ 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/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/write_file_use_case.dart';
import 'package:minecraft_server_installer/main/constants.dart';
import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart';
import 'package:path/path.dart' as path;
class InstallationBloc extends Bloc<InstallationEvent, InstallationState> {
InstallationBloc(DownloadFileUseCase downloadFileUseCase) : super(const InstallationState.empty()) {
InstallationBloc(
DownloadFileUseCase downloadFileUseCase,
WriteFileUseCase writeFileUseCase,
) : super(const InstallationState.empty()) {
on<InstallationStartedEvent>((_, emit) async {
if (!state.canStartToInstall) {
return;
@ -24,6 +28,11 @@ class InstallationBloc extends Bloc<InstallationEvent, InstallationState> {
onProgressChanged: (progressValue) => add(_InstallationProgressValueChangedEvent(progressValue)),
);
await writeFileUseCase(
path.join(savePath, Constants.startScriptFileName),
'java -jar ${Constants.serverFileName}\n',
);
emit(state.copyWith(isLocked: false, downloadProgress: const ProgressViewModel.complete()));
});

View File

@ -1,5 +1,7 @@
typedef DownloadProgressCallback = void Function(double progress);
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);
}

View File

@ -6,5 +6,5 @@ class DownloadFileUseCase {
DownloadFileUseCase(this._installationRepository);
Future<void> call(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) =>
_installationRepository.downloadServerFile(url, path, onProgressChanged: onProgressChanged);
_installationRepository.downloadFile(url, path, onProgressChanged: onProgressChanged);
}

View 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);
}

View File

@ -1,4 +1,8 @@
import 'dart:io';
abstract class Constants {
static const gameVersionListUrl = 'https://www.dropbox.com/s/mtz3moc9dpjtz7s/GameVersions.txt?dl=1';
static const serverFileName = 'server.jar';
static final startScriptFileName = Platform.isWindows ? 'start.bat' : 'start.sh';
}

View File

@ -7,12 +7,14 @@ class InstallationFileStorageImpl implements InstallationFileStorage {
@override
Future<void> saveFile(Uint8List fileBytes, String path) async {
final file = File(path);
if (!await file.parent.exists()) {
await file.parent.create(recursive: true);
}
await file.create();
await file.create(recursive: true, exclusive: false);
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);
}
}

View File

@ -4,6 +4,7 @@ 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_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/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/storage/installation_file_storage_impl.dart';
import 'package:minecraft_server_installer/main/framework/ui/basic_configuration_tab.dart';
@ -28,6 +29,7 @@ class MinecraftServerInstaller extends StatelessWidget {
final gameVersionRepository = VanillaRepositoryImpl(gameVersionApiService);
final downloadFileUseCase = DownloadFileUseCase(installationRepository);
final writeFileUseCase = WriteFileUseCase(installationRepository);
final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository);
return MaterialApp(
@ -35,7 +37,7 @@ class MinecraftServerInstaller extends StatelessWidget {
theme: ThemeData.light().copyWith(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade900)),
home: MultiBlocProvider(
providers: [
BlocProvider(create: (_) => InstallationBloc(downloadFileUseCase)),
BlocProvider(create: (_) => InstallationBloc(downloadFileUseCase, writeFileUseCase)),
BlocProvider<VanillaBloc>(
create: (_) => VanillaBloc(getGameVersionListUseCase)..add(VanillaGameVersionListLoadedEvent()),
),