static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step) { timer_private_t *private_info = timer->private_info; switch_status_t status = SWITCH_STATUS_SUCCESS; if (globals.RUNNING != 1 || !private_info->ready) { return SWITCH_STATUS_SUCCESS; } check_roll(); timer->tick = TIMER_MATRIX[timer->interval].tick; if (timer->tick < private_info->reference) { timer->diff = private_info->reference - timer->tick; } else { timer->diff = 0; } if (timer->diff) { status = SWITCH_STATUS_FALSE; } else if (step) { timer_step(timer); } return status; }
static switch_status_t timer_sync(switch_timer_t *timer) { timer_private_t *private_info = timer->private_info; if (globals.RUNNING != 1 || private_info->ready == 0) { return SWITCH_STATUS_FALSE; } /* sync the clock */ private_info->reference = timer->tick = TIMER_MATRIX[timer->interval].tick; /* apply timestamp */ timer_step(timer); return SWITCH_STATUS_SUCCESS; }
void core_loop(void) { SDL_Event event; while (! app.exit) { while (SDL_PollEvent(&event)) { event_handle(&event); } if (! timer.paused) { process_update(); view_update(); } view_render(); timer_step(); } }
static switch_status_t timer_next(switch_timer_t *timer) { timer_private_t *private_info = timer->private_info; #ifdef DISABLE_1MS_COND int cond_index = timer->interval; #else int cond_index = 1; #endif int delta = (int) (private_info->reference - TIMER_MATRIX[timer->interval].tick); /* sync up timer if it's not been called for a while otherwise it will return instantly several times until it catches up */ if (delta < -1) { private_info->reference = timer->tick = TIMER_MATRIX[timer->interval].tick; } timer_step(timer); if (!MATRIX) { do_sleep(1000 * timer->interval); goto end; } while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) { check_roll(); if (globals.timer_count >= runtime.tipping_point) { os_yield(); globals.use_cond_yield = 0; } else { if (globals.use_cond_yield == 1) { switch_mutex_lock(TIMER_MATRIX[cond_index].mutex); if (TIMER_MATRIX[timer->interval].tick < private_info->reference) { switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex); } switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex); } else { do_sleep(1000); } } } end: return globals.RUNNING == 1 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
ScriptEngine::ScriptEngine(ClientInterface *c) { myclient = c; armScriptEngine(&myengine); connect(&manager, SIGNAL(finished(QNetworkReply*)), SLOT(webCall_replyFinished(QNetworkReply*))); changeScript(ScriptUtils::loadScripts()); changeBattleScript(ScriptUtils::loadScripts(ScriptUtils::BattleScripts)); QTimer *step_timer = new QTimer(this); step_timer->setSingleShot(false); step_timer->start(1000); connect(step_timer, SIGNAL(timeout()), SLOT(timer_step())); QSettings s; safeScripts = s.value("ScriptWindow/safeScripts", true).toBool(); warnings = s.value("ScriptWindow/warn", true).toBool(); datalocation = appDataPath("Scripts/", true) + "/data.ini"; }
static switch_status_t timer_sync(switch_timer_t *timer) { timer_private_t *private_info = timer->private_info; if (globals.RUNNING != 1 || private_info->ready == 0) { return SWITCH_STATUS_FALSE; } /* sync the clock */ private_info->reference = timer->tick = TIMER_MATRIX[timer->interval].tick; /* apply timestamp */ if (timer_step(timer) == SWITCH_STATUS_SUCCESS) { /* push the reference into the future to prevent collision */ private_info->reference++; } return SWITCH_STATUS_SUCCESS; }
int l_timer_step(lua_State* state) { (void)state; timer_step(); return 0; }
void main_loop(void *data) { MainLoopData* loopData = (MainLoopData*)data; // TODO use registry to get love.update and love.draw? chdir("love"); timer_step(); graphics_clear(); matrixstack_origin(); lua_rawgeti(loopData->luaState, LUA_REGISTRYINDEX, loopData->errhand); lua_getglobal(loopData->luaState, "love"); lua_pushstring(loopData->luaState, "update"); lua_rawget(loopData->luaState, -2); lua_pushnumber(loopData->luaState, timer_getDelta()); pcall(loopData->luaState, 1); lua_pushstring(loopData->luaState, "draw"); lua_rawget(loopData->luaState, -2); pcall(loopData->luaState, 0); graphics_DisplayState curState = *graphics_getState(); matrixstack_push(); mouse_cursor_draw(); matrixstack_pop(); graphics_setState(&curState); graphics_swap(); lua_pop(loopData->luaState, 1); SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: keyboard_keypressed(event.key.keysym.sym); break; case SDL_KEYUP: keyboard_keyreleased(event.key.keysym.sym); break; case SDL_TEXTINPUT: keyboard_textInput(event.text.text); break; case SDL_MOUSEMOTION: mouse_mousemoved(event.motion.x, event.motion.y); break; case SDL_MOUSEBUTTONDOWN: mouse_mousepressed(event.button.x, event.button.y, event.button.button); break; case SDL_MOUSEBUTTONUP: mouse_mousereleased(event.button.x, event.button.y, event.button.button); break; case SDL_JOYDEVICEADDED: joystick_deviceAdded(event.jdevice.which); break; case SDL_JOYDEVICEREMOVED: joystick_deviceRemoved(event.jdevice.which); break; case SDL_JOYBUTTONUP: joystick_buttonReleased(event.jbutton.which, event.jbutton.button); break; case SDL_JOYBUTTONDOWN: joystick_buttonPressed(event.jbutton.which, event.jbutton.button); break; case SDL_JOYAXISMOTION: joystick_axisEvent(event.jaxis.which, event.jaxis.axis, event.jaxis.value); break; case SDL_CONTROLLERBUTTONUP: joystick_controllerButtonReleased(event.jbutton.which, event.jbutton.button); break; case SDL_CONTROLLERBUTTONDOWN: joystick_controllerButtonPressed(event.jbutton.which, event.jbutton.button); break; case SDL_CONTROLLERAXISMOTION: joystick_controllerAxisEvent(event.jaxis.which, event.jaxis.axis, event.jaxis.value); break; #ifndef EMSCRIPTEN case SDL_QUIT: exit(0); #endif } } audio_updateStreams(); //lua_gc(loopData->luaState, LUA_GCCOLLECT, 0); }
void Client::step(float dtime) { DSTACK(__FUNCTION_NAME); m_uptime += dtime; // Limit a bit if(dtime > 2.0) dtime = 2.0; if(m_ignore_damage_timer > dtime) m_ignore_damage_timer -= dtime; else m_ignore_damage_timer = 0.0; m_animation_time += dtime; if(m_animation_time > 60.0) m_animation_time -= 60.0; m_time_of_day_update_timer += dtime; ReceiveAll(); /* Packet counter */ { float &counter = m_packetcounter_timer; counter -= dtime; if(counter <= 0.0) { counter = 20.0; verbosestream << "Client packetcounter (" << m_packetcounter_timer << "):"<<std::endl; m_packetcounter.print(verbosestream); m_packetcounter.clear(); } } // UGLY hack to fix 2 second startup delay caused by non existent // server client startup synchronization in local server or singleplayer mode static bool initial_step = true; if (initial_step) { initial_step = false; } else if(m_state == LC_Created) { float &counter = m_connection_reinit_timer; counter -= dtime; if(counter <= 0.0) { counter = 2.0; Player *myplayer = m_env.getLocalPlayer(); FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment."); // Send TOSERVER_INIT_LEGACY // [0] u16 TOSERVER_INIT_LEGACY // [2] u8 SER_FMT_VER_HIGHEST_READ // [3] u8[20] player_name // [23] u8[28] password (new in some version) // [51] u16 minimum supported network protocol version (added sometime) // [53] u16 maximum supported network protocol version (added later than the previous one) /* char pName[PLAYERNAME_SIZE]; char pPassword[PASSWORD_SIZE]; memset(pName, 0, PLAYERNAME_SIZE * sizeof(char)); memset(pPassword, 0, PASSWORD_SIZE * sizeof(char)); */ std::string hashed_password = translatePassword(myplayer->getName(), m_password); /* snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); snprintf(pPassword, PASSWORD_SIZE, "%s", hashed_password.c_str()); sendLegacyInit(pName, pPassword); */ sendLegacyInit(myplayer->getName(), hashed_password); if (LATEST_PROTOCOL_VERSION >= 25) sendInit(myplayer->getName()); } // Not connected, return return; } /* Do stuff if connected */ unsigned int max_cycle_ms = 200/g_settings->getFloat("wanted_fps"); /* Run Map's timers and unload unused data */ const float map_timer_and_unload_dtime = 10.25; if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) { ScopeProfiler sp(g_profiler, "Client: map timer and unload"); std::vector<v3s16> deleted_blocks; if(m_env.getMap().timerUpdate(m_uptime, g_settings->getFloat("client_unload_unused_data_timeout"), g_settings->getS32("client_mapblock_limit"), max_cycle_ms, &deleted_blocks)) m_map_timer_and_unload_interval.run_next(map_timer_and_unload_dtime); /*if(deleted_blocks.size() > 0) infostream<<"Client: Unloaded "<<deleted_blocks.size() <<" unused blocks"<<std::endl;*/ /* Send info to server NOTE: This loop is intentionally iterated the way it is. */ auto i = deleted_blocks.begin(); std::vector<v3s16> sendlist; for(;;) { if(sendlist.size() == 255 || i == deleted_blocks.end()) { if(sendlist.empty()) break; sendDeletedBlocks(sendlist); if(i == deleted_blocks.end()) break; sendlist.clear(); } sendlist.push_back(*i); ++i; } } /* Handle environment */ // Control local player (0ms) LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); player->applyControl(dtime, &m_env); // Step environment m_env.step(dtime, m_uptime, max_cycle_ms); /* Get events */ for(;;) { ClientEnvEvent event = m_env.getClientEvent(); if(event.type == CEE_NONE) { break; } else if(event.type == CEE_PLAYER_DAMAGE) { if(m_ignore_damage_timer <= 0) { u8 damage = event.player_damage.amount; if(event.player_damage.send_to_server) sendDamage(damage); // Add to ClientEvent queue ClientEvent event; event.type = CE_PLAYER_DAMAGE; event.player_damage.amount = damage; m_client_event_queue.push(event); } } else if(event.type == CEE_PLAYER_BREATH) { u16 breath = event.player_breath.amount; sendBreath(breath); } } /* Print some info */ float &counter = m_avg_rtt_timer; counter += dtime; if(counter >= 10) { counter = 0.0; // connectedAndInitialized() is true, peer exists. #if MINETEST_PROTO float avg_rtt = getRTT(); infostream<<"Client: avg_rtt="<<avg_rtt<<std::endl; #endif sendDrawControl(); //not very good place. maybe 5s timer better } /* Send player position to server */ { float &counter = m_playerpos_send_timer; counter += dtime; if((m_state == LC_Ready) && (counter >= m_recommended_send_interval)) { counter = 0.0; sendPlayerPos(); } } /* Replace updated meshes */ { TimeTaker timer_step("Client: Replace updated meshes"); int num_processed_meshes = 0; u32 end_ms = porting::getTimeMs() + 10; /* auto lock = m_env.getMap().m_blocks.try_lock_shared_rec(); if (!lock->owns_lock()) { infostream<<"skip updating meshes"<<std::endl; } else */ { while (!m_mesh_update_thread.m_queue_out.empty_try()) { num_processed_meshes++; MinimapMapblock *minimap_mapblock = NULL; bool do_mapper_update = true; MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx(); if (!r.mesh) continue; auto block = m_env.getMap().getBlock(r.p); if(block) { block->setMesh(r.mesh); if (r.mesh) { minimap_mapblock = r.mesh->moveMinimapMapblock(); if (minimap_mapblock == NULL) do_mapper_update = false; } if (r.mesh && r.mesh->getMesh()->getMeshBufferCount() == 0) { //delete r.mesh; } else { // Replace with the new mesh block->mesh = r.mesh; } } else { //delete r.mesh; } if (do_mapper_update) m_mapper->addBlock(r.p, minimap_mapblock); if (porting::getTimeMs() > end_ms) { break; } } if(num_processed_meshes > 0) g_profiler->graphAdd("num_processed_meshes", num_processed_meshes); } } /* Load fetched media */ if (m_media_downloader && m_media_downloader->isStarted()) { m_media_downloader->step(this); if (m_media_downloader->isDone()) { received_media(); delete m_media_downloader; m_media_downloader = NULL; } } /* If the server didn't update the inventory in a while, revert the local inventory (so the player notices the lag problem and knows something is wrong). */ if(m_inventory_from_server) { float interval = 10.0; float count_before = floor(m_inventory_from_server_age / interval); m_inventory_from_server_age += dtime; float count_after = floor(m_inventory_from_server_age / interval); if(count_after != count_before) { // Do this every <interval> seconds after TOCLIENT_INVENTORY // Reset the locally changed inventory to the authoritative inventory Player *player = m_env.getLocalPlayer(); player->inventory = *m_inventory_from_server; m_inventory_updated = true; } } /* Update positions of sounds attached to objects */ { for(std::map<int, u16>::iterator i = m_sounds_to_objects.begin(); i != m_sounds_to_objects.end(); ++i) { int client_id = i->first; u16 object_id = i->second; ClientActiveObject *cao = m_env.getActiveObject(object_id); if(!cao) continue; v3f pos = cao->getPosition(); m_sound->updateSoundPosition(client_id, pos); } } /* Handle removed remotely initiated sounds */ m_removed_sounds_check_timer += dtime; if(m_removed_sounds_check_timer >= 2.32) { m_removed_sounds_check_timer = 0; // Find removed sounds and clear references to them std::vector<s32> removed_server_ids; for(std::map<s32, int>::iterator i = m_sounds_server_to_client.begin(); i != m_sounds_server_to_client.end();) { s32 server_id = i->first; int client_id = i->second; ++i; if(!m_sound->soundExists(client_id)) { m_sounds_server_to_client.erase(server_id); m_sounds_client_to_server.erase(client_id); m_sounds_to_objects.erase(client_id); removed_server_ids.push_back(server_id); } } // Sync to server if(!removed_server_ids.empty()) { sendRemovedSounds(removed_server_ids); } } float timelapse = g_settings->getFloat("timelapse"); if (timelapse) { m_timelapse_timer += dtime; if (m_timelapse_timer > timelapse) { m_timelapse_timer = 0; makeScreenshot("timelapse_"); } } }
void ClientMap::updateDrawList(video::IVideoDriver* driver, float dtime, unsigned int max_cycle_ms) { ScopeProfiler sp(g_profiler, "CM::updateDrawList()", SPT_AVG); //g_profiler->add("CM::updateDrawList() count", 1); TimeTaker timer_step("ClientMap::updateDrawList"); INodeDefManager *nodemgr = m_gamedef->ndef(); if (!m_drawlist_last) m_drawlist_current = !m_drawlist_current; auto & drawlist = m_drawlist_current ? m_drawlist_1 : m_drawlist_0; if (!max_cycle_ms) max_cycle_ms = 300/getControl().fps_wanted; m_camera_mutex.Lock(); v3f camera_position = m_camera_position; f32 camera_fov = m_camera_fov; //v3s16 camera_offset = m_camera_offset; m_camera_mutex.Unlock(); // Use a higher fov to accomodate faster camera movements. // Blocks are cropped better when they are drawn. // Or maybe they aren't? Well whatever. camera_fov *= 1.2; v3s16 cam_pos_nodes = floatToInt(camera_position, BS); v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1); v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d; v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d; // Take a fair amount as we will be dropping more out later // Umm... these additions are a bit strange but they are needed. v3s16 p_blocks_min( p_nodes_min.X / MAP_BLOCKSIZE - 3, p_nodes_min.Y / MAP_BLOCKSIZE - 3, p_nodes_min.Z / MAP_BLOCKSIZE - 3); v3s16 p_blocks_max( p_nodes_max.X / MAP_BLOCKSIZE + 1, p_nodes_max.Y / MAP_BLOCKSIZE + 1, p_nodes_max.Z / MAP_BLOCKSIZE + 1); // Number of blocks in rendering range u32 blocks_in_range = 0; // Number of blocks occlusion culled u32 blocks_occlusion_culled = 0; // Number of blocks in rendering range but don't have a mesh u32 blocks_in_range_without_mesh = 0; // Blocks that had mesh that would have been drawn according to // rendering range (if max blocks limit didn't kick in) u32 blocks_would_have_drawn = 0; // Blocks that were drawn and had a mesh u32 blocks_drawn = 0; // Blocks which had a corresponding meshbuffer for this pass //u32 blocks_had_pass_meshbuf = 0; // Blocks from which stuff was actually drawn //u32 blocks_without_stuff = 0; // Distance to farthest drawn block float farthest_drawn = 0; int m_mesh_queued = 0; bool free_move = g_settings->getBool("free_move"); float range_max = 100000 * BS; if(m_control.range_all == false) range_max = m_control.wanted_range * BS; if (draw_nearest.empty()) { //ScopeProfiler sp(g_profiler, "CM::updateDrawList() make list", SPT_AVG); TimeTaker timer_step("ClientMap::updateDrawList make list"); auto lock = m_blocks.try_lock_shared_rec(); if (!lock->owns_lock()) return; draw_nearest.clear(); for(auto & ir : m_blocks) { auto bp = ir.first; if(m_control.range_all == false) { if(bp.X < p_blocks_min.X || bp.X > p_blocks_max.X || bp.Z > p_blocks_max.Z || bp.Z < p_blocks_min.Z || bp.Y < p_blocks_min.Y || bp.Y > p_blocks_max.Y) continue; } v3s16 blockpos_nodes = bp * MAP_BLOCKSIZE; // Block center position v3f blockpos( ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS, ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS, ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS ); f32 d = radius_box(blockpos, camera_position); //blockpos_relative.getLength(); if (d> range_max) continue; int range = d / (MAP_BLOCKSIZE * BS); draw_nearest.emplace_back(std::make_pair(bp, range)); } } const int maxq = 1000; // No occlusion culling when free_move is on and camera is // inside ground bool occlusion_culling_enabled = true; if(free_move) { MapNode n = getNodeNoEx(cam_pos_nodes); if(n.getContent() == CONTENT_IGNORE || nodemgr->get(n).solidness == 2) occlusion_culling_enabled = false; } u32 calls = 0, end_ms = porting::getTimeMs() + u32(max_cycle_ms); std::unordered_map<v3POS, bool, v3POSHash, v3POSEqual> occlude_cache; while (!draw_nearest.empty()) { auto ir = draw_nearest.back(); auto bp = ir.first; int range = ir.second; draw_nearest.pop_back(); ++calls; //auto block = getBlockNoCreateNoEx(bp); auto block = m_blocks.get(bp); if (!block) continue; int mesh_step = getFarmeshStep(m_control, getNodeBlockPos(cam_pos_nodes), bp); /* Compare block position to camera position, skip if not seen on display */ auto mesh = block->getMesh(mesh_step); if (mesh) mesh->updateCameraOffset(m_camera_offset); blocks_in_range++; auto smesh_size = block->mesh_size; /* Ignore if mesh doesn't exist */ { if(!mesh) { blocks_in_range_without_mesh++; if (m_mesh_queued < maxq || range <= 2) { m_client->addUpdateMeshTask(bp, false); ++m_mesh_queued; } continue; } if(mesh_step == mesh->step && block->getTimestamp() <= mesh->timestamp && !smesh_size) { blocks_in_range_without_mesh++; continue; } } /* Occlusion culling */ v3s16 cpn = bp * MAP_BLOCKSIZE; cpn += v3s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2); float step = BS*1; float stepfac = 1.2; float startoff = BS*1; float endoff = -BS*MAP_BLOCKSIZE; //*1.42; //*1.42; v3s16 spn = cam_pos_nodes + v3s16(0,0,0); s16 bs2 = MAP_BLOCKSIZE/2 + 1; u32 needed_count = 1; if( range > 1 && smesh_size && occlusion_culling_enabled && isOccluded(this, spn, cpn + v3s16(0,0,0), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(bs2,bs2,-bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(bs2,-bs2,bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(bs2,-bs2,-bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(-bs2,bs2,bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(-bs2,bs2,-bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) && isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,-bs2), step, stepfac, startoff, endoff, needed_count, nodemgr, occlude_cache) ) { blocks_occlusion_culled++; continue; } // This block is in range. Reset usage timer. block->resetUsageTimer(); // Limit block count in case of a sudden increase blocks_would_have_drawn++; /* if(blocks_drawn >= m_control.wanted_max_blocks && m_control.range_all == false && d > m_control.wanted_min_range * BS) continue; */ if (mesh_step != mesh->step && (m_mesh_queued < maxq*1.2 || range <= 2)) { m_client->addUpdateMeshTask(bp); ++m_mesh_queued; } if (block->getTimestamp() > mesh->timestamp + (smesh_size ? 0 : range >= 1 ? 60 : 5) && (m_mesh_queued < maxq*1.5 || range <= 2)) { m_client->addUpdateMeshTaskWithEdge(bp); ++m_mesh_queued; } if(!smesh_size) continue; mesh->incrementUsageTimer(dtime); // Add to set //block->refGrab(); block->resetUsageTimer(); drawlist.set(bp, block); blocks_drawn++; if(range * MAP_BLOCKSIZE > farthest_drawn) farthest_drawn = range * MAP_BLOCKSIZE; if (farthest_drawn > m_control.farthest_drawn) m_control.farthest_drawn = farthest_drawn; if (porting::getTimeMs() > end_ms) { break; } } m_drawlist_last = draw_nearest.size(); //if (m_drawlist_last) infostream<<"breaked UDL "<<m_drawlist_last<<" collected="<<drawlist.size()<<" calls="<<calls<<" s="<<m_blocks.size()<<" maxms="<<max_cycle_ms<<" fw="<<getControl().fps_wanted<<" morems="<<porting::getTimeMs() - end_ms<< " meshq="<<m_mesh_queued<<" occache="<<occlude_cache.size()<<std::endl; if (m_drawlist_last) return; //for (auto & ir : *m_drawlist) // ir.second->refDrop(); auto m_drawlist_old = !m_drawlist_current ? &m_drawlist_1 : &m_drawlist_0; m_drawlist = m_drawlist_current ? &m_drawlist_1 : &m_drawlist_0; m_drawlist_old->clear(); m_control.blocks_would_have_drawn = blocks_would_have_drawn; m_control.blocks_drawn = blocks_drawn; m_control.farthest_drawn = farthest_drawn; g_profiler->avg("CM: blocks total", m_blocks.size()); g_profiler->avg("CM: blocks in range", blocks_in_range); g_profiler->avg("CM: blocks occlusion culled", blocks_occlusion_culled); if(blocks_in_range != 0) g_profiler->avg("CM: blocks in range without mesh (frac)", (float)blocks_in_range_without_mesh/blocks_in_range); g_profiler->avg("CM: blocks drawn", blocks_drawn); g_profiler->avg("CM: farthest drawn", farthest_drawn); g_profiler->avg("CM: wanted max blocks", m_control.wanted_max_blocks); }
void main_loop(void *data) { MainLoopData* loopData = (MainLoopData*)data; timer_step(); lua_rawgeti(loopData->luaState, LUA_REGISTRYINDEX, loopData->errhand); lua_getglobal(loopData->luaState, "love"); lua_pushstring(loopData->luaState, "update"); lua_rawget(loopData->luaState, -2); lua_pushnumber(loopData->luaState, timer_getDelta()); if (swap_At == 1){ if(luaL_dofile(loopData->luaState, "main.lua")) { printf("Error: %s\n", lua_tostring(loopData->luaState, -1)); } } if(lua_pcall(loopData->luaState, 1, 0, 0)) { printf("Lua error: %s\n", lua_tostring(loopData->luaState, -1)); #ifdef EMSCRIPTEN quit_function(loopData->luaState); emscripten_force_exit(1); #else exit(1); #endif } graphics_clear(); lua_pushstring(loopData->luaState, "draw"); lua_rawget(loopData->luaState, -2); if(lua_pcall(loopData->luaState, 0, 0, 0)) { printf("Lua error: %s\n", lua_tostring(loopData->luaState, -1)); #ifdef EMSCRIPTEN quit_function(loopData->luaState); emscripten_force_exit(1); l_running = 0; #else l_running = 0; #endif } graphics_swap(); // silly hack for love.event.quit() #ifdef WINDOWS event_force_quit = graphics_stop_windows(); if(!event_force_quit) l_running = 0; #endif //This will affect only Windows users // lua_pop(loopData->luaState, 1); #ifdef UNIX SDL_Event event; while(SDL_PollEvent(&event)) { if (event.type == SDL_WINDOWEVENT) { switch (event.window.event) { case SDL_WINDOWEVENT_ENTER: graphics_setMouseFocus(1); break; case SDL_WINDOWEVENT_LEAVE: graphics_setMouseFocus(0); break; case SDL_WINDOWEVENT_FOCUS_LOST: graphics_setFocus(0); break; case SDL_WINDOWEVENT_FOCUS_GAINED: graphics_setFocus(1); break; default: break; } } switch(event.wheel.type) { case SDL_MOUSEWHEEL: mouse_mousewheel(event.wheel.y); int _what = event.wheel.y == 1 ? SDL_BUTTON_WHEEL_UP : SDL_BUTTON_WHEEL_DOWN; mouse_mousepressed(event.button.x, event.button.y, _what); break; default: break; } switch(event.type) { case SDL_KEYDOWN: keyboard_keypressed(event.key.keysym.sym); break; case SDL_KEYUP: keyboard_keyreleased(event.key.keysym.sym); break; case SDL_TEXTINPUT: keyboard_textInput(event.text.text); break; case SDL_MOUSEMOTION: mouse_mousemoved(event.motion.x, event.motion.y); break; case SDL_MOUSEBUTTONDOWN: mouse_mousepressed(event.button.x, event.button.y, event.button.button); break; case SDL_MOUSEBUTTONUP: mouse_mousereleased(event.button.x, event.button.y, event.button.button); break; #ifndef EMSCRIPTEN case SDL_QUIT: quit_function(loopData->luaState); l_running = 0; #endif } } #endif }