zip压缩文件的加载

This commit is contained in:
unanmed 2023-06-08 19:23:43 +08:00
parent 5cbd9950b9
commit b5649c996b
5 changed files with 105 additions and 18 deletions

View File

@ -19,6 +19,7 @@
"ant-design-vue": "^3.2.20", "ant-design-vue": "^3.2.20",
"axios": "^1.4.0", "axios": "^1.4.0",
"chart.js": "^4.3.0", "chart.js": "^4.3.0",
"jszip": "^3.10.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lz-string": "^1.5.0", "lz-string": "^1.5.0",
"mutate-animate": "^1.1.1", "mutate-animate": "^1.1.1",

View File

@ -13,6 +13,9 @@ dependencies:
chart.js: chart.js:
specifier: ^4.3.0 specifier: ^4.3.0
version: 4.3.0 version: 4.3.0
jszip:
specifier: ^3.10.1
version: 3.10.1
lodash-es: lodash-es:
specifier: ^4.17.21 specifier: ^4.17.21
version: 4.17.21 version: 4.17.21
@ -2605,7 +2608,6 @@ packages:
/core-util-is@1.0.3: /core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
dev: true
/create-require@1.1.1: /create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
@ -3184,6 +3186,10 @@ packages:
dev: true dev: true
optional: true optional: true
/immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
dev: false
/imurmurhash@0.1.4: /imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'} engines: {node: '>=0.8.19'}
@ -3212,7 +3218,6 @@ packages:
/inherits@2.0.4: /inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/ip@2.0.0: /ip@2.0.0:
resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==}
@ -3367,7 +3372,6 @@ packages:
/isarray@1.0.0: /isarray@1.0.0:
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
dev: true
/isexe@2.0.0: /isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
@ -3409,6 +3413,15 @@ packages:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
dev: true dev: true
/jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
dependencies:
lie: 3.3.0
pako: 1.0.11
readable-stream: 2.3.8
setimmediate: 1.0.5
dev: false
/kind-of@6.0.3: /kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -3448,6 +3461,12 @@ packages:
- supports-color - supports-color
dev: true dev: true
/lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
dependencies:
immediate: 3.0.6
dev: false
/lines-and-columns@1.2.4: /lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true dev: true
@ -3892,6 +3911,10 @@ packages:
aggregate-error: 3.1.0 aggregate-error: 3.1.0
dev: true dev: true
/pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
dev: false
/pako@2.1.0: /pako@2.1.0:
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
dev: true dev: true
@ -3956,7 +3979,6 @@ packages:
/process-nextick-args@2.0.1: /process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: true
/promise-inflight@1.0.1: /promise-inflight@1.0.1:
resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==}
@ -4050,7 +4072,6 @@ packages:
safe-buffer: 5.1.2 safe-buffer: 5.1.2
string_decoder: 1.1.1 string_decoder: 1.1.1
util-deprecate: 1.0.2 util-deprecate: 1.0.2
dev: true
/readable-stream@3.6.2: /readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
@ -4204,7 +4225,6 @@ packages:
/safe-buffer@5.1.2: /safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
dev: true
/safe-buffer@5.2.1: /safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@ -4253,6 +4273,10 @@ packages:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: true dev: true
/setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
dev: false
/shallow-equal@1.2.1: /shallow-equal@1.2.1:
resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
dev: false dev: false
@ -4368,7 +4392,6 @@ packages:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
dependencies: dependencies:
safe-buffer: 5.1.2 safe-buffer: 5.1.2
dev: true
/string_decoder@1.3.0: /string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
@ -4680,7 +4703,6 @@ packages:
/util-deprecate@1.0.2: /util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: true
/uuid@2.0.3: /uuid@2.0.3:
resolution: {integrity: sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg==} resolution: {integrity: sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg==}

View File

