Files
cell/scripts/modules/resources.js
John Alanbrook b42eec96f6
Some checks failed
Build and Deploy / build-macos (push) Failing after 5s
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
Build and Deploy / build-linux (push) Failing after 1m30s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
separate the idea of misty actor and scene tree actor
2025-05-23 12:20:47 -05:00

222 lines
6.3 KiB
JavaScript

var io = use_embed('io');
var miniz = use_embed('miniz');
var os = use_embed('os');
Object.defineProperty(Function.prototype, "hashify", {
value: function () {
var hash = new Map()
var fn = this
function hashified(...args) {
var key = args[0]
if (!hash.has(key)) hash.set(key, fn(...args))
return hash.get(key)
}
return hashified
},
})
// Merge of the old resources.js and packer.js functionalities
var Resources = {}
// Determine the shared library extension based on the OS
var so_ext
switch(os.platform()) {
case 'Windows':
so_ext = '.dll'
break
default:
so_ext = '.so'
break
}
// Recognized resource extensions
Resources.scripts = ["js"]
Resources.images = ["qoi", "png", "gif", "jpg", "jpeg", "ase", "aseprite"]
Resources.sounds = ["wav", "flac", "mp3", "qoa"]
Resources.fonts = ["ttf"]
Resources.lib = [so_ext]
// Helper function: get extension from path in lowercase (e.g., "image.png" -> "png")
function getExtension(path) {
var idx = path.lastIndexOf('.')
if (idx < 0) return ''
return path.substring(idx + 1).toLowerCase()
}
// Return true if ext is in at least one of the recognized lists
function isRecognizedExtension(ext) {
if (!ext) return false
if (Resources.scripts.includes(ext)) return true
if (Resources.images.includes(ext)) return true
if (Resources.sounds.includes(ext)) return true
if (Resources.fonts.includes(ext)) return true
if (Resources.lib.includes('.' + ext)) return true // for .so or .dll
return false
}
function find_in_path(filename, exts = []) {
if (typeof filename !== 'string') return undefined
if (filename.includes('.')) {
for (var dir of prosperon.PATH) {
var candidate = dir + filename
if (io.exists(candidate) && !io.is_directory(candidate)) return candidate
}
return undefined
}
for (var dir of prosperon.PATH) {
// Only check extensions if exts is provided and not empty
if (exts.length > 0) {
for (var ext of exts) {
var candidate = dir + filename + '.' + ext
if (io.exists(candidate) && !io.is_directory(candidate)) return candidate
}
} else {
// Fallback to extensionless file only if no extensions are specified
var candidate = dir + filename
if (io.exists(candidate) && !io.is_directory(candidate)) return candidate
}
}
return undefined
}
// Return a canonical path (the real directory plus the path)
Resources.canonical = function(file) {
return io.realdir(file) + file
}
// The resource finders
Resources.find_image = function(file) {
return find_in_path(file, Resources.images)
}.hashify()
Resources.find_sound = function(file) {
return find_in_path(file, Resources.sounds)
}.hashify()
Resources.find_script = function(file) {
return find_in_path(file, Resources.scripts)
}.hashify()
Resources.find_font = function(file) {
return find_in_path(file, Resources.fonts)
}.hashify()
// .prosperonignore reading helper
function read_ignore(dir) {
var path = dir + '/.prosperonignore'
var patterns = []
if (io.exists(path)) {
var lines = io.slurp(path).split('\n')
for (var line of lines) {
line = line.trim()
if (!line || line.startsWith('#')) continue
patterns.push(line)
}
}
return patterns
}
// Return a list of recognized files in the directory (and subdirectories),
// skipping those matched by .prosperonignore. Directory paths are skipped.
Resources.getAllFiles = function(dir = "") {
var patterns = read_ignore(dir)
var all = io.globfs(patterns, dir)
var results = []
for (var f of all) {
var fullPath = dir + '/' + f
try {
var st = io.stat(fullPath)
// skip directories (filesize=0) or unrecognized extension
if (!st.filesize) continue
var ext = getExtension(f)
if (!isRecognizedExtension(ext)) continue
results.push(fullPath)
} catch(e) {}
}
return results
}
Resources.getAllFiles[prosperon.DOC] = `
Return a list of recognized files in the given directory that are not matched by
.prosperonignore, skipping directories. Recognized extensions include scripts,
images, sounds, fonts, and libs.
:param dir: The directory to search.
:return: An array of recognized file paths.
`
// Categorize files by resource type
Resources.gatherStats = function(filePaths) {
var stats = {
scripts:0, images:0, sounds:0, fonts:0, lib:0, other:0, total:filePaths.length
}
for (var path of filePaths) {
var ext = getExtension(path)
if (Resources.scripts.includes(ext)) {
stats.scripts++
continue
}
if (Resources.images.includes(ext)) {
stats.images++
continue
}
if (Resources.sounds.includes(ext)) {
stats.sounds++
continue
}
if (Resources.fonts.includes(ext)) {
stats.fonts++
continue
}
// For so_ext, we store it in Resources.lib as ['.so'] or ['.dll'], so match that form
if (Resources.lib.includes('.' + ext)) {
stats.lib++
continue
}
stats.other++
}
return stats
}
Resources.gatherStats[prosperon.DOC] = `
Analyze a list of recognized files and categorize them by scripts, images, sounds,
fonts, libs, or other. Return a stats object with these counts and the total.
:param filePaths: An array of file paths to analyze.
:return: { scripts, images, sounds, fonts, lib, other, total }
`
// Create a ZIP of recognized files in a directory, skipping ignored ones, and write to outPath
Resources.pack = function(dir, outPath) {
if (!io.exists(dir))
throw Error("Directory does not exist: " + dir)
var files = Resources.getAllFiles(dir)
var writer = miniz.write(outPath)
for (var fullPath of files) {
try {
var st = io.stat(fullPath)
if (!st.filesize) continue // skip directories
// Path in the ZIP: remove leading dir + '/'
var pathInZip = fullPath.substring(dir.length + 1)
var data = io.slurpbytes(fullPath)
writer.add_file(pathInZip, data)
} catch(e) {
// Optionally handle or log errors
}
}
}
Resources.pack[prosperon.DOC] = `
Create a ZIP archive of all recognized files (skipping those matched by .prosperonignore)
in the specified directory and write it to outPath. Recognized extensions are scripts,
images, sounds, fonts, or libs.
:param dir: The directory to zip.
:param outPath: The path (including filename) for the resulting ZIP file.
:return: None
:raises Error: If the directory does not exist.
`
return Resources