1
0
forked from noxious/server

Continue working on spritesheet generator

This commit is contained in:
2025-01-28 14:29:45 +01:00
parent d17408acd9
commit dbdc8c9d6e
6 changed files with 122 additions and 77 deletions

View File

@ -46,9 +46,9 @@ export abstract class BaseEntity {
throw error
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message :
error && typeof error === 'object' && 'toString' in error ? error.toString() :
String(error)
const errorMessage = error instanceof Error ? error.message : error && typeof error === 'object' && 'toString' in error ? error.toString() : String(error)
console.log(errorMessage)
this.logger.error(`Failed to ${actionDescription}: ${errorMessage}`)
throw error
}

View File

@ -21,7 +21,7 @@ export default class ToggleFogCommand extends BaseEvent {
const args = ChatService.getArgs('fog', data.message)
await WeatherManager.setFogValue(args![0] ? Number(args![0]) : null);
await WeatherManager.setFogValue(args![0] ? Number(args![0]) : null)
callback(true)
} catch (error: any) {
this.logger.error('command error', error.message)

View File

@ -21,7 +21,7 @@ export default class ToggleRainCommand extends BaseEvent {
let args = ChatService.getArgs('rain', data.message)
await WeatherManager.setRainValue(args![0] ? Number(args![0]) : null);
await WeatherManager.setRainValue(args![0] ? Number(args![0]) : null)
callback(true)
} catch (error: any) {
this.logger.error('command error', error.message)

View File

@ -1,6 +1,8 @@
import { BaseEvent } from '#application/base/baseEvent'
import { UUID } from '#application/types'
import SpriteRepository from '#repositories/spriteRepository'
import { SpriteAction } from '#entities/spriteAction'
import sharp from 'sharp'
type Payload = {
id: UUID
@ -27,13 +29,35 @@ export default class SpriteUpdateEvent extends BaseEvent {
const sprite = await spriteRepository.getById(data.id)
if (!sprite) return callback(false)
await spriteRepository.getEntityManager().populate(sprite, ['spriteActions']);
await spriteRepository.getEntityManager().populate(sprite, ['spriteActions'])
// Update sprite in database
await sprite
.setName(data.name)
.setSpriteActions(data.spriteActions)
.save()
await sprite.setName(data.name).save()
const existingActions = sprite.getSpriteActions()
// Remove all existing actions - we'll recreate the ones we need
for (const existingAction of existingActions) {
await spriteRepository.getEntityManager().removeAndFlush(existingAction)
}
// Create new actions
for (const actionData of data.spriteActions) {
const spriteAction = new SpriteAction()
spriteAction.setSprite(sprite)
sprite.getSpriteActions().add(spriteAction)
spriteAction
.setAction(actionData.action)
.setSprites(actionData.sprites)
.setOriginX(actionData.originX)
.setOriginY(actionData.originY)
.setFrameWidth(await this.calculateWidth(actionData.sprites[0]))
.setFrameHeight(await this.calculateHeight(actionData.sprites[0]))
.setFrameRate(actionData.frameRate)
await spriteRepository.getEntityManager().persistAndFlush(spriteAction)
}
return callback(true)
} catch (error) {
@ -41,4 +65,28 @@ export default class SpriteUpdateEvent extends BaseEvent {
return callback(false)
}
}
}
private async calculateWidth(base64: string): Promise<number> {
const uri = base64.split(';base64,').pop()
if (!uri) return 0
const imgBuffer = Buffer.from(uri, 'base64')
const image = await sharp(imgBuffer).metadata()
return image.width ?? 0
}
private async calculateHeight(base64: string): Promise<number> {
const uri = base64.split(';base64,').pop()
if (!uri) return 0
const imgBuffer = Buffer.from(uri, 'base64')
const image = await sharp(imgBuffer).metadata()
return image.height ?? 0
}
private generateSpriteSheet(sprites: string[]) {
// In here comes a function that generates a sprite sheet from the given sprites using Sharp.
// This function takes an array of base64 encoded sprites and generates a single png sprite sheet.
// Then proceeds to save ths sprite sheet to the public/sprites/{spriteId}/ directory. The file name is {action}.png.
}
}

View File

@ -39,7 +39,7 @@ class WeatherManager {
return { ...this.weatherState }
}
public randomWeatherValue(type: 'rain' | 'fog' ) {
public randomWeatherValue(type: 'rain' | 'fog') {
switch (type) {
case 'rain':
return this.getRandomNumber(WeatherManager.CONFIG.RAIN_PERCENTAGE_RANGE.min, WeatherManager.CONFIG.RAIN_PERCENTAGE_RANGE.max)
@ -48,7 +48,7 @@ class WeatherManager {
}
}
public async setRainValue(value : number | null): Promise<void> {
public async setRainValue(value: number | null): Promise<void> {
if (value === null) {
value = this.randomWeatherValue('rain')
}
@ -57,7 +57,7 @@ class WeatherManager {
await this.saveAndEmitWeather()
}
public async setFogValue(value : number | null): Promise<void> {
public async setFogValue(value: number | null): Promise<void> {
if (value === null) {
value = this.randomWeatherValue('fog')
}
@ -90,7 +90,7 @@ class WeatherManager {
private updateRandomWeather(): void {
if (Math.random() < WeatherManager.CONFIG.RAIN_CHANCE) {
this.updateWeatherProperty('rain', this.randomWeatherValue('rain') )
this.updateWeatherProperty('rain', this.randomWeatherValue('rain'))
}
if (Math.random() < WeatherManager.CONFIG.FOG_CHANCE) {
this.updateWeatherProperty('fog', this.randomWeatherValue('fog'))
@ -99,11 +99,11 @@ class WeatherManager {
private updateWeatherProperty(type: 'rain' | 'fog', value: number): void {
if (type === 'rain') {
this.weatherState.rainPercentage = value
this.weatherState.rainPercentage = value
}
if (type === 'fog') {
this.weatherState.fogDensity = value
this.weatherState.fogDensity = value
}
}
@ -124,10 +124,7 @@ class WeatherManager {
if (!world) world = new World()
//the data model still contains the booleans
await world
.setRainPercentage(this.weatherState.rainPercentage)
.setFogDensity(this.weatherState.fogDensity)
.save()
await world.setRainPercentage(this.weatherState.rainPercentage).setFogDensity(this.weatherState.fogDensity).save()
} catch (error) {
this.logError('save', error)
}