@ -175,7 +175,7 @@ async function rewriteMain(sourceIndex: Record<string, number>) {
.replace(/this\.USE_RESOURCE\s*\=\s*false/, 'this.USE_RESOURCE = true') .replace(/this\.USE_RESOURCE\s*\=\s*false/, 'this.USE_RESOURCE = true')
.replace( .replace(
/this\.RESOURCE_URL\s*\=\s*'.*'/, /this\.RESOURCE_URL\s*\=\s*'.*'/,
"this.RESOURCE_URL = '/games/HumanBreakRes/'" "this.RESOURCE_URL = '/games/HumanBreakRes'"
) )
.replace( .replace(
/this\.RESOURCE_SYMBOL\s*\=\s*'.*'/, /this\.RESOURCE_SYMBOL\s*\=\s*'.*'/,

View File

@ -1,12 +1,16 @@
import axios, { AxiosResponse } from 'axios'; import axios, { AxiosResponse } from 'axios';
import { Disposable } from '../common/disposable'; import { Disposable } from '../common/disposable';
import { ensureArray } from '../../plugin/game/utils'; import { ensureArray } from '../../plugin/game/utils';
import { has } from '../../plugin/utils';
import JSZip from 'jszip';
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
interface ResourceData { interface ResourceData {
image: HTMLImageElement; image: HTMLImageElement;
arraybuffer: ArrayBuffer; arraybuffer: ArrayBuffer;
text: string; text: string;
json: any; json: any;
zip: ZippedResource;
} }
type ResourceType = keyof ResourceData; type ResourceType = keyof ResourceData;
@ -25,20 +29,43 @@ export class Resource<
super(resource); super(resource);
this.data = this.resolveUrl(resource); this.data = this.resolveUrl(resource);
this.format = type; this.format = type;
this.on('active', this.load); this.on('active', this.load);
} }
/**
* url
* @param resource
* @returns url
*/
protected resolveUrl(resource: string) { protected resolveUrl(resource: string) {
const resolve = resource.split('.'); const resolve = resource.split('.');
const type = resolve[0]; const type = resolve[0];
const name = resolve.slice(1).join('.'); const name = resolve.slice(1, -1).join('.');
return resource; const ext = '.' + resolve.at(-1);
if (!main.USE_RESOURCE) {
return `/games/${core.data.firstData.name}/project/${type}/${name}${ext}`;
}
const base = main.RESOURCE_URL;
const indexes = main.RESOURCE_INDEX;
const symbol = main.RESOURCE_SYMBOL;
if (has(indexes[`${type}.*`])) {
const i = indexes[`${type}.*`];
return `${base}${i}/${type}/${name}-${symbol}${ext}`;
} else {
const i = indexes[`${type}.${name}${ext}`];
const index = has(i) ? i : 0;
return `${base}${index}/${type}/${name}-${symbol}${ext}`;
}
} }
/** /**
* *
*/ */
protected async load() { protected load() {
const data = this.data; const data = this.data;
if (!data) { if (!data) {
throw new Error(`Unexpected null of url in loading resource.`); throw new Error(`Unexpected null of url in loading resource.`);
@ -53,11 +80,23 @@ export class Resource<
res('@imageLoaded'); res('@imageLoaded');
}); });
}); });
} else { } else if (
this.format === 'json' ||
this.format === 'text' ||
this.format === 'arraybuffer'
) {
this.request = axios this.request = axios
.get(data, { responseType: this.format }) .get(data, { responseType: this.format })
.then(v => { .then(v => {
this.resource = v; this.resource = v.data;
this.loaded = true;
return v;
});
} else if (this.format === 'zip') {
this.request = axios
.get(data, { responseType: 'arraybuffer' })
.then(v => {
this.resource = new ZippedResource(v.data);
this.loaded = true; this.loaded = true;
return v; return v;
}); });
@ -68,15 +107,35 @@ export class Resource<
* *
*/ */
async getData(): Promise<ResourceData[T] | null> { async getData(): Promise<ResourceData[T] | null> {
if (!this.activated) return null;
if (this.loaded) return this.resource ?? null; if (this.loaded) return this.resource ?? null;
else { else {
if (!this.request) this.load();
await this.request; await this.request;
return this.resource ?? null; return this.resource ?? null;
} }
} }
} }
class ReosurceStore extends Map<string, Resource> { interface ZippedEvent extends EmitableEvent {
ready: (data: JSZip) => void;
}
export class ZippedResource extends EventEmitter<ZippedEvent> {
zip: Promise<JSZip>;
data?: JSZip;
constructor(buffer: ArrayBuffer) {
super();
this.zip = JSZip.loadAsync(buffer).then(v => {
this.emit('ready', v);
this.data = v;
return v;
});
}
}
class ResourceStore extends Map<string, Resource> {
active(key: string[] | string) { active(key: string[] | string) {
const keys = ensureArray(key); const keys = ensureArray(key);
keys.forEach(v => this.get(v)?.active()); keys.forEach(v => this.get(v)?.active());
@ -115,10 +174,10 @@ class ReosurceStore extends Map<string, Resource> {
declare global { declare global {
interface Window { interface Window {
/** 游戏资源 */ /** 游戏资源 */
gameResource: ReosurceStore; gameResource: ResourceStore;
} }
/** 游戏资源 */ /** 游戏资源 */
const gameResource: ReosurceStore; const gameResource: ResourceStore;
} }
window.gameResource = new ReosurceStore(); window.gameResource = new ResourceStore();

5
src/types/core.d.ts vendored
View File

@ -1256,6 +1256,11 @@ interface Main extends MainData {
*/ */
readonly __VERSION_CODE__: number; readonly __VERSION_CODE__: number;
readonly RESOURCE_INDEX: Record<string, string>;
readonly RESOURCE_URL: string;
readonly RESOURCE_SYMBOL: string;
readonly USE_RESOURCE: boolean;
/** /**
* *
* @param mode * @param mode