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"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.16.13",
|
"version": "20.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.13.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.1.tgz",
|
||||||
"integrity": "sha512-GjQ7im10B0labo8ZGXDGROUl9k0BNyDgzfGpb4g/cl+4yYDWVKcozANF4FGr4/p0O/rAkQClM6Wiwkije++1Tg==",
|
"integrity": "sha512-j2VlPv1NnwPJbaCNv69FO/1z4lId0QmGvpT41YxitRtWlg96g/j8qcv2RKsLKe2F6OJgyXhupN1Xo17b2m139Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.19.2"
|
"undici-types": "~6.19.2"
|
||||||
@ -926,9 +926,9 @@
|
|||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/bullmq": {
|
"node_modules/bullmq": {
|
||||||
"version": "5.21.1",
|
"version": "5.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.21.2.tgz",
|
||||||
"integrity": "sha512-+yvsd5LkbWkTW2K5C/1s8h1+gGK4F9wVfKM6AJUBSWGsbfWHXnni0Se7xHj1dieVkx6XEsfCzFtO6kZnD+mtHQ==",
|
"integrity": "sha512-LPuNoGaDc5CON2X6h4cJ2iVfd+B+02xubFU+IB/fyJHd+/HqUZRqnlYryUCAuhVHBhUKtA6oyVdJxqSa62i+og==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cron-parser": "^4.6.0",
|
"cron-parser": "^4.6.0",
|
||||||
@ -2479,9 +2479,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/socket.io": {
|
"node_modules/socket.io": {
|
||||||
"version": "4.8.0",
|
"version": "4.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
|
||||||
"integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==",
|
"integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.4",
|
"accepts": "~1.3.4",
|
||||||
|
@ -2,8 +2,7 @@ import { Zone } from '@prisma/client'
|
|||||||
import ZoneRepository from '../repositories/zoneRepository'
|
import ZoneRepository from '../repositories/zoneRepository'
|
||||||
import ZoneService from '../services/zoneService'
|
import ZoneService from '../services/zoneService'
|
||||||
import LoadedZone from '../models/loadedZone'
|
import LoadedZone from '../models/loadedZone'
|
||||||
import zoneRepository from '../repositories/zoneRepository'
|
import { gameLogger } from '../utilities/logger'
|
||||||
import { gameMasterLogger } from '../utilities/logger'
|
|
||||||
|
|
||||||
class ZoneManager {
|
class ZoneManager {
|
||||||
private loadedZones: LoadedZone[] = []
|
private loadedZones: LoadedZone[] = []
|
||||||
@ -21,36 +20,20 @@ class ZoneManager {
|
|||||||
await this.loadZone(zone)
|
await this.loadZone(zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
gameMasterLogger.info('Zone manager loaded')
|
gameLogger.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)]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to handle individual zoneEditor loading
|
// Method to handle individual zoneEditor loading
|
||||||
public async loadZone(zone: Zone) {
|
public async loadZone(zone: Zone) {
|
||||||
const loadedZone = new LoadedZone(zone)
|
const loadedZone = new LoadedZone(zone)
|
||||||
this.loadedZones.push(loadedZone)
|
this.loadedZones.push(loadedZone)
|
||||||
await this.getZoneAssets(zone)
|
gameLogger.info(`Zone ID ${zone.id} loaded`)
|
||||||
gameMasterLogger.info(`Zone ID ${zone.id} loaded`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to handle individual zoneEditor unloading
|
// Method to handle individual zoneEditor unloading
|
||||||
public unloadZone(zoneId: number) {
|
public unloadZone(zoneId: number) {
|
||||||
this.loadedZones = this.loadedZones.filter((loadedZone) => loadedZone.getZone().id !== zoneId)
|
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
|
// Getter for loaded zones
|
||||||
|
@ -2,6 +2,8 @@ import { Zone, ZoneEventTile, ZoneEventTileType, ZoneObject } from '@prisma/clie
|
|||||||
import prisma from '../utilities/prisma'
|
import prisma from '../utilities/prisma'
|
||||||
import { ZoneEventTileWithTeleport } from '../socketEvents/zone/characterMove'
|
import { ZoneEventTileWithTeleport } from '../socketEvents/zone/characterMove'
|
||||||
import { appLogger } from '../utilities/logger'
|
import { appLogger } from '../utilities/logger'
|
||||||
|
import { TAsset } from '../utilities/types'
|
||||||
|
import tileRepository from './tileRepository'
|
||||||
|
|
||||||
class ZoneRepository {
|
class ZoneRepository {
|
||||||
async getFirst(): Promise<Zone | null> {
|
async getFirst(): Promise<Zone | null> {
|
||||||
@ -22,7 +24,7 @@ class ZoneRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getById(id: number): Promise<Zone | null> {
|
async getById(id: number) {
|
||||||
try {
|
try {
|
||||||
return await prisma.zone.findUnique({
|
return await prisma.zone.findUnique({
|
||||||
where: {
|
where: {
|
||||||
@ -77,7 +79,7 @@ class ZoneRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getObjects(id: number): Promise<ZoneObject[]> {
|
async getZoneObjects(id: number): Promise<ZoneObject[]> {
|
||||||
try {
|
try {
|
||||||
return await prisma.zoneObject.findMany({
|
return await prisma.zoneObject.findMany({
|
||||||
where: {
|
where: {
|
||||||
@ -89,6 +91,52 @@ class ZoneRepository {
|
|||||||
return []
|
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()
|
export default new ZoneRepository()
|
||||||
|
@ -3,95 +3,12 @@ import UserService from '../services/userService'
|
|||||||
import jwt from 'jsonwebtoken'
|
import jwt from 'jsonwebtoken'
|
||||||
import config from './config'
|
import config from './config'
|
||||||
import { loginAccountSchema, registerAccountSchema } from './zodTypes'
|
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 fs from 'fs'
|
||||||
import { httpLogger } from './logger'
|
import { httpLogger } from './logger'
|
||||||
import { getPublicPath } from './storage'
|
import { getPublicPath } from './storage'
|
||||||
|
import zoneRepository from '../repositories/zoneRepository'
|
||||||
|
|
||||||
async function addHttpRoutes(app: Application) {
|
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
|
* Login
|
||||||
* @param req
|
* @param req
|
||||||
@ -141,6 +58,70 @@ async function addHttpRoutes(app: Application) {
|
|||||||
return res.status(400).json({ message: 'Failed to register user' })
|
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')
|
httpLogger.info('Web routes added')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user