poi-plugin-quest-info-2 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.eslintrc.js +1 -2
  2. package/build/kcQuestsData/DATA_VERSION +1 -1
  3. package/build/kcQuestsData/index.ts +1 -1
  4. package/build/kcQuestsData/quests-scn-new.json +1 -3
  5. package/build/kcQuestsData/quests-scn.json +72 -72
  6. package/build/kcanotifyGamedata/DATA_VERSION +1 -1
  7. package/build/kcanotifyGamedata/index.ts +1 -1
  8. package/build/kcanotifyGamedata/quests-en.json +12 -0
  9. package/build/kcanotifyGamedata/quests-jp.json +12 -0
  10. package/build/kcanotifyGamedata/quests-ko.json +12 -5
  11. package/build/kcanotifyGamedata/quests-scn.json +12 -0
  12. package/build/kcanotifyGamedata/quests-tcn.json +12 -0
  13. package/build/prePostQuest.json +4498 -0
  14. package/build/questCategory.json +590 -588
  15. package/build/questCodeMap.json +575 -0
  16. package/i18n/en-US.json +1 -0
  17. package/i18n/ja-JP.json +1 -0
  18. package/i18n/ko-KR.json +1 -0
  19. package/i18n/zh-CN.json +1 -0
  20. package/i18n/zh-TW.json +1 -0
  21. package/package.json +15 -15
  22. package/src/__tests__/__snapshots__/questCategory.spec.ts.snap +113 -113
  23. package/src/__tests__/kcanotifyData.spec.ts +14 -1
  24. package/src/__tests__/kcwikiData.spec.ts +11 -1
  25. package/src/__tests__/questCategory.spec.ts +4 -4
  26. package/src/components/QuestCard/MinimalQuestCard.tsx +14 -14
  27. package/src/components/QuestCard/index.tsx +90 -55
  28. package/src/components/QuestCard/styles.ts +17 -0
  29. package/src/components/QuestList.tsx +5 -8
  30. package/src/components/QuestTag.tsx +104 -0
  31. package/src/poi/hooks.ts +8 -5
  32. package/src/questHelper.ts +25 -4
  33. package/src/store/kcwiki.ts +7 -3
  34. package/src/store/quest.ts +91 -10
  35. package/src/tags.tsx +2 -2
  36. package/scripts/convertAssets.ts +0 -57
  37. package/scripts/downloadKcQuestsData.ts +0 -136
  38. package/scripts/downloadKcanotifyGamedata.ts +0 -132
  39. package/scripts/downloadSprites.ts +0 -126
  40. package/scripts/genQuestCategory.ts +0 -58
  41. package/scripts/proxyFetch.ts +0 -42
  42. package/scripts/utils.ts +0 -8
  43. package/src/components/PreTaskTag.tsx +0 -40
@@ -1,20 +1,29 @@
1
1
  import { useCallback } from 'react'
2
- import { QuestData } from '../../build/kcanotifyGamedata'
3
2
  import { useGameQuest, usePluginTranslation } from '../poi/hooks'
4
- import { getCategory } from '../questHelper'
3
+ import {
4
+ DocQuest,
5
+ getCategory,
6
+ getKcanotifyQuestData,
7
+ getQuestIdByCode,
8
+ getQuestPrePost,
9
+ QUEST_STATUS,
10
+ } from '../questHelper'
5
11
  import type { UnionQuest } from '../questHelper'
6
12
  import { useKcwikiData, checkIsKcwikiSupportedLanguages } from './kcwiki'
7
13
  import { useStore, useSyncWithGame } from './store'
8
14
 
9
15
  const DEFAULT_LANG = 'ja-JP'
10
16
 
11
- export const checkIsKcanotifySupportedLanguages = (
17
+ const checkIsKcanotifySupportedLanguages = (
12
18
  lang: string
13
- ): lang is keyof typeof QuestData => lang in QuestData
19
+ ): lang is keyof typeof kcaQuestData => {
20
+ const kcaQuestData = getKcanotifyQuestData()
21
+ return lang in kcaQuestData
22
+ }
14
23
 
