Skip to content

Commit

Permalink
feat: add export dialog for normal exporting
Browse files Browse the repository at this point in the history
  • Loading branch information
ci010 committed Sep 1, 2020
1 parent 3841eb1 commit 52b1df3
Show file tree
Hide file tree
Showing 7 changed files with 405 additions and 165 deletions.
99 changes: 66 additions & 33 deletions src/main/service/InstanceIOService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { copyPassively, isDirectory, isFile, readdirIfPresent } from '@main/util/fs';
import { copyPassively, isDirectory, isFile, readdirIfPresent, exists } from '@main/util/fs';
import { getCurseforgeUrl } from '@main/util/resource';
import { openCompressedStreamTask } from '@main/util/zip';
import { createTemplate, InstanceConfig } from '@universal/store/modules/instance';
Expand All @@ -11,12 +11,14 @@ import { Task } from '@xmcl/task';
import Unzip from '@xmcl/unzip';
import { createReadStream, mkdtemp, readdir, readJson, remove, stat } from 'fs-extra';
import { tmpdir } from 'os';
import { basename, join, resolve, relative } from 'path';
import { basename, join, relative, resolve } from 'path';
import { Modpack } from './CurseForgeService';
import InstanceResourceService from './InstanceResourceService';
import InstanceService, { EditInstanceOptions } from './InstanceService';
import ResourceService from './ResourceService';
import Service, { Inject, Singleton } from './Service';
import { Modpack } from './CurseForgeService';

export interface InstanceFile { path: string; isDirectory: boolean; isResource: boolean }

export interface ExportInstanceOptions {
/**
Expand All @@ -27,10 +29,31 @@ export interface ExportInstanceOptions {
* The dest path of the exported instance
*/
destinationPath: string;

/**
* Does this export include the libraries?
* @default true
*/
includeLibraries?: boolean;

/**
* Does this export includes assets?
* @default true
*/
includeAssets?: boolean;

/**
* The export mod of this operation
* Does this export includes the minecraft version jar? (like <minecraft>/versions/1.14.4.jar).
* If this is false, then it will only export with version json.
* @default true
*/
mode: 'full' | 'no-assets';
includeVersionJar?: boolean;

/**
* If this is present, it will only exports the file paths in this array.
* By default this is `undefined`, and it will export everything in the instance.
*/
files?: string[];
}

