From 9d6de8a1a93209fc4d921d95db9f0cf403b4c052 Mon Sep 17 00:00:00 2001
From: Dennis Postma <dennis@directonline.io>
Date: Sat, 21 Sep 2024 23:54:52 +0200
Subject: [PATCH] Mass replace parameter order (socket,io)>(io,socket), worked
 on queueing system

---
 src/jobs/characterLeaveZone.ts                | 16 +++
 src/managers/characterManager.ts              |  2 +-
 src/managers/queueManager.ts                  | 98 +++++++++++++++----
 src/repositories/zoneRepository.ts            |  2 +-
 src/server.ts                                 |  9 +-
 .../character/connect.ts                      | 13 ++-
 .../character/create.ts                       |  2 +-
 .../character/delete.ts                       |  2 +-
 .../character/list.ts                         |  2 +-
 .../chat/gameMaster/alertCommand.ts           |  2 +-
 .../chat/gameMaster/teleportCommand.ts        |  5 +-
 .../chat/sendMessage.ts                       |  0
 src/{events => socketEvents}/disconnect.ts    |  4 +-
 .../gameMaster/assetManager/object/list.ts    |  4 +-
 .../gameMaster/assetManager/object/remove.ts  |  4 +-
 .../gameMaster/assetManager/object/update.ts  |  4 +-
 .../gameMaster/assetManager/object/upload.ts  |  2 +-
 .../gameMaster/assetManager/sprite/create.ts  |  4 +-
 .../gameMaster/assetManager/sprite/delete.ts  |  2 +-
 .../gameMaster/assetManager/sprite/list.ts    |  4 +-
 .../gameMaster/assetManager/sprite/update.ts  |  4 +-
 .../gameMaster/assetManager/tile/delete.ts    |  2 +-
 .../gameMaster/assetManager/tile/list.ts      |  4 +-
 .../gameMaster/assetManager/tile/update.ts    |  4 +-
 .../gameMaster/assetManager/tile/upload.ts    |  4 +-
 .../gameMaster/zoneEditor/create.ts           |  4 +-
 .../gameMaster/zoneEditor/delete.ts           |  6 +-
 .../gameMaster/zoneEditor/list.ts             |  6 +-
 .../gameMaster/zoneEditor/request.ts          |  4 +-
 .../gameMaster/zoneEditor/update.ts           |  4 +-
 src/{events => socketEvents}/login.ts         |  2 +-
 .../zone/characterJoin.ts                     |  6 +-
 .../zone/characterLeave.ts                    |  2 +-
 .../zone/characterMove.ts                     | 10 +-
 src/utilities/http.ts                         | 32 +++---
 src/utilities/logger.ts                       | 52 +++++-----
 36 files changed, 206 insertions(+), 121 deletions(-)
 create mode 100644 src/jobs/characterLeaveZone.ts
 rename src/{events => socketEvents}/character/connect.ts (65%)
 rename src/{events => socketEvents}/character/create.ts (96%)
 rename src/{events => socketEvents}/character/delete.ts (94%)
 rename src/{events => socketEvents}/character/list.ts (89%)
 rename src/{events => socketEvents}/chat/gameMaster/alertCommand.ts (93%)
 rename src/{events => socketEvents}/chat/gameMaster/teleportCommand.ts (98%)
 rename src/{events => socketEvents}/chat/sendMessage.ts (100%)
 rename src/{events => socketEvents}/disconnect.ts (92%)
 rename src/{events => socketEvents}/gameMaster/assetManager/object/list.ts (91%)
 rename src/{events => socketEvents}/gameMaster/assetManager/object/remove.ts (94%)
 rename src/{events => socketEvents}/gameMaster/assetManager/object/update.ts (94%)
 rename src/{events => socketEvents}/gameMaster/assetManager/object/upload.ts (98%)
 rename src/{events => socketEvents}/gameMaster/assetManager/sprite/create.ts (94%)
 rename src/{events => socketEvents}/gameMaster/assetManager/sprite/delete.ts (99%)
 rename src/{events => socketEvents}/gameMaster/assetManager/sprite/list.ts (91%)
 rename src/{events => socketEvents}/gameMaster/assetManager/sprite/update.ts (98%)
 rename src/{events => socketEvents}/gameMaster/assetManager/tile/delete.ts (98%)
 rename src/{events => socketEvents}/gameMaster/assetManager/tile/list.ts (90%)
 rename src/{events => socketEvents}/gameMaster/assetManager/tile/update.ts (92%)
 rename src/{events => socketEvents}/gameMaster/assetManager/tile/upload.ts (94%)
 rename src/{events => socketEvents}/gameMaster/zoneEditor/create.ts (95%)
 rename src/{events => socketEvents}/gameMaster/zoneEditor/delete.ts (93%)
 rename src/{events => socketEvents}/gameMaster/zoneEditor/list.ts (92%)
 rename src/{events => socketEvents}/gameMaster/zoneEditor/request.ts (94%)
 rename src/{events => socketEvents}/gameMaster/zoneEditor/update.ts (97%)
 rename src/{events => socketEvents}/login.ts (77%)
 rename src/{events => socketEvents}/zone/characterJoin.ts (94%)
 rename src/{events => socketEvents}/zone/characterLeave.ts (99%)
 rename src/{events => socketEvents}/zone/characterMove.ts (94%)

