Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.2.0 #62

Merged
merged 13 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' # optional, change this to force refresh cache
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' # optional, change this to specify the cache path
- run: chmod +x ./build.sh
- run: ./build.sh
- run: flutter config --enable-macos-desktop
- run: flutter build -v macos --release
- run: ditto -c -k --sequesterRsrc --keepParent retro.app $GITHUB_WORKSPACE/retro.zip
Expand All @@ -36,6 +38,7 @@ jobs:
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' # optional, change this to force refresh cache
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' # optional, change this to specify the cache path
- run: ./build.ps1
- run: flutter config --enable-windows-desktop
- run: flutter build windows --release
- uses: actions/upload-artifact@v3
Expand All @@ -54,13 +57,15 @@ jobs:
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' # optional, change this to force refresh cache
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' # optional, change this to specify the cache path
- run: chmod +x ./build.sh
- run: ./build.sh
- run: flutter config --enable-linux-desktop
- run: flutter build linux --release
- name: Create AppImage
run: |
wget "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod a+x appimagetool-x86_64.AppImage

# Create AppDir
cp -r build/linux/x64/release/bundle/ retro.AppDir
cp assets/icon-macos.png retro.AppDir/retro.png
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ app.*.symbols
# Obfuscation related
app.*.map.json

# Autogenerated file
# lib/auto/build.dart

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
Expand Down
10 changes: 10 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Remove-Item -Force lib/auto/build.dart
New-Item -ItemType File -Path lib/auto/build.dart

$BRANCH = git rev-parse --abbrev-ref HEAD
$COMMIT_HASH = git rev-parse --short HEAD
$COMMIT_DATE = git show -s --format=%ci

"const String branch = '$BRANCH';" | Out-File -FilePath lib/auto/build.dart -Encoding utf8
"const String commitHash = '$COMMIT_HASH';" | Out-File -FilePath lib/auto/build.dart -Encoding utf8 -Append
"const String commitDate = '$COMMIT_DATE';" | Out-File -FilePath lib/auto/build.dart -Encoding utf8 -Append
9 changes: 9 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
rm -f lib/auto/build.dart
touch lib/auto/build.dart
BRANCH=$(git rev-parse --abbrev-ref HEAD)
COMMIT_HASH=$(git rev-parse --short HEAD)
COMMIT_DATE=$(git show -s --format=%ci)

echo "const String branch = '$BRANCH';" > lib/auto/build.dart
echo "const String commitHash = '$COMMIT_HASH';" >> lib/auto/build.dart
echo "const String commitDate = '$COMMIT_DATE';" >> lib/auto/build.dart
10 changes: 7 additions & 3 deletions lib/arc/arc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,16 @@ class Arc {
continue;
}

