182 lines
5.4 KiB
JavaScript
182 lines
5.4 KiB
JavaScript
import decompress from "decompress";
|
|
import sharp from 'sharp';
|
|
sharp.cache({ files : 0 });
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
const collection = 'assets';
|
|
|
|
/**
|
|
* Game objects manager
|
|
*/
|
|
class GameObjectsManager{
|
|
name = 'gameObject';
|
|
|
|
/**
|
|
* Plugin initializer
|
|
* @param {App} app The Application
|
|
*/
|
|
init(app){
|
|
const {db, config} = app;
|
|
|
|
/**
|
|
* Gets last asset Id from database
|
|
* @returns {Number} Last Asset Id
|
|
*/
|
|
this.getLastId = async function(){
|
|
let ag = await db.aggregate(collection, [
|
|
{
|
|
$group:{
|
|
_id: null,
|
|
max: {
|
|
$max: "$id",
|
|
},
|
|
},
|
|
},
|
|
]);
|
|
return ag.max || 0;
|
|
}
|
|
|
|
/**
|
|
* Creates a game object
|
|
* @param {Context} ctx Request context
|
|
* @param {GameObject} data Asset data
|
|
*/
|
|
this.create = async function(ctx, data){
|
|
data.id = (await this.getLastId()) + 1;
|
|
await db.create(collection, data);
|
|
if (ctx.files?.file){
|
|
await this.addFile(data, ctx.files.file)
|
|
await fs.promises.unlink(ctx.files.file.path)
|
|
await db.update(collection, {id: data.id}, data);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Retrieves game object from database
|
|
* @param {Number} id Game object ID
|
|
* @returns {GameObject} The game object
|
|
*/
|
|
this.read = async function(id){
|
|
id = parseInt(id);
|
|
return await db.get(collection, {id});
|
|
}
|
|
|
|
/**
|
|
* Updates game object into the database
|
|
* @param {Context} ctx Request context
|
|
* @param {GameObject} data Game object
|
|
*/
|
|
this.update = async function(ctx, data){
|
|
data.id = parseInt(data.id);
|
|
let object = await this.read(data.id);
|
|
data = Object.assign(object, data);
|
|
if (ctx.files?.file){
|
|
await this.addFile(data, ctx.files.file)
|
|
await fs.promises.unlink(ctx.files.file.path)
|
|
}if (ctx.files?.thumb){
|
|
await this.addThumb(data, ctx.files.thumb.path);
|
|
await fs.promises.unlink(ctx.files.thumb.path)
|
|
}
|
|
await db.update(collection, {id: data.id}, data);
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Removes game object from database
|
|
* @param {Number} id Game object ID
|
|
*/
|
|
this.remove = async function(id){
|
|
id = parseInt(id);
|
|
await db.remove(collection, {id});
|
|
}
|
|
|
|
/**
|
|
* Assigns a file to a game object
|
|
* @param {GameObject} object Game object
|
|
* @param {File} tmpFile A file
|
|
*/
|
|
this.addFile = async function(object, tmpFile){
|
|
let i = tmpFile;
|
|
let ofn = i.name;
|
|
let ext = path.extname(ofn).toLowerCase();
|
|
let src = `${config.fs.repo}/source/${object.id}${ext}`;
|
|
let def = `${config.fs.repo}/default/${object.id}`;
|
|
await fs.promises.copyFile(i.path, src);
|
|
object.asset = {
|
|
ofn,
|
|
name: `${object.id}${ext}`
|
|
}
|
|
if (ext == '.zip'){
|
|
let result = await decompress(src, def);
|
|
object.asset.list = result.map(f=>f.path);
|
|
object.asset.type = 'bundle';
|
|
object.asset.name = `${object.id}/` + result.find(f=>f.path.endsWith('.gltf'))?.path;
|
|
}else{
|
|
object.asset.type = 'single';
|
|
await fs.promises.copyFile(src, def + ext);
|
|
if (['.jpg', '.png', '.webp'].includes(ext)){
|
|
await this.addThumb(object, src);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assigns a thumbnail to a game object
|
|
* @param {GameObject} object Game object
|
|
* @param {File} thumbSrc A thumbnail
|
|
*/
|
|
this.addThumb = async function(object, thumbSrc){
|
|
let dest = `${config.fs.repo}/thumb/${object.id}.webp`;
|
|
await sharp(thumbSrc).resize({height: 250}).toFile(dest);
|
|
object.asset.thumb = `${object.id}.webp`;
|
|
}
|
|
|
|
/**
|
|
* Returns list of GameObjects
|
|
* @param {Object} query Query to DB
|
|
* @returns {GameObject[]} Array of game objects
|
|
*/
|
|
this.list = async function(query){
|
|
return await db.list(collection, {
|
|
query: {},
|
|
project: { name:1, id:1, type:1, asset:1}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class starter
|
|
* @param {App} app The application
|
|
*/
|
|
async start(app){
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GameObject entity, can be: panorama picture, 3d environment, 3d object, 2d object (picture), a player (3d), audio or video asset
|
|
*/
|
|
class GameObject {
|
|
/**
|
|
* Game object name
|
|
* @type string
|
|
*/
|
|
name = null;
|
|
|
|
/**
|
|
* Game object type
|
|
* @type string
|
|
*/
|
|
type = null;
|
|
|
|
/**
|
|
* Associated file
|
|
* @type File
|
|
*/
|
|
file = null;
|
|
}
|
|
|
|
export { GameObjectsManager } |