Skip to content

Commit d1b3ec3

Browse files
committed
feat: 将乐曲复制到另一份游戏实例
1 parent b1e73cc commit d1b3ec3

File tree

8 files changed

+131
-4
lines changed

8 files changed

+131
-4
lines changed

MaiChartManager/Controllers/AssetDirController.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ public void RequestLocalImportDir()
5555
if (Program.BrowserWin is null) return;
5656
var dialog = new FolderBrowserDialog
5757
{
58-
Description = "请选择资源目录(OPT)的文件夹"
58+
Description = "请选择资源目录(OPT)的文件夹",
59+
ShowNewFolderButton = false
5960
};
6061
if (Program.BrowserWin.Invoke(() => dialog.ShowDialog(Program.BrowserWin)) != DialogResult.OK) return;
6162
var src = dialog.SelectedPath;
@@ -103,5 +104,6 @@ public void RequestLocalImportDir()
103104
settings.ScanVersionList();
104105
settings.ScanAssetBundles();
105106
settings.ScanSoundData();
107+
settings.ScanMovieData();
106108
}
107109
}

MaiChartManager/Controllers/MusicController.cs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using AssetStudio;
22
using MaiChartManager.Models;
33
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.VisualBasic.FileIO;
45
using Sitreamai;
56
using Sitreamai.Models;
67
using Standart.Hash.xxHash;
@@ -9,7 +10,7 @@ namespace MaiChartManager.Controllers;
910

1011
[ApiController]
1112
[Route("MaiChartManagerServlet/[action]Api/{id:int}")]
12-
public class MusicController(StaticSettings settings, ILogger<StaticSettings> logger) : ControllerBase
13+
public class MusicController(StaticSettings settings, ILogger<MusicController> logger) : ControllerBase
1314
{
1415
[HttpGet]
1516
public MusicXmlWithABJacket? GetMusicDetail(int id)
@@ -233,4 +234,62 @@ public void SetAudio(int id, [FromForm] float padding, IFormFile file, IFormFile
233234
StaticSettings.AcbAwb[$"music{id:000000}.acb"] = targetAcbPath;
234235
StaticSettings.AcbAwb[$"music{id:000000}.awb"] = targetAwbPath;
235236
}
237+
238+
[HttpPost]
239+
public void RequestCopyTo(int id)
240+
{
241+
if (Program.BrowserWin is null) return;
242+
var dialog = new FolderBrowserDialog
243+
{
244+
Description = "请选择要复制到的另一份游戏的资源目录(Axxx)位置"
245+
};
246+
if (Program.BrowserWin.Invoke(() => dialog.ShowDialog(Program.BrowserWin)) != DialogResult.OK) return;
247+
var dest = dialog.SelectedPath;
248+
logger.LogInformation("CopyTo: {dest}", dest);
249+
250+
var music = settings.MusicList.Find(it => it.Id == id);
251+
if (music is null) return;
252+
253+
// copy music
254+
Directory.CreateDirectory(Path.Combine(dest, "music"));
255+
FileSystem.CopyDirectory(Path.GetDirectoryName(music.FilePath), Path.Combine(dest, $@"music\{music.Id:000000}"), UIOption.OnlyErrorDialogs);
256+
257+
// copy jacket
258+
Directory.CreateDirectory(Path.Combine(dest, @"AssetBundleImages\jacket"));
259+
if (music.JacketPath is not null)
260+
{
261+
FileSystem.CopyFile(music.JacketPath, Path.Combine(dest, $@"AssetBundleImages\jacket\ui_jacket_{music.NonDxId:000000}{Path.GetExtension(music.JacketPath)}"), UIOption.OnlyErrorDialogs);
262+
}
263+
else if (music.AssetBundleJacket is not null)
264+
{
265+
FileSystem.CopyFile(music.AssetBundleJacket, Path.Combine(dest, $@"AssetBundleImages\jacket\{Path.GetFileName(music.AssetBundleJacket)}"), UIOption.OnlyErrorDialogs);
266+
if (System.IO.File.Exists(music.AssetBundleJacket + ".manifest"))
267+
{
268+
FileSystem.CopyFile(music.AssetBundleJacket + ".manifest", Path.Combine(dest, $@"AssetBundleImages\jacket\{Path.GetFileName(music.AssetBundleJacket)}.manifest"), UIOption.OnlyErrorDialogs);
269+
}
270+
}
271+
else if (music.PseudoAssetBundleJacket is not null)
272+
{
273+
FileSystem.CopyFile(music.PseudoAssetBundleJacket, Path.Combine(dest, $@"AssetBundleImages\jacket\{Path.GetFileName(music.PseudoAssetBundleJacket)}"), UIOption.OnlyErrorDialogs);
274+
}
275+
276+
// copy acbawb
277+
Directory.CreateDirectory(Path.Combine(dest, "SoundData"));
278+
if (StaticSettings.AcbAwb.TryGetValue($"music{music.NonDxId:000000}.acb", out var acb))
279+
{
280+
FileSystem.CopyFile(acb, Path.Combine(dest, $@"SoundData\music{music.NonDxId:000000}.acb"), UIOption.OnlyErrorDialogs);
281+
}
282+
283+
if (StaticSettings.AcbAwb.TryGetValue($"music{music.NonDxId:000000}.awb", out var awb))
284+
{
285+
FileSystem.CopyFile(awb, Path.Combine(dest, $@"SoundData\music{music.NonDxId:000000}.awb"), UIOption.OnlyErrorDialogs);
286+
}
287+
288+
// copy movie data
289+
if (StaticSettings.MovieDataMap.TryGetValue(music.NonDxId, out var movie))
290+
{
291+
Directory.CreateDirectory(Path.Combine(dest, "MovieData"));
292+
FileSystem.CopyFile(movie, Path.Combine(dest, $@"MovieData\{music.NonDxId:000000}.dat"), UIOption.OnlyErrorDialogs);
293+
}
294+
}
236295
}

