forked from noxious/server
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import fs from 'fs'
|
|
|
|
import { Request, Response } from 'express'
|
|
import sharp from 'sharp'
|
|
|
|
import { BaseController } from '#application/base/baseController'
|
|
import Storage from '#application/storage'
|
|
import { UUID } from '#application/types'
|
|
import CharacterHairRepository from '#repositories/characterHairRepository'
|
|
import CharacterRepository from '#repositories/characterRepository'
|
|
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
|
|
|
interface AvatarOptions {
|
|
characterTypeId: UUID
|
|
characterHairId?: UUID
|
|
}
|
|
|
|
export class AvatarController extends BaseController {
|
|
private readonly characterTypeRepository = new CharacterTypeRepository()
|
|
private readonly characterHairRepository = new CharacterHairRepository()
|
|
private readonly characterRepository = new CharacterRepository()
|
|
|
|
/**
|
|
* Get avatar by character
|
|
* @param req
|
|
* @param res
|
|
*/
|
|
public async getByName(req: Request, res: Response) {
|
|
const character = await this.characterRepository.getByName(req.params.characterName)
|
|
if (!character?.characterType) {
|
|
return this.sendError(res, 'Character or character type not found', 404)
|
|
}
|
|
|
|
return this.generateAvatar(res, {
|
|
characterTypeId: character.characterType.id,
|
|
characterHairId: character.characterHair?.id
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Get avatar by character type and hair
|
|
* @param req
|
|
* @param res
|
|
*/
|
|
public async getByParams(req: Request, res: Response) {
|
|
return this.generateAvatar(res, {
|
|
characterTypeId: req.params.characterTypeId as UUID,
|
|
characterHairId: req.params.characterHairId ? (req.params.characterHairId as UUID) : undefined
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Generate avatar
|
|
* @param res
|
|
* @param options
|
|
* @private
|
|
*/
|
|
private async generateAvatar(res: Response, options: AvatarOptions) {
|
|
try {
|
|
const characterType = await this.characterTypeRepository.getById(options.characterTypeId)
|
|
if (!characterType?.sprite?.id) {
|
|
return this.sendError(res, 'Character type not found', 404)
|
|
}
|
|
|
|
const bodySpritePath = Storage.getPublicPath('sprites', characterType.sprite.id, 'idle_right_down.png')
|
|
if (!fs.existsSync(bodySpritePath)) {
|
|
return this.sendError(res, 'Body sprite file not found', 404)
|
|
}
|
|
|
|
let avatar = sharp(bodySpritePath).extend({
|
|
top: 2,
|
|
bottom: 2,
|
|
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
})
|
|
|
|
if (options.characterHairId) {
|
|
const characterHair = await this.characterHairRepository.getById(options.characterHairId)
|
|
if (characterHair?.sprite?.id) {
|
|
const hairSpritePath = Storage.getPublicPath('sprites', characterHair.sprite.id, 'front.png')
|
|
if (fs.existsSync(hairSpritePath)) {
|
|
avatar = avatar.composite([{ input: hairSpritePath, gravity: 'north' }])
|
|
}
|
|
}
|
|
}
|
|
|
|
res.setHeader('Content-Type', 'image/png')
|
|
return avatar.pipe(res)
|
|
} catch (error) {
|
|
return this.sendError(res, 'Error generating avatar', 500)
|
|
}
|
|
}
|
|
}
|