Client/game-server/src/sockets/handlers/dungeonHandler.js

122 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}