mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-02-06 15:10:20 +00:00
feat: use unp4k_rs
This commit is contained in:
@@ -6,10 +6,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
|
||||
class BinaryModuleConf {
|
||||
static const _modules = {
|
||||
"aria2c": "0",
|
||||
"unp4kc": "1",
|
||||
};
|
||||
static const _modules = {"aria2c": "0"};
|
||||
|
||||
static Future extractModule(List<String> modules, String workingDir) async {
|
||||
for (var m in _modules.entries) {
|
||||
@@ -18,11 +15,8 @@ class BinaryModuleConf {
|
||||
final version = m.value;
|
||||
final dir = "$workingDir\\$name";
|
||||
final versionFile = File("$dir\\version");
|
||||
if (kReleaseMode &&
|
||||
await versionFile.exists() &&
|
||||
(await versionFile.readAsString()).trim() == version) {
|
||||
dPrint(
|
||||
"BinaryModuleConf.extractModule skip $name version == $version");
|
||||
if (kReleaseMode && await versionFile.exists() && (await versionFile.readAsString()).trim() == version) {
|
||||
dPrint("BinaryModuleConf.extractModule skip $name version == $version");
|
||||
continue;
|
||||
}
|
||||
// write model file
|
||||
|
||||
50
lib/common/rust/api/unp4k_api.dart
Normal file
50
lib/common/rust/api/unp4k_api.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||
part 'unp4k_api.freezed.dart';
|
||||
|
||||
/// 打开 P4K 文件
|
||||
Future<BigInt> p4KOpen({required String p4KPath}) =>
|
||||
RustLib.instance.api.crateApiUnp4KApiP4KOpen(p4KPath: p4KPath);
|
||||
|
||||
/// 获取所有文件列表
|
||||
Future<List<P4kFileItem>> p4KGetAllFiles() =>
|
||||
RustLib.instance.api.crateApiUnp4KApiP4KGetAllFiles();
|
||||
|
||||
/// 获取指定目录下的文件列表
|
||||
Future<List<P4kFileItem>> p4KGetFilesInDirectory({required String directory}) =>
|
||||
RustLib.instance.api.crateApiUnp4KApiP4KGetFilesInDirectory(
|
||||
directory: directory,
|
||||
);
|
||||
|
||||
/// 提取文件到内存
|
||||
Future<Uint8List> p4KExtractToMemory({required String filePath}) =>
|
||||
RustLib.instance.api.crateApiUnp4KApiP4KExtractToMemory(filePath: filePath);
|
||||
|
||||
/// 提取文件到磁盘
|
||||
Future<void> p4KExtractToDisk({
|
||||
required String filePath,
|
||||
required String outputPath,
|
||||
}) => RustLib.instance.api.crateApiUnp4KApiP4KExtractToDisk(
|
||||
filePath: filePath,
|
||||
outputPath: outputPath,
|
||||
);
|
||||
|
||||
/// 关闭 P4K 读取器
|
||||
Future<void> p4KClose() => RustLib.instance.api.crateApiUnp4KApiP4KClose();
|
||||
|
||||
/// P4K 文件项信息
|
||||
@freezed
|
||||
sealed class P4kFileItem with _$P4kFileItem {
|
||||
const factory P4kFileItem({
|
||||
required String name,
|
||||
required bool isDirectory,
|
||||
required BigInt size,
|
||||
required BigInt compressedSize,
|
||||
}) = _P4kFileItem;
|
||||
}
|
||||
274
lib/common/rust/api/unp4k_api.freezed.dart
Normal file
274
lib/common/rust/api/unp4k_api.freezed.dart
Normal file
@@ -0,0 +1,274 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'unp4k_api.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$P4kFileItem {
|
||||
|
||||
String get name; bool get isDirectory; BigInt get size; BigInt get compressedSize;
|
||||
/// Create a copy of P4kFileItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$P4kFileItemCopyWith<P4kFileItem> get copyWith => _$P4kFileItemCopyWithImpl<P4kFileItem>(this as P4kFileItem, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is P4kFileItem&&(identical(other.name, name) || other.name == name)&&(identical(other.isDirectory, isDirectory) || other.isDirectory == isDirectory)&&(identical(other.size, size) || other.size == size)&&(identical(other.compressedSize, compressedSize) || other.compressedSize == compressedSize));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,name,isDirectory,size,compressedSize);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'P4kFileItem(name: $name, isDirectory: $isDirectory, size: $size, compressedSize: $compressedSize)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $P4kFileItemCopyWith<$Res> {
|
||||
factory $P4kFileItemCopyWith(P4kFileItem value, $Res Function(P4kFileItem) _then) = _$P4kFileItemCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String name, bool isDirectory, BigInt size, BigInt compressedSize
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$P4kFileItemCopyWithImpl<$Res>
|
||||
implements $P4kFileItemCopyWith<$Res> {
|
||||
_$P4kFileItemCopyWithImpl(this._self, this._then);
|
||||
|
||||
final P4kFileItem _self;
|
||||
final $Res Function(P4kFileItem) _then;
|
||||
|
||||
/// Create a copy of P4kFileItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? name = null,Object? isDirectory = null,Object? size = null,Object? compressedSize = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String,isDirectory: null == isDirectory ? _self.isDirectory : isDirectory // ignore: cast_nullable_to_non_nullable
|
||||
as bool,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
||||
as BigInt,compressedSize: null == compressedSize ? _self.compressedSize : compressedSize // ignore: cast_nullable_to_non_nullable
|
||||
as BigInt,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [P4kFileItem].
|
||||
extension P4kFileItemPatterns on P4kFileItem {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _P4kFileItem value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _P4kFileItem() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _P4kFileItem value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _P4kFileItem():
|
||||
return $default(_that);}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _P4kFileItem value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _P4kFileItem() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String name, bool isDirectory, BigInt size, BigInt compressedSize)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _P4kFileItem() when $default != null:
|
||||
return $default(_that.name,_that.isDirectory,_that.size,_that.compressedSize);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String name, bool isDirectory, BigInt size, BigInt compressedSize) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _P4kFileItem():
|
||||
return $default(_that.name,_that.isDirectory,_that.size,_that.compressedSize);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String name, bool isDirectory, BigInt size, BigInt compressedSize)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _P4kFileItem() when $default != null:
|
||||
return $default(_that.name,_that.isDirectory,_that.size,_that.compressedSize);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _P4kFileItem implements P4kFileItem {
|
||||
const _P4kFileItem({required this.name, required this.isDirectory, required this.size, required this.compressedSize});
|
||||
|
||||
|
||||
@override final String name;
|
||||
@override final bool isDirectory;
|
||||
@override final BigInt size;
|
||||
@override final BigInt compressedSize;
|
||||
|
||||
/// Create a copy of P4kFileItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$P4kFileItemCopyWith<_P4kFileItem> get copyWith => __$P4kFileItemCopyWithImpl<_P4kFileItem>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _P4kFileItem&&(identical(other.name, name) || other.name == name)&&(identical(other.isDirectory, isDirectory) || other.isDirectory == isDirectory)&&(identical(other.size, size) || other.size == size)&&(identical(other.compressedSize, compressedSize) || other.compressedSize == compressedSize));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,name,isDirectory,size,compressedSize);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'P4kFileItem(name: $name, isDirectory: $isDirectory, size: $size, compressedSize: $compressedSize)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$P4kFileItemCopyWith<$Res> implements $P4kFileItemCopyWith<$Res> {
|
||||
factory _$P4kFileItemCopyWith(_P4kFileItem value, $Res Function(_P4kFileItem) _then) = __$P4kFileItemCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String name, bool isDirectory, BigInt size, BigInt compressedSize
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$P4kFileItemCopyWithImpl<$Res>
|
||||
implements _$P4kFileItemCopyWith<$Res> {
|
||||
__$P4kFileItemCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _P4kFileItem _self;
|
||||
final $Res Function(_P4kFileItem) _then;
|
||||
|
||||
/// Create a copy of P4kFileItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? name = null,Object? isDirectory = null,Object? size = null,Object? compressedSize = null,}) {
|
||||
return _then(_P4kFileItem(
|
||||
name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String,isDirectory: null == isDirectory ? _self.isDirectory : isDirectory // ignore: cast_nullable_to_non_nullable
|
||||
as bool,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
||||
as BigInt,compressedSize: null == compressedSize ? _self.compressedSize : compressedSize // ignore: cast_nullable_to_non_nullable
|
||||
as BigInt,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -7,6 +7,7 @@ import 'api/asar_api.dart';
|
||||
import 'api/http_api.dart';
|
||||
import 'api/ort_api.dart';
|
||||
import 'api/rs_process.dart';
|
||||
import 'api/unp4k_api.dart';
|
||||
import 'api/win32_api.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
@@ -69,7 +70,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
||||
String get codegenVersion => '2.11.1';
|
||||
|
||||
@override
|
||||
int get rustContentHash => -518970253;
|
||||
int get rustContentHash => -737964996;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig =
|
||||
ExternalLibraryLoaderConfig(
|
||||
@@ -119,6 +120,25 @@ abstract class RustLibApi extends BaseApi {
|
||||
required bool useXnnpack,
|
||||
});
|
||||
|
||||
Future<void> crateApiUnp4KApiP4KClose();
|
||||
|
||||
Future<void> crateApiUnp4KApiP4KExtractToDisk({
|
||||
required String filePath,
|
||||
required String outputPath,
|
||||
});
|
||||
|
||||
Future<Uint8List> crateApiUnp4KApiP4KExtractToMemory({
|
||||
required String filePath,
|
||||
});
|
||||
|
||||
Future<List<P4kFileItem>> crateApiUnp4KApiP4KGetAllFiles();
|
||||
|
||||
Future<List<P4kFileItem>> crateApiUnp4KApiP4KGetFilesInDirectory({
|
||||
required String directory,
|
||||
});
|
||||
|
||||
Future<BigInt> crateApiUnp4KApiP4KOpen({required String p4KPath});
|
||||
|
||||
Future<void> crateApiAsarApiRsiLauncherAsarDataWriteMainJs({
|
||||
required RsiLauncherAsarData that,
|
||||
required List<int> content,
|
||||
@@ -456,6 +476,163 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["modelPath", "modelKey", "quantizationSuffix", "useXnnpack"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiUnp4KApiP4KClose() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__unp4k_api__p4k_close(port_);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiP4KCloseConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KCloseConstMeta =>
|
||||
const TaskConstMeta(debugName: "p4k_close", argNames: []);
|
||||
|
||||
@override
|
||||
Future<void> crateApiUnp4KApiP4KExtractToDisk({
|
||||
required String filePath,
|
||||
required String outputPath,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(filePath);
|
||||
var arg1 = cst_encode_String(outputPath);
|
||||
return wire.wire__crate__api__unp4k_api__p4k_extract_to_disk(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiP4KExtractToDiskConstMeta,
|
||||
argValues: [filePath, outputPath],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KExtractToDiskConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "p4k_extract_to_disk",
|
||||
argNames: ["filePath", "outputPath"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Uint8List> crateApiUnp4KApiP4KExtractToMemory({
|
||||
required String filePath,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(filePath);
|
||||
return wire.wire__crate__api__unp4k_api__p4k_extract_to_memory(
|
||||
port_,
|
||||
arg0,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_list_prim_u_8_strict,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiP4KExtractToMemoryConstMeta,
|
||||
argValues: [filePath],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KExtractToMemoryConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "p4k_extract_to_memory",
|
||||
argNames: ["filePath"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<List<P4kFileItem>> crateApiUnp4KApiP4KGetAllFiles() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__unp4k_api__p4k_get_all_files(port_);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_list_p_4_k_file_item,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiP4KGetAllFilesConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KGetAllFilesConstMeta =>
|
||||
const TaskConstMeta(debugName: "p4k_get_all_files", argNames: []);
|
||||
|
||||
@override
|
||||
Future<List<P4kFileItem>> crateApiUnp4KApiP4KGetFilesInDirectory({
|
||||
required String directory,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(directory);
|
||||
return wire.wire__crate__api__unp4k_api__p4k_get_files_in_directory(
|
||||
port_,
|
||||
arg0,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_list_p_4_k_file_item,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiP4KGetFilesInDirectoryConstMeta,
|
||||
argValues: [directory],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KGetFilesInDirectoryConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "p4k_get_files_in_directory",
|
||||
argNames: ["directory"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<BigInt> crateApiUnp4KApiP4KOpen({required String p4KPath}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(p4KPath);
|
||||
return wire.wire__crate__api__unp4k_api__p4k_open(port_, arg0);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_usize,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiP4KOpenConstMeta,
|
||||
argValues: [p4KPath],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KOpenConstMeta =>
|
||||
const TaskConstMeta(debugName: "p4k_open", argNames: ["p4KPath"]);
|
||||
|
||||
@override
|
||||
Future<void> crateApiAsarApiRsiLauncherAsarDataWriteMainJs({
|
||||
required RsiLauncherAsarData that,
|
||||
@@ -820,6 +997,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return (raw as List<dynamic>).map(dco_decode_String).toList();
|
||||
}
|
||||
|
||||
@protected
|
||||
List<P4kFileItem> dco_decode_list_p_4_k_file_item(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return (raw as List<dynamic>).map(dco_decode_p_4_k_file_item).toList();
|
||||
}
|
||||
|
||||
@protected
|
||||
List<int> dco_decode_list_prim_u_8_loose(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -886,6 +1069,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return raw == null ? null : dco_decode_list_prim_u_8_strict(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
P4kFileItem dco_decode_p_4_k_file_item(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
final arr = raw as List<dynamic>;
|
||||
if (arr.length != 4)
|
||||
throw Exception('unexpected arr length: expect 4 but see ${arr.length}');
|
||||
return P4kFileItem(
|
||||
name: dco_decode_String(arr[0]),
|
||||
isDirectory: dco_decode_bool(arr[1]),
|
||||
size: dco_decode_u_64(arr[2]),
|
||||
compressedSize: dco_decode_u_64(arr[3]),
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
ProcessInfo dco_decode_process_info(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -988,6 +1185,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return;
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_usize(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return dcoDecodeU64(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1064,6 +1267,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return ans_;
|
||||
}
|
||||
|
||||
@protected
|
||||
List<P4kFileItem> sse_decode_list_p_4_k_file_item(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
var len_ = sse_decode_i_32(deserializer);
|
||||
var ans_ = <P4kFileItem>[];
|
||||
for (var idx_ = 0; idx_ < len_; ++idx_) {
|
||||
ans_.add(sse_decode_p_4_k_file_item(deserializer));
|
||||
}
|
||||
return ans_;
|
||||
}
|
||||
|
||||
@protected
|
||||
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1175,6 +1392,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
P4kFileItem sse_decode_p_4_k_file_item(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var var_name = sse_decode_String(deserializer);
|
||||
var var_isDirectory = sse_decode_bool(deserializer);
|
||||
var var_size = sse_decode_u_64(deserializer);
|
||||
var var_compressedSize = sse_decode_u_64(deserializer);
|
||||
return P4kFileItem(
|
||||
name: var_name,
|
||||
isDirectory: var_isDirectory,
|
||||
size: var_size,
|
||||
compressedSize: var_compressedSize,
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
ProcessInfo sse_decode_process_info(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1283,6 +1515,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_usize(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
return deserializer.buffer.getBigUint64();
|
||||
}
|
||||
|
||||
@protected
|
||||
bool cst_encode_bool(bool raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
@@ -1423,6 +1661,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_list_p_4_k_file_item(
|
||||
List<P4kFileItem> self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_i_32(self.length, serializer);
|
||||
for (final item in self) {
|
||||
sse_encode_p_4_k_file_item(item, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_list_prim_u_8_loose(
|
||||
List<int> self,
|
||||
@@ -1540,6 +1790,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_p_4_k_file_item(P4kFileItem self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_String(self.name, serializer);
|
||||
sse_encode_bool(self.isDirectory, serializer);
|
||||
sse_encode_u_64(self.size, serializer);
|
||||
sse_encode_u_64(self.compressedSize, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_process_info(ProcessInfo self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1632,4 +1891,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
void sse_encode_unit(void self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_usize(BigInt self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
serializer.buffer.putBigUint64(self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'api/asar_api.dart';
|
||||
import 'api/http_api.dart';
|
||||
import 'api/ort_api.dart';
|
||||
import 'api/rs_process.dart';
|
||||
import 'api/unp4k_api.dart';
|
||||
import 'api/win32_api.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
@@ -56,6 +57,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
List<String> dco_decode_list_String(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<P4kFileItem> dco_decode_list_p_4_k_file_item(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<int> dco_decode_list_prim_u_8_loose(dynamic raw);
|
||||
|
||||
@@ -89,6 +93,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw);
|
||||
|
||||
@protected
|
||||
P4kFileItem dco_decode_p_4_k_file_item(dynamic raw);
|
||||
|
||||
@protected
|
||||
ProcessInfo dco_decode_process_info(dynamic raw);
|
||||
|
||||
@@ -122,6 +129,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void dco_decode_unit(dynamic raw);
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_usize(dynamic raw);
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
|
||||
|
||||
@@ -159,6 +169,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
List<String> sse_decode_list_String(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<P4kFileItem> sse_decode_list_p_4_k_file_item(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer);
|
||||
|
||||
@@ -196,6 +211,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
P4kFileItem sse_decode_p_4_k_file_item(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
ProcessInfo sse_decode_process_info(SseDeserializer deserializer);
|
||||
|
||||
@@ -237,6 +255,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_decode_unit(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_usize(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> cst_encode_AnyhowException(
|
||||
AnyhowException raw,
|
||||
@@ -307,6 +328,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
return ans;
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<wire_cst_list_p_4_k_file_item> cst_encode_list_p_4_k_file_item(
|
||||
List<P4kFileItem> raw,
|
||||
) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
final ans = wire.cst_new_list_p_4_k_file_item(raw.length);
|
||||
for (var i = 0; i < raw.length; ++i) {
|
||||
cst_api_fill_to_wire_p_4_k_file_item(raw[i], ans.ref.ptr[i]);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_loose> cst_encode_list_prim_u_8_loose(
|
||||
List<int> raw,
|
||||
@@ -390,6 +423,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
return raw.toSigned(64).toInt();
|
||||
}
|
||||
|
||||
@protected
|
||||
int cst_encode_usize(BigInt raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
return raw.toSigned(64).toInt();
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_box_autoadd_rsi_launcher_asar_data(
|
||||
RsiLauncherAsarData apiObj,
|
||||
@@ -398,6 +437,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
cst_api_fill_to_wire_rsi_launcher_asar_data(apiObj, wireObj.ref);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_p_4_k_file_item(
|
||||
P4kFileItem apiObj,
|
||||
wire_cst_p_4_k_file_item wireObj,
|
||||
) {
|
||||
wireObj.name = cst_encode_String(apiObj.name);
|
||||
wireObj.is_directory = cst_encode_bool(apiObj.isDirectory);
|
||||
wireObj.size = cst_encode_u_64(apiObj.size);
|
||||
wireObj.compressed_size = cst_encode_u_64(apiObj.compressedSize);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_process_info(
|
||||
ProcessInfo apiObj,
|
||||
@@ -524,6 +574,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_encode_list_String(List<String> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_p_4_k_file_item(
|
||||
List<P4kFileItem> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer);
|
||||
|
||||
@@ -572,6 +628,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_p_4_k_file_item(P4kFileItem self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_process_info(ProcessInfo self, SseSerializer serializer);
|
||||
|
||||
@@ -619,6 +678,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
|
||||
@protected
|
||||
void sse_encode_unit(void self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_usize(BigInt self, SseSerializer serializer);
|
||||
}
|
||||
|
||||
// Section: wire_class
|
||||
@@ -917,6 +979,140 @@ class RustLibWire implements BaseWire {
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_close(int port_) {
|
||||
return _wire__crate__api__unp4k_api__p4k_close(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__p4k_closePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_close',
|
||||
);
|
||||
late final _wire__crate__api__unp4k_api__p4k_close =
|
||||
_wire__crate__api__unp4k_api__p4k_closePtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_extract_to_disk(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> file_path,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> output_path,
|
||||
) {
|
||||
return _wire__crate__api__unp4k_api__p4k_extract_to_disk(
|
||||
port_,
|
||||
file_path,
|
||||
output_path,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__p4k_extract_to_diskPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_extract_to_disk',
|
||||
);
|
||||
late final _wire__crate__api__unp4k_api__p4k_extract_to_disk =
|
||||
_wire__crate__api__unp4k_api__p4k_extract_to_diskPtr
|
||||
.asFunction<
|
||||
void Function(
|
||||
int,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_extract_to_memory(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> file_path,
|
||||
) {
|
||||
return _wire__crate__api__unp4k_api__p4k_extract_to_memory(
|
||||
port_,
|
||||
file_path,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__p4k_extract_to_memoryPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_extract_to_memory',
|
||||
);
|
||||
late final _wire__crate__api__unp4k_api__p4k_extract_to_memory =
|
||||
_wire__crate__api__unp4k_api__p4k_extract_to_memoryPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_get_all_files(int port_) {
|
||||
return _wire__crate__api__unp4k_api__p4k_get_all_files(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__p4k_get_all_filesPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_get_all_files',
|
||||
);
|
||||
late final _wire__crate__api__unp4k_api__p4k_get_all_files =
|
||||
_wire__crate__api__unp4k_api__p4k_get_all_filesPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_get_files_in_directory(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> directory,
|
||||
) {
|
||||
return _wire__crate__api__unp4k_api__p4k_get_files_in_directory(
|
||||
port_,
|
||||
directory,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__p4k_get_files_in_directoryPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_get_files_in_directory',
|
||||
);
|
||||
late final _wire__crate__api__unp4k_api__p4k_get_files_in_directory =
|
||||
_wire__crate__api__unp4k_api__p4k_get_files_in_directoryPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_open(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> p4k_path,
|
||||
) {
|
||||
return _wire__crate__api__unp4k_api__p4k_open(port_, p4k_path);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__p4k_openPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>('frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_open');
|
||||
late final _wire__crate__api__unp4k_api__p4k_open =
|
||||
_wire__crate__api__unp4k_api__p4k_openPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_rsi_launcher_asar_data> that,
|
||||
@@ -1247,6 +1443,21 @@ class RustLibWire implements BaseWire {
|
||||
late final _cst_new_list_String = _cst_new_list_StringPtr
|
||||
.asFunction<ffi.Pointer<wire_cst_list_String> Function(int)>();
|
||||
|
||||
ffi.Pointer<wire_cst_list_p_4_k_file_item> cst_new_list_p_4_k_file_item(
|
||||
int len,
|
||||
) {
|
||||
return _cst_new_list_p_4_k_file_item(len);
|
||||
}
|
||||
|
||||
late final _cst_new_list_p_4_k_file_itemPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<wire_cst_list_p_4_k_file_item> Function(ffi.Int32)
|
||||
>
|
||||
>('frbgen_starcitizen_doctor_cst_new_list_p_4_k_file_item');
|
||||
late final _cst_new_list_p_4_k_file_item = _cst_new_list_p_4_k_file_itemPtr
|
||||
.asFunction<ffi.Pointer<wire_cst_list_p_4_k_file_item> Function(int)>();
|
||||
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_loose> cst_new_list_prim_u_8_loose(
|
||||
int len,
|
||||
) {
|
||||
@@ -1370,6 +1581,26 @@ final class wire_cst_list_prim_u_8_loose extends ffi.Struct {
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_p_4_k_file_item extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> name;
|
||||
|
||||
@ffi.Bool()
|
||||
external bool is_directory;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int size;
|
||||
|
||||
@ffi.Uint64()
|
||||
external int compressed_size;
|
||||
}
|
||||
|
||||
final class wire_cst_list_p_4_k_file_item extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_p_4_k_file_item> ptr;
|
||||
|
||||
@ffi.Int32()
|
||||
external int len;
|
||||
}
|
||||
|
||||
final class wire_cst_process_info extends ffi.Struct {
|
||||
@ffi.Uint32()
|
||||
external int pid;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
@@ -7,15 +6,11 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:starcitizen_doctor/api/analytics.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/binary_conf.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/rs_process.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/provider.dart';
|
||||
import 'package:starcitizen_doctor/data/app_unp4k_p4k_item_data.dart';
|
||||
import 'package:starcitizen_doctor/ui/tools/tools_ui_model.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/rs_process.dart'
|
||||
as rs_process;
|
||||
import 'package:starcitizen_doctor/common/rust/api/unp4k_api.dart' as unp4k_api;
|
||||
|
||||
part 'unp4kc.freezed.dart';
|
||||
|
||||
@@ -36,14 +31,9 @@ abstract class Unp4kcState with _$Unp4kcState {
|
||||
|
||||
@riverpod
|
||||
class Unp4kCModel extends _$Unp4kCModel {
|
||||
int? _rsPid;
|
||||
|
||||
@override
|
||||
Unp4kcState build() {
|
||||
state = Unp4kcState(
|
||||
startUp: false,
|
||||
curPath: '\\',
|
||||
endMessage: S.current.tools_unp4k_msg_init);
|
||||
state = Unp4kcState(startUp: false, curPath: '\\', endMessage: S.current.tools_unp4k_msg_init);
|
||||
_init();
|
||||
return state;
|
||||
}
|
||||
@@ -52,129 +42,72 @@ class Unp4kCModel extends _$Unp4kCModel {
|
||||
|
||||
String getGamePath() => _toolsState.scInstalledPath;
|
||||
|
||||
bool _hasUnp4kRunTimeError = false;
|
||||
|
||||
void _init() async {
|
||||
final execDir = "${appGlobalState.applicationBinaryModuleDir}\\unp4kc";
|
||||
await BinaryModuleConf.extractModule(
|
||||
["unp4kc"], appGlobalState.applicationBinaryModuleDir!);
|
||||
final exec = "$execDir\\unp4kc.exe";
|
||||
|
||||
final stream = rs_process.start(
|
||||
executable: exec, arguments: [], workingDirectory: execDir);
|
||||
|
||||
stream.listen((event) async {
|
||||
switch (event.dataType) {
|
||||
case RsProcessStreamDataType.output:
|
||||
_rsPid = event.rsPid;
|
||||
try {
|
||||
final eventJson = await compute(json.decode, event.data);
|
||||
_handleMessage(eventJson, event.rsPid);
|
||||
} catch (e) {
|
||||
dPrint("[unp4kc] json error: $e");
|
||||
}
|
||||
break;
|
||||
case RsProcessStreamDataType.error:
|
||||
dPrint("[unp4kc] stderr: ${event.data}");
|
||||
if (state.errorMessage.isEmpty) {
|
||||
state = state.copyWith(errorMessage: event.data);
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
errorMessage: "${state.errorMessage}\n${event.data}");
|
||||
}
|
||||
if (!_hasUnp4kRunTimeError) {
|
||||
if (checkRunTimeError(state.errorMessage)) {
|
||||
_hasUnp4kRunTimeError = true;
|
||||
AnalyticsApi.touch("unp4k_no_runtime");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RsProcessStreamDataType.exit:
|
||||
dPrint("[unp4kc] exit: ${event.data}");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
ref.onDispose(() {
|
||||
state = state.copyWith(fs: null);
|
||||
if (_rsPid != null) {
|
||||
Process.killPid(_rsPid!);
|
||||
dPrint("[unp4kc] kill ...");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DateTime? _loadStartTime;
|
||||
|
||||
void _handleMessage(Map<String, dynamic> eventJson, int rsPid) async {
|
||||
final action = eventJson["action"];
|
||||
final data = eventJson["data"];
|
||||
final gamePath = getGamePath();
|
||||
final gameP4kPath = "$gamePath\\Data.p4k";
|
||||
switch (action.toString().trim()) {
|
||||
case "info: startup":
|
||||
rs_process.write(rsPid: rsPid, data: "$gameP4kPath\n");
|
||||
break;
|
||||
case "info: Reading_p4k_file":
|
||||
_loadStartTime = DateTime.now();
|
||||
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading);
|
||||
break;
|
||||
case "info: All Ready":
|
||||
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading2);
|
||||
break;
|
||||
case "data: P4K_Files":
|
||||
final p4kFiles = (data as List<dynamic>);
|
||||
final files = <String, AppUnp4kP4kItemData>{};
|
||||
final fs = MemoryFileSystem(style: FileSystemStyle.posix);
|
||||
|
||||
var nextAwait = 0;
|
||||
for (var i = 0; i < p4kFiles.length; i++) {
|
||||
final item = AppUnp4kP4kItemData.fromJson(p4kFiles[i]);
|
||||
item.name = "${item.name}";
|
||||
files["\\${item.name}"] = item;
|
||||
await fs
|
||||
.file(item.name?.replaceAll("\\", "/") ?? "")
|
||||
.create(recursive: true);
|
||||
if (i == nextAwait) {
|
||||
state = state.copyWith(
|
||||
endMessage:
|
||||
S.current.tools_unp4k_msg_reading3(i, p4kFiles.length));
|
||||
await Future.delayed(Duration.zero);
|
||||
nextAwait += 20000;
|
||||
}
|
||||
try {
|
||||
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading);
|
||||
|
||||
final loadStartTime = DateTime.now();
|
||||
|
||||
// 使用 Rust API 打开 P4K 文件(异步)
|
||||
await unp4k_api.p4KOpen(p4KPath: gameP4kPath);
|
||||
|
||||
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading2);
|
||||
|
||||
// 获取所有文件列表(异步)
|
||||
final p4kFiles = await unp4k_api.p4KGetAllFiles();
|
||||
|
||||
final files = <String, AppUnp4kP4kItemData>{};
|
||||
final fs = MemoryFileSystem(style: FileSystemStyle.posix);
|
||||
|
||||
var nextAwait = 0;
|
||||
for (var i = 0; i < p4kFiles.length; i++) {
|
||||
final item = p4kFiles[i];
|
||||
final fileData = AppUnp4kP4kItemData(
|
||||
name: item.name,
|
||||
isDirectory: item.isDirectory,
|
||||
size: item.size.toInt(),
|
||||
compressedSize: item.compressedSize.toInt(),
|
||||
);
|
||||
|
||||
files[item.name] = fileData;
|
||||
|
||||
if (!item.isDirectory) {
|
||||
await fs.file(item.name.replaceAll("\\", "/")).create(recursive: true);
|
||||
}
|
||||
final endTime = DateTime.now();
|
||||
state = state.copyWith(
|
||||
files: files,
|
||||
fs: fs,
|
||||
endMessage: S.current.tools_unp4k_msg_read_completed(files.length,
|
||||
endTime.difference(_loadStartTime!).inMilliseconds));
|
||||
_loadStartTime = null;
|
||||
break;
|
||||
case "info: Extracted_Open":
|
||||
final filePath = data.toString();
|
||||
dPrint("[unp4kc] Extracted_Open file: $filePath");
|
||||
const textExt = [".txt", ".xml", ".json", ".lua", ".cfg", ".ini"];
|
||||
const imgExt = [".png"];
|
||||
String openType = "unknown";
|
||||
for (var element in textExt) {
|
||||
if (filePath.toLowerCase().endsWith(element)) {
|
||||
openType = "text";
|
||||
}
|
||||
|
||||
if (i == nextAwait) {
|
||||
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading3(i, p4kFiles.length));
|
||||
await Future.delayed(Duration.zero);
|
||||
nextAwait += 20000;
|
||||
}
|
||||
for (var element in imgExt) {
|
||||
if (filePath.endsWith(element)) {
|
||||
openType = "image";
|
||||
}
|
||||
}
|
||||
state = state.copyWith(
|
||||
tempOpenFile: MapEntry(openType, filePath),
|
||||
endMessage: S.current.tools_unp4k_msg_open_file(filePath));
|
||||
break;
|
||||
default:
|
||||
dPrint("[unp4kc] unknown action: $action");
|
||||
break;
|
||||
}
|
||||
|
||||
final endTime = DateTime.now();
|
||||
state = state.copyWith(
|
||||
files: files,
|
||||
fs: fs,
|
||||
endMessage: S.current.tools_unp4k_msg_read_completed(
|
||||
files.length,
|
||||
endTime.difference(loadStartTime).inMilliseconds,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
dPrint("[unp4k] error: $e");
|
||||
state = state.copyWith(errorMessage: e.toString());
|
||||
AnalyticsApi.touch("unp4k_error");
|
||||
}
|
||||
|
||||
ref.onDispose(() async {
|
||||
state = state.copyWith(fs: null);
|
||||
try {
|
||||
await unp4k_api.p4KClose();
|
||||
} catch (e) {
|
||||
dPrint("[unp4k] close error: $e");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
List<AppUnp4kP4kItemData>? getFiles() {
|
||||
@@ -204,8 +137,7 @@ class Unp4kCModel extends _$Unp4kCModel {
|
||||
result.add(f);
|
||||
}
|
||||
} else {
|
||||
result.add(AppUnp4kP4kItemData(
|
||||
name: file.path.replaceAll("/", "\\"), isDirectory: true));
|
||||
result.add(AppUnp4kP4kItemData(name: file.path.replaceAll("/", "\\"), isDirectory: true));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -221,58 +153,67 @@ class Unp4kCModel extends _$Unp4kCModel {
|
||||
|
||||
Future<void> openFile(String filePath) async {
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
final tempPath =
|
||||
"${tempDir.absolute.path}\\SCToolbox_unp4kc\\${SCLoggerHelper.getGameChannelID(getGamePath())}\\";
|
||||
final tempPath = "${tempDir.absolute.path}\\SCToolbox_unp4kc\\${SCLoggerHelper.getGameChannelID(getGamePath())}\\";
|
||||
state = state.copyWith(
|
||||
tempOpenFile: const MapEntry("loading", ""),
|
||||
endMessage: S.current.tools_unp4k_msg_open_file(filePath));
|
||||
tempOpenFile: const MapEntry("loading", ""),
|
||||
endMessage: S.current.tools_unp4k_msg_open_file(filePath),
|
||||
);
|
||||
extractFile(filePath, tempPath, mode: "extract_open");
|
||||
}
|
||||
|
||||
Future<void> extractFile(String filePath, String outputPath,
|
||||
{String mode = "extract"}) async {
|
||||
// remove first \\
|
||||
if (filePath.startsWith("\\")) {
|
||||
filePath = filePath.substring(1);
|
||||
}
|
||||
outputPath = "$outputPath$filePath";
|
||||
dPrint("extractFile .... $filePath");
|
||||
if (_rsPid != null) {
|
||||
rs_process.write(
|
||||
rsPid: _rsPid!, data: "$mode<:,:>$filePath<:,:>$outputPath\n");
|
||||
Future<void> extractFile(String filePath, String outputPath, {String mode = "extract"}) async {
|
||||
try {
|
||||
// remove first \\
|
||||
if (filePath.startsWith("\\")) {
|
||||
filePath = filePath.substring(1);
|
||||
}
|
||||
|
||||
final fullOutputPath = "$outputPath$filePath";
|
||||
dPrint("extractFile .... $filePath -> $fullOutputPath");
|
||||
|
||||
await unp4k_api.p4KExtractToDisk(filePath: filePath, outputPath: fullOutputPath);
|
||||
|
||||
if (mode == "extract_open") {
|
||||
const textExt = [".txt", ".xml", ".json", ".lua", ".cfg", ".ini"];
|
||||
const imgExt = [".png"];
|
||||
String openType = "unknown";
|
||||
for (var element in textExt) {
|
||||
if (filePath.toLowerCase().endsWith(element)) {
|
||||
openType = "text";
|
||||
}
|
||||
}
|
||||
for (var element in imgExt) {
|
||||
if (filePath.endsWith(element)) {
|
||||
openType = "image";
|
||||
}
|
||||
}
|
||||
state = state.copyWith(
|
||||
tempOpenFile: MapEntry(openType, fullOutputPath),
|
||||
endMessage: S.current.tools_unp4k_msg_open_file(filePath),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
dPrint("[unp4k] extractFile error: $e");
|
||||
state = state.copyWith(errorMessage: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkRunTimeError(String errorMessage) {
|
||||
if (errorMessage
|
||||
.contains("You must install .NET to run this application") ||
|
||||
errorMessage.contains(
|
||||
"You must install or update .NET to run this application") ||
|
||||
errorMessage.contains(
|
||||
"It was not possible to find any compatible framework version")) {
|
||||
AnalyticsApi.touch("unp4k_no_runtime");
|
||||
return true;
|
||||
}
|
||||
// Rust 实现不再需要 .NET runtime,这个方法保留以兼容现有代码
|
||||
return false;
|
||||
}
|
||||
|
||||
static Future<Uint8List> unp4kTools(
|
||||
String applicationBinaryModuleDir, List<String> args) async {
|
||||
await BinaryModuleConf.extractModule(
|
||||
["unp4kc"], applicationBinaryModuleDir);
|
||||
final execDir = "$applicationBinaryModuleDir\\unp4kc";
|
||||
final exec = "$execDir\\unp4kc.exe";
|
||||
final r = await Process.run(exec, args);
|
||||
if (r.exitCode != 0) {
|
||||
Process.killPid(r.pid);
|
||||
throw Exception(
|
||||
"error: ${r.exitCode} , info= ${r.stdout} , err= ${r.stderr}");
|
||||
/// 从 P4K 文件中提取指定文件到内存
|
||||
/// [p4kPath] P4K 文件路径
|
||||
/// [filePath] 要提取的文件路径(P4K 内部路径)
|
||||
static Future<Uint8List> extractP4kFileToMemory(String p4kPath, String filePath) async {
|
||||
try {
|
||||
await unp4k_api.p4KOpen(p4KPath: p4kPath);
|
||||
final data = await unp4k_api.p4KExtractToMemory(filePath: filePath);
|
||||
await unp4k_api.p4KClose();
|
||||
return Uint8List.fromList(data);
|
||||
} catch (e) {
|
||||
throw Exception("extractP4kFileToMemory error: $e");
|
||||
}
|
||||
final eventJson = await compute(json.decode, r.stdout.toString());
|
||||
if (eventJson["action"] == "data: Uint8List") {
|
||||
final data = eventJson["data"];
|
||||
return Uint8List.fromList((data as List).cast<int>());
|
||||
}
|
||||
throw Exception("error: data error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ final class Unp4kCModelProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$unp4kCModelHash() => r'410461980f6173fdbb5d92cbaa3f4c2f57c1ad8d';
|
||||
String _$unp4kCModelHash() => r'fe88d52b11464fdbded606bacbd833c1e908b738';
|
||||
|
||||
abstract class _$Unp4kCModel extends $Notifier<Unp4kcState> {
|
||||
Unp4kcState build();
|
||||
|
||||
@@ -13,7 +13,6 @@ import 'package:re_highlight/styles/vs2015.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:starcitizen_doctor/api/analytics.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/provider.dart';
|
||||
import 'package:starcitizen_doctor/data/app_advanced_localization_data.dart';
|
||||
import 'package:starcitizen_doctor/data/sc_localization_data.dart';
|
||||
import 'package:starcitizen_doctor/provider/unp4kc.dart';
|
||||
@@ -218,11 +217,10 @@ class AdvancedLocalizationUIModel extends _$AdvancedLocalizationUIModel {
|
||||
|
||||
Future<String> readEnglishInI(String gameDir) async {
|
||||
try {
|
||||
var data = await Unp4kCModel.unp4kTools(appGlobalState.applicationBinaryModuleDir!, [
|
||||
"extract_memory",
|
||||
var data = await Unp4kCModel.extractP4kFileToMemory(
|
||||
"$gameDir\\Data.p4k",
|
||||
"Data\\Localization\\english\\global.ini",
|
||||
]);
|
||||
);
|
||||
// remove bom
|
||||
if (data.length > 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) {
|
||||
data = data.sublist(3);
|
||||
|
||||
@@ -41,7 +41,7 @@ final class PartyRoomUIModelProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$partyRoomUIModelHash() => r'add4703c9129465718a7850ea09025aa1ff35358';
|
||||
String _$partyRoomUIModelHash() => r'b22ad79b6d4a877876b2534f35fb0448b34d4ad5';
|
||||
|
||||
abstract class _$PartyRoomUIModel extends $Notifier<PartyRoomUIState> {
|
||||
PartyRoomUIState build();
|
||||
|
||||
@@ -66,7 +66,7 @@ final class PartyRoomGameLogTrackerProviderProvider
|
||||
}
|
||||
|
||||
String _$partyRoomGameLogTrackerProviderHash() =>
|
||||
r'3e1560b2fffc5461a41bece57b43e27f4112ad0c';
|
||||
r'7c9413736b0a3357075ab5309f0e746f0d6e3fc3';
|
||||
|
||||
final class PartyRoomGameLogTrackerProviderFamily extends $Family
|
||||
with
|
||||
|
||||
Reference in New Issue
Block a user