static si_t _server_lib_handle_request(addr_t body, si_t detail_type, union respond* respond_ptr, addr_t app_addr) { /** 存储调用实际操作函数结果的变量 **/ si_t func_ret = 0; /** 存储_server_lib_handle_request()返回值的变量 **/ si_t handler_ret = SELECTER_RETURN_TYPE_CONTINUE; switch(detail_type) { case REQUEST_TYPE_REGISTER_APPLICATION: { si_t video_access_mode = 0, application_type = 0; char* app_name = NULL; request_get_register_application(body, &video_access_mode, &application_type, &app_name, NULL); func_ret = register_application_handler(app_addr, video_access_mode, application_type, app_name); respond_set_normal(respond_ptr, RESPOND_TYPE_REGISTER_APPLICATION, func_ret); } break; case REQUEST_TYPE_CANCEL_APPLICATION: respond_set_normal(respond_ptr, RESPOND_TYPE_CANCEL_APPLICATION, 0); handler_ret = SELECTER_RETURN_TYPE_REMOVE_HANDLER; break; /** * 处理初始化/清理图形设备的请求: * 首先从请求包中获取必要参数, * 接着调用graph模块的函数对图形设备初始化/清理, * 接着将获得的参数和应用程序指针传递给上层的回调函数进行处理 * 最后将上层回调函数的返回值作为回应包的返回值 **/ case REQUEST_TYPE_GRAPHICS_DEVICE_INIT: { si_t gd = request_call_by_graphics_device_init(body, engine_graphics_device_init); func_ret = graphics_device_init_handler(app_addr, gd); respond_set_normal(respond_ptr, RESPOND_TYPE_GRAPHICS_DEVICE_INIT, gd); } break; case REQUEST_TYPE_GRAPHICS_DEVICE_EXIT: { si_t gd = 0; request_get_graphics_device_exit(body, &gd); func_ret = request_call_by_graphics_device_exit(body, engine_graphics_device_exit); func_ret = graphics_device_exit_handler(app_addr, gd); respond_set_normal(respond_ptr, RESPOND_TYPE_GRAPHICS_DEVICE_EXIT, func_ret); } break; /** * 接到window_manager_quit命令 若成功执行则返回退出循环的 **/ case REQUEST_TYPE_WINDOW_MANAGER_QUIT: func_ret = window_manager_exit_handler(app_addr); respond_set_normal(respond_ptr, RESPOND_TYPE_WINDOW_MANAGER_QUIT, func_ret); if(0 == func_ret) { handler_ret = SELECTER_RETURN_TYPE_END; } break; case REQUEST_TYPE_DESKTOP_DIRTY: func_ret = desktop_dirty_handler(app_addr); respond_set_normal(respond_ptr, RESPOND_TYPE_DESKTOP_DIRTY, func_ret); break; case REQUEST_TYPE_UPDATE: { si_t gd = 0; request_get_update(body, &gd); func_ret = update_handler(app_addr, gd); respond_set_normal(respond_ptr, RESPOND_TYPE_UPDATE, func_ret); } break; case REQUEST_TYPE_ACTIVATE_WINDOW: { si_t window_descripter = 0; request_get_activate_window(body, &window_descripter); func_ret = activate_window_handler(app_addr, window_descripter); respond_set_normal(respond_ptr, RESPOND_TYPE_ACTIVATE_WINDOW, func_ret); } break; case REQUEST_TYPE_REGISTER_WINDOW: { si_t window_descripter = 0, x_axis = 0, y_axis = 0, x_size = 0, y_size = 0, maxable = 0, minable = 0, model = 0; char* title = NULL; request_get_register_window(body, &window_descripter, &title, NULL, &x_axis, &y_axis, &x_size, &y_size, &minable, &maxable, &model); func_ret = register_window_handler(app_addr, window_descripter, title, x_axis, y_axis, x_size, y_size, minable, maxable, model); respond_set_normal(respond_ptr, RESPOND_TYPE_REGISTER_WINDOW, func_ret); } break; case REQUEST_TYPE_CANCEL_WINDOW: { si_t window_descripter = 0; request_get_cancel_window(body, &window_descripter); func_ret = cancel_window_handler(app_addr, window_descripter); respond_set_normal(respond_ptr, RESPOND_TYPE_CANCEL_WINDOW, func_ret); } break; case REQUEST_TYPE_MOVE_WINDOW: { si_t window_descripter = 0, x_axis = 0, y_axis = 0; request_get_move_window(body, &window_descripter, &x_axis, &y_axis); func_ret = move_window_handler(app_addr, window_descripter, x_axis, y_axis); respond_set_normal(respond_ptr, RESPOND_TYPE_MOVE_WINDOW, func_ret); } break; case REQUEST_TYPE_RESIZE_WINDOW: { si_t window_descripter = 0, x_axis = 0, y_axis = 0, x_size = 0, y_size = 0; request_get_resize_window(body, &window_descripter, &x_axis, &y_axis, &x_size, &y_size); func_ret = resize_window_handler(app_addr, window_descripter, x_axis, y_axis, x_size, y_size); respond_set_normal(respond_ptr, RESPOND_TYPE_RESIZE_WINDOW, func_ret); } break; case REQUEST_TYPE_MINIMIZE_WINDOW: { si_t window_descripter = 0; request_get_minimize_window(body, &window_descripter); func_ret = minimize_window_handler(app_addr, window_descripter); respond_set_normal(respond_ptr, RESPOND_TYPE_MINIMIZE_WINDOW, func_ret); } break; case REQUEST_TYPE_MAXIMIZE_WINDOW: { si_t window_descripter = 0; struct rectangle area; request_get_maximize_window(body, &window_descripter); func_ret = maximize_window_handler(app_addr, window_descripter, &area); respond_set_rectangle(respond_ptr, RESPOND_TYPE_MAXIMIZE_WINDOW, &area); } break; case REQUEST_TYPE_RESTORE_WINDOW: { si_t window_descripter = 0; struct rectangle area; request_get_restore_window(body, &window_descripter, &area.x, &area.y, &area.width, &area.height); func_ret = restore_window_handler(app_addr, window_descripter, &area); respond_set_normal(respond_ptr, RESPOND_TYPE_RESTORE_WINDOW, func_ret); } break; case REQUEST_TYPE_GET_WINDOW_TITLE: { si_t window_descripter = 0; char* title = NULL; request_get_window_title(body, &window_descripter); get_window_title(app_addr, window_descripter, &title); respond_set_va(respond_ptr, RESPOND_TYPE_GET_WINDOW_TITLE, title, strlen(title) + 1); } break; } return handler_ret; }
void game_loop( void ) { struct timeval last_time; gettimeofday( &last_time, NULL ); current_time = last_time.tv_sec; // Main loop while( !mud_down ) { accept_new( control ); // Primative, yet effective infinite loop catcher. At least that's the idea. set_alarm( 30 ); alarm_section = "game_loop"; // If no descriptors are present, why bother processing input for them? if( dlist.size( ) > 0 ) process_input( ); #if !defined(__CYGWIN__) #ifdef MULTIPORT mud_recv_message( ); #endif #endif #ifdef IMC imc_loop( ); #endif // Autonomous game motion. Stops processing when there are no people at all online. if( dlist.size( ) > 0 ) update_handler( ); // Event handling. Will continue to process even with nobody around. Keeps areas fresh this way. run_events( current_time ); // If no descriptors are present, why bother processing output for them? if( dlist.size( ) > 0 ) process_output( ); /* * Synchronize to a clock. ( Would have moved this to its own function, but the code REALLY hated that plan.... ) * Sleep( last_time + 1/PULSE_PER_SECOND - now ). * Careful here of signed versus unsigned arithmetic. */ { struct timeval now_time; long secDelta; long usecDelta; gettimeofday( &now_time, NULL ); usecDelta = ( last_time.tv_usec ) - ( now_time.tv_usec ) + 1000000 / sysdata->pulsepersec; secDelta = ( last_time.tv_sec ) - ( now_time.tv_sec ); while( usecDelta < 0 ) { usecDelta += 1000000; secDelta -= 1; } while( usecDelta >= 1000000 ) { usecDelta -= 1000000; secDelta += 1; } if( secDelta > 0 || ( secDelta == 0 && usecDelta > 0 ) ) { struct timeval stall_time; stall_time.tv_usec = usecDelta; stall_time.tv_sec = secDelta; if( select( 0, NULL, NULL, NULL, &stall_time ) < 0 && errno != EINTR ) { perror( "game_loop: select: stall" ); exit( 1 ); } } } gettimeofday( &last_time, NULL ); current_time = last_time.tv_sec; // Dunno if it needs to be reset, but I'll do it anyway. End of the loop here. set_alarm( 0 ); /* * This will be the very last thing done here, because if you can't make it through * one lousy loop without crashing a second time..... */ sigsegv = false; } // End of main game loop // Returns back to 'main', and will result in mud shutdown }