MaiChartManager/Controllers/MusicListController.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ public void ReloadAll()
3434
settings.ScanVersionList();
3535
settings.ScanAssetBundles();
3636
settings.ScanSoundData();
37+
settings.ScanMovieData();
3738
}
3839
}

MaiChartManager/Front/src/client/apiGen.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,20 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
13241324
...params,
13251325
}),
13261326

1327+
/**
1328+
* No description
1329+
*
1330+
* @tags Music
1331+
* @name RequestCopyTo
1332+
* @request POST:/MaiChartManagerServlet/RequestCopyToApi/{id}
1333+
*/
1334+
RequestCopyTo: (id: number, params: RequestParams = {}) =>
1335+
this.request<void, any>({
1336+
path: `/MaiChartManagerServlet/RequestCopyToApi/${id}`,
1337+
method: "POST",
1338+
...params,
1339+
}),
1340+
13271341
/**
13281342
* No description
13291343
*
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { defineComponent, ref } from "vue";
2+
import api from "@/client/api";
3+
import { selectMusicId, updateMusicList } from "@/store/refs";
4+
import { NButton, useDialog } from "naive-ui";
5+
6+
export default defineComponent({
7+
setup() {
8+
const wait = ref(false);
9+
const dialog = useDialog();
10+
11+
const copy = async () => {
12+
if (location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {
13+
dialog.info({
14+
title: '提示',
15+
content: '暂时不支持远程,请在本地使用'
16+
})
17+
return;
18+
}
19+
try {
20+
wait.value = true;
21+
await api.RequestCopyTo(selectMusicId.value);
22+
} finally {
23+
wait.value = false;
24+
}
25+
}
26+
27+
return () => <NButton secondary onClick={copy} loading={wait.value}>
28+
复制到...
29+
</NButton>;
30+
}
31+
});

MaiChartManager/Front/src/components/MusicSelectedTopRightToolbar/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { defineComponent } from "vue";
22
import { selectMusicId } from "@/store/refs";
33
import DeleteMusicButton from "@/components/MusicSelectedTopRightToolbar/DeleteMusicButton";
44
import SaveButton from "@/components/MusicSelectedTopRightToolbar/SaveButton";
5+
import CopyToButton from "@/components/MusicSelectedTopRightToolbar/CopyToButton";
56

67
export default defineComponent({
78
setup() {
89
return () => !!selectMusicId.value && <>
910
<DeleteMusicButton/>
11+
<CopyToButton/>
1012
<SaveButton/>
1113
</>;
1214
}

MaiChartManager/Front/src/views/Index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default defineComponent({
4343
},
4444
render() {
4545
return <NFlex justify="center">
46-
<div class="grid cols-[40em_1fr] w-[min(90rem,100%)]">
46+
<div class="grid cols-[40em_1fr] w-[min(100rem,100%)]">
4747
<div class="p-xy h-100vh">
4848
<MusicList/>
4949
</div>

MaiChartManager/StaticSettings.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public StaticSettings(ILogger<StaticSettings> logger)
3333
ScanVersionList();
3434
ScanAssetBundles();
3535
ScanSoundData();
36+
ScanMovieData();
3637
}
3738
catch (Exception e)
3839
{
@@ -69,6 +70,7 @@ public string AssetDir
6970
public static List<VersionXml> VersionList { get; set; } = [];
7071
public static Dictionary<int, string> AssetBundleJacketMap { get; set; } = new();
7172
public static Dictionary<int, string> PseudoAssetBundleJacketMap { get; set; } = new();
73+
public static Dictionary<int, string> MovieDataMap { get; set; } = new();
7274
public static Dictionary<string, string> AcbAwb { get; set; } = new();
7375

7476
public void ScanMusicList()
@@ -167,7 +169,7 @@ public void ScanSoundData()
167169
AcbAwb.Clear();
168170
foreach (var a in AssetsDirs)
169171
{
170-
if (!Directory.Exists(Path.Combine(StreamingAssets, a, @"SoundData"))) continue;
172+
if (!Directory.Exists(Path.Combine(StreamingAssets, a, "SoundData"))) continue;
171173
foreach (var sound in Directory.EnumerateFiles(Path.Combine(StreamingAssets, a, @"SoundData")))
172174
{
173175
AcbAwb[Path.GetFileName(sound).ToLower()] = sound;
@@ -177,6 +179,22 @@ public void ScanSoundData()
177179
_logger.LogInformation($"Scan SoundData, found {AcbAwb.Count} SoundData.");
178180
}
179181

182+
public void ScanMovieData()
183+
{
184+
MovieDataMap.Clear();
185+
foreach (var a in AssetsDirs)
186+
{
187+
if (!Directory.Exists(Path.Combine(StreamingAssets, a, "MovieData"))) continue;
188+
foreach (var dat in Directory.EnumerateFiles(Path.Combine(StreamingAssets, a, @"MovieData"), "*.dat"))
189+
{
190+
if (!int.TryParse(Path.GetFileNameWithoutExtension(dat), out var id)) continue;
191+
MovieDataMap[id] = dat;
192+
}
193+
}
194+
195+
_logger.LogInformation($"Scan MovieData, found {MovieDataMap.Count} MovieData.");
196+
}
197+
180198
private void GetGameVersion()
181199
{
182200
try

0 commit comments

Comments
 (0)