log('File name: $fileName');
if (fileName != null && fileName != '(signature)' && fileName != '(listfile)' && fileName != '(attributes)') {
if (fileName != '(signature)' && fileName != '(listfile)' && fileName != '(attributes)') {
files.add(fileName);
if(onFile != null) {
final file = mpqArchive.openFileEx(fileName, 0);
await onFile(fileName, file.read(file.size()));
try {
final size = file.size();
await onFile(fileName, file.read(size));
} catch (e) {
log('Skipping file $fileName: $e');
}
}
}
} on StormLibException catch (e) {
Expand Down
3 changes: 3 additions & 0 deletions lib/auto/build.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const String branch = 'v0.2.0';
const String commitHash = '705c17d';
const String commitDate = '2024-06-03 23:53:34 -0600';
7 changes: 7 additions & 0 deletions lib/context.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:retro/utils/git.dart';

class RetroContext {
static const String versionName = '0.2.0';
static const int versionCode = 0;
static late GitInfo git;
}
137 changes: 75 additions & 62 deletions lib/features/create/create_custom/create_custom_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,72 +26,85 @@ class _CreateCustomScreenState extends State<CreateCustomScreen> {
Widget build(BuildContext context) {
final theme = Theme.of(context);
final textTheme = theme.textTheme;
final viewModel =
Provider.of<CreateCustomViewModel>(context);
final finishViewModel =
Provider.of<CreateFinishViewModel>(context);
final viewModel = Provider.of<CreateCustomViewModel>(context);
final finishViewModel = Provider.of<CreateFinishViewModel>(context);
final i18n = AppLocalizations.of(context)!;

return CustomScaffold(
title: i18n.createCustomScreen_title,
subtitle: i18n.createCustomScreen_subtitle,
onBackButtonPressed: () {
viewModel.reset();
Navigator.of(context).pop();
},
content: Expanded(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: OutlinedButton(
onPressed: viewModel.onSelectFiles,
style: ElevatedButton.styleFrom(
minimumSize: const Size(200, 50),),
child:
Text(i18n.createCustomScreen_selectButton),),
),
Text(viewModel.path),
],
),
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'${i18n.createCustomScreen_fileToInsert}${viewModel.files.length}',
style: textTheme.titleMedium,
),
title: i18n.createCustomScreen_title,
subtitle: i18n.createCustomScreen_subtitle,
onBackButtonPressed: () {
viewModel.reset();
Navigator.of(context).pop();
},
content: Expanded(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: OutlinedButton(
onPressed: viewModel.onSelectFiles,
style: ElevatedButton.styleFrom(
minimumSize: const Size(200, 50),
),
child: Text(i18n.createCustomScreen_selectButton),
),
Expanded(
child: ListView.builder(
itemCount: viewModel.files.length,
itemBuilder: (context, index) {
return Text(p.relative(
viewModel.files[index].path,
from: viewModel.path,),);
},),),
ElevatedButton(
onPressed: viewModel.files.isNotEmpty &&
viewModel.path.isNotEmpty
? () {
finishViewModel.onAddCustomStageEntries(
viewModel.files, viewModel.path,);
viewModel.reset();
Navigator.of(context).popUntil(
ModalRoute.withName('/create_selection'),);
}
: null,
style: ElevatedButton.styleFrom(
minimumSize: Size(
MediaQuery.of(context).size.width * 0.5, 50,),),
child: Text(i18n.createCustomScreen_stageFiles),),
],
),),),);
),
Text(viewModel.path),
],
),
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'${i18n.createCustomScreen_fileToInsert}${viewModel.files.length}',
style: textTheme.titleMedium,
),
),
),
Expanded(
child: ListView.builder(
itemCount: viewModel.files.length,
itemBuilder: (context, index) {
return Text(
p.relative(
viewModel.files[index].path,
from: viewModel.path,
),
);
},
),
),
ElevatedButton(
onPressed: viewModel.files.isNotEmpty && viewModel.path.isNotEmpty
? () {
finishViewModel.onAddCustomStageEntries(
viewModel.files,
viewModel.path,
);
viewModel.reset();
Navigator.of(context).popUntil(
ModalRoute.withName('/create_selection'),
);
}
: null,
style: ElevatedButton.styleFrom(
minimumSize: Size(
MediaQuery.of(context).size.width * 0.5,
50,
),
),
child: Text(i18n.createCustomScreen_stageFiles),
),
],
),
),
),
);
}
}
17 changes: 12 additions & 5 deletions lib/features/create/create_finish/create_finish_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ class CreateFinishViewModel with ChangeNotifier {
notifyListeners();
}

