@@ -24,15 +24,14 @@ mod threed;
2424mod uml;
2525
2626use anyhow:: Result ;
27- use core:: f64;
2827use data:: Data ;
2928use macroquad:: prelude:: * ;
3029use prpr:: {
3130 build_conf,
3231 core:: { init_assets, PGR_FONT } ,
3332 ext:: SafeTexture ,
3433 log,
35- scene:: { show_error, show_message } ,
34+ scene:: show_error,
3635 time:: TimeManager ,
3736 ui:: { FontArc , TextPainter } ,
3837 Main ,
@@ -53,7 +52,6 @@ use jni::{
5352} ;
5453
5554static MESSAGES_TX : Mutex < Option < mpsc:: Sender < bool > > > = Mutex :: new ( None ) ;
56- static AA_TX : Mutex < Option < mpsc:: Sender < i32 > > > = Mutex :: new ( None ) ;
5755static DATA_PATH : Mutex < Option < String > > = Mutex :: new ( None ) ;
5856static CACHE_DIR : Mutex < Option < String > > = Mutex :: new ( None ) ;
5957pub static mut DATA : Option < Data > = None ;
@@ -211,23 +209,11 @@ async fn the_main() -> Result<()> {
211209 rx
212210 } ;
213211
214- let aa_rx = {
215- let ( tx, rx) = mpsc:: channel ( ) ;
216- * AA_TX . lock ( ) . unwrap ( ) = Some ( tx) ;
217- rx
218- } ;
219-
220212 unsafe { get_internal_gl ( ) }
221213 . quad_context
222214 . display_mut ( )
223215 . set_pause_resume_listener ( on_pause_resume) ;
224216
225- if let Some ( me) = & get_data ( ) . me {
226- anti_addiction_action ( "startup" , Some ( format ! ( "phira-{}" , me. id) ) ) ;
227- // The native HYKB SDK is (re)entered and verified against the restored
228- // session by the blocking startup check in `HomePage`, not here.
229- }
230-
231217 let pgr_font = FontArc :: try_from_vec ( load_file ( "phigros.ttf" ) . await ?) ?;
232218 PGR_FONT . with ( move |it| * it. borrow_mut ( ) = Some ( TextPainter :: new ( pgr_font, None ) ) ) ;
233219
@@ -244,8 +230,6 @@ async fn the_main() -> Result<()> {
244230 let mut last_frame_start = f32:: NAN ;
245231 let mut fps_time_sum = 0. ;
246232
247- let mut exit_time = f64:: INFINITY ;
248-
249233 ' app: loop {
250234 let frame_start = tm. real_time ( ) ;
251235 if !last_frame_start. is_nan ( ) {
@@ -277,48 +261,8 @@ async fn the_main() -> Result<()> {
277261 break ' app;
278262 }
279263
280- if let Ok ( code) = aa_rx. try_recv ( ) {
281- info ! ( "anti addiction callback: {code}" ) ;
282- match code {
283- // login success
284- 500 => {
285- anti_addiction_action ( "enterGame" , None ) ;
286- }
287- // switch account
288- 1001 => {
289- anti_addiction_action ( "exit" , None ) ;
290- get_data_mut ( ) . me = None ;
291- get_data_mut ( ) . tokens = None ;
292- let _ = save_data ( ) ;
293- sync_data ( ) ;
294- use crate :: login:: L10N_LOCAL ;
295- show_message ( crate :: login:: tl!( "logged-out" ) ) . ok ( ) ;
296- }
297- // period restrict
298- 1030 => {
299- show_and_exit ( "你当前为未成年账号,已被纳入防沉迷系统。根据国家相关规定,周五、周六、周日及法定节假日 20 点 - 21 点之外为健康保护时段。当前时间段无法游玩,请合理安排时间。" ) ;
300- exit_time = frame_start;
301- }
302- // duration limit
303- 1050 => {
304- show_and_exit ( "你当前为未成年账号,已被纳入防沉迷系统。根据国家相关规定,周五、周六、周日及法定节假日 20 点 - 21 点之外为健康保护时段。你已达时间限制,无法继续游戏。" ) ;
305- exit_time = frame_start;
306- }
307- // stopped
308- 9002 => {
309- show_and_exit ( "必须实名认证方可进行游戏。" ) ;
310- exit_time = frame_start;
311- }
312- _ => { }
313- }
314- }
315-
316264 let t = tm. real_time ( ) ;
317265
318- if t > exit_time + 5. {
319- break ;
320- }
321-
322266 let fps_now = t as i32 ;
323267 if fps_now != fps_time {
324268 fps_time = fps_now;
@@ -334,13 +278,6 @@ async fn the_main() -> Result<()> {
334278 Ok ( ( ) )
335279}
336280
337- fn show_and_exit ( msg : & str ) {
338- prpr:: ui:: Dialog :: simple ( msg)
339- . buttons ( vec ! [ "确定" . to_owned( ) ] )
340- . listener ( |_, _| std:: process:: exit ( 0 ) )
341- . show ( ) ;
342- }
343-
344281fn build_global_window_conf ( ) -> Conf {
345282 let mut conf = build_conf ( ) ;
346283 conf. window_title = "Phira" . to_owned ( ) ;
@@ -388,7 +325,6 @@ pub extern "C" fn Java_quad_1native_QuadNative_initializeEnvironment(env: EnvUno
388325#[ cfg( target_os = "android" ) ]
389326#[ no_mangle]
390327pub extern "C" fn Java_quad_1native_QuadNative_prprActivityOnPause ( _env : EnvUnowned , _class : JClass ) {
391- anti_addiction_action ( "leaveGame" , None ) ;
392328 if let Some ( tx) = MESSAGES_TX . lock ( ) . unwrap ( ) . as_mut ( ) {
393329 let _ = tx. send ( true ) ;
394330 }
@@ -397,7 +333,6 @@ pub extern "C" fn Java_quad_1native_QuadNative_prprActivityOnPause(_env: EnvUnow
397333#[ cfg( target_os = "android" ) ]
398334#[ no_mangle]
399335pub extern "C" fn Java_quad_1native_QuadNative_prprActivityOnResume ( _env : EnvUnowned , _class : JClass ) {
400- anti_addiction_action ( "enterGame" , None ) ;
401336 if let Some ( tx) = MESSAGES_TX . lock ( ) . unwrap ( ) . as_mut ( ) {
402337 let _ = tx. send ( false ) ;
403338 }
@@ -459,40 +394,6 @@ pub extern "C" fn Java_quad_1native_QuadNative_setInputText(_env: EnvUnowned, _c
459394 INPUT_TEXT . lock ( ) . unwrap ( ) . 1 = Some ( text. to_string ( ) ) ;
460395}
461396
462- #[ cfg( not( all( target_os = "android" , feature = "hykb" ) ) ) ]
463- pub fn anti_addiction_action ( _action : & str , _arg : Option < String > ) { }
464-
465- #[ cfg( all( target_os = "android" , feature = "hykb" ) ) ]
466- pub fn anti_addiction_action ( action : & str , arg : Option < String > ) {
467- use jni:: { jni_sig, jni_str, objects:: JObject , vm:: JavaVM } ;
468-
469- JavaVM :: singleton ( )
470- . unwrap ( )
471- . attach_current_thread ( |env| -> jni:: errors:: Result < ( ) > {
472- let ctx = unsafe { JObject :: from_raw ( env, ndk_context:: android_context ( ) . context ( ) as _ ) } ;
473- let action = env. new_string ( action) ?;
474- #[ allow( clippy:: redundant_closure) ]
475- let arg = arg
476- . as_ref ( )
477- . map ( |it| env. new_string ( it) )
478- . transpose ( ) ?
479- . map_or_else ( || JObject :: null ( ) , |s| s. into ( ) ) ;
480- env. call_method ( ctx, jni_str ! ( "antiAddiction" ) , jni_sig ! ( "(Ljava/lang/String;Ljava/lang/String;)V" ) , & [ ( & action) . into ( ) , ( & arg) . into ( ) ] ) ?;
481- Ok ( ( ) )
482- } )
483- . unwrap ( ) ;
484- }
485-
486- #[ cfg( target_os = "android" ) ]
487- #[ no_mangle]
488- pub extern "C" fn Java_quad_1native_QuadNative_antiAddictionCallback ( _env : EnvUnowned , _class : JClass , #[ allow( dead_code) ] code : jint ) {
489- if cfg ! ( feature = "hykb" ) {
490- if let Some ( tx) = AA_TX . lock ( ) . unwrap ( ) . as_mut ( ) {
491- let _ = tx. send ( code) ;
492- }
493- }
494- }
495-
496397/// Credentials obtained from the native HYKB (好游快爆) login SDK.
497398pub struct HykbCredential {
498399 /// SDK result code: 0 on success, otherwise an error / user cancellation.
@@ -511,6 +412,14 @@ impl HykbCredential {
511412 if self . code == 0 {
512413 Ok ( self )
513414 } else {
415+ // A non-zero code is any failure the HYKB SDK reports: 2001 auth
416+ // failed, 2002 login failed, 2003 cancelled, 2004 exception, 2005
417+ // developer-requested exit / account logout. A HYKB build mandates a
418+ // valid, matching HYKB session, so every one of these must tear the
419+ // in-game session down — otherwise cancelling the HYKB prompt during
420+ // a silent re-verify would leave the player signed in and bypass the
421+ // gate entirely.
422+ force_logout ( ) ;
514423 anyhow:: bail!( "{}" , crate :: ttl!( "hykb-login-cancelled" ) )
515424 }
516425 }
@@ -566,6 +475,18 @@ pub fn hykb_logout() {
566475#[ cfg( not( all( target_os = "android" , feature = "hykb" ) ) ) ]
567476pub fn hykb_logout ( ) { }
568477
478+ /// Tear down the local session: sign out of the native HYKB SDK, clear the
479+ /// stored account and tokens, then re-sync. Shared by every path that must
480+ /// reject a login — a failed/cancelled HYKB verification, a uid mismatch, or
481+ /// the player logging out from their profile.
482+ pub fn force_logout ( ) {
483+ hykb_logout ( ) ;
484+ get_data_mut ( ) . me = None ;
485+ get_data_mut ( ) . tokens = None ;
486+ let _ = save_data ( ) ;
487+ sync_data ( ) ;
488+ }
489+
569490/// Trigger the native HYKB login and await its credentials.
570491#[ allow( unused) ]
571492pub async fn obtain_hykb_credential ( ) -> Result < HykbCredential > {
@@ -611,6 +532,13 @@ pub extern "C" fn Java_quad_1native_QuadNative_hykbLoginCallback(
611532 nick,
612533 access_token,
613534 } ) ;
535+ } else if code == 2005 {
536+ // No login is in flight, so this is the SDK's asynchronous
537+ // anti-addiction "exit game" action: the player hit a play-time limit
538+ // and chose to quit from the SDK's own dialog. Honor it by exiting.
539+ // Other async codes (e.g. 2008 "continue playing") are handled inside
540+ // the SDK and need no response here.
541+ std:: process:: exit ( 0 ) ;
614542 }
615543}
616544
0 commit comments