fix(framework): player_login.version 改为数字 versionCode(联调登录成功)
真机联调发现:协议 version 字段=数字 versionCode(源码 8 处 data.version=GameData.versionCode), 框架原发字符串 '1.1' 被服务器版本校验拒绝(kick_server 检查到新版本)。改为数字后登录成功 (state:0 playerid:430511)。 - ChannelIdentity/LoginRequestData.version: string→number,去掉冗余 versionCode 与未发送的 '1.1' 串 - query-string version 解析为数字;测试 fixture 同步 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,8 +4,7 @@ export interface ChannelIdentity {
|
|||||||
channelid: string | number;
|
channelid: string | number;
|
||||||
gameid: string;
|
gameid: string;
|
||||||
marketid: string | number;
|
marketid: string | number;
|
||||||
version: string; // 旧 GameData.Version
|
version: number; // 协议 player_login.version 字段 = 数字 versionCode(非 "1.1" 显示串,逐字对齐源码 data.version=GameData.versionCode)
|
||||||
versionCode: number; // 旧 GameData.versionCode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 身份来源:返回部分字段覆盖。 */
|
/** 身份来源:返回部分字段覆盖。 */
|
||||||
|
|||||||
@@ -9,6 +9,5 @@ export const BUILD_IDENTITY: ChannelIdentity = {
|
|||||||
channelid: 'FtJf073aa0d6rI1xD8J1Y42fINTm0ziK',
|
channelid: 'FtJf073aa0d6rI1xD8J1Y42fINTm0ziK',
|
||||||
gameid: 'jzWe0kzmN0tAcZ5MLks3rFWcxNecogyu',
|
gameid: 'jzWe0kzmN0tAcZ5MLks3rFWcxNecogyu',
|
||||||
marketid: 4,
|
marketid: 4,
|
||||||
version: '1.1',
|
version: 10000, // 数字 versionCode(联调时改成本地服要求的版本号)
|
||||||
versionCode: 10000,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function queryStringSource(search: string): IdentitySource {
|
|||||||
const agentid = q.get('agentid'); if (agentid) out.agentid = agentid;
|
const agentid = q.get('agentid'); if (agentid) out.agentid = agentid;
|
||||||
const channelid = q.get('channelid'); if (channelid) out.channelid = channelid;
|
const channelid = q.get('channelid'); if (channelid) out.channelid = channelid;
|
||||||
const marketid = q.get('marketid'); if (marketid) out.marketid = marketid;
|
const marketid = q.get('marketid'); if (marketid) out.marketid = marketid;
|
||||||
const version = q.get('version'); if (version) out.version = version;
|
const version = q.get('version'); if (version) out.version = Number(version); // 协议 version 为数字
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export interface LoginRequestData {
|
|||||||
province: string;
|
province: string;
|
||||||
city: string;
|
city: string;
|
||||||
unionid: string | number;
|
unionid: string | number;
|
||||||
version: string;
|
version: number; // 数字 versionCode(源码 data.version=GameData.versionCode)
|
||||||
channelid: number | string;
|
channelid: number | string;
|
||||||
marketid: number | string;
|
marketid: number | string;
|
||||||
[extra: string]: unknown; // location/ip/machineid/telphone 等由 Send_login 注入,见 docs/protocol/01 §6
|
[extra: string]: unknown; // location/ip/machineid/telphone 等由 Send_login 注入,见 docs/protocol/01 §6
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ test('BUILD_IDENTITY 含全部字段且 gameid 为固定 token', () => {
|
|||||||
assert.ok('agentid' in BUILD_IDENTITY);
|
assert.ok('agentid' in BUILD_IDENTITY);
|
||||||
assert.ok('channelid' in BUILD_IDENTITY);
|
assert.ok('channelid' in BUILD_IDENTITY);
|
||||||
assert.ok('marketid' in BUILD_IDENTITY);
|
assert.ok('marketid' in BUILD_IDENTITY);
|
||||||
assert.equal(typeof BUILD_IDENTITY.version, 'string');
|
assert.equal(typeof BUILD_IDENTITY.version, 'number'); // 协议 version = 数字 versionCode
|
||||||
assert.equal(typeof BUILD_IDENTITY.versionCode, 'number');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('resolveIdentity:后面的 source 覆盖前面的', () => {
|
test('resolveIdentity:后面的 source 覆盖前面的', () => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
|||||||
import { getParam, resolveServers, type RemoteConfig } from '../../YouleNexus/assets/framework/config/remote-config.ts';
|
import { getParam, resolveServers, type RemoteConfig } from '../../YouleNexus/assets/framework/config/remote-config.ts';
|
||||||
import type { ChannelIdentity } from '../../YouleNexus/assets/framework/config/identity.ts';
|
import type { ChannelIdentity } from '../../YouleNexus/assets/framework/config/identity.ts';
|
||||||
|
|
||||||
const ID: ChannelIdentity = { agentid: 'A', channelid: 'C', gameid: 'G', marketid: 2, version: '1', versionCode: 1 };
|
const ID: ChannelIdentity = { agentid: 'A', channelid: 'C', gameid: 'G', marketid: 2, version: 1 };
|
||||||
|
|
||||||
const CONFIG: RemoteConfig = {
|
const CONFIG: RemoteConfig = {
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import assert from 'node:assert/strict';
|
|||||||
import { queryStringSource } from '../../../YouleNexus/assets/framework/config/sources/query-string.ts';
|
import { queryStringSource } from '../../../YouleNexus/assets/framework/config/sources/query-string.ts';
|
||||||
|
|
||||||
test('解析 agentid/channelid/marketid/version', () => {
|
test('解析 agentid/channelid/marketid/version', () => {
|
||||||
const src = queryStringSource('?agentid=A1&channelid=C1&marketid=2&version=9.9');
|
const src = queryStringSource('?agentid=A1&channelid=C1&marketid=2&version=10001');
|
||||||
assert.deepEqual(src(), { agentid: 'A1', channelid: 'C1', marketid: '2', version: '9.9' });
|
assert.deepEqual(src(), { agentid: 'A1', channelid: 'C1', marketid: '2', version: 10001 }); // version 解析为数字
|
||||||
});
|
});
|
||||||
|
|
||||||
test('缺省键不出现在结果里', () => {
|
test('缺省键不出现在结果里', () => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { LoginRequestData, LoginResponseData } from '../../YouleNexus/asset
|
|||||||
|
|
||||||
const out: OutboundEnvelope<LoginRequestData> = {
|
const out: OutboundEnvelope<LoginRequestData> = {
|
||||||
app: 'youle', route: 'agent', rpc: 'player_login',
|
app: 'youle', route: 'agent', rpc: 'player_login',
|
||||||
data: { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: '1', channelid: 0, marketid: 0 },
|
data: { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: 1, channelid: 0, marketid: 0 },
|
||||||
};
|
};
|
||||||
const inb: InboundMessage<LoginResponseData> = { route: 'agent', rpc: 'player_login', data: { state: 0, playerid: 9 } };
|
const inb: InboundMessage<LoginResponseData> = { route: 'agent', rpc: 'player_login', data: { state: 0, playerid: 9 } };
|
||||||
void out; void inb;
|
void out; void inb;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { parseLoginResponse } from '../../YouleNexus/assets/framework/protocol/l
|
|||||||
import type { Clock } from '../../YouleNexus/assets/framework/net/heartbeat.ts';
|
import type { Clock } from '../../YouleNexus/assets/framework/net/heartbeat.ts';
|
||||||
|
|
||||||
const realishClock: Clock = { setTimeout: (fn, ms) => setTimeout(fn, ms), clearTimeout: (h: any) => clearTimeout(h) };
|
const realishClock: Clock = { setTimeout: (fn, ms) => setTimeout(fn, ms), clearTimeout: (h: any) => clearTimeout(h) };
|
||||||
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: '1', channelid: 0, marketid: 0 };
|
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: 1, channelid: 0, marketid: 0 };
|
||||||
|
|
||||||
test('login 全流程:握手→登录→业务包,且 parseLoginResponse 识别房间恢复', async () => {
|
test('login 全流程:握手→登录→业务包,且 parseLoginResponse 识别房间恢复', async () => {
|
||||||
const t = new FakeTransport();
|
const t = new FakeTransport();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ function fakeClock() {
|
|||||||
return { clock, advance };
|
return { clock, advance };
|
||||||
}
|
}
|
||||||
|
|
||||||
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: '1', channelid: 0, marketid: 0 };
|
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: 1, channelid: 0, marketid: 0 };
|
||||||
|
|
||||||
function makeClient(transports: FakeTransport[], clock: Clock) {
|
function makeClient(transports: FakeTransport[], clock: Clock) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { test } from 'node:test';
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { buildLoginRequest, parseLoginResponse } from '../../YouleNexus/assets/framework/protocol/login.ts';
|
import { buildLoginRequest, parseLoginResponse } from '../../YouleNexus/assets/framework/protocol/login.ts';
|
||||||
|
|
||||||
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 1, province: 'p', city: 'c', unionid: 'u', version: '1.0', channelid: 7, marketid: 9 };
|
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 1, province: 'p', city: 'c', unionid: 'u', version: 10001, channelid: 7, marketid: 9 };
|
||||||
|
|
||||||
test('buildLoginRequest 透传必备身份字段', () => {
|
test('buildLoginRequest 透传必备身份字段', () => {
|
||||||
const d = buildLoginRequest(IDENTITY);
|
const d = buildLoginRequest(IDENTITY);
|
||||||
|
|||||||
Reference in New Issue
Block a user