feat: integrate login flow, lobby UI and bitmap font resources

This commit is contained in:
2026-09-06 13:46:57 +08:00
parent e1bcfd91ec
commit 842c68ef55
141 changed files with 11279 additions and 1717 deletions
@@ -0,0 +1,10 @@
type BrowserHost={kind:'settings';browser(url:string):void}|{kind:'bridge';call(name:'browser',data:string):void}|{kind:'h5';open(url:string):void};
/** 05_Func.fixUrl + browser. The settings host alone appends timestamp. */
export function openLobbyUrl(url:string,host:BrowserHost,now:()=>number):void {
if(!url)return;
const index=url.indexOf('?');
const fixed=index<0?url:url.slice(0,index+1)+url.slice(index+1).replace(/\?/g,'&');
if(host.kind==='settings')host.browser(`${fixed}&timestamp=${now()}`);
else if(host.kind==='bridge')host.call('browser',fixed);
else host.open(fixed);
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "5953d513-a238-4d0f-a3e4-d8c7dbb1e4cb",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -8,7 +8,7 @@ export interface LoginNativeSettings {
getcompareCode(): number | string;
}
interface Options {
storage: {getItem(key:string):string|null;setItem(key:string,value:string):void};
storage: {getItem(key:string):string|null;setItem(key:string,value:string):void;removeItem(key:string):void};
settings?:LoginNativeSettings; random():number; now():number;
gameid:string|number;agentid:string|number;policy:LoginPolicy;
submit(account:LoginAccountIdentity,device:DeviceLoginMode):void;tip(message:string):void;
@@ -106,6 +106,16 @@ export class LoginAccounts {
this.options.submit(account,{enabled:true,telphone:data.telphone});
}else this.options.submit(account,{enabled:false});
}
/** Invalidate all auto-login paths, including visitor precedence, before returning to login. */
logout():void {
// GameUI case 58 deletes wxinfo/devicePlayer. Keep credential cleanup here
// so every caller invalidates the same automatic-login sources.
this.options.storage.setItem('tsgame_validtime','0');
this.options.storage.removeItem('tsgame_wxinfo');
this.options.storage.removeItem('tsgame_devicePlayer');
this.options.storage.setItem(`tsgame_playerid_${this.options.gameid}${this.options.agentid}`,'');
this.options.storage.setItem('tsgame_dLogin','0');
}
authorize(provider:'wechat'|'qq'):void {
if(!this.requireAgreement())return;
if(!this.options.settings){this.options.tip('当前宿主未提供原生登录授权接口');return;}
@@ -118,16 +128,17 @@ export class LoginAccounts {
this.save(account,channel==='global'&&this.options.policy.showVisitor?'tsgame_visitorinfo':'tsgame_wxinfo');
this.options.submit(account,{enabled:false});
}
/** 仅本次手机登录要求 tel,不能依据按钮显示配置要求游客响应携带手机号。 */
/** Desk.login saves the server identity whenever sysConfig.deviceLogin is enabled. */
loginSucceeded(value:unknown,mode:DeviceLoginMode):void {
const data=record(value);
if(data.state!==0)throw Error('Cannot cache an unsuccessful login');
if(typeof data.playerid!=='string'&&(typeof data.playerid!=='number'||!Number.isFinite(data.playerid)))throw Error('Invalid login playerid');
// Button availability is not the authentication mode of this request.
if(mode.enabled){
if(typeof data.tel!=='string')throw Error('Device login response missing tel');
if(this.options.policy.deviceLogin){
if((mode.enabled||data.tel!==undefined)&&typeof data.tel!=='string')throw Error('Device login response missing tel');
const account=accountFrom({...data,headimgurl:data.avatar,Province:data.province});
this.save(account,'tsgame_devicePlayer',data.tel);
// Desk.login copies the server sex verbatim; sharelogin normalizes it only on use.
if(typeof data.sex!=='number'||!Number.isFinite(data.sex))throw Error('Invalid login sex');
this.save({...account,sex:data.sex},'tsgame_devicePlayer',data.tel as string|undefined);
this.options.storage.setItem('tsgame_dLogin','1');
}
this.options.storage.setItem(`tsgame_playerid_${this.options.gameid}${this.options.agentid}`,String(data.playerid));
@@ -164,6 +175,9 @@ export class LoginAccounts {
phone(phone:string,code:string):void {
if(!this.requireAgreement())return;
if(!phone||!code){this.options.tip('手机号与验证码均不能为空!');return;}
this.options.submit(this.deviceAccount(phone),{enabled:true,telphone:phone,smmcode:code});
const account=this.deviceAccount(phone);
// Func.phoneLogin -> sharelogin saves visitorinfo before Net.Send_login when showVisitor is enabled.
if(this.options.policy.showVisitor)this.save(account,'tsgame_visitorinfo',phone);
this.options.submit(account,{enabled:true,telphone:phone,smmcode:code});
}
}