diff --git a/src/jobs/characterLeaveZone.ts b/src/jobs/characterLeaveZone.ts
new file mode 100644
index 0000000..f547f4c
--- /dev/null
+++ b/src/jobs/characterLeaveZone.ts
@@ -0,0 +1,16 @@
+import { TSocket } from '../utilities/types'
+import { Server as SocketServer } from 'socket.io'
+
+export default class SomeJob {
+  constructor(private params: any) {}
+
+  async execute(io: SocketServer, socket?: TSocket) {
+    // Handle the event
+    console.log('Event params:', this.params)
+    if (socket) {
+      socket.emit('notification', { message: 'Something happened with socket' })
+    }
+    // Use io for broadcasting if needed
+    io.emit('notification', { message: 'Something happened' })
+  }
+}
diff --git a/src/managers/characterManager.ts b/src/managers/characterManager.ts
index 160e699..6fc17a1 100644
--- a/src/managers/characterManager.ts
+++ b/src/managers/characterManager.ts
@@ -31,7 +31,7 @@ class CharacterManager {
   }
 
   public hasResetMovement(character: ExtendedCharacter) {
-    return this.characters.find(x => x.id === character.id)?.resetMovement;
+    return this.characters.find((x) => x.id === character.id)?.resetMovement
   }
 
   public getCharactersInZone(zone: Zone) {
diff --git a/src/managers/queueManager.ts b/src/managers/queueManager.ts
index 38f342d..bff56d6 100644
--- a/src/managers/queueManager.ts
+++ b/src/managers/queueManager.ts
@@ -1,29 +1,91 @@
-import IORedis from 'ioredis';
+import IORedis from 'ioredis'
 import { Job, Queue, Worker } from 'bullmq'
 import config from '../utilities/config'
+import { Server as SocketServer } from 'socket.io'
+import { TSocket } from '../utilities/types'
+import { queueLogger } from '../utilities/logger'
 
 class QueueManager {
-  private connection!: IORedis;
-  public queue!: Queue;
-  public worker!: Worker;
+  private connection!: IORedis
+  private queue!: Queue
+  private worker!: Worker
+  private io!: SocketServer
+
+  public async boot(io: SocketServer) {
+    this.io = io
 
-  public async boot() {
     this.connection = new IORedis(config.REDIS_URL, {
       maxRetriesPerRequest: null
-    });
-  //   this.queue = new Queue('myqueue', { connection: this.connection });
-  //   this.worker = new Worker('myqueue', async (job: Job)=>{
-  //     console.log('hallo')
-  //     console.log(job.data);
-  //     console.log(job.data.data.classobj);
-  //     const test = job.data.data.classobj();
-  //     console.log(test);
-  //     console.log(job.data);
-  //   }, { connection: this.connection, concurrency: 10000 });
-  //
+    })
 
-    console.log('hallo')
+    try {
+      await this.connection.ping()
+      queueLogger.info('Successfully connected to Redis')
+    } catch (error) {
+      queueLogger.error('Failed to connect to Redis:', error)
+      process.exit(1)
+    }
+
+    this.queue = new Queue('jobs')
+    this.worker = new Worker('jobs', this.processJob.bind(this), {
+      connection: this.connection,
+      concurrency: 10000
+    })
+
+    this.worker.on('completed', (job) => {
+      queueLogger.info(`Job ${job?.id} has completed`)
+    })
+
+    this.worker.on('failed', (job, err) => {
+      queueLogger.error(`Job ${job?.id} failed with error: ${err}`)
+    })
+
+    queueLogger.info('Queue manager loaded')
+  }
+
+  private async processJob(job: Job) {
+    const { jobClass, params, socketId } = job.data
+
+    console.log('Processing job:', job)
+    try {
+      const JobClass = await import(`../jobs/${jobClass}`)
+
+      if (!JobClass) {
+        queueLogger.warn(`Job class not found: ${jobClass}`)
+        return
+      }
+
+      console.log('Job class:', JobClass)
+
+      console.log('Job class:', JobClass.name)
+
+      const job = new JobClass(params)
+
+      if (socketId && this.io) {
+        const socket = this.io.sockets.sockets.get(socketId)
+        if (socket) {
+          await job.execute(this.io, socket)
+        } else {
+          queueLogger.warn(`Socket not found for job: ${socketId}`)
+          await job.execute(this.io)
+        }
+      } else {
+        await job.execute(this.io)
+      }
+    } catch (error: any) {
+      queueLogger.error(`Error processing job: ${error.message}`)
+    }
+  }
+
+  public async addToQueue(jobClass: any, params: any, socket?: TSocket) {
+    const jobData = {
+      jobClass: jobClass.name,
+      params,
+      socketId: socket?.id
+    }
+
+    await this.queue.add('job', jobData)
   }
 }
 
