forked from noxious/server
npm update, http asset endpoint changes
This commit is contained in:
parent
5631930bf5
commit
9d08073fa8
18
package-lock.json
generated
18
package-lock.json
generated
@ -719,9 +719,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.16.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.13.tgz",
|
||||
"integrity": "sha512-GjQ7im10B0labo8ZGXDGROUl9k0BNyDgzfGpb4g/cl+4yYDWVKcozANF4FGr4/p0O/rAkQClM6Wiwkije++1Tg==",
|
||||
"version": "20.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.1.tgz",
|
||||
"integrity": "sha512-j2VlPv1NnwPJbaCNv69FO/1z4lId0QmGvpT41YxitRtWlg96g/j8qcv2RKsLKe2F6OJgyXhupN1Xo17b2m139Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
@ -926,9 +926,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/bullmq": {
|
||||
"version": "5.21.1",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.21.1.tgz",
|
||||
"integrity": "sha512-+yvsd5LkbWkTW2K5C/1s8h1+gGK4F9wVfKM6AJUBSWGsbfWHXnni0Se7xHj1dieVkx6XEsfCzFtO6kZnD+mtHQ==",
|
||||
"version": "5.21.2",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.21.2.tgz",
|
||||
"integrity": "sha512-LPuNoGaDc5CON2X6h4cJ2iVfd+B+02xubFU+IB/fyJHd+/HqUZRqnlYryUCAuhVHBhUKtA6oyVdJxqSa62i+og==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cron-parser": "^4.6.0",
|
||||
@ -2479,9 +2479,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz",
|
||||
"integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==",
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
|
||||
"integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
|
@ -2,8 +2,7 @@ import { Zone } from '@prisma/client'
|
||||
import ZoneRepository from '../repositories/zoneRepository'
|
||||
import ZoneService from '../services/zoneService'
|
||||
import LoadedZone from '../models/loadedZone'
|
||||
import zoneRepository from '../repositories/zoneRepository'
|
||||
import { gameMasterLogger } from '../utilities/logger'
|
||||
import { gameLogger } from '../utilities/logger'
|
||||
|
||||
class ZoneManager {
|
||||
private loadedZones: LoadedZone[] = []
|
||||
@ -21,36 +20,20 @@ class ZoneManager {
|
||||
await this.loadZone(zone)
|
||||
}
|
||||
|
||||
gameMasterLogger.info('Zone manager loaded')
|
||||
}
|
||||
|
||||
public async getZoneAssets(zone: Zone): Promise<ZoneAssets> {
|
||||
const tiles: string[] = this.getUnique((JSON.parse(JSON.stringify(zone.tiles)) as string[][]).reduce((acc, val) => [...acc, ...val]))
|
||||
const objects = await zoneRepository.getObjects(zone.id)
|
||||
const mappedObjects = this.getUnique(objects.map((x) => x.objectId))
|
||||
|
||||
return {
|
||||
tiles: tiles,
|
||||
objects: mappedObjects
|
||||
} as ZoneAssets
|
||||
}
|
||||
|
||||
private getUnique<T>(array: T[]) {
|
||||
return [...new Set<T>(array)]
|
||||
gameLogger.info('Zone manager loaded')
|
||||
}
|
||||
|
||||
// Method to handle individual zoneEditor loading
|
||||
public async loadZone(zone: Zone) {
|
||||
const loadedZone = new LoadedZone(zone)
|
||||
this.loadedZones.push(loadedZone)
|
||||
await this.getZoneAssets(zone)
|
||||
gameMasterLogger.info(`Zone ID ${zone.id} loaded`)
|
||||
gameLogger.info(`Zone ID ${zone.id} loaded`)
|
||||
}
|
||||
|
||||
// Method to handle individual zoneEditor unloading
|
||||
public unloadZone(zoneId: number) {
|
||||
this.loadedZones = this.loadedZones.filter((loadedZone) => loadedZone.getZone().id !== zoneId)
|
||||
gameMasterLogger.info(`Zone ID ${zoneId} unloaded`)
|
||||
gameLogger.info(`Zone ID ${zoneId} unloaded`)
|
||||
}
|
||||
|
||||
// Getter for loaded zones
|
||||
|
@ -2,6 +2,8 @@ import { Zone, ZoneEventTile, ZoneEventTileType, ZoneObject } from '@prisma/clie
|
||||
import prisma from '../utilities/prisma'
|
||||
import { ZoneEventTileWithTeleport } from '../socketEvents/zone/characterMove'
|
||||
import { appLogger } from '../utilities/logger'
|
||||
import { TAsset } from '../utilities/types'
|
||||
import tileRepository from './tileRepository'
|
||||
|
||||
class ZoneRepository {
|
||||
async getFirst(): Promise<Zone | null> {
|
||||
@ -22,7 +24,7 @@ class ZoneRepository {
|
||||
}
|
||||
}
|
||||
|
||||
async getById(id: number): Promise<Zone | null> {
|
||||
async getById(id: number) {
|
||||
try {
|
||||
return await prisma.zone.findUnique({
|
||||
where: {
|
||||
@ -77,7 +79,7 @@ class ZoneRepository {
|
||||
}
|
||||
}
|
||||
|
||||
async getObjects(id: number): Promise<ZoneObject[]> {
|
||||
async getZoneObjects(id: number): Promise<ZoneObject[]> {
|
||||
try {
|
||||
return await prisma.zoneObject.findMany({
|
||||
where: {
|
||||
@ -89,6 +91,52 @@ class ZoneRepository {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
async getZoneAssets(zone_id: number): Promise<TAsset[]> {
|
||||
const zone = await this.getById(zone_id)
|
||||
if (!zone) return []
|
||||
|
||||
const assets: TAsset[] = []
|
||||
|
||||
// zone.tiles is prisma jsonvalue
|
||||
let tiles = JSON.parse(JSON.stringify(zone.tiles))
|
||||
tiles = [...new Set(tiles.flat())]
|
||||
|
||||
// Add tile assets
|
||||
for (const tile of tiles) {
|
||||
const tileInfo = await tileRepository.getById(tile)
|
||||
if (!tileInfo) continue
|
||||
|
||||
assets.push({
|
||||
key: tileInfo.id,
|
||||
url: '/assets/tiles/' + tileInfo.id + '.png',
|
||||
group: 'tiles',
|
||||
updatedAt: tileInfo?.updatedAt || new Date()
|
||||
})
|
||||
}
|
||||
|
||||
// Add object assets
|
||||
for (const zoneObject of zone.zoneObjects) {
|
||||
if (!zoneObject.object) continue
|
||||
|
||||
assets.push({
|
||||
key: zoneObject.object.id,
|
||||
url: '/assets/objects/' + zoneObject.object.id + '.png',
|
||||
group: 'objects',
|
||||
updatedAt: zoneObject.object.updatedAt || new Date()
|
||||
})
|
||||
}
|
||||
|
||||
// Filter out duplicate assets
|
||||
return assets.reduce((acc: TAsset[], current) => {
|
||||
const x = acc.find((item) => item.key === current.key && item.group === current.group)
|
||||
if (!x) {
|
||||
return acc.concat([current])
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, [])
|
||||
}
|
||||
}
|
||||
|
||||
export default new ZoneRepository()
|
||||
|
@ -3,95 +3,12 @@ import UserService from '../services/userService'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import config from './config'
|
||||
import { loginAccountSchema, registerAccountSchema } from './zodTypes'
|
||||
import { TAsset } from './types'
|
||||
import tileRepository from '../repositories/tileRepository'
|
||||
import objectRepository from '../repositories/objectRepository'
|
||||
import spriteRepository from '../repositories/spriteRepository'
|
||||
import fs from 'fs'
|
||||
import { httpLogger } from './logger'
|
||||
import { getPublicPath } from './storage'
|
||||
import zoneRepository from '../repositories/zoneRepository'
|
||||
|
||||
async function addHttpRoutes(app: Application) {
|
||||
/**
|
||||
* Get all base sprite, assets
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
app.get('/assets', async (req: Request, res: Response) => {
|
||||
let assets: TAsset[] = []
|
||||
|
||||
const sprites = await spriteRepository.getAll()
|
||||
const tiles = await tileRepository.getAll()
|
||||
const objects = await objectRepository.getAll()
|
||||
|
||||
// sprites all contain spriteActions, loop through these
|
||||
sprites.forEach((sprite) => {
|
||||
sprite.spriteActions.forEach((spriteAction) => {
|
||||
assets.push({
|
||||
key: sprite.id + '-' + spriteAction.action,
|
||||
url: '/assets/sprites/' + sprite.id + '/' + spriteAction.action + '.png',
|
||||
group: spriteAction.isAnimated ? 'sprite_animations' : 'sprites',
|
||||
updatedAt: sprite.updatedAt,
|
||||
frameCount: JSON.parse(JSON.stringify(spriteAction.sprites)).length,
|
||||
frameWidth: spriteAction.frameWidth,
|
||||
frameHeight: spriteAction.frameHeight,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Get all tiles
|
||||
tiles.forEach((tile) => {
|
||||
assets.push({
|
||||
key: tile.id,
|
||||
url: '/assets/tiles/' + tile.id + '.png',
|
||||
group: 'tiles',
|
||||
updatedAt: tile.updatedAt
|
||||
})
|
||||
})
|
||||
|
||||
// Get all objects
|
||||
objects.forEach((object) => {
|
||||
assets.push({
|
||||
key: object.id,
|
||||
url: '/assets/objects/' + object.id + '.png',
|
||||
group: 'objects',
|
||||
updatedAt: object.updatedAt
|
||||
})
|
||||
})
|
||||
|
||||
res.json(assets)
|
||||
})
|
||||
|
||||
/**
|
||||
* Get a specific asset
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
app.get('/assets/:type/:spriteId?/:file', (req: Request, res: Response) => {
|
||||
const assetType = req.params.type
|
||||
const spriteId = req.params.spriteId
|
||||
const fileName = req.params.file
|
||||
|
||||
let assetPath
|
||||
if (assetType === 'sprites' && spriteId) {
|
||||
assetPath = getPublicPath(assetType, spriteId, fileName)
|
||||
} else {
|
||||
assetPath = getPublicPath(assetType, fileName)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(assetPath)) {
|
||||
httpLogger.error(`File not found: ${assetPath}`)
|
||||
return res.status(404).send('Asset not found')
|
||||
}
|
||||
|
||||
res.sendFile(assetPath, (err) => {
|
||||
if (err) {
|
||||
httpLogger.error('Error sending file:', err)
|
||||
res.status(500).send('Error downloading the asset')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Login
|
||||
* @param req
|
||||
@ -141,6 +58,70 @@ async function addHttpRoutes(app: Application) {
|
||||
return res.status(400).json({ message: 'Failed to register user' })
|
||||
})
|
||||
|
||||
/**
|
||||
* Get all tiles from a zone as an array of ids
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
app.get('/assets/tiles/:zoneId', async (req: Request, res: Response) => {
|
||||
const zoneId = req.params.zoneId
|
||||
|
||||
// Check if zoneId is valid number
|
||||
if (!zoneId || parseInt(zoneId) === 0) {
|
||||
return res.status(400).json({ message: 'Invalid zone ID' })
|
||||
}
|
||||
|
||||
// Get zone by id
|
||||
const zone = await zoneRepository.getById(parseInt(zoneId))
|
||||
if (!zone) {
|
||||
return res.status(404).json({ message: 'Zone not found' })
|
||||
}
|
||||
|
||||
let tiles = zone.tiles;
|
||||
|
||||
// Convert to array
|
||||
tiles = JSON.parse(JSON.stringify(tiles)) as string[]
|
||||
|
||||
// Flatten the array
|
||||
tiles = [...new Set(tiles.flat())]
|
||||
|
||||
// Remove duplicates
|
||||
tiles = tiles.filter((value, index, self) => self.indexOf(value) === index);
|
||||
|
||||
// Return the array
|
||||
res.json(tiles)
|
||||
})
|
||||
|
||||
/**
|
||||
* Get a specific asset
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
app.get('/assets/:type/:spriteId?/:file', (req: Request, res: Response) => {
|
||||
const assetType = req.params.type
|
||||
const spriteId = req.params.spriteId
|
||||
const fileName = req.params.file
|
||||
|
||||
let assetPath
|
||||
if (assetType === 'sprites' && spriteId) {
|
||||
assetPath = getPublicPath(assetType, spriteId, fileName)
|
||||
} else {
|
||||
assetPath = getPublicPath(assetType, fileName)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(assetPath)) {
|
||||
httpLogger.error(`File not found: ${assetPath}`)
|
||||
return res.status(404).send('Asset not found')
|
||||
}
|
||||
|
||||
res.sendFile(assetPath, (err) => {
|
||||
if (err) {
|
||||
httpLogger.error('Error sending file:', err)
|
||||
res.status(500).send('Error downloading the asset')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
httpLogger.info('Web routes added')
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user