康复游戏-拔萝卜游戏
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

148 lines
3.7 KiB

let connected = false; // socket 是否连接
let socket = null; // websocket 实例
let lockSocket = false;
let socketMsgQueue = []; // socket消息队列
let prevTimestamp = 0; // 上次收到消息的时间戳
let sendHeartTimer = null; // 💓的timer计时器
let ws = null;
initSocket();
function initSocket() {
if (lockSocket) return;
lockSocket = true;
ws = new WebSocket('wss://www.tall.wiki/websocket/recovery/recovery/ws');
ws.onopen = onOpen;
ws.onmessage = onMessage;
ws.onclose = onClose;
lockSocket = false;
}
// ws 打开
function onOpen(event) {
connected = true;
prevTimestamp = Date.now();
auth(); // 认证
for (let i = 0; i < socketMsgQueue.length; i += 1) {
send(socketMsgQueue[i]);
}
socketMsgQueue = [];
}
// ws收到消息
function onMessage(res) {
try {
prevTimestamp = Date.now();
// console.warn('message: ', res, new Date().toLocaleString());
if (res && res.data && JSON.parse(res.data)) {
const resData = JSON.parse(res.data);
const { messageSet, ackId } = resData;
// 处理消息体对象
messageSet.forEach(item => handleMessagesData(item));
// console.log('ackId', ackId);
// 有ackId 发送ack
ackId && send({ type: 'Ack', data: { ackId } });
}
} catch (error) {
console.error(error);
}
}
/**
* 处理收到的消息内容
* @param {object} item 单个消息体对象
*/
function handleMessagesData(item) {
const data = JSON.parse(item.data);
switch (data.type) {
case 'ChannelStatus': // 认证消息
handleAuthMessage(data);
break;
case 'feedback': // 收到拔萝卜的动作反馈
console.log('score', data.data.score)
data.data && data.data.result === 1 && handlePull(data.data.times);
onScoreMessage(data.data.score, data.data.times);
break;
case 'startDrill': // 开始训练游戏
console.log(data.data);
window.gameInfo = data.data;
initBeginCount();
break;
case 'countdown':
onCountdownMessage();
break;
case 'score':
onScoreMessage(data.data.score, data.data.times);
break;
default:
break;
}
}
// ws 关闭
function onClose(event) {
connected = false;
if (sendHeartTimer) clearInterval(sendHeartTimer);
// console.warn('close:', connected, new Date().toLocaleString());
if (!event || event.code !== 1005) {
socket.close();
}
setTimeout(() => {
// connected 在这里的作用是:
// 在发生重连 但是还没连上之前 不要再次重连
initSocket();
}, 300);
}
/**
* 发送消息
* @param data
*/
function send(data) {
if (connected) {
if (ws.readyState === 1) {
ws.send(JSON.stringify({ toDomain: 'Server', data: JSON.stringify(data) }));
}
} else {
socketMsgQueue.push(data);
}
}
// 认证消息
function auth() {
// TODO: userId拿父框架传递过来的
const data = { type: 'Auth', data: { userId: '1399952569681448962' } };
send(data);
}
// 心跳检测
function sendHeart() {
if (sendHeartTimer) clearInterval(sendHeartTimer);
sendHeartTimer = setInterval(() => {
if (Date.now() - prevTimestamp >= 15000) {
send({ type: 'Ping' });
if (Date.now() - prevTimestamp > 20000) {
// console.warn('手动断开');
ws.close();
}
}
}, 5000);
}
/**
* 处理auth认证返回的ChannelStatus消息
* @param {object} data 消息内容对象
*/
function handleAuthMessage(data) {
if (data.data.authed) {
// 认证成功
sendHeart();
} else {
console.error('消息系统认证失败');
// 清除掉本地无用的token
ws = null;
}
}