-export default new QueueManager();
\ No newline at end of file
+export default new QueueManager()
diff --git a/src/repositories/zoneRepository.ts b/src/repositories/zoneRepository.ts
index ec3cd42..214ccde 100644
--- a/src/repositories/zoneRepository.ts
+++ b/src/repositories/zoneRepository.ts
@@ -1,6 +1,6 @@
 import { Zone, ZoneEventTile, ZoneEventTileType, ZoneObject } from '@prisma/client'
 import prisma from '../utilities/prisma'
-import { ZoneEventTileWithTeleport } from '../events/zone/characterMove'
+import { ZoneEventTileWithTeleport } from '../socketEvents/zone/characterMove'
 import { appLogger } from '../utilities/logger'
 
 class ZoneRepository {
diff --git a/src/server.ts b/src/server.ts
index 2c227b7..d6af995 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -58,14 +58,15 @@ export class Server {
       appLogger.error(`Socket.IO failed to start: ${error.message}`)
     }
 
+    // Load queue manager
+    await QueueManager.boot(this.io)
+
     // Add http API routes
     await addHttpRoutes(this.app)
 
     // Load user manager
     await UserManager.boot()
 
-    await QueueManager.boot();
-
     // Load zoneEditor manager
     await ZoneManager.boot()
 
@@ -85,7 +86,7 @@ export class Server {
    * @private
    */
   private async handleConnection(socket: TSocket) {
-    const eventsPath = path.join(__dirname, 'events')
+    const eventsPath = path.join(__dirname, 'socketEvents')
     try {
       await this.loadEventHandlers(eventsPath, socket)
     } catch (error: any) {
@@ -112,7 +113,7 @@ export class Server {
               eventInstance.listen()
             } else {
               // This is a function-based event
-              module.default(socket, this.io)
+              module.default(this.io, socket)
             }
           } else {
             appLogger.warn(`Unrecognized export in ${file.name}`)
diff --git a/src/events/character/connect.ts b/src/socketEvents/character/connect.ts
similarity index 65%
rename from src/events/character/connect.ts
rename to src/socketEvents/character/connect.ts
index b280cdb..7ca259d 100644
--- a/src/events/character/connect.ts
+++ b/src/socketEvents/character/connect.ts
@@ -2,19 +2,22 @@ import { Server } from 'socket.io'
 import { TSocket, ExtendedCharacter } from '../../utilities/types'
 import CharacterRepository from '../../repositories/characterRepository'
 import CharacterManager from '../../managers/characterManager'
+import QueueManager from '../../managers/queueManager'
+import SomeJob from '../../jobs/characterLeaveZone'
 
 type SocketResponseT = {
   character_id: number
 }
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('character:connect', async (data: SocketResponseT) => {
     console.log('character:connect requested', data)
     try {
-      const character = await CharacterRepository.getByUserAndId(socket?.user?.id as number, data.character_id);
-      if(!character) return;
-      socket.characterId = character.id;
-      CharacterManager.initCharacter(character as ExtendedCharacter);
+      const character = await CharacterRepository.getByUserAndId(socket?.user?.id as number, data.character_id)
+      if (!character) return
+      socket.characterId = character.id
+      await QueueManager.addToQueue(SomeJob, { someParam: 'value' }, socket)
+      CharacterManager.initCharacter(character as ExtendedCharacter)
       socket.emit('character:connect', character)
     } catch (error: any) {
       console.log('character:connect error', error)
diff --git a/src/events/character/create.ts b/src/socketEvents/character/create.ts
similarity index 96%
rename from src/events/character/create.ts
rename to src/socketEvents/character/create.ts
index 0417f86..0126036 100644
--- a/src/events/character/create.ts
+++ b/src/socketEvents/character/create.ts
@@ -6,7 +6,7 @@ import { ZCharacterCreate } from '../../utilities/zodTypes'
 import prisma from '../../utilities/prisma'
 import { gameLogger } from '../../utilities/logger'
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('character:create', async (data: any) => {
     console.log('character:create requested', data)
     // zod validate
diff --git a/src/events/character/delete.ts b/src/socketEvents/character/delete.ts
similarity index 94%
rename from src/events/character/delete.ts
rename to src/socketEvents/character/delete.ts
index 0fdbb64..04f2bac 100644
--- a/src/events/character/delete.ts
+++ b/src/socketEvents/character/delete.ts
@@ -12,7 +12,7 @@ type TypeResponse = {
   characters: Character[]
 }
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('character:delete', async (data: TypePayload, callback: (response: TypeResponse) => void) => {
     // zod validate
     try {
diff --git a/src/events/character/list.ts b/src/socketEvents/character/list.ts
similarity index 89%
rename from src/events/character/list.ts
rename to src/socketEvents/character/list.ts
index d994aea..2243e6e 100644
--- a/src/events/character/list.ts
+++ b/src/socketEvents/character/list.ts
@@ -3,7 +3,7 @@ import { TSocket } from '../../utilities/types'
 import { Character } from '@prisma/client'
 import CharacterRepository from '../../repositories/characterRepository'
 
-export default function CharacterList(socket: TSocket, io: Server) {
+export default function CharacterList(io: Server, socket: TSocket) {
   socket.on('character:list', async (data: any) => {
     try {
       console.log('character:list requested')
diff --git a/src/events/chat/gameMaster/alertCommand.ts b/src/socketEvents/chat/gameMaster/alertCommand.ts
similarity index 93%
rename from src/events/chat/gameMaster/alertCommand.ts
rename to src/socketEvents/chat/gameMaster/alertCommand.ts
index 1210e0b..3ffbdce 100644
--- a/src/events/chat/gameMaster/alertCommand.ts
+++ b/src/socketEvents/chat/gameMaster/alertCommand.ts
@@ -7,7 +7,7 @@ type TypePayload = {
   message: string
 }
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('chat:send_message', async (data: TypePayload, callback: (response: boolean) => void) => {
     try {
       if (!isCommand(data.message, 'alert')) return
diff --git a/src/events/chat/gameMaster/teleportCommand.ts b/src/socketEvents/chat/gameMaster/teleportCommand.ts
similarity index 98%
rename from src/events/chat/gameMaster/teleportCommand.ts
rename to src/socketEvents/chat/gameMaster/teleportCommand.ts
index 0c65aeb..1c0b0a6 100644
--- a/src/events/chat/gameMaster/teleportCommand.ts
+++ b/src/socketEvents/chat/gameMaster/teleportCommand.ts
@@ -21,7 +21,7 @@ export default class TeleportCommandEvent {
 
   private async handleTeleportCommand(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
     try {
-      const character = CharacterManager.getCharacterFromSocket(this.socket);
+      const character = CharacterManager.getCharacterFromSocket(this.socket)
       if (!character) {
         this.socket.emit('notification', { title: 'Server message', message: 'Character not found' })
         return
@@ -61,12 +61,11 @@ export default class TeleportCommandEvent {
       this.io.to(zone.id.toString()).emit('zone:character:join', character)
       this.socket.join(zone.id.toString())
 
-
       character.zoneId = zone.id
       character.positionX = 0
       character.positionY = 0
 
-      character.resetMovement = true;
+      character.resetMovement = true
 
       this.socket.emit('zone:character:teleport', {
         zone,
diff --git a/src/events/chat/sendMessage.ts b/src/socketEvents/chat/sendMessage.ts
similarity index 100%
rename from src/events/chat/sendMessage.ts
rename to src/socketEvents/chat/sendMessage.ts
diff --git a/src/events/disconnect.ts b/src/socketEvents/disconnect.ts
similarity index 92%
rename from src/events/disconnect.ts
rename to src/socketEvents/disconnect.ts
index 3b5a13a..83585cf 100644
--- a/src/events/disconnect.ts
+++ b/src/socketEvents/disconnect.ts
@@ -2,7 +2,7 @@ import { Server } from 'socket.io'
 import { TSocket } from '../utilities/types'
 import CharacterManager from '../managers/characterManager'
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('disconnect', async (data: any) => {
     if (!socket.user) {
       console.log('User disconnected but had no user set')
@@ -11,7 +11,7 @@ export default function (socket: TSocket, io: Server) {
 
     io.emit('user:disconnect', socket.user.id)
 
-    const character = CharacterManager.getCharacterFromSocket(socket);
+    const character = CharacterManager.getCharacterFromSocket(socket)
 
     if (!character) {
       console.log('User disconnected but had no character set')
diff --git a/src/events/gameMaster/assetManager/object/list.ts b/src/socketEvents/gameMaster/assetManager/object/list.ts
similarity index 91%
rename from src/events/gameMaster/assetManager/object/list.ts
rename to src/socketEvents/gameMaster/assetManager/object/list.ts
index 860119d..472cf47 100644
--- a/src/events/gameMaster/assetManager/object/list.ts
+++ b/src/socketEvents/gameMaster/assetManager/object/list.ts
@@ -12,9 +12,9 @@ interface IPayload {}
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:object:list', async (data: any, callback: (response: Object[]) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return callback([])
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/object/remove.ts b/src/socketEvents/gameMaster/assetManager/object/remove.ts
similarity index 94%
rename from src/events/gameMaster/assetManager/object/remove.ts
rename to src/socketEvents/gameMaster/assetManager/object/remove.ts
index 77299b2..aba06c2 100644
--- a/src/events/gameMaster/assetManager/object/remove.ts
+++ b/src/socketEvents/gameMaster/assetManager/object/remove.ts
@@ -15,9 +15,9 @@ interface IPayload {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:object:remove', async (data: IPayload, callback: (response: boolean) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return callback(false)
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/object/update.ts b/src/socketEvents/gameMaster/assetManager/object/update.ts
similarity index 94%
rename from src/events/gameMaster/assetManager/object/update.ts
rename to src/socketEvents/gameMaster/assetManager/object/update.ts
index 156f68d..60bd1b7 100644
--- a/src/events/gameMaster/assetManager/object/update.ts
+++ b/src/socketEvents/gameMaster/assetManager/object/update.ts
@@ -21,9 +21,9 @@ type Payload = {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:object:update', async (data: Payload, callback: (success: boolean) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return callback(false)
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/object/upload.ts b/src/socketEvents/gameMaster/assetManager/object/upload.ts
similarity index 98%
rename from src/events/gameMaster/assetManager/object/upload.ts
rename to src/socketEvents/gameMaster/assetManager/object/upload.ts
index 8fd0b3f..22ab62c 100644
--- a/src/events/gameMaster/assetManager/object/upload.ts
+++ b/src/socketEvents/gameMaster/assetManager/object/upload.ts
@@ -24,7 +24,7 @@ export default class ObjectUploadEvent {
 
   private async handleObjectUpload(data: IObjectData, callback: (response: boolean) => void): Promise<void> {
     try {
-      const character = await characterRepository.getById(this.socket.characterId as number);
+      const character = await characterRepository.getById(this.socket.characterId as number)
       if (!character) return callback(false)
 
       if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/sprite/create.ts b/src/socketEvents/gameMaster/assetManager/sprite/create.ts
similarity index 94%
rename from src/events/gameMaster/assetManager/sprite/create.ts
rename to src/socketEvents/gameMaster/assetManager/sprite/create.ts
index a849707..ad0dda4 100644
--- a/src/events/gameMaster/assetManager/sprite/create.ts
+++ b/src/socketEvents/gameMaster/assetManager/sprite/create.ts
@@ -11,10 +11,10 @@ import characterRepository from '../../../../repositories/characterRepository'
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:sprite:create', async (data: undefined, callback: (response: boolean) => void) => {
     try {
-      const character = await characterRepository.getById(socket.characterId as number);
+      const character = await characterRepository.getById(socket.characterId as number)
       if (!character) return callback(false)
 
       if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/sprite/delete.ts b/src/socketEvents/gameMaster/assetManager/sprite/delete.ts
similarity index 99%
rename from src/events/gameMaster/assetManager/sprite/delete.ts
rename to src/socketEvents/gameMaster/assetManager/sprite/delete.ts
index 8a4cc90..15f572c 100644
--- a/src/events/gameMaster/assetManager/sprite/delete.ts
+++ b/src/socketEvents/gameMaster/assetManager/sprite/delete.ts
@@ -25,7 +25,7 @@ export default class GMSpriteDeleteEvent {
   }
 
   private async handleSpriteDelete(data: Payload, callback: (response: boolean) => void): Promise<void> {
-    const character = CharacterManager.getCharacterFromSocket(this.socket);
+    const character = CharacterManager.getCharacterFromSocket(this.socket)
     if (character?.role !== 'gm') {
       return callback(false)
     }
diff --git a/src/events/gameMaster/assetManager/sprite/list.ts b/src/socketEvents/gameMaster/assetManager/sprite/list.ts
similarity index 91%
rename from src/events/gameMaster/assetManager/sprite/list.ts
rename to src/socketEvents/gameMaster/assetManager/sprite/list.ts
index cf24eb7..ae68853 100644
--- a/src/events/gameMaster/assetManager/sprite/list.ts
+++ b/src/socketEvents/gameMaster/assetManager/sprite/list.ts
@@ -12,9 +12,9 @@ interface IPayload {}
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:sprite:list', async (data: any, callback: (response: Sprite[]) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return callback([])
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/sprite/update.ts b/src/socketEvents/gameMaster/assetManager/sprite/update.ts
similarity index 98%
rename from src/events/gameMaster/assetManager/sprite/update.ts
rename to src/socketEvents/gameMaster/assetManager/sprite/update.ts
index b3c1615..37805bc 100644
--- a/src/events/gameMaster/assetManager/sprite/update.ts
+++ b/src/socketEvents/gameMaster/assetManager/sprite/update.ts
@@ -27,9 +27,9 @@ interface ProcessedSpriteAction extends SpriteActionInput {
   }>
 }
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:sprite:update', async (data: Payload, callback: (success: boolean) => void) => {
-    const character = CharacterManager.getCharacterFromSocket(socket);
+    const character = CharacterManager.getCharacterFromSocket(socket)
     if (character?.role !== 'gm') {
       return callback(false)
     }
diff --git a/src/events/gameMaster/assetManager/tile/delete.ts b/src/socketEvents/gameMaster/assetManager/tile/delete.ts
similarity index 98%
rename from src/events/gameMaster/assetManager/tile/delete.ts
rename to src/socketEvents/gameMaster/assetManager/tile/delete.ts
index bdb5eb7..0fca22b 100644
--- a/src/events/gameMaster/assetManager/tile/delete.ts
+++ b/src/socketEvents/gameMaster/assetManager/tile/delete.ts
@@ -25,7 +25,7 @@ export default class GMTileDeleteEvent {
   }
 
   private async handleTileDelete(data: Payload, callback: (response: boolean) => void): Promise<void> {
-    const character = await characterRepository.getById(this.socket.characterId as number);
+    const character = await characterRepository.getById(this.socket.characterId as number)
     if (!character) return callback(false)
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/tile/list.ts b/src/socketEvents/gameMaster/assetManager/tile/list.ts
similarity index 90%
rename from src/events/gameMaster/assetManager/tile/list.ts
rename to src/socketEvents/gameMaster/assetManager/tile/list.ts
index 5b8cce0..1acf814 100644
--- a/src/events/gameMaster/assetManager/tile/list.ts
+++ b/src/socketEvents/gameMaster/assetManager/tile/list.ts
@@ -12,9 +12,9 @@ interface IPayload {}
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:tile:list', async (data: any, callback: (response: Tile[]) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/tile/update.ts b/src/socketEvents/gameMaster/assetManager/tile/update.ts
similarity index 92%
rename from src/events/gameMaster/assetManager/tile/update.ts
rename to src/socketEvents/gameMaster/assetManager/tile/update.ts
index d6db7a8..800973b 100644
--- a/src/events/gameMaster/assetManager/tile/update.ts
+++ b/src/socketEvents/gameMaster/assetManager/tile/update.ts
@@ -15,9 +15,9 @@ type Payload = {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:tile:update', async (data: Payload, callback: (success: boolean) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return callback(false)
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/assetManager/tile/upload.ts b/src/socketEvents/gameMaster/assetManager/tile/upload.ts
similarity index 94%
rename from src/events/gameMaster/assetManager/tile/upload.ts
rename to src/socketEvents/gameMaster/assetManager/tile/upload.ts
index b215672..d994da2 100644
--- a/src/events/gameMaster/assetManager/tile/upload.ts
+++ b/src/socketEvents/gameMaster/assetManager/tile/upload.ts
@@ -16,10 +16,10 @@ interface ITileData {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:tile:upload', async (data: ITileData, callback: (response: boolean) => void) => {
     try {
-      const character = await characterRepository.getById(socket.characterId as number);
+      const character = await characterRepository.getById(socket.characterId as number)
       if (!character) return callback(false)
 
       if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/zoneEditor/create.ts b/src/socketEvents/gameMaster/zoneEditor/create.ts
similarity index 95%
rename from src/events/gameMaster/zoneEditor/create.ts
rename to src/socketEvents/gameMaster/zoneEditor/create.ts
index 73b4be2..9d5e627 100644
--- a/src/events/gameMaster/zoneEditor/create.ts
+++ b/src/socketEvents/gameMaster/zoneEditor/create.ts
@@ -17,9 +17,9 @@ type Payload = {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:zone_editor:zone:create', async (data: Payload, callback: (response: Zone[]) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/zoneEditor/delete.ts b/src/socketEvents/gameMaster/zoneEditor/delete.ts
similarity index 93%
rename from src/events/gameMaster/zoneEditor/delete.ts
rename to src/socketEvents/gameMaster/zoneEditor/delete.ts
index 1b5acb0..2825f5c 100644
--- a/src/events/gameMaster/zoneEditor/delete.ts
+++ b/src/socketEvents/gameMaster/zoneEditor/delete.ts
@@ -14,11 +14,11 @@ type Payload = {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:zone_editor:zone:delete', async (data: Payload, callback: (response: boolean) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return
-    
+
     if (character.role !== 'gm') {
       gameMasterLogger.info(`User ${character.id} tried to delete zone but is not a game master.`)
       return
diff --git a/src/events/gameMaster/zoneEditor/list.ts b/src/socketEvents/gameMaster/zoneEditor/list.ts
similarity index 92%
rename from src/events/gameMaster/zoneEditor/list.ts
rename to src/socketEvents/gameMaster/zoneEditor/list.ts
index 7420796..6ef2c3f 100644
--- a/src/events/gameMaster/zoneEditor/list.ts
+++ b/src/socketEvents/gameMaster/zoneEditor/list.ts
@@ -12,11 +12,11 @@ interface IPayload {}
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:zone_editor:zone:list', async (data: IPayload, callback: (response: Zone[]) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return
-    
+
     if (character.role !== 'gm') {
       gameMasterLogger.info(`User ${character.id} tried to list zones but is not a game master.`)
       return
diff --git a/src/events/gameMaster/zoneEditor/request.ts b/src/socketEvents/gameMaster/zoneEditor/request.ts
similarity index 94%
rename from src/events/gameMaster/zoneEditor/request.ts
rename to src/socketEvents/gameMaster/zoneEditor/request.ts
index 289a1ad..a6cc47c 100644
--- a/src/events/gameMaster/zoneEditor/request.ts
+++ b/src/socketEvents/gameMaster/zoneEditor/request.ts
@@ -14,9 +14,9 @@ interface IPayload {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:zone_editor:zone:request', async (data: IPayload, callback: (response: Zone) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return
 
     if (character.role !== 'gm') {
diff --git a/src/events/gameMaster/zoneEditor/update.ts b/src/socketEvents/gameMaster/zoneEditor/update.ts
similarity index 97%
rename from src/events/gameMaster/zoneEditor/update.ts
rename to src/socketEvents/gameMaster/zoneEditor/update.ts
index 436a30a..498908d 100644
--- a/src/events/gameMaster/zoneEditor/update.ts
+++ b/src/socketEvents/gameMaster/zoneEditor/update.ts
@@ -32,9 +32,9 @@ interface IPayload {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('gm:zone_editor:zone:update', async (data: IPayload, callback: (response: Zone) => void) => {
-    const character = await characterRepository.getById(socket.characterId as number);
+    const character = await characterRepository.getById(socket.characterId as number)
     if (!character) return
 
     if (character.role !== 'gm') {
diff --git a/src/events/login.ts b/src/socketEvents/login.ts
similarity index 77%
rename from src/events/login.ts
rename to src/socketEvents/login.ts
index a64fa4c..8cce6f8 100644
--- a/src/events/login.ts
+++ b/src/socketEvents/login.ts
@@ -1,7 +1,7 @@
 import { Server } from 'socket.io'
 import { TSocket } from '../utilities/types'
 
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('login', () => {
     if (!socket.user) return
     socket.emit('logged_in', { user: socket.user })
diff --git a/src/events/zone/characterJoin.ts b/src/socketEvents/zone/characterJoin.ts
similarity index 94%
rename from src/events/zone/characterJoin.ts
rename to src/socketEvents/zone/characterJoin.ts
index a015992..b3ce383 100644
--- a/src/events/zone/characterJoin.ts
+++ b/src/socketEvents/zone/characterJoin.ts
@@ -19,13 +19,13 @@ interface IResponse {
  * @param socket
  * @param io
  */
-export default function (socket: TSocket, io: Server) {
+export default function (io: Server, socket: TSocket) {
   socket.on('zone:character:join', async (callback: (response: IResponse) => void) => {
     try {
       if (!socket.characterId) return
-      const character = CharacterManager.getCharacterFromSocket(socket);
+      const character = CharacterManager.getCharacterFromSocket(socket)
 
-      if(!character) return
+      if (!character) return
 
       const zone = await ZoneRepository.getById(character.zoneId)
 
diff --git a/src/events/zone/characterLeave.ts b/src/socketEvents/zone/characterLeave.ts
similarity index 99%
rename from src/events/zone/characterLeave.ts
rename to src/socketEvents/zone/characterLeave.ts
index 881bc82..565f904 100644
--- a/src/events/zone/characterLeave.ts
+++ b/src/socketEvents/zone/characterLeave.ts
@@ -16,7 +16,7 @@ export default class ZoneLeaveEvent {
 
   private async handleZoneLeave(): Promise<void> {
     try {
-      const character = CharacterManager.getCharacterFromSocket(this.socket);
+      const character = CharacterManager.getCharacterFromSocket(this.socket)
       if (!character) {
         gameLogger.error('zone:character:leave error', 'Character not found')
         return
diff --git a/src/events/zone/characterMove.ts b/src/socketEvents/zone/characterMove.ts
similarity index 94%
rename from src/events/zone/characterMove.ts
rename to src/socketEvents/zone/characterMove.ts
index 17304a4..ba4a642 100644
--- a/src/events/zone/characterMove.ts
+++ b/src/socketEvents/zone/characterMove.ts
@@ -17,7 +17,7 @@ export default class CharacterMove {
   private characterMoveService: CharacterMoveService
   private zoneEventTileService: ZoneEventTileService
   private nextPath: { [index: number]: { x: number; y: number }[] } = []
-  private currentZoneId: {[index:number]: number} = []
+  private currentZoneId: { [index: number]: number } = []
 
   constructor(
     private readonly io: Server,
@@ -58,7 +58,7 @@ export default class CharacterMove {
     }
     if (!character.isMoving && !character.resetMovement) {
       character.isMoving = true
-      this.currentZoneId[character.id] = character.zoneId;
+      this.currentZoneId[character.id] = character.zoneId
       await this.moveAlongPath(character, path)
     }
   }
@@ -112,11 +112,11 @@ export default class CharacterMove {
 
     if (CharacterManager.hasResetMovement(character)) {
       character.resetMovement = false
-      if(this.currentZoneId[character.id] === character.zoneId) {
+      if (this.currentZoneId[character.id] === character.zoneId) {
         await this.moveAlongPath(character, this.nextPath[character.id])
       } else {
-        delete this.currentZoneId[character.id];
-        character.isMoving = false;
+        delete this.currentZoneId[character.id]
+        character.isMoving = false
       }
     } else {
       this.finalizeMovement(character)
diff --git a/src/utilities/http.ts b/src/utilities/http.ts
index 75a1e70..7805a4b 100644
--- a/src/utilities/http.ts
+++ b/src/utilities/http.ts
@@ -75,29 +75,33 @@ async function addHttpRoutes(app: Application) {
    */
   app.get('/assets/zone/:zoneId', async (req: Request, res: Response) => {
     const zoneId = req.params.zoneId
-    if(!zoneId || parseInt(zoneId) === 0) {
+    if (!zoneId || parseInt(zoneId) === 0) {
       return res.status(400).json({ message: 'Invalid zone ID' })
     }
 
     const zone = await zoneRepository.getById(parseInt(zoneId))
-    if(!zone) {
+    if (!zone) {
       return res.status(404).json({ message: 'Zone not found' })
     }
 
-    const assets = await zoneManager.getZoneAssets(zone);
+    const assets = await zoneManager.getZoneAssets(zone)
 
     res.json([
-      ...assets.tiles.map(x => { return {
-        key: x,
-        url: '/assets/tiles/' + x + '.png',
-        group: 'tiles'
-      }}),
-      ...assets.objects.map(x => { return {
-        key: x,
-        url: '/assets/objects/' + x + '.png',
-        group: 'objects'
-      }})
-    ]);
+      ...assets.tiles.map((x) => {
+        return {
+          key: x,
+          url: '/assets/tiles/' + x + '.png',
+          group: 'tiles'
+        }
+      }),
+      ...assets.objects.map((x) => {
+        return {
+          key: x,
+          url: '/assets/objects/' + x + '.png',
+          group: 'objects'
+        }
+      })
+    ])
   })
 
   /**
diff --git a/src/utilities/logger.ts b/src/utilities/logger.ts
index d042f00..803bdf3 100644
--- a/src/utilities/logger.ts
+++ b/src/utilities/logger.ts
@@ -3,46 +3,46 @@ import fs from 'fs'
 import path from 'path'
 
 // Array of log types
-const LOG_TYPES = ['http', 'game', 'gameMaster', 'app'] as const
-type LogType = typeof LOG_TYPES[number]
+const LOG_TYPES = ['http', 'game', 'gameMaster', 'app', 'queue'] as const
+type LogType = (typeof LOG_TYPES)[number]
 
-const createLogger = (name: LogType) => pino({
-  level: process.env.LOG_LEVEL || 'debug',
-  transport: {
-    target: 'pino/file',
-    options: {
-      destination: `./logs/${name}.log`,
-      mkdir: true
-    }
-  },
-  formatters: {
-    level: (label) => {
-      return { level: label.toUpperCase() }
-    }
-  },
-  timestamp: pino.stdTimeFunctions.isoTime,
-  base: null
-})
+const createLogger = (name: LogType) =>
+  pino({
+    level: process.env.LOG_LEVEL || 'debug',
+    transport: {
+      target: 'pino/file',
+      options: {
+        destination: `./logs/${name}.log`,
+        mkdir: true
+      }
+    },
+    formatters: {
+      level: (label) => {
+        return { level: label.toUpperCase() }
+      }
+    },
+    timestamp: pino.stdTimeFunctions.isoTime,
+    base: null
+  })
 
 // Create logger instances
-const loggers = Object.fromEntries(
-  LOG_TYPES.map(type => [type, createLogger(type)])
-) as Record<LogType, ReturnType<typeof createLogger>>
+const loggers = Object.fromEntries(LOG_TYPES.map((type) => [type, createLogger(type)])) as Record<LogType, ReturnType<typeof createLogger>>
 
 const watchLogs = () => {
-  LOG_TYPES.forEach(type => {
+  LOG_TYPES.forEach((type) => {
     const logFile = path.join(__dirname, '../../logs', `${type}.log`)
 
     fs.watchFile(logFile, (curr, prev) => {
       if (curr.size > prev.size) {
         const stream = fs.createReadStream(logFile, { start: prev.size, end: curr.size })
         stream.on('data', (chunk) => {
-          console.log(`[${type}] \n ${chunk.toString()}`)
+          console.log(`[${type}]\n${chunk.toString()}`)
         })
       }
     })
   })
 }
 
-export const { http: httpLogger, game: gameLogger, gameMaster: gameMasterLogger, app: appLogger } = loggers
-export { watchLogs }
\ No newline at end of file
+export const { http: httpLogger, game: gameLogger, gameMaster: gameMasterLogger, app: appLogger, queue: queueLogger } = loggers
+
+export { watchLogs }