forked from noxious/server
Merge remote-tracking branch 'origin/main' into feature/#182-reset-password
# Conflicts: # src/utilities/http.ts
This commit is contained in:
commit
c04c52aed0
30
package-lock.json
generated
30
package-lock.json
generated
@ -721,9 +721,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.1.tgz",
|
||||
"integrity": "sha512-j2VlPv1NnwPJbaCNv69FO/1z4lId0QmGvpT41YxitRtWlg96g/j8qcv2RKsLKe2F6OJgyXhupN1Xo17b2m139Q==",
|
||||
"version": "20.17.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.5.tgz",
|
||||
"integrity": "sha512-n8FYY/pRxu496441gIcAQFZPKXbhsd6VZygcq+PTSZ75eMh/Ke0hCAROdUa21qiFqKNsPPYic46yXDO1JGiPBQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
@ -790,9 +790,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
|
||||
"integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@ -938,9 +938,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/bullmq": {
|
||||
"version": "5.21.2",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.21.2.tgz",
|
||||
"integrity": "sha512-LPuNoGaDc5CON2X6h4cJ2iVfd+B+02xubFU+IB/fyJHd+/HqUZRqnlYryUCAuhVHBhUKtA6oyVdJxqSa62i+og==",
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.22.0.tgz",
|
||||
"integrity": "sha512-nwjJSQt/kpO4bIfAznyKKz3+m5OZ6YSaz2Vg7oNoZWTD5wCnJJJy6b9iWM5QIF0bADhDWyorLCO0hU3de+iKMA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cron-parser": "^4.6.0",
|
||||
@ -1907,9 +1907,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/msgpackr": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.0.tgz",
|
||||
"integrity": "sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==",
|
||||
"version": "1.11.2",
|
||||
"resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz",
|
||||
"integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==",
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"msgpackr-extract": "^3.0.2"
|
||||
@ -2740,9 +2740,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
|
||||
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
|
@ -1,5 +1,8 @@
|
||||
import prisma from '../utilities/prisma' // Import the global Prisma instance
|
||||
import { Tile } from '@prisma/client'
|
||||
import zoneRepository from './zoneRepository'
|
||||
import { unduplicateArray } from '../utilities/utilities'
|
||||
import { FlattenZoneArray } from '../utilities/zone'
|
||||
|
||||
class TileRepository {
|
||||
async getById(id: string): Promise<Tile | null> {
|
||||
@ -8,9 +11,28 @@ class TileRepository {
|
||||
})
|
||||
}
|
||||
|
||||
async getByIds(ids: string[]): Promise<Tile[]> {
|
||||
return prisma.tile.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: ids
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getAll(): Promise<Tile[]> {
|
||||
return prisma.tile.findMany()
|
||||
}
|
||||
|
||||
async getByZoneId(zoneId: number): Promise<Tile[]> {
|
||||
const zone = await zoneRepository.getById(zoneId)
|
||||
if (!zone) return []
|
||||
|
||||
const zoneTileArray = unduplicateArray(FlattenZoneArray(JSON.parse(JSON.stringify(zone.tiles))))
|
||||
|
||||
return this.getByIds(zoneTileArray)
|
||||
}
|
||||
}
|
||||
|
||||
export default new TileRepository()
|
||||
|
@ -2,7 +2,7 @@ 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 { AssetData } from '../utilities/types'
|
||||
import tileRepository from './tileRepository'
|
||||
|
||||
class ZoneRepository {
|
||||
@ -91,52 +91,6 @@ 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()
|
||||
|
@ -33,6 +33,7 @@ class UserService {
|
||||
/**
|
||||
* Register user
|
||||
* @param username
|
||||
* @param email
|
||||
* @param password
|
||||
*/
|
||||
async register(username: string, email: string, password: string): Promise<boolean | User> {
|
||||
|
@ -1,4 +1,14 @@
|
||||
import prisma from '../utilities/prisma'
|
||||
import { AssetData } from '../utilities/types'
|
||||
import tileRepository from '../repositories/tileRepository'
|
||||
import zoneRepository from '../repositories/zoneRepository'
|
||||
import { Object, Zone, ZoneObject } from '@prisma/client'
|
||||
|
||||
type getZoneAsetsZoneType = Zone & {
|
||||
zoneObjects: (ZoneObject & {
|
||||
object: Object
|
||||
})[]
|
||||
}
|
||||
|
||||
class ZoneService {
|
||||
async createDemoZone(): Promise<boolean> {
|
||||
@ -27,6 +37,49 @@ class ZoneService {
|
||||
console.log('Demo zone created.')
|
||||
return true
|
||||
}
|
||||
|
||||
async getZoneAssets(zone: getZoneAsetsZoneType): Promise<AssetData[]> {
|
||||
const assets: AssetData[] = []
|
||||
|
||||
// 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,
|
||||
data: '/assets/tiles/' + tileInfo.id + '.png',
|
||||
group: 'tiles',
|
||||
updatedAt: tileInfo?.updatedAt || new Date()
|
||||
} as AssetData)
|
||||
}
|
||||
|
||||
// Add object assets
|
||||
for (const zoneObject of zone.zoneObjects) {
|
||||
if (!zoneObject.object) continue
|
||||
|
||||
assets.push({
|
||||
key: zoneObject.object.id,
|
||||
data: '/assets/objects/' + zoneObject.object.id + '.png',
|
||||
group: 'objects',
|
||||
updatedAt: zoneObject.object.updatedAt || new Date()
|
||||
} as AssetData)
|
||||
}
|
||||
|
||||
// Filter out duplicate assets
|
||||
return assets.reduce((acc: AssetData[], 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 ZoneService
|
||||
|
@ -6,7 +6,10 @@ import { loginAccountSchema, registerAccountSchema, resetPasswordSchema } from '
|
||||
import fs from 'fs'
|
||||
import { httpLogger } from './logger'
|
||||
import { getPublicPath } from './storage'
|
||||
import zoneRepository from '../repositories/zoneRepository'
|
||||
import TileRepository from '../repositories/tileRepository'
|
||||
import { AssetData } from './types'
|
||||
import ZoneRepository from '../repositories/zoneRepository'
|
||||
import SpriteRepository from '../repositories/spriteRepository'
|
||||
|
||||
async function addHttpRoutes(app: Application) {
|
||||
/**
|
||||
@ -87,37 +90,90 @@ async function addHttpRoutes(app: Application) {
|
||||
* @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)
|
||||
// })
|
||||
app.get('/assets/list_tiles', async (req: Request, res: Response) => {
|
||||
// Get all tiles
|
||||
let assets: AssetData[] = []
|
||||
const tiles = await TileRepository.getAll()
|
||||
for (const tile of tiles) {
|
||||
assets.push({
|
||||
key: tile.id,
|
||||
data: '/assets/tiles/' + tile.id + '.png',
|
||||
group: 'tiles',
|
||||
updatedAt: tile.updatedAt
|
||||
} as AssetData)
|
||||
}
|
||||
|
||||
// Return the array
|
||||
res.json(assets)
|
||||
})
|
||||
|
||||
/**
|
||||
* Get a specific asset
|
||||
* Get all tiles from a zone and serve as AssetData array
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
app.get('/assets/list_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' })
|
||||
}
|
||||
|
||||
// Get all tiles
|
||||
let assets: AssetData[] = []
|
||||
const tiles = await TileRepository.getByZoneId(parseInt(zoneId))
|
||||
for (const tile of tiles) {
|
||||
assets.push({
|
||||
key: tile.id,
|
||||
data: '/assets/tiles/' + tile.id + '.png',
|
||||
group: 'tiles',
|
||||
updatedAt: tile.updatedAt
|
||||
} as AssetData)
|
||||
}
|
||||
|
||||
// Return the array
|
||||
res.json(assets)
|
||||
})
|
||||
|
||||
app.get('/assets/list_sprite_actions/:spriteId', async (req: Request, res: Response) => {
|
||||
const spriteId = req.params.spriteId
|
||||
// Check if spriteId is valid number
|
||||
if (!spriteId || parseInt(spriteId) === 0) {
|
||||
return res.status(400).json({ message: 'Invalid sprite ID' })
|
||||
}
|
||||
// Get sprite by id
|
||||
const sprite = await SpriteRepository.getById(spriteId)
|
||||
if (!sprite) {
|
||||
return res.status(404).json({ message: 'Sprite not found' })
|
||||
}
|
||||
|
||||
let assets: AssetData[] = []
|
||||
sprite.spriteActions.forEach((spriteAction) => {
|
||||
assets.push({
|
||||
key: sprite.id + '-' + spriteAction.action,
|
||||
data: '/assets/sprites/' + sprite.id + '/' + spriteAction.action + '.png',
|
||||
group: spriteAction.isAnimated ? 'sprite_animations' : 'sprites',
|
||||
updatedAt: sprite.updatedAt,
|
||||
isAnimated: spriteAction.isAnimated,
|
||||
frameCount: JSON.parse(JSON.stringify(spriteAction.sprites)).length,
|
||||
frameWidth: spriteAction.frameWidth,
|
||||
frameHeight: spriteAction.frameHeight
|
||||
})
|
||||
})
|
||||
|
||||
// Return the array
|
||||
res.json(assets)
|
||||
})
|
||||
|
||||
/**
|
||||
* Download asset file
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
|
@ -21,11 +21,12 @@ export type ExtendedCharacter = Character & {
|
||||
resetMovement: boolean
|
||||
}
|
||||
|
||||
export type TAsset = {
|
||||
export type AssetData = {
|
||||
key: string
|
||||
url: string
|
||||
data: string
|
||||
group: 'tiles' | 'objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other'
|
||||
updatedAt: Date
|
||||
isAnimated?: boolean
|
||||
frameCount?: number
|
||||
frameWidth?: number
|
||||
frameHeight?: number
|
||||
|
3
src/utilities/utilities.ts
Normal file
3
src/utilities/utilities.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function unduplicateArray(array: any[]) {
|
||||
return [...new Set(array.flat())]
|
||||
}
|
9
src/utilities/zone.ts
Normal file
9
src/utilities/zone.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export function FlattenZoneArray(tiles: string[][]) {
|
||||
const normalArray = []
|
||||
|
||||
for (const row of tiles) {
|
||||
normalArray.push(...row)
|
||||
}
|
||||
|
||||
return normalArray
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user