1
0
forked from noxious/server

Typescript fix, almost finished the sprite generator

This commit is contained in:
Dennis Postma 2024-07-26 17:26:09 +02:00
parent e3bafca0ad
commit fb6e9d2fcc
2 changed files with 88 additions and 22 deletions
src
events/gm/sprite
repositories

@ -1,38 +1,80 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../utilities/Types'
import prisma from '../../../utilities/Prisma'
import type { SpriteAction } from '@prisma/client'
import type { Prisma, SpriteAction } from '@prisma/client'
import path from 'path'
import { writeFile } from 'node:fs/promises'
import fs from 'fs/promises'
import spriteRepository from '../../../repositories/SpriteRepository'
import sharp from 'sharp'
type SpriteActionInput = Omit<SpriteAction, 'id' | 'spriteId' | 'frameWidth' | 'frameHeight'> & {
sprites: string[]
}
type Payload = {
id: string
name: string
spriteActions: SpriteAction[]
spriteActions: Prisma.JsonValue
}
export default function (socket: TSocket, io: Server) {
socket.on('gm:sprite:update', async (data: Payload, callback: (success: boolean) => void) => {
if (socket.character?.role !== 'gm') {
callback(false)
return
}
try {
// Parse and validate spriteActions
let parsedSpriteActions: SpriteActionInput[];
try {
parsedSpriteActions = JSON.parse(JSON.stringify(data.spriteActions)) as SpriteActionInput[];
if (!Array.isArray(parsedSpriteActions)) {
throw new Error('spriteActions is not an array');
}
} catch (error) {
console.error('Error parsing spriteActions:', error);
callback(false);
return;
}
// Process the sprites to determine the largest dimensions
const processedActions = await Promise.all(parsedSpriteActions.map(async (spriteAction) => {
const { action, sprites } = spriteAction;
if (!Array.isArray(sprites) || sprites.length === 0) {
throw new Error(`Invalid sprites array for action: ${action}`);
}
// Convert base64 strings to buffers and get dimensions
const buffersWithDimensions = await Promise.all(sprites.map(async (sprite: string) => {
const buffer = Buffer.from(sprite.split(',')[1], 'base64');
const { width, height } = await sharp(buffer).metadata();
return { buffer, width, height };
}));
// Find the largest width and height
const frameWidth = Math.max(...buffersWithDimensions.map(b => b.width || 0));
const frameHeight = Math.max(...buffersWithDimensions.map(b => b.height || 0));
return {
...spriteAction,
frameWidth,
frameHeight,
buffersWithDimensions
};
}));
// Update the database with the new sprite actions (including calculated frame sizes)
await prisma.sprite.update({
where: {
id: data.id
},
where: { id: data.id },
data: {
name: data.name,
spriteActions: {
deleteMany: {
spriteId: data.id
},
create: data.spriteActions.map((spriteAction) => ({
deleteMany: { spriteId: data.id },
create: processedActions.map((spriteAction) => ({
action: spriteAction.action,
sprites: spriteAction.sprites as string[],
sprites: spriteAction.sprites,
origin_x: spriteAction.origin_x,
origin_y: spriteAction.origin_y,
isAnimated: spriteAction.isAnimated,
@ -43,19 +85,43 @@ export default function (socket: TSocket, io: Server) {
}))
}
}
})
});
const public_folder = path.join(process.cwd(), 'public', 'sprites', data.id)
const public_folder = path.join(process.cwd(), 'public', 'sprites', data.id);
await fs.mkdir(public_folder, { recursive: true });
// Ensure the folder exists
await fs.mkdir(public_folder, { recursive: true })
// Process and save each spriteAction
await Promise.all(processedActions.map(async (spriteAction) => {
const { action, buffersWithDimensions, frameWidth, frameHeight } = spriteAction;
const sprite = await spriteRepository.getById(data.id)
// Combine all sprites into a single image
const combinedImage = await sharp({
create: {
width: frameWidth * buffersWithDimensions.length,
height: frameHeight,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 }
}
})
.composite(
buffersWithDimensions.map(({ buffer }, index) => ({
input: buffer,
left: index * frameWidth,
top: 0
}))
)
.png()
.toBuffer();
callback(true)
// Save the combined image
const filename = path.join(public_folder, `${action}.png`);
await writeFile(filename, combinedImage);
}));
callback(true);
} catch (error) {
console.error(error)
callback(false)
console.error('Error updating sprite:', error);
callback(false);
}
})
});
}

@ -1,5 +1,5 @@
import prisma from '../utilities/Prisma' // Import the global Prisma instance
import { Sprite } from '@prisma/client'
import { Sprite, SpriteAction } from '@prisma/client'
class SpriteRepository {
async getById(id: string): Promise<Sprite | null> {
@ -19,7 +19,7 @@ class SpriteRepository {
})
}
async getSpriteActions(spriteId: string) {
async getSpriteActions(spriteId: string): Promise<SpriteAction[]> {
return prisma.spriteAction.findMany({
where: {
spriteId