15
24
  export const isSupportedLanguages = (
16
25
  lang: string
17
- ): lang is keyof typeof QuestData =>
26
+ ): lang is keyof ReturnType<typeof getKcanotifyQuestData> =>
18
27
  checkIsKcanotifySupportedLanguages(lang) ||
19
28
  checkIsKcwikiSupportedLanguages(lang)
20
29
 
@@ -28,13 +37,14 @@ export const useLanguage = () => {
28
37
  return lang
29
38
  }
30
39
 
31
- const useQuestMap = () => {
40
+ const useQuestMap = (): Record<string, DocQuest> => {
32
41
  const lang = useLanguage()
33
42
  const kcwikiData = useKcwikiData(lang)
34
43
  if (kcwikiData) {
35
44
  return kcwikiData
36
45
  }
37
- return QuestData[lang]
46
+ const kcaQuestData = getKcanotifyQuestData()
47
+ return kcaQuestData[lang]
38
48
  }
39
49
 
40
50
  export const useQuest = (): UnionQuest[] => {
@@ -44,12 +54,12 @@ export const useQuest = (): UnionQuest[] => {
44
54
 
45
55
  if (syncWithGame && gameQuest.length) {
46
56
  return gameQuest.map((quest) => {
47
- const gameId = String(quest.api_no)
57
+ const gameId = quest.api_no
48
58
  if (gameId in docQuestMap) {
49
59
  return {
50
60
  gameId,
51
61
  gameQuest: quest,
52
- docQuest: docQuestMap[gameId as keyof typeof docQuestMap],
62
+ docQuest: docQuestMap[String(gameId) as keyof typeof docQuestMap],
53
63
  }
54
64
  }
55
65
 
@@ -68,7 +78,7 @@ export const useQuest = (): UnionQuest[] => {
68
78
  } else {
69
79
  // Return all recorded quests
70
80
  return Object.entries(docQuestMap).map(([gameId, val]) => ({
71
- gameId,
81
+ gameId: +gameId,
72
82
  // Maybe empty
73
83
  gameQuest: gameQuest.find((quest) => quest.api_no === Number(gameId))!,
74
84
  docQuest: val,
@@ -76,6 +86,77 @@ export const useQuest = (): UnionQuest[] => {
76
86
  }
77
87
  }
78
88
 
89
+ export const useQuestByCode = (code: string): UnionQuest | null => {
90
+ const questMap = useQuestMap()
91
+ const gameId = getQuestIdByCode(code)
92
+ if (gameId && gameId in questMap) {
93
+ return {
94
+ gameId,
95
+ docQuest: questMap[String(gameId) as keyof typeof questMap],
96
+ }
97
+ }
98
+ return null
99
+ }
100
+
101
+ const useCompletedQuest = () => {
102
+ const completedQuest: Record<number, true> = {}
103
+ const gameQuest = useGameQuest()
104
+ const queue: number[] = gameQuest.map((quest) => quest.api_no)
105
+ while (queue.length) {
106
+ const gameId = queue.shift()!
107
+ if (gameId in completedQuest) {
108
+ continue
109
+ }
110
+ completedQuest[gameId] = true
111
+
112
+ const prePostQuests = getQuestPrePost(gameId)
113
+ prePostQuests.pre.forEach((nextCode) => {
114
+ const nextGameId = getQuestIdByCode(nextCode)
115
+ if (nextGameId) {
116
+ queue.push(nextGameId)
117
+ }
118
+ })
119
+ }
120
+ return completedQuest
121
+ }
122
+
123
+ const useLockedQuest = () => {
124
+ const lockedQuest: Record<number, true> = {}
125
+ const gameQuest = useGameQuest()
126
+ const queue: number[] = gameQuest.map((quest) => quest.api_no)
127
+ while (queue.length) {
128
+ const gameId = queue.shift()!
129
+ if (gameId in lockedQuest) {
130
+ continue
131
+ }
132
+ lockedQuest[gameId] = true
133
+ const prePostQuests = getQuestPrePost(gameId)
134
+ prePostQuests.post.forEach((nextCode) => {
135
+ const nextGameId = getQuestIdByCode(nextCode)
136
+ if (nextGameId) {
137
+ queue.push(nextGameId)
138
+ }
139
+ })
140
+ }
141
+ return lockedQuest
142
+ }
143
+
144
+ export const useQuestStatus = (gameId: number | null) => {
145
+ const completedQuest = useCompletedQuest()
146
+ const lockedQuest = useLockedQuest()
147
+
148
+ if (!gameId) {
149
+ return QUEST_STATUS.DEFAULT
150
+ }
151
+ if (gameId in completedQuest) {
152
+ return QUEST_STATUS.ALREADY_COMPLETED
153
+ }
154
+ if (gameId in lockedQuest) {
155
+ return QUEST_STATUS.LOCKED
156
+ }
157
+ return QUEST_STATUS.DEFAULT
158
+ }
159
+
79
160
  /**
80
161
  * @deprecated Not large card now
81
162
  */
package/src/tags.tsx CHANGED
@@ -38,12 +38,12 @@ export const ALL_CATEGORY_TAG = {
38
38
  export const ALL_TYPE_TAG = ALL_CATEGORY_TAG
39
39
 
40
40
  const withDocQuest =
41
- <T extends any>(filterFn: (q: UnionQuest['docQuest']) => T) =>
41
+ <T,>(filterFn: (q: UnionQuest['docQuest']) => T) =>
42
42
  (unionQuest: UnionQuest) =>
43
43
  filterFn(unionQuest.docQuest)
44
44
 
45
45
  const withGameQuestOr =
46
- <T extends any>(filterFn: (q: GameQuest) => T, fallback: T) =>
46
+ <T,>(filterFn: (q: GameQuest) => T, fallback: T) =>
47
47
  ({ gameQuest }: UnionQuest) => {
48
48
  if (!gameQuest) {
49
49
  return fallback
@@ -1,57 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
- import { prepareDir } from './utils'
4
-
5
- const ASSETS_PATH = path.resolve('assets')
6
- const OUTPUT_PATH = path.resolve('build')
7
- const OUTPUT_FILE = path.resolve(OUTPUT_PATH, 'assets.ts')
8
- const CONVERT_EXTS = ['jpg', 'png'] as const
9
-
10
- const HEADER = `/* eslint-disable prettier/prettier */
11
- /**
12
- * This file was automatically generated by \`${path.relative(
13
- // project root
14
- process.cwd(),
15
- __filename
16
- )}\`
17
- * Do not edit this file directly.
18
- */` as const
19
-
20
- function base64Encode(file: string) {
21
- const bitmap = fs.readFileSync(file)
22
- return bitmap.toString('base64')
23
- }
24
-
25
- function main() {
26
- prepareDir(OUTPUT_PATH)
27
- const imageData = fs
28
- .readdirSync(ASSETS_PATH)
29
- // exclusive ignored ext
30
- .filter((f) => CONVERT_EXTS.some((ext) => f.endsWith('.' + ext)))
31
- .map((fileName) => {
32
- const filePath = path.resolve(ASSETS_PATH, fileName)
33
- const parsedFile = path.parse(fileName)
34
- return {
35
- name: parsedFile.name,
36
- ext: parsedFile.ext.slice(1),
37
- base64: base64Encode(filePath),
38
- }
39
- })
40
-
41
- const data = `${HEADER}
42
-
43
- ${imageData
44
- .map(
45
- ({ name, ext, base64 }) =>
46
- `export const ${name} = 'data:image/${ext};base64, ${base64}'`
47
- )
48
- .join('\n')}
49
- `
50
-
51
- fs.writeFileSync(OUTPUT_FILE, data)
52
-
53
- // eslint-disable-next-line no-console
54
- console.log('Converted', imageData.length, 'images.')
55
- }
56
-
57
- main()
@@ -1,136 +0,0 @@
1
- /* eslint-disable no-console */
2
- import { existsSync, readFileSync, writeFileSync } from 'fs'
3
- import pangu from 'pangu'
4
- import path from 'path'
5
- import { fetch } from './proxyFetch'
6
- import { prepareDir } from './utils'
7
-
8
- // See https://github.com/kcwikizh/kcQuests
9
-
10
- const OUTPUT_PATH = path.resolve('build', 'kcQuestsData')
11
- const DATA_FILE_NAME = 'quests-scn.json'
12
- const DATA_URL = `https://kcwikizh.github.io/kcQuests/${DATA_FILE_NAME}`
13
- const NEW_QUEST_FILE_NAME = 'quests-scn-new.json'
14
- const NEW_QUEST_URL = `https://kcwikizh.github.io/kcQuests/${NEW_QUEST_FILE_NAME}`
15
- const VERSION_URL =
16
- 'https://api.github.com/repos/kcwikizh/kcQuests/branches/main'
17
-
18
- // maybe need ignore some expired quest
19
- const IGNORE_DATA = [] as const
20
-
21
- const getRemoteVersion = async () => {
22
- const resp = await fetch(VERSION_URL)
23
- if (!resp.ok) {
24
- throw new Error(`Fetch Error!\nurl: ${resp.url}\nstatus: ${resp.status}`)
25
- }
26
- return (await resp.json()).commit.sha
27
- }
28
-
29
- const getLocalVersion = () => {
30
- const localVersionFile = path.resolve(OUTPUT_PATH, 'DATA_VERSION')
31
- const version = existsSync(localVersionFile)
32
- ? readFileSync(localVersionFile).toString()
33
- : '0'
34
- return version
35
- }
36
-
37
- /**
38
- * @example
39
- * ```ts
40
- * import zh_CN from './quests-scn.json'
41
- * export default {
42
- * 'zh-CN': zh_CN,
43
- * }
44
- * export const version = '5.1.2.1'
45
- * ```
46
- */
47
- const genTS = (version: string) => {
48
- const importCode = `import zh_CN from './quests-scn.json'`
49
-
50
- const exportCode = [
51
- 'export const KcwikiQuestData = {',
52
- ` 'zh-CN': zh_CN,`,
53
- '}',
54
- ].join('\n')
55
-
56
- const versionCode = `export const version = '${version}'`
57
- return `${importCode}\n\n${exportCode}\n\n${versionCode}\n`
58
- }
59
-
60
- const downloadQuestData = async () => {
61
- const resp = await fetch(DATA_URL)
62
- if (!resp.ok) {
63
- console.error(`Fetch Error!\nurl: ${resp.url}\nstatus: ${resp.status}`)
64
- return
65
- }
66
- const text = await resp.text()
67
-
68
- const json = JSON.parse(text) as {
69
- [gameId: string]: {
70
- code: string
71
- name: string
72
- desc: string
73
- memo?: string
74
- memo2?: string
75
- }
76
- }
77
- for (const gameId in json) {
78
- const { code, name, desc, memo, memo2 } = json[gameId]
79
- json[gameId].code = code.trim()
80
- json[gameId].name = pangu.spacing(name)
81
- json[gameId].desc = pangu.spacing(desc)
82
- if (memo) {
83
- json[gameId].memo = pangu.spacing(memo)
84
- }
85
- if (memo2) {
86
- json[gameId].memo2 = pangu.spacing(memo2)
87
- }
88
- }
89
-
90
- IGNORE_DATA.forEach((gameId) => delete json[gameId])
91
- const data = JSON.stringify(json, undefined, 2)
92
- writeFileSync(path.resolve(OUTPUT_PATH, DATA_FILE_NAME), data)
93
- }
94
-
95
- const downloadNewQuest = async () => {
96
- const resp = await fetch(NEW_QUEST_URL)
97
- if (!resp.ok) {
98
- console.error(`Fetch Error!\nurl: ${resp.url}\nstatus: ${resp.status}`)
99
- return
100
- }
101
- const text = await resp.text()
102
- const json = Object.keys(JSON.parse(text))
103
- const data = JSON.stringify(json, undefined, 2)
104
- writeFileSync(path.resolve(OUTPUT_PATH, NEW_QUEST_FILE_NAME), data)
105
- }
106
-
107
- const main = async () => {
108
- const args = process.argv.slice(2)
109
-
110
- prepareDir(OUTPUT_PATH)
111
- const remoteVersion = await getRemoteVersion()
112
- const localVersion = getLocalVersion()
113
- if (remoteVersion === localVersion) {
114
- console.log('The local version is up to date. Version:', localVersion)
115
- if (!args.find((v) => v === '-f' || v === '--force')) {
116
- return
117
- }
118
- } else {
119
- console.log('New Version Detected. Version:', remoteVersion)
120
- }
121
-
122
- console.log(`Download kcQuests data...`)
123
- await Promise.all([downloadQuestData(), downloadNewQuest()])
124
-
125
- const ts = genTS(remoteVersion)
126
- writeFileSync(`${OUTPUT_PATH}/index.ts`, ts)
127
-
128
- // Finally record the version number
129
- writeFileSync(`${OUTPUT_PATH}/DATA_VERSION`, remoteVersion)
130
- }
131
-
132
- main()
133
-
134
- process.on('unhandledRejection', (up) => {
135
- throw up
136
- })
@@ -1,132 +0,0 @@
1
- /* eslint-disable no-console */
2
- import { existsSync, readFileSync, writeFileSync } from 'fs'
3
- import pangu from 'pangu'
4
- import path from 'path'
5
- import { fetch } from './proxyFetch'
6
- import { prepareDir } from './utils'
7
-
8
- // See https://github.com/antest1/kcanotify-gamedata
9
-
10
- const OUTPUT_PATH = path.resolve('build', 'kcanotifyGamedata')
11
- const URL_PREFIX =
12
- 'https://raw.githubusercontent.com/antest1/kcanotify-gamedata/master'
13
- const VERSION_URL = `${URL_PREFIX}/KCAINFO`
14
- const DATA_URL = `${URL_PREFIX}/files`
15
- const LANGS = ['scn', 'tcn', 'jp', 'en', 'ko'] as const
16
- const LOCALES = ['zh-CN', 'zh-TW', 'ja-JP', 'en-US', 'ko-KR'] as const
17
-
18
- const getRemoteVersion = async () => {
19
- const resp = await fetch(VERSION_URL)
20
- if (!resp.ok) {
21
- throw new Error(`Fetch Error!\nurl: ${resp.url}\nstatus: ${resp.status}`)
22
- }
23
- const KCAINFO: {
24
- version: string
25
- data_version: string
26
- kcadata_version: number
27
- kc_maintenance: string[]
28
- } = await resp.json()
29
-
30
- return String(KCAINFO.kcadata_version)
31
- }
32
-
33
- const getLocalVersion = () => {
34
- const localVersionFile = path.resolve(OUTPUT_PATH, 'DATA_VERSION')
35
- const version = existsSync(localVersionFile)
36
- ? readFileSync(localVersionFile).toString()
37
- : '0'
38
- return version
39
- }
40
-
41
- /**
42
- * @example
43
- * ```ts
44
- * import zh_CN from './quests-scn.json'
45
- * export default {
46
- * 'zh-CN': zh_CN,
47
- * }
48
- * export const version = '5.1.2.1'
49
- * ```
50
- */
51
- const genTS = (version: string) => {
52
- const importCode = LOCALES.map(
53
- (locale, idx) =>
54
- `import ${locale.replace('-', '_')} from './quests-${LANGS[idx]}.json'`
55
- ).join('\n')
56
-
57
- const exportCode =
58
- 'export const QuestData = {\n' +
59
- LOCALES.map((locale) => ` '${locale}': ${locale.replace('-', '_')},`).join(
60
- '\n'
61
- ) +
62
- '\n}'
63
-
64
- const versionCode = `export const version = '${version}'`
65
- return `${importCode}\n\n${exportCode}\n\n${versionCode}\n`
66
- }
67
-
68
- const main = async () => {
69
- const args = process.argv.slice(2)
70
-
71
- prepareDir(OUTPUT_PATH)
72
- const remoteVersion = await getRemoteVersion()
73
- const localVersion = getLocalVersion()
74
- if (remoteVersion === localVersion) {
75
- console.log('The local version is up to date. Version:', localVersion)
76
- if (!args.find((v) => v === '-f' || v === '--force')) {
77
- return
78
- }
79
- } else {
80
- console.log('New Version Detected. Version:', remoteVersion)
81
- }
82
-
83
- await Promise.all(
84
- LANGS.map(async (lang) => {
85
- const filename = `quests-${lang}.json`
86
- const fileURL = `${DATA_URL}/${filename}`
87
-
88
- console.log(`Download ${filename}...`)
89
- const resp = await fetch(fileURL)
90
- if (!resp.ok) {
91
- console.error(`Fetch Error!\nurl: ${resp.url}\nstatus: ${resp.status}`)
92
- return
93
- }
94
- let text = await resp.text()
95
- // TODO fix source file
96
- // Remove BOM(U+FEFF) from the header of the quests-ko.json
97
- text = text.trim()
98
-
99
- const json = JSON.parse(text) as {
100
- [gameId: string]: {
101
- code: string
102
- name: string
103
- desc: string
104
- memo?: string
105
- }
106
- }
107
- for (const gameId in json) {
108
- const { name, desc, memo } = json[gameId]
109
- json[gameId].name = pangu.spacing(name)
110
- json[gameId].desc = pangu.spacing(desc)
111
- if (memo) {
112
- json[gameId].memo = pangu.spacing(memo)
113
- }
114
- }
115
-
116
- const data = JSON.stringify(json, undefined, 2)
117
- writeFileSync(`${OUTPUT_PATH}/${filename}`, data)
118
- })
119
- )
120
-
121
- const ts = genTS(remoteVersion)
122
- writeFileSync(`${OUTPUT_PATH}/index.ts`, ts)
123
-
124
- // Finally record the version number
125
- writeFileSync(`${OUTPUT_PATH}/DATA_VERSION`, remoteVersion)
126
- }
127
-
128
- main()
129
-
130
- process.on('unhandledRejection', (up) => {
131
- throw up
132
- })
@@ -1,126 +0,0 @@
1
- /* eslint-disable no-console */
2
- import path from 'path'
3
- import fs from 'fs'
4
- import crypto from 'crypto'
5
- // See https://sharp.pixelplumbing.com/
6
- import sharp from 'sharp'
7
- import { fetch } from './proxyFetch'
8
- import { prepareDir } from './utils'
9
-
10
- const OUTPUT_PATH = path.resolve('build', 'dutySprites')
11
-
12
- const SERVER_URL = 'http://203.104.209.199'
13
- const JSON_PATH = '/kcs2/img/duty/duty_main.json'
14
- const SPRITES_PATH = '/kcs2/img/duty/duty_main.png'
15
- const VERSION = '5.1.2.0'
16
- const SPRITES_URL = `${SERVER_URL}${SPRITES_PATH}?version=${VERSION}`
17
- const META_URL = `${SERVER_URL}${JSON_PATH}?version=${VERSION}`
18
-
19
- const getFilename = (url: string) => {
20
- const pathname = new URL(url).pathname
21
- const index = pathname.lastIndexOf('/')
22
- return index !== -1 ? pathname.slice(index + 1) : pathname
23
- }
24
-
25
- const download = async (url: string, filename?: string) => {
26
- if (!filename) {
27
- filename = getFilename(url)
28
- }
29
- const filePath = path.resolve(OUTPUT_PATH, filename)
30
- const response = await fetch(url)
31
- const buffer = await response.buffer()
32
- await fs.writeFileSync(filePath, buffer)
33
- return { filePath, buffer }
34
- }
35
-
36
- const checksumFile = (algorithm: string, path: fs.PathLike) => {
37
- return new Promise<string>((resolve, reject) => {
38
- const hash = crypto.createHash(algorithm)
39
- const stream = fs.createReadStream(path)
40
- stream.on('error', (err) => reject(err))
41
- stream.on('data', (chunk) => hash.update(chunk))
42
- stream.on('end', () => resolve(hash.digest('hex')))
43
- })
44
- }
45
-
46
- const cropAndSaveImage = (
47
- img: Buffer,
48
- {
49
- name,
50
- format,
51
- x,
52
- y,
53
- w,
54
- h,
55
- }: {
56
- name: string
57
- format: string
58
- x: number
59
- y: number
60
- w: number
61
- h: number
62
- }
63
- ) => {
64
- const filename = `${name}.${format}`
65
- sharp(img)
66
- .extract({ left: x, top: y, width: w, height: h })
67
- .toFile(path.resolve(OUTPUT_PATH, filename))
68
- .catch((err) => {
69
- console.error('Failed to process image:', filename, err)
70
- })
71
- }
72
-
73
- type KCS2Meta = {
74
- frames: {
75
- [name: string]: {
76
- frame: {
77
- x: number
78
- y: number
79
- w: number
80
- h: number
81
- }
82
- rotated: boolean
83
- trimmed: boolean
84
- spriteSourceSize: {
85
- x: number
86
- y: number
87
- w: number
88
- h: number
89
- }
90
- sourceSize: {
91
- w: number
92
- h: number
93
- }
94
- }
95
- }
96
- meta: any
97
- }
98
-
99
- const parseSprites = (sprites: Buffer, meta: KCS2Meta) => {
100
- const { frames } = meta
101
- for (const [name, { frame }] of Object.entries(frames)) {
102
- cropAndSaveImage(sprites, { ...frame, name, format: 'png' })
103
- }
104
- }
105
-
106
- const main = async () => {
107
- prepareDir(OUTPUT_PATH)
108
- const [
109
- { buffer: metaBuffer },
110
- { filePath: spritesPath, buffer: spritesBuffer },
111
- ] = await Promise.all([download(META_URL), download(SPRITES_URL)])
112
-
113
- const spritesFilename = path.parse(spritesPath).base
114
- const md5 = await checksumFile('md5', spritesPath)
115
- fs.writeFileSync(path.resolve(OUTPUT_PATH, `${spritesFilename}.md5`), md5)
116
- console.log('File download complete')
117
- console.log(spritesFilename, 'MD5:', md5)
118
-
119
- parseSprites(spritesBuffer, JSON.parse(metaBuffer.toString()))
120
- }
121
-
122
- main()
123
-
124
- process.on('unhandledRejection', (up) => {
125
- throw up
126
- })
@@ -1,58 +0,0 @@
1
- import { writeFileSync } from 'fs'
2
- import path from 'path'
3
- import { QuestData } from '../build/kcanotifyGamedata'
4
- import { KcwikiQuestData } from '../build/kcQuestsData'
5
-
6
- const OUTPUT_PATH = path.resolve('build', 'questCategory.json')
7
-
8
- const kcaQuestStartsFilter = (str: string) =>
9
- Object.entries(QuestData['zh-CN'])
10
- .filter(([, quest]) => quest.name.startsWith(str))
11
- .map(([gameId]) => gameId)
12
-
13
- const kcwikiDataSelector = () => Object.entries(KcwikiQuestData['zh-CN'])
14
- const mergeDataSelector = () =>
15
- Object.entries({ ...QuestData['zh-CN'], ...KcwikiQuestData['zh-CN'] })
16
-
17
- const main = () => {
18
- const dailyQuest = kcaQuestStartsFilter('(日任)')
19
- const weeklyQuest = kcaQuestStartsFilter('(周任)')
20
- const monthlyQuest = kcaQuestStartsFilter('(月任)')
21
- const quarterlyQuest = [
22
- ...new Set([
23
- ...kcaQuestStartsFilter('(季任)'),
24
- ...kcwikiDataSelector()
25
- .filter(([, quest]) => quest.memo2.includes('季常任务'))
26
- .map(([gameId]) => gameId),
27
- ]),
28
- ].sort((a, b) => +a - +b)
29
- // (年任) (年任 / x 月)
30
- const yearlyQuest = kcwikiDataSelector()
31
- .filter(([, quest]) => quest.memo2.includes('年常任务'))
32
- .map(([gameId]) => gameId)
33
- const singleQuest = mergeDataSelector()
34
- .filter(
35
- ([gameId]) =>
36
- ![
37
- ...dailyQuest,
38
- ...weeklyQuest,
39
- ...monthlyQuest,
40
- ...quarterlyQuest,
41
- ...yearlyQuest,
42
- ].includes(gameId)
43
- )
44
- .map(([gameId]) => gameId)
45
-
46
- const data = {
47
- dailyQuest,
48
- weeklyQuest,
49
- monthlyQuest,
50
- quarterlyQuest,
51
- yearlyQuest,
52
- singleQuest,
53
- }
54
-
55
- writeFileSync(OUTPUT_PATH, JSON.stringify(data, null, 2))
56
- }
57
-
58
- main()