XVoxel-ASync/modules/resources.js

170 lines
4.2 KiB
JavaScript

class ResourcePack {
constructor (data) {
this.name = data.name;
this.description = data.description;
this.meta = data.meta;
this.models = data.models || new global.Map();
this.textures = data.textures || new global.Map();
this.sounds = new global.Map();
}
static loadFromZIP (zipBuffer) {
if (!zipBuffer) return Promise.reject(new Error("Missing argument zipBuffer. "));
return new Promise(function (resolve, reject) {
global.fflate.unzip(new Uint8Array(zipBuffer), {}, function (error, data) {
if (error) return reject(error);
if (!data["pack.json"]) return reject(new Error("pack.json not found in zip file. "));
let packMeta;
try {
packMeta = JSON.parse(global.fflate.strFromU8(data["pack.json"]));
} catch (err) {
return reject(err);
}
var packData = readPackMeta(packMeta, data);
packData.meta = packMeta;
var resourceLoadings = [];
resourceLoadings.push(loadU8Textures(packMeta, data).then(function (textureMap) {
packData.textures = textureMap;
}).catch(reject));
resourceLoadings.push(loadU8Models(packMeta, data).then(function (modelMap) {
packData.models = modelMap;
}).catch(reject));
Promise.all(resourceLoadings).then(function () {
var resourcePack = new ResourcePack(packData);
global.core.emit("resourcepack-load", resourcePack);
resolve(resourcePack);
}).catch(reject);
});
});
}
}
var readPackMeta = function (packMeta, packArchive) {
var pack = {
"name": packMeta.name,
"description": packMeta.description
};
return pack;
};
var loadU8Textures = function (packMeta, packData) {
return new Promise(function (resolve, reject) {
var textureMap = new global.Map();
var textureLoadings = [];
var textureMeta = packMeta.textures;
for (var textureName in textureMeta) {
if (textureMeta.hasOwnProperty(textureName)) {
var textureData = textureMeta[textureName];
if (textureData.path) {
var splitPath = textureData.path.split(/[\/\.]+/g);
var extension = splitPath[splitPath.length - 1].toLowerCase();
if (extension == "jpg") extension = "jpeg";
if ((["png", "jpeg", "webp", "gif", "apng", "avif"]).indexOf(extension) > -1) {
var type = "image";
} else if ((["mp4", "mkv", "ogg", "webm"]).indexOf(extension) > -1) {
var type = "video";
}
var mimeType = type + "/" + extension;
if (!packData[textureData.path]) reject(new Error("Texture doesn't exist at " + textureData.path + ". "));
var textureBind = {
"name": textureName
};
textureLoadings.push(new Promise((function(res, rej) {
var imageData = packData[textureData.path];
var imageBlob = new Blob([imageData.buffer], {"type": mimeType});
var imageObjectURL = URL.createObjectURL(imageBlob);
var texture = new global.three.Texture();
var image = new global.Image();
texture.minFilter = global.three.NearestFilter;
texture.magFilter = global.three.NearestFilter;
image.onload = (function () {
texture.image = image;
texture.needsUpdate = true;
var data = {
"map": texture
};
textureMap.set(this.name, data);
res(data);
}).bind(textureBind);
image.src = imageObjectURL;
}).bind(textureBind)));
} else if (textureData.texture) {
var data = {
};
textureMap.set(textureName, data);
textureLoadings.push(Promise.resolve(data));
}
}
}
Promise.all(textureLoadings).then(function (textures) {
resolve(textureMap);
}).catch(reject);
});
};
var loadU8Models = function (packMeta, packData) {
return new Promise(function (resolve, reject) {
var modelMap = new global.Map();
var modelLoadings = [];
var modelMeta = packMeta.models;
for (var modelName in modelMeta) {
if (modelMeta.hasOwnProperty(modelName)) {
var modelData = modelMeta[modelName];
var modelString = global.fflate.strFromU8(packData[modelData.path]);
var modelJSON = JSON.parse(modelString);
modelMap.set(modelName, modelJSON);
modelLoadings.push(Promise.resolve(modelJSON));
}
}
Promise.all(modelLoadings).then(function (models) {
resolve(modelMap);
}).catch(reject);
});
};
module.exports = {
"ResourcePack": ResourcePack
};