122 lines
3.9 KiB
JavaScript
122 lines
3.9 KiB
JavaScript
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);
|
||
}
|
||
}
|