From f29cef440f74a63fbab6566628aa2162f31d9e56 Mon Sep 17 00:00:00 2001 From: "Lillith Rose (Device: Lucia)" Date: Sat, 28 Jun 2025 14:44:05 -0400 Subject: [PATCH] initial commit --- action.yml | 15 ++++++++ index.js | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 10 +++++ 3 files changed, 128 insertions(+) create mode 100644 action.yml create mode 100644 index.js create mode 100644 package.json diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..75c4a56 --- /dev/null +++ b/action.yml @@ -0,0 +1,15 @@ +name: Create UnityPackage +description: Create a .unitypackage from Unity project files with .meta files +inputs: + projectDir: + description: Path to the root of your Unity project + required: true + filesDir: + description: Subfolder to pack (relative to projectDir) + required: true + output: + description: Output path for the .unitypackage file + required: true +runs: + using: "node20" + main: "index.js" diff --git a/index.js b/index.js new file mode 100644 index 0000000..70b75f6 --- /dev/null +++ b/index.js @@ -0,0 +1,103 @@ +import { + mkdirSync, + mkdtempSync, + readdirSync, + createReadStream, + createWriteStream, + existsSync, +} from "fs"; +import { copyFile, readFile, writeFile, rm } from "fs/promises"; +import { tmpdir } from "os"; +import { join } from "path"; +import * as tar from "tar-stream"; +import { createGzip } from "zlib"; +import { parse as yamlParse } from "yaml"; + +const projectDir = process.env["INPUT_PROJECTDIR"]; +const filesDir = process.env["INPUT_FILESDIR"]; +const output = process.env["INPUT_OUTPUT"]; + +if (!projectDir || !filesDir || !output) { + console.error("Missing required input(s)."); + process.exit(1); +} + +const tempdir = (name) => { + const dir = mkdtempSync(join(tmpdir(), name)); + return dir; +}; + +const mkdir = (dir, recursive = false) => { + mkdirSync(dir, { recursive }); + return dir; +}; + +const getMetaFiles = (root) => { + const recurse = (dir) => { + const entries = readdirSync(join(root, dir), { withFileTypes: true }); + let files = []; + for (const entry of entries) { + const fullPath = join(dir, entry.name); + if (entry.isDirectory()) { + files = files.concat(recurse(fullPath)); + } else if (entry.name.endsWith(".meta")) { + files.push(fullPath); + } + } + return files; + }; + return recurse("."); +}; + +const createUnityPackage = async () => { + const metaFiles = getMetaFiles(join(projectDir, filesDir)); + const tempDir = tempdir("unitypackage-create-"); + + for await (const metaFile of metaFiles) { + const assetPath = metaFile.replace(/\.meta$/, ""); + const metaPath = join(projectDir, filesDir, metaFile); + + const meta = yamlParse(await readFile(metaPath, "utf8")); + const guid = meta.guid; + if (!guid) continue; + + const dir = mkdir(join(tempDir, guid), true); + + const assetFullPath = join(projectDir, filesDir, assetPath); + if (!meta.folderAsset && existsSync(assetFullPath)) { + await copyFile(assetFullPath, join(dir, "asset")); + } + await copyFile(metaPath, join(dir, "asset.meta")); + await writeFile(join(dir, "pathname"), join(filesDir, assetPath)); + } + + const pack = tar.pack(); + for (const guidDir of readdirSync(tempDir)) { + const entryDir = join(tempDir, guidDir); + for (const entry of readdirSync(entryDir)) { + const filePath = join(entryDir, entry); + const stream = createReadStream(filePath); + const buffer = await new Promise((resolve) => { + const chunks = []; + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => resolve(Buffer.concat(chunks))); + }); + pack.entry({ name: join(guidDir, entry), type: "file" }, buffer); + } + } + + pack.finalize(); + + const writeStream = createWriteStream(output); + pack.pipe(createGzip()).pipe(writeStream); + + await new Promise((resolve, reject) => { + writeStream.on("finish", resolve); + writeStream.on("error", reject); + }); + + await rm(tempDir, { recursive: true, force: true }); + console.log(`UnityPackage created: ${output}`); +}; + +createUnityPackage(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..4fbf29e --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "create-unitypackage-action", + "type": "module", + "main": "index.js", + "dependencies": { + "tar-stream": "^3.1.7", + "yaml": "^2.3.4" + } + } + \ No newline at end of file