aboutsummaryrefslogtreecommitdiff
path: root/src/game.cpp
diff options
context:
space:
mode:
authorWeblate <42@minetest.ru>2013-05-13 18:19:51 +0200
committerWeblate <42@minetest.ru>2013-05-13 18:19:51 +0200
commite0564d5de01dd26f7b4f4d188415f5cf5a47b5d0 (patch)
tree79a5a18634069822b84b9c878d8d26742567c4a3 /src/game.cpp
parentbe96fa2fb884fca571b92f63d33e0c5a592a2aad (diff)
parent822723c2468ea763cdef447218059a5586e8e033 (diff)
downloadminetest-e0564d5de01dd26f7b4f4d188415f5cf5a47b5d0.tar.gz
minetest-e0564d5de01dd26f7b4f4d188415f5cf5a47b5d0.tar.bz2
minetest-e0564d5de01dd26f7b4f4d188415f5cf5a47b5d0.zip
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src/game.cpp')
-rw-r--r--src/game.cpp308
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();