const { Player, Inventory } = require("../../models"); const DatapackLoader = require("../../game/DatapackLoader"); const dungeonManager = require("../../game/DungeonManager"); module.exports = (io, socket) => { const userId = socket.user?.id; socket.on("dungeon:start", async ({ dungeonId }) => { try { if (!userId) return; const dungeon = DatapackLoader.getDungeon(dungeonId); const player = await Player.findByPk(userId); const energyCost = dungeon?.meta?.energyCost || 0; if (!dungeon) return socket.emit("error", { message: "Dungeon not found" }); if (player.energy < energyCost) return socket.emit("error", { message: "Insufficient energy" }); await player.decrement("energy", { by: energyCost }); const startData = await dungeonManager.startDungeon(userId, dungeonId); socket.emit("dungeon:started", { dungeonId: dungeon.id, room: startData.config, hostiles: startData.hostiles, battle: startData.battle, roomIndex: startData.roomIndex, totalRooms: startData.totalRooms, remainingEnergy: player.energy - energyCost, }); } catch (err) { console.log(err); socket.emit("error", { message: "Deployment failure" }); } }); socket.on("dungeon:combat_action", async ({ targetInstanceId }) => { try { if (!userId) return; const result = dungeonManager.processCombatAction( userId, targetInstanceId, ); if (!result) return; socket.emit("dungeon:battle_update", { battle: result.battle, log: result.log, status: result.status, }); if (result.status === "defeat") { dungeonManager.leaveDungeon(userId); socket.emit("dungeon:failed", { message: "Neural link severed." }); } } catch (err) { socket.emit("error", { message: "Synchronization error" }); } }); socket.on("dungeon:next_room", async () => { try { if (!userId) return; const nextRoom = await dungeonManager.moveToNextRoom(userId); if (!nextRoom) return socket.emit("error", { message: "Navigation error" }); if (nextRoom.status === "completed") { await finalizeDungeon(socket, nextRoom.rewards); } else { socket.emit("dungeon:room_update", nextRoom); } } catch (err) { socket.emit("error", { message: "Navigation error" }); } }); socket.on("dungeon:leave", () => { if (userId) dungeonManager.leaveDungeon(userId); }); }; async function finalizeDungeon(socket, sessionRewards) { const userId = socket.user.id; try { const player = await Player.findByPk(userId); if (sessionRewards.credits > 0) await player.increment("credits", { by: sessionRewards.credits }); if (sessionRewards.xp > 0) await player.increment("experience", { by: sessionRewards.xp }); if (sessionRewards.items.length > 0) { const consolidated = sessionRewards.items.reduce((acc, curr) => { acc[curr.id] = (acc[curr.id] || 0) + curr.count; return acc; }, {}); for (const [itemId, totalCount] of Object.entries(consolidated)) { const [invItem] = await Inventory.findOrCreate({ where: { playerId: userId, itemId: itemId }, defaults: { quantity: 0 }, }); await invItem.increment("quantity", { by: totalCount }); } // Оновлюємо масив для фронтенда, щоб не було дублікатів у списку sessionRewards.items = Object.entries(consolidated).map( ([id, count]) => ({ id, count }), ); } console.log("FINAL REWARDS SAVED:", sessionRewards); socket.emit("dungeon:completed", { rewards: sessionRewards }); } catch (err) { console.error(err); socket.emit("error", { message: "Failed to save rewards" }); } finally { dungeonManager.leaveDungeon(userId); } }