update:新版本websocket
This commit is contained in:
+93
-8
@@ -30,6 +30,7 @@ const pendingAcks = [];
|
||||
const ACK_AUDIO_TIMEOUT_MS = 9000;
|
||||
const READY_ROUTE_FALLBACK_DELAY_MS = 300;
|
||||
const ROUND_AUDIO_NAMES = ["一", "二", "三", "四", "五"];
|
||||
const MATCH_STATUS_HALF_REST = 3;
|
||||
|
||||
// 比赛服消息类型先映射成项目里已有的 V2 业务消息,页面仍然复用原来的 socket-inbox 流程。
|
||||
const BUSINESS_TYPE_BY_SERVER_TYPE = {
|
||||
@@ -39,7 +40,6 @@ const BUSINESS_TYPE_BY_SERVER_TYPE = {
|
||||
[ServerMessageType.SERVER_MSG_SHOT]: MESSAGETYPESV2.ShootResult,
|
||||
[ServerMessageType.SERVER_MSG_NEW_ROUND]: MESSAGETYPESV2.NewRound,
|
||||
[ServerMessageType.SERVER_MSG_MATCH_END]: MESSAGETYPESV2.BattleEnd,
|
||||
[ServerMessageType.SERVER_MSG_TIMEOUT]: MESSAGETYPESV2.BattleEnd,
|
||||
[ServerMessageType.SERVER_MSG_CHECK]: MESSAGETYPESV2.TestDistance,
|
||||
[ServerMessageType.SERVER_MSG_NOT_ENOUGH_DISTANCE]: MESSAGETYPESV2.InvalidShot,
|
||||
[ServerMessageType.SERVER_MSG_PRACTICE_END]: MESSAGETYPESV2.BattleEnd,
|
||||
@@ -76,12 +76,73 @@ function normalizePracticeInfo(practiceInfo = {}) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function getCurrentMode(message = {}, normalizedInfo = {}) {
|
||||
const mode = Number(
|
||||
pickField(message, "mode") ??
|
||||
normalizedInfo.mode ??
|
||||
currentContext?.mode
|
||||
);
|
||||
return Number.isFinite(mode) ? mode : undefined;
|
||||
}
|
||||
|
||||
function isMeleeMessage(message = {}, normalizedInfo = {}) {
|
||||
const mode = getCurrentMode(message, normalizedInfo);
|
||||
if (mode !== undefined) return mode > 3;
|
||||
if (currentContext?.isMelee !== undefined) return currentContext.isMelee;
|
||||
return normalizeRoute(getCurrentPageInfo()?.route) === "pages/melee-battle";
|
||||
}
|
||||
|
||||
function isHalfRestTimeout(message = {}, matchInfo = {}) {
|
||||
if (message.type !== ServerMessageType.SERVER_MSG_TIMEOUT) return false;
|
||||
if (!isMeleeMessage(message, matchInfo)) return false;
|
||||
|
||||
const status = Number(pickField(message, "status") ?? matchInfo.status);
|
||||
return status === MATCH_STATUS_HALF_REST || !Number.isFinite(status);
|
||||
}
|
||||
|
||||
function getBusinessType(message, matchInfo) {
|
||||
if (isHalfRestTimeout(message, matchInfo)) return MESSAGETYPESV2.HalfRest;
|
||||
if (message.type === ServerMessageType.SERVER_MSG_TIMEOUT) {
|
||||
return MESSAGETYPESV2.BattleEnd;
|
||||
}
|
||||
return BUSINESS_TYPE_BY_SERVER_TYPE[message.type];
|
||||
}
|
||||
|
||||
function buildBusinessMessage(message) {
|
||||
const businessType = BUSINESS_TYPE_BY_SERVER_TYPE[message.type];
|
||||
const matchInfo = normalizeMatchInfo(message.match_info);
|
||||
if (
|
||||
message.type === ServerMessageType.SERVER_MSG_MATCH_READY &&
|
||||
(matchInfo.status === undefined ||
|
||||
matchInfo.status === null ||
|
||||
matchInfo.status === "")
|
||||
) {
|
||||
matchInfo.status = 0;
|
||||
}
|
||||
const practiceInfo = normalizePracticeInfo(message.practice_info);
|
||||
const businessType = getBusinessType(message, matchInfo);
|
||||
if (!businessType) return null;
|
||||
|
||||
const matchInfo = normalizeMatchInfo(message.match_info);
|
||||
const practiceInfo = normalizePracticeInfo(message.practice_info);
|
||||
const mode = getCurrentMode(message, matchInfo);
|
||||
const isMelee = isMeleeMessage(message, matchInfo);
|
||||
const isSecondHalfStart =
|
||||
message.type === ServerMessageType.SERVER_MSG_MATCH_START &&
|
||||
isMelee &&
|
||||
currentContext?.meleeHalfRest === true;
|
||||
|
||||
if (currentContext) {
|
||||
if (mode !== undefined) {
|
||||
currentContext.mode = mode;
|
||||
currentContext.isMelee = isMelee;
|
||||
} else if (isMelee) {
|
||||
currentContext.isMelee = true;
|
||||
}
|
||||
if (businessType === MESSAGETYPESV2.HalfRest) {
|
||||
currentContext.meleeHalfRest = true;
|
||||
} else if (message.type === ServerMessageType.SERVER_MSG_MATCH_START) {
|
||||
currentContext.meleeHalfRest = false;
|
||||
}
|
||||
}
|
||||
|
||||
const matchId = normalizeId(
|
||||
pickField(message, "matchId", "match_id") ||
|
||||
matchInfo.matchId ||
|
||||
@@ -109,6 +170,7 @@ function buildBusinessMessage(message) {
|
||||
timestamp: message.timestamp,
|
||||
matchWsType: message.type,
|
||||
matchWsTypeName: getServerMessageTypeName(message.type),
|
||||
isSecondHalfStart,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -250,13 +312,23 @@ function getTestDistanceAudioKeys(shootData) {
|
||||
function getAckAudioKeys(message, businessMessage) {
|
||||
switch (message.type) {
|
||||
case ServerMessageType.SERVER_MSG_MATCH_START:
|
||||
return ["比赛开始"];
|
||||
return [businessMessage?.isSecondHalfStart ? "下半场开始" : "比赛开始"];
|
||||
case ServerMessageType.SERVER_MSG_NOW_YOU:
|
||||
if (isMeleeMessage(message, businessMessage)) return [];
|
||||
return getNowYouAudioKeys(businessMessage);
|
||||
case ServerMessageType.SERVER_MSG_SHOT:
|
||||
if (
|
||||
isMeleeMessage(message, businessMessage) &&
|
||||
String(businessMessage?.shootData?.playerId) !== String(currentContext?.userId)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
return getShootResultAudioKeys(businessMessage?.shootData);
|
||||
case ServerMessageType.SERVER_MSG_MATCH_END:
|
||||
return ["比赛结束"];
|
||||
case ServerMessageType.SERVER_MSG_TIMEOUT:
|
||||
if (businessMessage?.type === MESSAGETYPESV2.HalfRest) return ["中场休息"];
|
||||
return ["比赛结束"];
|
||||
case ServerMessageType.SERVER_MSG_PRACTICE_END:
|
||||
return ["比赛结束"];
|
||||
case ServerMessageType.SERVER_MSG_CHECK:
|
||||
@@ -268,7 +340,14 @@ function getAckAudioKeys(message, businessMessage) {
|
||||
}
|
||||
}
|
||||
|
||||
function shouldCloseAfterAck(message) {
|
||||
function shouldCloseAfterAck(message, businessMessage) {
|
||||
if (
|
||||
message.type === ServerMessageType.SERVER_MSG_TIMEOUT &&
|
||||
businessMessage?.type === MESSAGETYPESV2.HalfRest
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
message.type === ServerMessageType.SERVER_MSG_MATCH_END ||
|
||||
message.type === ServerMessageType.SERVER_MSG_TIMEOUT ||
|
||||
@@ -416,7 +495,7 @@ function queueAckAfterAudio(message, businessMessage) {
|
||||
pickField(message, "matchId", "match_id") || currentContext?.matchId
|
||||
),
|
||||
sequence: message.sequence,
|
||||
leaveAfterAck: shouldCloseAfterAck(message),
|
||||
leaveAfterAck: shouldCloseAfterAck(message, businessMessage),
|
||||
};
|
||||
|
||||
const audioKeys = getAckAudioKeys(message, businessMessage).filter(Boolean);
|
||||
@@ -503,10 +582,11 @@ function sendLeave() {
|
||||
|
||||
export function connectMatchWebSocket(options = {}) {
|
||||
// 入口参数来自原 websocket 的比赛服地址通知,不影响原有 websocket 连接。
|
||||
const { serverAddr, matchId, userId, token } = options;
|
||||
const { serverAddr, matchId, userId, token, mode } = options;
|
||||
const url = normalizeServerUrl(serverAddr, token);
|
||||
const normalizedMatchId = normalizeId(matchId);
|
||||
const normalizedUserId = normalizeId(userId);
|
||||
const normalizedMode = Number(mode);
|
||||
|
||||
if (!url || !normalizedMatchId) {
|
||||
console.log("[match-ws] missing serverAddr or matchId", options);
|
||||
@@ -536,6 +616,10 @@ export function connectMatchWebSocket(options = {}) {
|
||||
matchId: normalizedMatchId,
|
||||
userId: normalizedUserId,
|
||||
url,
|
||||
mode: Number.isFinite(normalizedMode) ? normalizedMode : undefined,
|
||||
isMelee:
|
||||
Number.isFinite(normalizedMode) ? normalizedMode > 3 : undefined,
|
||||
meleeHalfRest: false,
|
||||
};
|
||||
ensureAudioAckListener();
|
||||
|
||||
@@ -596,6 +680,7 @@ export function connectMatchWebSocketFromNotice(notice, fallbackUserId) {
|
||||
serverAddr: pickField(notice, "serverAddr", "server_addr"),
|
||||
matchId: pickField(notice, "matchId", "match_id"),
|
||||
userId: pickField(notice, "userId", "user_id") || fallbackUserId,
|
||||
mode: pickField(notice, "mode"),
|
||||
token: notice.token || notice.wsToken || notice.ws_token,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user