export interface ExportCurseforgeModpackOptions {
Expand Down Expand Up @@ -85,47 +108,57 @@ export default class InstanceIOService extends Service {
async exportInstance(options: ExportInstanceOptions) {
requireObject(options);

let { src = this.state.instance.path, destinationPath: dest, mode = 'full' } = options;
const { src = this.state.instance.path, destinationPath: dest, includeAssets = true, includeLibraries = true, files, includeVersionJar = true } = options;

if (this.state.instance.all[src]) {
if (!this.state.instance.all[src]) {
this.warn(`Cannot export unmanaged instance ${src}`);
return;
}

let root = this.state.root;
// let instanceObject = this.state.instance.all[src];
const root = this.state.root;
const from = src;

let from = src;

let { task, include, add, end } = openCompressedStreamTask(from);
let handle = this.submit(task);
await include(from, from);
const { task, include, add, end } = openCompressedStreamTask(dest);
(task as any).name = 'profile.modpack.export';
const handle = this.submit(task);

let defaultMcversion = this.state.instance.all[src].runtime.minecraft;
const version = await Version.parse(root, this.getters.instanceVersion.folder);

let parsedVersion = await Version.parse(root, defaultMcversion);
let verionsChain = parsedVersion.pathChain;
// add assets
if (includeAssets) {
const assetsJson = resolve(root, 'assets', 'indexes', `${version.assets}.json`);
await add(assetsJson, `assets/indexes/${version.assets}.json`);
const objects = await readJson(assetsJson).then(manifest => manifest.objects);
for (const hash of Object.keys(objects).map(k => objects[k].hash)) {
await add(resolve(root, 'assets', 'objects', hash.substring(0, 2), hash), `assets/objects/${hash.substring(0, 2)}/${hash}`);
}
}

if (mode === 'full') {
let assetsJson = resolve(root, 'assets', 'indexes', `${parsedVersion.assets}.json`);
add(assetsJson, `assets/indexes/${parsedVersion.assets}.json`);
let objects = await readJson(assetsJson).then(manifest => manifest.objects);
for (let hash of Object.keys(objects).map(k => objects[k].hash)) {
add(resolve(root, 'assets', 'objects', hash.substring(0, 2), hash), `assets/objects/${hash.substring(0, 2)}/${hash}`);
// add version json and jar
const verionsChain = version.pathChain;
for (const versionPath of verionsChain) {
const versionId = basename(versionPath);
if (includeVersionJar && await exists(join(versionPath, `${versionId}.jar`))) {
await add(join(versionPath, `${versionId}.jar`), `versions/${versionId}/${versionId}.jar`);
}
await add(join(versionPath, `${versionId}.json`), `versions/${versionId}/${versionId}.json`);
}

for (let versionPath of verionsChain) {
let versionId = basename(versionPath);
let versionFiles = await readdir(versionPath);
for (let versionFile of versionFiles) {
add(join(versionPath, versionFile), `versions/${versionId}/${versionFile}`);
// add libraries
if (includeLibraries) {
for (const lib of version.libraries) {
await add(resolve(root, 'libraries', lib.download.path),
`libraries/${lib.download.path}`);
}
}

for (let lib of parsedVersion.libraries) {
add(resolve(root, 'libraries', lib.download.path),
`libraries/${lib.download.path}`);
// add misc files like config, log...
if (files) {
for (const file of files) {
await add(join(src, file), file);
}
} else {
await include(from, from);
}

end();
Expand All @@ -137,9 +170,9 @@ export default class InstanceIOService extends Service {
* Scan all the files under the current instance.
* It will hint if a mod resource is in curseforge
*/
async getInstanceFiles(): Promise<{ path: string; isDirectory: boolean; isResource: boolean }[]> {
async getInstanceFiles(): Promise<InstanceFile[]> {
const path = this.state.instance.path;
const files = [] as { path: string; isDirectory: boolean; isResource: boolean }[];
const files = [] as InstanceFile[];

const scan = async (p: string) => {
const status = await stat(p);
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@
"importCurseforge": "Import from Curseforge Modpack",
"importFolder": "Import from Folder",
"importZip": "Import from Zip",
"instanceVersion": "Modpack Version",
"launchArguments": "Launch Arguments Preview",
"launchingDetail": "Launch Detail",
"localVersion": "Local Version",
Expand Down Expand Up @@ -615,7 +616,11 @@
"exportCurseforge": "Export Curseforge Modpack",
"general": "General Information",
"name": "Modpack | Modpacks",
"includeLibraries": "Include Libraries",
"includeAssets": "Include Assets",
"includeVersion": "Include Version | Include Versions",
"overrides": "overrides",
"includes": "Files to includes",
"profile": "Profile Name"
},
"name": "Profile Name",
Expand Down Expand Up @@ -675,6 +680,7 @@
"today": "Today",
"url": "URL",
"version": "Selected Version",
"gameVersion": "Game Version",
"versionHint": "The Minecraft version of this game",
"versionSetting": "Version Setting",
"vmOptions": "JVM Options",
Expand Down Expand Up @@ -751,6 +757,8 @@
"autoDownloadDescription": "Auto Download Update if it's Avaiable",
"autoInstallOnAppQuit": "Autoinstall",
"autoInstallOnAppQuitDescription": "Autoinstall the Update on App Quit",
"blurMainBody": "Blur Main Body",
"blurMainBodyDescription": "Should the launcher right pane be blurred",
"browseRoot": "Browse",
"checkUpdate": "Check Update",
"cleanOldData": "Clear Data",
Expand Down
12 changes: 10 additions & 2 deletions src/renderer/assets/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@
"autoAlloc": "自动分配",
"browse": "浏览java可执行文件",
"browser": "从文件导入 Java",
"refresh": "刷新本地 Java",
"errorDownload": "自动下载Java失败,请检查你的网络连接。当然你也可以点击返回尝试别的方法。",
"incompatibleJava": "不兼容的 Java",
"incompatibleJavaHint": "当前 Java 版本无法运已选择的 Minecraft 版本",
Expand All @@ -435,6 +434,7 @@
"noJavaInPath": "还是无法在PATH中找到java可执行文件。你可以尝试其他方法。",
"noLegalJava": "启动器认为这个Java可执行文件是无效的。请尝试其他的方法。",
"noMemory": "不设置内存限制",
"refresh": "刷新本地 Java",
"refreshAfter": "请在安装后刷新。",
"switchVersion": "已切换 Java 版本"
},
Expand All @@ -449,11 +449,11 @@
"crash": "游戏崩溃了!",
"failed": {
"description": "没有找到崩溃报告,这里是游戏错误日志和最新的日志文件",
"latest": "最新日志文件",
"general": "启动失败",
"generalText": "如果你反复出现同样的问题,请联系作者!",
"illegalAuth": "用户数据为空",
"illegalAuthText": "无效的用户数据!请尝试重新登陆或切换账号",
"latest": "最新日志文件",
"selectProfileEmpty": "启动配置为空",
"selectProfileEmptyText": "很奇怪,你可以尝试重新创建当前的启动配置。如果你老遇到这个问题请联系作者!",
"title": "游戏未正常退出",
Expand Down Expand Up @@ -560,6 +560,7 @@
},
"forceLocalVersion": "启动指定本地版本",
"forgeSetting": "Forge设置",
"gameVersion": "游戏版本",
"import": {
"description": "导入 Minecraft 到启动器",
"start": "开始导入",
Expand All @@ -568,6 +569,7 @@
"importCurseforge": "从 Curseforge 模组包导入",
"importFolder": "从文件夹导入",
"importZip": "从压缩包导入",
"instanceVersion": "整合包版本",
"launchArguments": "启动命令预览",
"launchingDetail": "启动配置",
"localVersion": "本地版本",
Expand Down Expand Up @@ -596,8 +598,12 @@
"export": "导出整合包",
"exportCurseforge": "导出为 Curseforge 整合包",
"general": "基本信息",
"includeAssets": "是否包含游戏资源 (assets) 文件",
"includeLibraries": "是否包含库文件",
"includeVersion": "包含游戏版本",
"name": "Mod包",
"overrides": "整合包打包覆盖 (overrides)",
"includes": "打包文件",
"profile": "文件名"
},
"name": "名称",
Expand Down Expand Up @@ -734,6 +740,8 @@
"autoDownloadDescription": "自动下载最新的版本",
"autoInstallOnAppQuit": "自动安装",
"autoInstallOnAppQuitDescription": "每次 App 退出后自动安装更新",
"blurMainBody": "模糊窗口主体",
"blurMainBodyDescription": "是否将启动器窗口右侧主体模糊",
"browseRoot": "更改",
"checkUpdate": "检查更新",
"cleanOldData": "清除旧数据",
Expand Down
25 changes: 11 additions & 14 deletions src/renderer/windows/main/pages/HomePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@
/>
<game-exit-dialog />
<feedback-dialog />
<curseforge-export-dialog v-model="isExportingCurseforge" />
<export-dialog
:value="isExportingCurseforge || isExportingModpack"
:is-curseforge="isExportingCurseforge"
@input="isExportingModpack = false; isExportingCurseforge = false"
/>
</v-layout>
</template>

Expand All @@ -180,7 +184,7 @@ import LogDialog from './HomePageLogDialog.vue';
import HomeHeader from './HomePageHeader.vue';
import ProblemsBar from './HomePageProblemsBar.vue';
import ServerStatusBar from './HomePageServerStatusBar.vue';
import CurseforgeExportDialog from './HomePageCurseforgeExportDialog.vue';
import ExportDialog from './HomePageExportDialog.vue';
import ExportSpeedDial from './HomePageExportSpeedDial.vue';
function setupLaunch() {
Expand Down Expand Up @@ -234,33 +238,25 @@ export default defineComponent({
ServerStatusBar,
GameExitDialog,
FeedbackDialog,
CurseforgeExportDialog,
ExportDialog,
ExportSpeedDial,
},
setup() {
const { $t } = useI18n();
const { showSaveDialog } = useNativeDialog();
const { isShown: isLogDialogShown, show: showLogDialog, hide: hideLogDialog } = useDialog('log');
const { show: showFeedbackDialog } = useDialog('feedback');
const { refreshing, name, isServer, exportInstance: exportTo, refreshServerStatus, path } = useInstance();
const { refreshing, name, isServer, refreshServerStatus, path } = useInstance();
const { openDirectory } = useService('BaseService');
const { subscribeTask } = useNotifier();
const { quit } = useQuit();
const isExportingCurseforge = ref(false);
const isExportingModpack = ref(false);
async function showExport(type: 'normal' | 'curseforge') {
if (type === 'curseforge') {
isExportingCurseforge.value = true;
} else {
if (refreshing.value) return;
const { filePath } = await showSaveDialog({
title: $t('profile.export.title'),
filters: [{ name: 'zip', extensions: ['zip'] }],
message: $t('profile.export.message'),
defaultPath: `${name.value}.zip`,
});
if (filePath) {
subscribeTask(exportTo({ destinationPath: filePath, mode: 'full' }), $t('profile.export.title'));
}
isExportingModpack.value = true;
}
}
function showInstanceFolder() {
Expand All @@ -280,6 +276,7 @@ export default defineComponent({
quit,
isExportingCurseforge,
isExportingModpack,
...setupLaunch(),
Expand Down
Loading

0 comments on commit 52b1df3

Please sign in to comment.