const Limiter = require("../Game/PacketLimiter"); const EquipmentLimiter = require("../Game/EquipmentLimiter"); const Inventory = require("../Game/Inventory"); const Player = require("../Game/Player"); const Game = require("../Game/Game"); const playerHandlers = require("../Handlers/Player"); const EnvironmentSetupPacket = require("../Packets/EnvironmentSetup"); const rewardCallback = require("../Callbacks/reward"); const attackCallback = require("../Callbacks/attack"); const baseStarterRewards = require("../Data/startRewards"); const { maps, players, guilds } = Game; const queries = require("../Data/queries"); const { QUERY_FETCH_PLAYER_DATA, QUERY_FETCH_PLAYER_INFORMATION, QUERY_FETCH_GUILD_INFORMATION, QUERY_INSERT_DEFAULT_PLAYER, QUERY_FETCH_ACTIVE_QUESTS, QUERY_FETCH_STATUS, QUERY_FETCH_RESOURCES, QUERY_FETCH_EQUIPMENTS } = queries; const playerEvents = Object.keys(playerHandlers); const PlayerBehaviour = require("../Game/PlayerBehaviour"); const DoubleLinkedList = require("../Utility/DoubleLinkedList"); global.actionContext = new DoubleLinkedList(); module.exports = async function (ws) { console.info("Before open for", ws.username, Game.state, ws.isAdmin); if (Game.state === 0 && !ws.isAdmin) return ws.end(1337); ws.connectedAt = Date.now(); let abruptDisconnectTest = performance.now(); const ID = ws.accountID; const sessionID = Date.now().toString(36) + Math.random().toString(36).substring(2) + "!" + ID; socket.sockets[sessionID] = ws; ws.id = sessionID; ws.limiter = new Limiter({ countThreshold: 10, timeThreshold: 1000 }); const alreadyConnectedPlayer = players[ID]; if (alreadyConnectedPlayer) { const player = alreadyConnectedPlayer; const alreadyConnectedSoket = socket.sockets[player.sessionID]; if (alreadyConnectedSoket) alreadyConnectedSoket.end(1); player.sessionID = sessionID; ws.subscribe(player.map.id.toString()); player.map.removePlayer(player.id); player.map.addPlayer(player); player.isUnderDisconnect = false; player.cancelDisconnect(); const packet = EnvironmentSetupPacket(player.map.id); return ws.send(packet, true, true); }; const playerBehaviour = new PlayerBehaviour({ size: 16, buffer: global.playerBehaviourContext, id: ID }); global.actionContext.addItem(ID, playerBehaviour); const generalQuery = execute(QUERY_FETCH_PLAYER_DATA, [ID]); const informationQuery = execute(QUERY_FETCH_PLAYER_INFORMATION, [ID]); const guildQuery = execute(QUERY_FETCH_GUILD_INFORMATION, [ID]); const questQuery = execute(QUERY_FETCH_ACTIVE_QUESTS, [ID]); const statusQuery = execute(QUERY_FETCH_STATUS, [ID, true]); const resourcesQuery = execute(QUERY_FETCH_RESOURCES, [ID]); const equipmentsQuery = execute(QUERY_FETCH_EQUIPMENTS, [ID]); const res = await Promise.all([generalQuery, informationQuery, guildQuery, questQuery, statusQuery, resourcesQuery, equipmentsQuery]); const hasError = res.some(q => q.error !== undefined); if (hasError) return; if (ws.isInterrupted) return; let isAlive = false; let map = null; let hitpoints = { current: 0, maximum: 0 }; let position = {}; let attemptToDoubleLog = false; let maximumCannonRange = 0; let maximumHarpoonerRange = 0; let textureID = 0; let sight = 0; let speed = 0; let globalRank = 0; let levelRank = 0; const playerFromDB = res[0].data[0]; const guildFromDB = res[2].data[0]; const questFromDB = res[3].data; const statusFromDB = res[4].data; const resourcesFromDB = res[5].data; const equipmentsFromDB = res[6].data; const statusPoints = []; const guildID = guildFromDB ? guildFromDB.id : 0; const guild = guilds[guildID]; const selectedAmmunition = playerFromDB ? playerFromDB.selectedAmmunitionID : 0; const selectedHarpoon = playerFromDB ? playerFromDB.selectedHarpoonID : 0; const resourceSharedLimiter = { cannon: new EquipmentLimiter({ maximum: 50 }), harpooner: new EquipmentLimiter({ maximum: 25 }), sail: new EquipmentLimiter({ maximum: 5 }), pirate: new EquipmentLimiter({ maximum: 250 }) }; const inventory = new Inventory({ resourceSharedLimiter }); resourcesFromDB.forEach(r => { switch (r.categoryID) { case 6: statusPoints.push(r); break; case 7: case 8: const equipment = equipmentsFromDB.find(e => e.id === r.id && e.categoryID === r.categoryID); r.amountEquipped = equipment ? equipment.amountEquipped : 0; break; }; inventory.refreshSingle(r); }); inventory.setSelectedAmmunition(selectedAmmunition); inventory.setSelectedHarpoon(selectedHarpoon); if (!attemptToDoubleLog) { const playerHasData = playerFromDB ? true : false; if (!playerHasData) { const startingMap = maps.find(m => m.id === 1); const { x, y } = startingMap.grid.randomNode(10); textureID = 1; sight = 450; speed = 250; globalRank = 1; levelRank = 1; isAlive = true; map = startingMap; position = { x, y }; hitpoints = { current: 10000, maximum: 50000 }; baseStarterRewards.forEach(r => inventory.refreshSingle(r)); await execute(QUERY_INSERT_DEFAULT_PLAYER, [ID, x, y, 1]); } else { textureID = playerFromDB.designID; sight = playerFromDB.sight; speed = playerFromDB.speed; globalRank = playerFromDB.globalRank; levelRank = playerFromDB.levelRank; isAlive = !!hitpoints; map = maps.find(m => m.id === playerFromDB.mapID); position = { x: playerFromDB.x, y: playerFromDB.y }; hitpoints = { current: playerFromDB.currentHitpoints, maximum: playerFromDB.maximumHitpoints }; }; }; const player = new Player({ id: ID, sessionID: ws.id, name: ws.username, textureID, map, guild, positionX: position.x, positionY: position.y, isAlive, hitpoints, maximumCannonRange, maximumHarpoonerRange, sight, speed, globalRank, levelRank, inventory, statusPoints, activeStatusEffects: statusFromDB, quests: questFromDB, rewardCallback, attackCallback }); player.setDesign(textureID); ws.subscribe(player.map.id.toString()); playerEvents.forEach(e => player.on(e, playerHandlers[e])); players[ID] = player; const packet = EnvironmentSetupPacket(player.map.id); ws.send(packet, true, true); };