forked from didirus/AstralRinth
* update add files copy and go to next step on just one file * rename and reorder stages * add metadata stage and update details stage * implement files inside metadata stage * use regular prettier instead of prettier eslint * remove changelog stage config * save button on details stage * update edit buttons in versions table * add collapse environment selector * implement dependencies list in metadata step * move dependencies into provider * add suggested dependencies to metadata stage * pnpm prepr * fix unused var * Revert "add collapse environment selector" This reverts commit f90fabc7a57ff201f26e1b628eeced8e6ef75865. * hide resource pack loader only when its the only loader * fix no dependencies for modpack * add breadcrumbs with hide breadcrumb option * wider stages * add proper horizonal scroll breadcrumbs * fix titles * handle save version in version page * remove box shadow * add notification provider to storybook * add drop area for versions to drop file right into page * fix mobile versions table buttons overflowing * pnpm prepr * fix drop file opening modal in wrong stage * implement invalid file for dropping files * allow horizontal scroll on breadcrumbs * update infer.js as best as possible * add create version button uploading version state * add extractVersionFromFilename for resource pack and datapack * allow jars for datapack project * detect multiple loaders when possible * iris means compatible with optifine too * infer environment on loader change as well * add tooltip * prevent navigate forward when cannot go to next step * larger breadcrumb click targets * hide loaders and mc versions stage until files added * fix max width in header * fix add files from metadata step jumping steps * define width in NewModal instead * disable remove dependency in metadata stage * switch metadata and details buttons positions * fix remove button spacing * do not allow duplicate suggested dependencies * fix version detection for fabric minecraft version semvar * better verion number detection based on filename * show resource pack loader but uneditable * remove vanilla shader detection * refactor: break up large infer.js into ts and modules * remove duplicated types * add fill missing from file name step * pnpm prepr * fix neoforge loader parse failing and not adding neoforge loader * add missing pack formats * handle new pack format * pnpm prepr * add another regex where it is version in anywhere in filename * only show resource pack or data pack options for filetype on datapack project * add redundant zip folder check * reject RP and DP if has redundant folder * fix hide stage in breadcrumb * add snapshot group key in case no release version. brings out 26.1 snapshots * pnpm prepr * open in group if has something selected * fix resource pack loader uneditable if accidentally selected on different project type * add new environment tags * add unknown and not applicable environment tags * pnpm prepr * use shared constant on labels * use ref for timeout * remove console logs * remove box shadow only for cm-content * feat: xhr upload + fix wrangler prettierignore * fix: upload content type fix * fix dependencies version width * fix already added dependencies logic * add changelog minheight * set progress percentage on button * add legacy fabric detection logic * lint * small update on create version button label --------- Co-authored-by: Calum H. (IMB11) <contact@cal.engineer> Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
133 lines
4.0 KiB
TypeScript
133 lines
4.0 KiB
TypeScript
import JSZip from 'jszip'
|
|
|
|
import { createLoaderParsers } from './loader-parsers'
|
|
import { createMultiFileDetectors } from './multi-file-detectors'
|
|
import { createPackParser } from './pack-parsers'
|
|
import { extractVersionDetailsFromFilename } from './version-utils'
|
|
|
|
export type GameVersion = { version: string; version_type: string }
|
|
|
|
export type Project = { title: string; actualProjectType?: string }
|
|
|
|
export type RawFile = File | (Blob & { name: string })
|
|
|
|
export interface InferredVersionInfo {
|
|
name?: string
|
|
version_number?: string
|
|
version_type?: 'alpha' | 'beta' | 'release'
|
|
loaders?: string[]
|
|
game_versions?: string[]
|
|
}
|
|
|
|
/**
|
|
* Fills in missing version information from the filename if not already present.
|
|
*/
|
|
function fillMissingFromFilename(
|
|
result: InferredVersionInfo,
|
|
filename: string,
|
|
projectTitle: string,
|
|
): InferredVersionInfo {
|
|
const filenameDetails = extractVersionDetailsFromFilename(filename)
|
|
|
|
if (!result.version_number && filenameDetails.versionNumber) {
|
|
result.version_number = filenameDetails.versionNumber
|
|
}
|
|
|
|
if (!result.version_type) {
|
|
result.version_type = filenameDetails.versionType
|
|
}
|
|
|
|
if (!result.name && result.version_number) {
|
|
result.name = `${projectTitle} ${result.version_number}`
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Main function to infer version information from a file.
|
|
* Analyzes mod loaders, packs, and other Minecraft-related file formats.
|
|
*/
|
|
export const inferVersionInfo = async function (
|
|
rawFile: RawFile,
|
|
project: Project,
|
|
gameVersions: GameVersion[],
|
|
): Promise<InferredVersionInfo> {
|
|
const simplifiedGameVersions = gameVersions
|
|
.filter((it) => it.version_type === 'release')
|
|
.map((it) => it.version)
|
|
|
|
const zipReader = new JSZip()
|
|
const zip = await zipReader.loadAsync(rawFile)
|
|
|
|
const loaderParsers = createLoaderParsers(project, gameVersions, simplifiedGameVersions)
|
|
const packParser = createPackParser(project, gameVersions, rawFile)
|
|
const multiFileDetectors = createMultiFileDetectors(project, gameVersions, rawFile)
|
|
|
|
const inferFunctions = {
|
|
...loaderParsers,
|
|
'pack.mcmeta': packParser,
|
|
}
|
|
|
|
// Multi-loader detection
|
|
const multiLoaderFiles = [
|
|
'META-INF/neoforge.mods.toml',
|
|
'META-INF/mods.toml',
|
|
'fabric.mod.json',
|
|
'quilt.mod.json',
|
|
]
|
|
const detectedLoaderFiles = multiLoaderFiles.filter((fileName) => zip.file(fileName) !== null)
|
|
if (detectedLoaderFiles.length > 1) {
|
|
const results: InferredVersionInfo[] = []
|
|
for (const fileName of detectedLoaderFiles) {
|
|
const file = zip.file(fileName)
|
|
if (file !== null) {
|
|
const text = await file.async('text')
|
|
const parser = inferFunctions[fileName as keyof typeof inferFunctions]
|
|
if (parser) {
|
|
const result = await parser(text, zip)
|
|
if (result && Object.keys(result).length > 0) results.push(result)
|
|
}
|
|
}
|
|
}
|
|
if (results.length > 0) {
|
|
const combinedLoaders = [...new Set(results.flatMap((r) => r.loaders || []))]
|
|
const allGameVersions = [...new Set(results.flatMap((r) => r.game_versions || []))]
|
|
const primaryResult = results.find((r) => r.version_number) || results[0]
|
|
|
|
const mergedResult = {
|
|
name: primaryResult.name,
|
|
version_number: primaryResult.version_number,
|
|
version_type: primaryResult.version_type,
|
|
loaders: combinedLoaders,
|
|
game_versions: allGameVersions,
|
|
}
|
|
return fillMissingFromFilename(mergedResult, rawFile.name, project.title)
|
|
}
|
|
}
|
|
|
|
// Standard single-loader detection
|
|
for (const fileName in inferFunctions) {
|
|
const file = zip.file(fileName)
|
|
|
|
if (file !== null) {
|
|
const text = await file.async('text')
|
|
const parser = inferFunctions[fileName as keyof typeof inferFunctions]
|
|
if (parser) {
|
|
const result = await parser(text, zip)
|
|
return fillMissingFromFilename(result, rawFile.name, project.title)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Multi-file detection functions
|
|
for (const detector of Object.values(multiFileDetectors)) {
|
|
const result = await detector(zip)
|
|
if (result !== null) {
|
|
return fillMissingFromFilename(result, rawFile.name, project.title)
|
|
}
|
|
}
|
|
|
|
return fillMissingFromFilename({}, rawFile.name, project.title)
|
|
}
|