diff options
Diffstat (limited to 'src/game.cpp')
-rw-r--r-- | src/game.cpp | 308 |
1 files changed, 227 insertions, 81 deletions
diff --git a/src/game.cpp b/src/game.cpp index 189003e4c..f63a4a400 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -395,11 +395,14 @@ PointedThing getPointedThing(Client *client, v3f player_position, /* Draws a screen with a single text on it. Text will be removed when the screen is drawn the next time. + Additionally, a progressbar can be drawn when percent is set between 0 and 100. */ /*gui::IGUIStaticText **/ void draw_load_screen(const std::wstring &text, - video::IVideoDriver* driver, gui::IGUIFont* font) + IrrlichtDevice* device, gui::IGUIFont* font, + float dtime=0 ,int percent=0, bool clouds=true) { + video::IVideoDriver* driver = device->getVideoDriver(); v2u32 screensize = driver->getScreenSize(); const wchar_t *loadingtext = text.c_str(); core::vector2d<u32> textsize_u = font->getDimension(loadingtext); @@ -411,7 +414,30 @@ void draw_load_screen(const std::wstring &text, loadingtext, textrect, false, false); guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); - driver->beginScene(true, true, video::SColor(255,0,0,0)); + bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds"); + if (cloud_menu_background) + { + g_menuclouds->step(dtime*3); + g_menuclouds->render(); + driver->beginScene(true, true, video::SColor(255,140,186,250)); + g_menucloudsmgr->drawAll(); + } + else + driver->beginScene(true, true, video::SColor(255,0,0,0)); + if (percent >= 0 && percent <= 100) // draw progress bar + { + core::vector2d<s32> barsize(256,32); + core::rect<s32> barrect(center-barsize/2, center+barsize/2); + driver->draw2DRectangle(video::SColor(255,255,255,255),barrect, NULL); // border + driver->draw2DRectangle(video::SColor(255,64,64,64), core::rect<s32> ( + barrect.UpperLeftCorner+1, + barrect.LowerRightCorner-1), NULL); // black inside the bar + driver->draw2DRectangle(video::SColor(255,128,128,128), core::rect<s32> ( + barrect.UpperLeftCorner+1, + core::vector2d<s32>( + barrect.LowerRightCorner.X-(barsize.X-1)+percent*(barsize.X-2)/100, + barrect.LowerRightCorner.Y-1)), NULL); // the actual progress + } guienv->drawAll(); driver->endScene(); @@ -789,6 +815,67 @@ public: } }; +void nodePlacementPrediction(Client &client, + const ItemDefinition &playeritem_def, + v3s16 nodepos, v3s16 neighbourpos) +{ + std::string prediction = playeritem_def.node_placement_prediction; + INodeDefManager *nodedef = client.ndef(); + ClientMap &map = client.getEnv().getClientMap(); + + if(prediction != "" && !nodedef->get(map.getNode(nodepos)).rightclickable) + { + verbosestream<<"Node placement prediction for " + <<playeritem_def.name<<" is " + <<prediction<<std::endl; + v3s16 p = neighbourpos; + // Place inside node itself if buildable_to + try{ + MapNode n_under = map.getNode(nodepos); + if(nodedef->get(n_under).buildable_to) + p = nodepos; + else if (!nodedef->get(map.getNode(p)).buildable_to) + return; + }catch(InvalidPositionException &e){} + // Find id of predicted node + content_t id; + bool found = nodedef->getId(prediction, id); + if(!found){ + errorstream<<"Node placement prediction failed for " + <<playeritem_def.name<<" (places " + <<prediction + <<") - Name not known"<<std::endl; + return; + } + // Predict param2 + u8 param2 = 0; + if(nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED){ + v3s16 dir = nodepos - neighbourpos; + if(abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))){ + param2 = dir.Y < 0 ? 1 : 0; + } else if(abs(dir.X) > abs(dir.Z)){ + param2 = dir.X < 0 ? 3 : 2; + } else { + param2 = dir.Z < 0 ? 5 : 4; + } + } + // TODO: Facedir prediction + // TODO: If predicted node is in attached_node group, check attachment + // Add node to client map + MapNode n(id, 0, param2); + try{ + // This triggers the required mesh update too + client.addNode(p, n); + }catch(InvalidPositionException &e){ + errorstream<<"Node placement prediction failed for " + <<playeritem_def.name<<" (places " + <<prediction + <<") - Position not loaded"<<std::endl; + } + } +} + + void the_game( bool &kill, bool random_input, @@ -821,7 +908,11 @@ void the_game( Draw "Loading" screen */ - draw_load_screen(L"Loading...", driver, font); + { + wchar_t* text = wgettext("Loading..."); + draw_load_screen(text, device, font,0,0); + delete[] text; + } // Create texture source IWritableTextureSource *tsrc = createTextureSource(device); @@ -878,7 +969,9 @@ void the_game( */ if(address == ""){ - draw_load_screen(L"Creating server...", driver, font); + wchar_t* text = wgettext("Creating server...."); + draw_load_screen(text, device, font,0,25); + delete[] text; infostream<<"Creating server"<<std::endl; server = new Server(map_dir, configpath, gamespec, simple_singleplayer_mode); @@ -891,7 +984,11 @@ void the_game( Create client */ - draw_load_screen(L"Creating client...", driver, font); + { + wchar_t* text = wgettext("Creating client..."); + draw_load_screen(text, device, font,0,50); + delete[] text; + } infostream<<"Creating client"<<std::endl; MapDrawControl draw_control; @@ -901,8 +998,12 @@ void the_game( // Client acts as our GameDef IGameDef *gamedef = &client; - - draw_load_screen(L"Resolving address...", driver, font); + + { + wchar_t* text = wgettext("Resolving address..."); + draw_load_screen(text, device, font,0,75); + delete[] text; + } Address connect_address(0,0,0,0, port); try{ if(address == "") @@ -934,15 +1035,26 @@ void the_game( bool could_connect = false; bool connect_aborted = false; try{ - float frametime = 0.033; float time_counter = 0.0; input->clear(); + float fps_max = g_settings->getFloat("fps_max"); + bool cloud_menu_background = g_settings->getBool("menu_clouds"); + u32 lasttime = device->getTimer()->getTime(); while(device->run()) { + f32 dtime=0; // in seconds + if (cloud_menu_background) { + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + dtime = (time - lasttime) / 1000.0; + else + dtime = 0; + lasttime = time; + } // Update client and server - client.step(frametime); + client.step(dtime); if(server != NULL) - server->step(frametime); + server->step(dtime); // End condition if(client.connectedAndInitialized()){ @@ -963,15 +1075,37 @@ void the_game( } // Display status - std::wostringstream ss; - ss<<L"Connecting to server... (press Escape to cancel)\n"; - std::wstring animation = L"/-\\|"; - ss<<animation[(int)(time_counter/0.2)%4]; - draw_load_screen(ss.str(), driver, font); + { + wchar_t* text = wgettext("Connecting to server..."); + draw_load_screen(text, device, font, dtime, 100); + delete[] text; + } - // Delay a bit - sleep_ms(1000*frametime); - time_counter += frametime; + // On some computers framerate doesn't seem to be + // automatically limited + if (cloud_menu_background) { + // Time of frame without fps limit + float busytime; + u32 busytime_u32; + // not using getRealTime is necessary for wine + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + busytime_u32 = time - lasttime; + else + busytime_u32 = 0; + busytime = busytime_u32 / 1000.0; + + // FPS limiter + u32 frametime_min = 1000./fps_max; + + if(busytime_u32 < frametime_min) { + u32 sleeptime = frametime_min - busytime_u32; + device->sleep(sleeptime); + } + } else { + sleep_ms(25); + } + time_counter += dtime; } } catch(con::PeerNotFoundException &e) @@ -995,15 +1129,26 @@ void the_game( bool got_content = false; bool content_aborted = false; { - float frametime = 0.033; float time_counter = 0.0; input->clear(); + float fps_max = g_settings->getFloat("fps_max"); + bool cloud_menu_background = g_settings->getBool("menu_clouds"); + u32 lasttime = device->getTimer()->getTime(); while(device->run()) { + f32 dtime=0; // in seconds + if (cloud_menu_background) { + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + dtime = (time - lasttime) / 1000.0; + else + dtime = 0; + lasttime = time; + } // Update client and server - client.step(frametime); + client.step(dtime); if(server != NULL) - server->step(frametime); + server->step(dtime); // End condition if(client.texturesReceived() && @@ -1025,21 +1170,52 @@ void the_game( } // Display status - std::wostringstream ss; - ss<<L"Waiting content... (press Escape to cancel)\n"; + std::ostringstream ss; + int progress=0; + if (!client.itemdefReceived()) + { + ss << "Item definitions..."; + progress = 0; + } + else if (!client.nodedefReceived()) + { + ss << "Node definitions..."; + progress = 25; + } + else + { + ss << "Media..."; + progress = 50+client.mediaReceiveProgress()*50+0.5; + } + wchar_t* text = wgettext(ss.str().c_str()); + draw_load_screen(text, device, font, dtime, progress); + delete[] text; + + // On some computers framerate doesn't seem to be + // automatically limited + if (cloud_menu_background) { + // Time of frame without fps limit + float busytime; + u32 busytime_u32; + // not using getRealTime is necessary for wine + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + busytime_u32 = time - lasttime; + else + busytime_u32 = 0; + busytime = busytime_u32 / 1000.0; - ss<<(client.itemdefReceived()?L"[X]":L"[ ]"); - ss<<L" Item definitions\n"; - ss<<(client.nodedefReceived()?L"[X]":L"[ ]"); - ss<<L" Node definitions\n"; - ss<<L"["<<(int)(client.mediaReceiveProgress()*100+0.5)<<L"%] "; - ss<<L" Media\n"; + // FPS limiter + u32 frametime_min = 1000./fps_max; - draw_load_screen(ss.str(), driver, font); - - // Delay a bit - sleep_ms(1000*frametime); - time_counter += frametime; + if(busytime_u32 < frametime_min) { + u32 sleeptime = frametime_min - busytime_u32; + device->sleep(sleeptime); + } + } else { + sleep_ms(25); + } + time_counter += dtime; } } @@ -1056,7 +1232,7 @@ void the_game( After all content has been received: Update cached textures, meshes and materials */ - client.afterContentReceived(); + client.afterContentReceived(device,font); /* Create the camera node @@ -1885,7 +2061,8 @@ void the_game( if(input->isKeyDown(irr::KEY_RIGHT)) dx += dtime * keyspeed;*/ - float d = 0.2; + float d = g_settings->getFloat("mouse_sensitivity"); + d = rangelim(d, 0.01, 100.0); camera_yaw -= dx*d; camera_pitch += dy*d; if(camera_pitch < -89.5) camera_pitch = -89.5; @@ -2198,17 +2375,15 @@ void the_game( - Can it point to liquids? */ ItemStack playeritem; - bool playeritem_usable = false; - bool playeritem_liquids_pointable = false; { InventoryList *mlist = local_inventory.getList("main"); if(mlist != NULL) { playeritem = mlist->getItem(client.getPlayerItem()); - playeritem_usable = playeritem.getDefinition(itemdef).usable; - playeritem_liquids_pointable = playeritem.getDefinition(itemdef).liquids_pointable; } } + const ItemDefinition &playeritem_def = + playeritem.getDefinition(itemdef); ToolCapabilities playeritem_toolcap = playeritem.getToolCapabilities(itemdef); @@ -2267,7 +2442,7 @@ void the_game( // input &client, player_position, camera_direction, camera_position, shootline, d, - playeritem_liquids_pointable, !ldown_for_dig, + playeritem_def.liquids_pointable, !ldown_for_dig, // output hilightboxes, selected_object); @@ -2327,7 +2502,7 @@ void the_game( else repeat_rightclick_timer = 0; - if(playeritem_usable && input->getLeftState()) + if(playeritem_def.usable && input->getLeftState()) { if(input->getLeftClicked()) client.interact(4, pointed); @@ -2534,46 +2709,13 @@ void the_game( // If the wielded item has node placement prediction, // make that happen - const ItemDefinition &def = - playeritem.getDefinition(itemdef); - if(def.node_placement_prediction != "" - && !nodedef->get(map.getNode(nodepos)).rightclickable) - do{ // breakable - verbosestream<<"Node placement prediction for " - <<playeritem.name<<" is " - <<def.node_placement_prediction<<std::endl; - v3s16 p = neighbourpos; - // Place inside node itself if buildable_to - try{ - MapNode n_under = map.getNode(nodepos); - if(nodedef->get(n_under).buildable_to) - p = nodepos; - }catch(InvalidPositionException &e){} - // Find id of predicted node - content_t id; - bool found = - nodedef->getId(def.node_placement_prediction, id); - if(!found){ - errorstream<<"Node placement prediction failed for " - <<playeritem.name<<" (places " - <<def.node_placement_prediction - <<") - Name not known"<<std::endl; - break; - } - MapNode n(id); - try{ - // This triggers the required mesh update too - client.addNode(p, n); - }catch(InvalidPositionException &e){ - errorstream<<"Node placement prediction failed for " - <<playeritem.name<<" (places " - <<def.node_placement_prediction - <<") - Position not loaded"<<std::endl; - } - }while(0); + nodePlacementPrediction(client, + playeritem_def, + nodepos, neighbourpos); // Read the sound - soundmaker.m_player_rightpunch_sound = def.sound_place; + soundmaker.m_player_rightpunch_sound = + playeritem_def.sound_place; } } } @@ -3193,6 +3335,8 @@ void the_game( clouds->drop(); if (gui_chat_console) gui_chat_console->drop(); + if (sky) + sky->drop(); clear_particles(); /* @@ -3201,7 +3345,9 @@ void the_game( */ { /*gui::IGUIStaticText *gui_shuttingdowntext = */ - draw_load_screen(L"Shutting down stuff...", driver, font); + wchar_t* text = wgettext("Shutting down stuff..."); + draw_load_screen(text, device, font, 0, -1, false); + delete[] text; /*driver->beginScene(true, true, video::SColor(255,0,0,0)); guienv->drawAll(); driver->endScene(); |