onAddCustomTextureEntry(
void onAddCustomTextureEntry(
HashMap<String, List<Tuple2<File, TextureManifestEntry>>> replacementMap,
) {
for (final entry in replacementMap.entries) {
if (entries.containsKey(entry.key) &&
entries[entry.key] is CustomTexturesEntry) {
(entries[entry.key] as CustomTexturesEntry).pairs.addAll(entry.value);
(entries[entry.key]! as CustomTexturesEntry).pairs.addAll(entry.value);
} else if (entries.containsKey(entry.key)) {
throw Exception('Cannot add custom texture entry to existing entry');
} else {
Expand All @@ -124,18 +124,25 @@ class CreateFinishViewModel with ChangeNotifier {
notifyListeners();
}

void onAddFile(File file, String path) {
entries[path] = CustomStageEntry([file]);
totalFiles++;
currentState = AppState.changesStaged;
notifyListeners();
}

void onRemoveFile(File file, String path) {
if (entries.containsKey(path) && entries[path] is CustomStageEntry) {
(entries[path] as CustomStageEntry).files.remove(file);
(entries[path]! as CustomStageEntry).files.remove(file);
} else if (entries.containsKey(path) &&
entries[path] is CustomSequencesEntry) {
(entries[path] as CustomSequencesEntry).pairs.removeWhere(
(entries[path]! as CustomSequencesEntry).pairs.removeWhere(
(pair) =>
pair.item1.path == file.path || pair.item2.path == file.path,
);
} else if (entries.containsKey(path) &&
entries[path] is CustomTexturesEntry) {
(entries[path] as CustomTexturesEntry)
(entries[path]! as CustomTexturesEntry)
.pairs
.removeWhere((pair) => pair.item1.path == file.path);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:retro/otr/resource.dart';
import 'package:retro/otr/resource_type.dart';
import 'package:retro/otr/types/background.dart';
import 'package:retro/otr/types/texture.dart';
import 'package:retro/otr/version.dart';
import 'package:retro/utils/log.dart';
import 'package:retro/utils/path.dart' as p;
import 'package:tuple/tuple.dart';
Expand Down Expand Up @@ -170,8 +171,8 @@ Future<HashMap<String, ProcessedFilesInFolder>?> processFolder(
return null;
}

String manifestContents = await manifestFile.readAsString();
Map<String, dynamic> manifest = json.decode(manifestContents) as Map<String, dynamic>;
final manifestContents = await manifestFile.readAsString();
final manifest = json.decode(manifestContents) as Map<String, dynamic>;

// find all images in folder
final supportedExtensions = <String>['.png', '.jpeg', '.jpg'];
Expand All @@ -187,7 +188,7 @@ Future<HashMap<String, ProcessedFilesInFolder>?> processFolder(
p.normalize(texFile.path.split('$folderPath/').last.split('.').first);
if (manifest.containsKey(texPathRelativeToFolder)) {
final manifestEntry =
TextureManifestEntry.fromJson(manifest[texPathRelativeToFolder]);
TextureManifestEntry.fromJson(manifest[texPathRelativeToFolder] as Map<String, dynamic>);
// if it is, check if the file has changed
final texFileBytes = await texFile.readAsBytes();
final texFileHash = sha256.convert(texFileBytes).toString();
Expand Down Expand Up @@ -218,38 +219,32 @@ Future<HashMap<String, ProcessedFilesInFolder>?> processFolder(

Future<HashMap<String, TextureManifestEntry>?> processOTR(
Tuple2<List<String>, String> params) async {
try {
var fileFound = false;
final processedFiles = HashMap<String, TextureManifestEntry>();
final processedFiles = HashMap<String, TextureManifestEntry>();

// just use the first otr in the list for the directory name
final otrNameForOutputDirectory =
params.item1[0].split(Platform.pathSeparator).last.split('.').first;

// if folder we'll export to exists, delete it
final dir = Directory('${params.item2}/$otrNameForOutputDirectory');
if (dir.existsSync()) {
log('Deleting existing folder: ${params.item2}/$otrNameForOutputDirectory');
await dir.delete(recursive: true);
}
// just use the first otr in the list for the directory name
final otrNameForOutputDirectory =
params.item1[0].split(Platform.pathSeparator).last.split('.').first;

for (final otrPath in params.item1) {
log('Processing OTR: $otrPath');
final arcFile = Arc(otrPath);
// if folder we'll export to exists, delete it
final dir = Directory('${params.item2}/$otrNameForOutputDirectory');
if (dir.existsSync()) {
log('Deleting existing folder: ${params.item2}/$otrNameForOutputDirectory');
await dir.delete(recursive: true);
}

await arcFile.listItems(onFile: (String fileName, Uint8List data) async {
await processFile(fileName, data, '${params.item2}/$otrNameForOutputDirectory/$fileName', (TextureManifestEntry entry) {
processedFiles[fileName] = entry;
});
},);
arcFile.close();
}
for (final otrPath in params.item1) {
log('Processing OTR: $otrPath');
final arcFile = Arc(otrPath);

return processedFiles;
} on StormLibException catch (e) {
log('Failed to find next file: ${e.message}');
return null;
await arcFile.listItems(onFile: (String fileName, Uint8List data) async {
await processFile(fileName, data, '${params.item2}/$otrNameForOutputDirectory/$fileName', (TextureManifestEntry entry) {
processedFiles[fileName] = entry;
});
},);
arcFile.close();
}

return processedFiles.isEmpty ? null : processedFiles;
}

Future<bool> processFile(String fileName, Uint8List data, String outputPath, Function onProcessed) async {
Expand All @@ -269,6 +264,11 @@ Future<bool> processFile(String fileName, Uint8List data, String outputPath, Fun
final texture = Texture.empty();
texture.open(data);

// don't try to extract hd textures
if(texture.gameVersion == Version.roy){
KiritoDv marked this conversation as resolved.
Show resolved Hide resolved
break;
}

final pngBytes = texture.toPNGBytes();
final textureFile = File('$outputPath.png');
await textureFile.create(recursive: true);
Expand Down
Loading
Loading