forked from noxious/server
#169 : Re-enabled command manager, created extrudeTiles command for testing
This commit is contained in:
parent
ddeee356b4
commit
3a83f2c1ff
6
package-lock.json
generated
6
package-lock.json
generated
@ -982,9 +982,9 @@
|
|||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/bullmq": {
|
"node_modules/bullmq": {
|
||||||
"version": "5.13.2",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.13.2.tgz",
|
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.14.0.tgz",
|
||||||
"integrity": "sha512-McGE8k3mrCvdUHdU0sHkTKDS1xr4pff+hbEKBY51wk5S6Za0gkuejYA620VQTo3Zz37E/NVWMgumwiXPQ3yZcA==",
|
"integrity": "sha512-qxZHtRuGEp0oHM1aNokuZ4gA0xr6vcZQPe1OLuQoDTuhaEXB4faxApUoo85v/PHnzrniAAqNT9kqD+UBbmECDQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cron-parser": "^4.6.0",
|
"cron-parser": "^4.6.0",
|
||||||
|
136
src/commands/extrudeTiles.ts
Normal file
136
src/commands/extrudeTiles.ts
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import { Server } from 'socket.io'
|
||||||
|
import ZoneManager from '../managers/zoneManager'
|
||||||
|
import sharp from 'sharp'
|
||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs'
|
||||||
|
import { commandLogger } from '../utilities/logger'
|
||||||
|
|
||||||
|
type CommandInput = string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extrude tiles command
|
||||||
|
* This command will get all the tiles inside process.cwd() > public > tiles
|
||||||
|
* And overwrite the existing tiles.
|
||||||
|
* @param input
|
||||||
|
* @param io
|
||||||
|
*/
|
||||||
|
export default async function extrudeTiles(input: CommandInput, io: Server) {
|
||||||
|
const [tileWidth, tileHeight, extrusion = '1', color = '0xffffff00'] = input
|
||||||
|
|
||||||
|
if (!tileWidth || !tileHeight) {
|
||||||
|
console.log('Missing tileWidth or tileHeight! Usage: extrudeTiles <tileWidth> <tileHeight> [extrusion] [color]')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
tileWidth: parseInt(tileWidth),
|
||||||
|
tileHeight: parseInt(tileHeight),
|
||||||
|
extrusion: parseInt(extrusion),
|
||||||
|
color: parseInt(color, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tilesDir = path.join(process.cwd(), 'public', 'tiles')
|
||||||
|
const files = fs.readdirSync(tilesDir).filter(file => file.endsWith('.png'))
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const inputPath = path.join(tilesDir, file)
|
||||||
|
const outputPath = path.join(tilesDir, `${path.parse(file).name}.png`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await extrudeTile(
|
||||||
|
options.tileWidth,
|
||||||
|
options.tileHeight,
|
||||||
|
inputPath,
|
||||||
|
outputPath,
|
||||||
|
options.extrusion,
|
||||||
|
options.color
|
||||||
|
)
|
||||||
|
commandLogger.info(`Extruded tile ${file}`)
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log(error)
|
||||||
|
commandLogger.error('Error extruding tile:', error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function extrudeTile(
|
||||||
|
tileWidth: number,
|
||||||
|
tileHeight: number,
|
||||||
|
inputPath: string,
|
||||||
|
outputPath: string,
|
||||||
|
extrusion: number,
|
||||||
|
backgroundColor: number
|
||||||
|
) {
|
||||||
|
const borderWidth = 4; // You can adjust this value to change the border width
|
||||||
|
|
||||||
|
const image = sharp(inputPath)
|
||||||
|
const metadata = await image.metadata()
|
||||||
|
|
||||||
|
if (!metadata.width || !metadata.height) {
|
||||||
|
throw new Error('Unable to get image dimensions')
|
||||||
|
}
|
||||||
|
|
||||||
|
const tilesX = Math.floor(metadata.width / tileWidth)
|
||||||
|
const tilesY = Math.floor(metadata.height / tileHeight)
|
||||||
|
|
||||||
|
// Use borderWidth in the new dimensions calculation
|
||||||
|
const newWidth = metadata.width + (tilesX + 1) * extrusion + tilesX * borderWidth * 2
|
||||||
|
const newHeight = metadata.height + (tilesY + 1) * extrusion + tilesY * borderWidth * 2
|
||||||
|
|
||||||
|
const background = {
|
||||||
|
r: (backgroundColor >> 24) & 0xff,
|
||||||
|
g: (backgroundColor >> 16) & 0xff,
|
||||||
|
b: (backgroundColor >> 8) & 0xff,
|
||||||
|
alpha: backgroundColor & 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
const newImage = sharp({
|
||||||
|
create: {
|
||||||
|
width: newWidth,
|
||||||
|
height: newHeight,
|
||||||
|
channels: 4,
|
||||||
|
background
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const compositeOperations = []
|
||||||
|
|
||||||
|
for (let y = 0; y < tilesY; y++) {
|
||||||
|
for (let x = 0; x < tilesX; x++) {
|
||||||
|
const tileBuffer = await image
|
||||||
|
.extract({
|
||||||
|
left: x * tileWidth,
|
||||||
|
top: y * tileHeight,
|
||||||
|
width: tileWidth,
|
||||||
|
height: tileHeight
|
||||||
|
})
|
||||||
|
.extend({
|
||||||
|
top: borderWidth,
|
||||||
|
bottom: borderWidth,
|
||||||
|
left: borderWidth,
|
||||||
|
right: borderWidth,
|
||||||
|
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||||
|
})
|
||||||
|
.raw()
|
||||||
|
.toBuffer()
|
||||||
|
|
||||||
|
compositeOperations.push({
|
||||||
|
input: tileBuffer,
|
||||||
|
// Use borderWidth in positioning calculation
|
||||||
|
left: x * (tileWidth + extrusion + borderWidth * 2),
|
||||||
|
top: y * (tileHeight + extrusion + borderWidth * 2),
|
||||||
|
raw: {
|
||||||
|
width: tileWidth + borderWidth * 2,
|
||||||
|
height: tileHeight + borderWidth * 2,
|
||||||
|
channels: 4
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await newImage
|
||||||
|
// @ts-ignore
|
||||||
|
.composite(compositeOperations)
|
||||||
|
.png()
|
||||||
|
.toFile(outputPath)
|
||||||
|
}
|
@ -2,6 +2,7 @@ import * as readline from 'readline'
|
|||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { Server } from 'socket.io'
|
import { Server } from 'socket.io'
|
||||||
|
import { commandLogger } from '../utilities/logger'
|
||||||
|
|
||||||
class CommandManager {
|
class CommandManager {
|
||||||
private commands: Map<string, Function> = new Map()
|
private commands: Map<string, Function> = new Map()
|
||||||
@ -23,7 +24,7 @@ class CommandManager {
|
|||||||
public async boot(io: Server) {
|
public async boot(io: Server) {
|
||||||
this.io = io
|
this.io = io
|
||||||
await this.loadCommands()
|
await this.loadCommands()
|
||||||
console.log('[✅] Command manager loaded')
|
commandLogger.info('Command manager loaded')
|
||||||
this.startPrompt()
|
this.startPrompt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +49,6 @@ class CommandManager {
|
|||||||
private handleUnknownCommand(command: string) {
|
private handleUnknownCommand(command: string) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case 'exit':
|
case 'exit':
|
||||||
console.log('Goodbye!')
|
|
||||||
this.rl.close()
|
this.rl.close()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -58,7 +58,7 @@ class CommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async loadCommands() {
|
private async loadCommands() {
|
||||||
const commandsDir = path.resolve(__dirname, 'commands')
|
const commandsDir = path.resolve(process.cwd(), 'src', 'commands')
|
||||||
try {
|
try {
|
||||||
const files: string[] = await fs.promises.readdir(commandsDir)
|
const files: string[] = await fs.promises.readdir(commandsDir)
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class CommandManager {
|
|||||||
await this.loadCommand(commandsDir, file)
|
await this.loadCommand(commandsDir, file)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[❌] Failed to read commands directory:', error)
|
commandLogger.error(`Failed to read commands directory: ${error}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,16 +79,16 @@ class CommandManager {
|
|||||||
|
|
||||||
this.registerCommand(commandName, module.default)
|
this.registerCommand(commandName, module.default)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[❌] Failed to load command:', file, error)
|
commandLogger.error(`Failed to load command: ${file}: ${error}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerCommand(name: string, command: (args: string[], io: Server) => void) {
|
private registerCommand(name: string, command: (args: string[], io: Server) => void) {
|
||||||
if (this.commands.has(name)) {
|
if (this.commands.has(name)) {
|
||||||
console.warn(`Command '${name}' is already registered. Overwriting...`)
|
commandLogger.warn(`Command '${name}' is already registered. Overwriting...`)
|
||||||
}
|
}
|
||||||
this.commands.set(name, command)
|
this.commands.set(name, command)
|
||||||
console.log(`Registered command: ${name}`)
|
commandLogger.info(`Registered command: ${name}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import express, { Application } from 'express'
|
import express, { Application } from 'express'
|
||||||
|
import config from './utilities/config'
|
||||||
import { createServer as httpServer, Server as HTTPServer } from 'http'
|
import { createServer as httpServer, Server as HTTPServer } from 'http'
|
||||||
import { addHttpRoutes } from './utilities/http'
|
import { addHttpRoutes } from './utilities/http'
|
||||||
import cors from 'cors'
|
import cors from 'cors'
|
||||||
import { Server as SocketServer } from 'socket.io'
|
import { Server as SocketServer } from 'socket.io'
|
||||||
import { TSocket } from './utilities/types'
|
|
||||||
import config from './utilities/config'
|
|
||||||
import prisma from './utilities/prisma'
|
|
||||||
import ZoneManager from './managers/zoneManager'
|
|
||||||
import UserManager from './managers/userManager'
|
|
||||||
import { Authentication } from './middleware/authentication'
|
import { Authentication } from './middleware/authentication'
|
||||||
// import CommandManager from './managers/CommandManager'
|
import { TSocket } from './utilities/types'
|
||||||
|
import prisma from './utilities/prisma'
|
||||||
import { Dirent } from 'node:fs'
|
import { Dirent } from 'node:fs'
|
||||||
import { appLogger, watchLogs } from './utilities/logger'
|
import { appLogger, watchLogs } from './utilities/logger'
|
||||||
|
import ZoneManager from './managers/zoneManager'
|
||||||
|
import UserManager from './managers/userManager'
|
||||||
|
import CommandManager from './managers/commandManager'
|
||||||
import CharacterManager from './managers/characterManager'
|
import CharacterManager from './managers/characterManager'
|
||||||
import QueueManager from './managers/queueManager'
|
import QueueManager from './managers/queueManager'
|
||||||
|
|
||||||
@ -58,12 +58,12 @@ export class Server {
|
|||||||
appLogger.error(`Socket.IO failed to start: ${error.message}`)
|
appLogger.error(`Socket.IO failed to start: ${error.message}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load queue manager
|
|
||||||
await QueueManager.boot(this.io)
|
|
||||||
|
|
||||||
// Add http API routes
|
// Add http API routes
|
||||||
await addHttpRoutes(this.app)
|
await addHttpRoutes(this.app)
|
||||||
|
|
||||||
|
// Load queue manager
|
||||||
|
await QueueManager.boot(this.io)
|
||||||
|
|
||||||
// Load user manager
|
// Load user manager
|
||||||
await UserManager.boot()
|
await UserManager.boot()
|
||||||
|
|
||||||
@ -73,8 +73,8 @@ export class Server {
|
|||||||
// Load character manager
|
// Load character manager
|
||||||
await CharacterManager.boot()
|
await CharacterManager.boot()
|
||||||
|
|
||||||
// Load command manager - Disabled for now
|
// Load command manager
|
||||||
// await CommandManager.boot(this.io);
|
await CommandManager.boot(this.io);
|
||||||
|
|
||||||
// Listen for socket connections
|
// Listen for socket connections
|
||||||
this.io.on('connection', this.handleConnection.bind(this))
|
this.io.on('connection', this.handleConnection.bind(this))
|
||||||
@ -106,15 +106,9 @@ export class Server {
|
|||||||
try {
|
try {
|
||||||
const module = await import(fullPath)
|
const module = await import(fullPath)
|
||||||
if (typeof module.default === 'function') {
|
if (typeof module.default === 'function') {
|
||||||
if (module.default.prototype && module.default.prototype.listen) {
|
|
||||||
// This is a class-based event
|
|
||||||
const EventClass = module.default
|
const EventClass = module.default
|
||||||
const eventInstance = new EventClass(this.io, socket)
|
const eventInstance = new EventClass(this.io, socket)
|
||||||
eventInstance.listen()
|
eventInstance.listen()
|
||||||
} else {
|
|
||||||
// This is a function-based event
|
|
||||||
module.default(this.io, socket)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
appLogger.warn(`Unrecognized export in ${file.name}`)
|
appLogger.warn(`Unrecognized export in ${file.name}`)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import fs from 'fs'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// Array of log types
|
// Array of log types
|
||||||
const LOG_TYPES = ['http', 'game', 'gameMaster', 'app', 'queue'] as const
|
const LOG_TYPES = ['http', 'game', 'gameMaster', 'app', 'queue', 'command'] as const
|
||||||
type LogType = (typeof LOG_TYPES)[number]
|
type LogType = (typeof LOG_TYPES)[number]
|
||||||
|
|
||||||
const createLogger = (name: LogType) =>
|
const createLogger = (name: LogType) =>
|
||||||
@ -43,6 +43,13 @@ const watchLogs = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const { http: httpLogger, game: gameLogger, gameMaster: gameMasterLogger, app: appLogger, queue: queueLogger } = loggers
|
export const {
|
||||||
|
http: httpLogger,
|
||||||
|
game: gameLogger,
|
||||||
|
gameMaster: gameMasterLogger,
|
||||||
|
app: appLogger,
|
||||||
|
queue: queueLogger,
|
||||||
|
command: commandLogger
|
||||||
|
} = loggers
|
||||||
|
|
||||||
export { watchLogs }
|
export { watchLogs }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user