From b36b5910f46200fccb094c78796764c6b4e8e728 Mon Sep 17 00:00:00 2001 From: sapier Date: Wed, 5 Mar 2014 23:30:38 +0100 Subject: [PATCH] Add support for thread names (linux only) Fix some unsafe array access operations Add support for doubleclick exit of formspecs (usefull primary for touchscreen environments) Use iterators to access vectors to avoid compiler to generate temporarys Remove a lot of temporarys in guiformspecmenu Minor fixes Lots of whitespace fixes Code cleanup --- src/client.cpp | 143 ++++++++++++----------- src/client.h | 3 +- src/connection.cpp | 22 ++-- src/content_cao.cpp | 2 +- src/emerge.cpp | 3 +- src/game.cpp | 205 +++++++++++++++++---------------- src/guiEngine.cpp | 5 +- src/guiFormSpecMenu.cpp | 245 +++++++++++++++++++++++++--------------- src/guiFormSpecMenu.h | 19 +++- src/httpfetch.cpp | 3 +- src/localplayer.cpp | 31 ++--- src/main.cpp | 7 +- src/porting.cpp | 44 ++++---- src/porting.h | 46 +++++--- src/server.cpp | 2 + src/settings.h | 3 +- src/tile.cpp | 17 ++- 17 files changed, 456 insertions(+), 344 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 654052ac0a40..aa849e1a0da6 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -71,7 +71,7 @@ QueuedMeshUpdate::~QueuedMeshUpdate() /* MeshUpdateQueue */ - + MeshUpdateQueue::MeshUpdateQueue() { } @@ -122,7 +122,7 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se return; } } - + /* Add the block */ @@ -165,9 +165,11 @@ void * MeshUpdateThread::Thread() log_register_thread("MeshUpdateThread"); DSTACK(__FUNCTION_NAME); - + BEGIN_DEBUG_EXCEPTION_HANDLER + porting::setThreadName("MeshUpdateThread"); + while(!StopRequested()) { QueuedMeshUpdate *q = m_queue_in.pop(); @@ -329,26 +331,26 @@ bool Client::connectedAndInitialized() { if(m_con.Connected() == false) return false; - + if(m_server_ser_ver == SER_FMT_VER_INVALID) return false; - + return true; } void Client::step(float dtime) { DSTACK(__FUNCTION_NAME); - + // 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; @@ -366,13 +368,13 @@ void Client::step(float dtime) if(counter <= 0.0) { counter = 20.0; - + infostream<<"Client packetcounter (20s):"<getFloat("client_delete_unused_sectors_timeout"); - + // Delete sector blocks /*u32 num = m_env.getMap().unloadUnusedData (delete_unused_sectors_timeout, true, &deleted_blocks);*/ - + // Delete whole sectors m_env.getMap().unloadUnusedData (delete_unused_sectors_timeout, @@ -416,14 +418,14 @@ void Client::step(float dtime) <<" unused sectors"<::Iterator i = deleted_blocks.begin(); core::list sendlist; for(;;) @@ -476,10 +478,10 @@ void Client::step(float dtime) counter = 2.0; //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - + Player *myplayer = m_env.getLocalPlayer(); assert(myplayer != NULL); - + // Send TOSERVER_INIT // [0] u16 TOSERVER_INIT // [2] u8 SER_FMT_VER_HIGHEST_READ @@ -499,7 +501,7 @@ void Client::step(float dtime) memset((char*)&data[23], 0, PASSWORD_SIZE); snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str()); - + writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN); writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX); @@ -514,7 +516,7 @@ void Client::step(float dtime) /* Do stuff if connected */ - + /* Run Map's timers and unload unused data */ @@ -526,11 +528,11 @@ void Client::step(float dtime) m_env.getMap().timerUpdate(map_timer_and_unload_dtime, g_settings->getFloat("client_unload_unused_data_timeout"), &deleted_blocks); - + /*if(deleted_blocks.size() > 0) infostream<<"Client: Unloaded "<updateSoundPosition(client_id, pos); } } - + /* Handle removed remotely initiated sounds */ @@ -800,7 +802,7 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) { // Silly irrlicht's const-incorrectness Buffer data_rw(data.c_str(), data.size()); - + std::string name; const char *image_ext[] = { @@ -938,7 +940,7 @@ void Client::ReceiveAll() // process if(porting::getTimeMs() > start_ms + 100) break; - + try{ Receive(); g_profiler->graphAdd("client_received_packets", 1); @@ -983,7 +985,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) //infostream<<"Client: received command="< reply(replysize); @@ -1094,6 +1096,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) p.X = readS16(&data[2]); p.Y = readS16(&data[4]); p.Z = readS16(&data[6]); + removeNode(p); } else if(command == TOCLIENT_ADDNODE) @@ -1108,13 +1111,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) MapNode n; n.deSerialize(&data[8], ser_version); - + bool remove_metadata = true; u32 index = 8 + MapNode::serializedLength(ser_version); if ((datasize >= index+1) && data[index]){ remove_metadata = false; } - + addNode(p, n, remove_metadata); } else if(command == TOCLIENT_BLOCKDATA) @@ -1122,23 +1125,23 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) // Ignore too small packet if(datasize < 8) return; - + v3s16 p; p.X = readS16(&data[2]); p.Y = readS16(&data[4]); p.Z = readS16(&data[6]); - + std::string datastring((char*)&data[8], datasize-8); std::istringstream istr(datastring, std::ios_base::binary); - + MapSector *sector; MapBlock *block; - + v2s16 p2d(p.X, p.Z); sector = m_env.getMap().emergeSector(p2d); - + assert(sector->getPos() == p2d); - + block = sector->getBlockNoCreateNoEx(p.Y); if(block) { @@ -1169,6 +1172,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) if(datasize < 3) return; + std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); @@ -1188,6 +1192,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) u16 time_of_day = readU16(&data[2]); time_of_day = time_of_day % 24000; + float time_speed = 0; if(datasize >= 2 + 2 + 4) @@ -1215,14 +1220,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) <<" time_diff="<hud_flags &= ~mask; player->hud_flags |= flags; } @@ -1998,7 +2003,7 @@ void Client::sendNodemetaFields(v3s16 p, const std::string &formname, // Send as reliable Send(0, data, true); } - + void Client::sendInventoryFields(const std::string &formname, const std::map &fields) { @@ -2028,13 +2033,13 @@ void Client::sendInventoryAction(InventoryAction *a) { std::ostringstream os(std::ios_base::binary); u8 buf[12]; - + // Write command writeU16(buf, TOSERVER_INVENTORY_ACTION); os.write((char*)buf, 2); a->serialize(os); - + // Make data buffer std::string s = os.str(); SharedBuffer data((u8*)s.c_str(), s.size()); @@ -2046,17 +2051,17 @@ void Client::sendChatMessage(const std::wstring &message) { std::ostringstream os(std::ios_base::binary); u8 buf[12]; - + // Write command writeU16(buf, TOSERVER_CHAT_MESSAGE); os.write((char*)buf, 2); - + // Write length size_t messagesize = message.size(); assert(messagesize <= 0xFFFF); writeU16(buf, (u16) (messagesize & 0xFF)); os.write((char*)buf, 2); - + // Write string for(unsigned int i=0; i data((u8*)s.c_str(), s.size()); @@ -2177,7 +2182,7 @@ void Client::sendPlayerPos() //JMutexAutoLock lock(m_con_mutex); //bulk comment-out our_peer_id = m_con.GetPeerID(); } - + // Set peer id if not set already if(myplayer->peer_id == PEER_ID_INEXISTENT) myplayer->peer_id = our_peer_id; @@ -2245,7 +2250,7 @@ void Client::removeNode(v3s16 p) catch(InvalidPositionException &e) { } - + // add urgent task to update the modified node addUpdateMeshTaskForNode(p, false, true); @@ -2270,7 +2275,7 @@ void Client::addNode(v3s16 p, MapNode n, bool remove_metadata) } catch(InvalidPositionException &e) {} - + for(std::map::iterator i = modified_blocks.begin(); i != modified_blocks.end(); ++i) @@ -2278,7 +2283,7 @@ void Client::addNode(v3s16 p, MapNode n, bool remove_metadata) addUpdateMeshTaskWithEdge(i->first); } } - + void Client::setPlayerControl(PlayerControl &control) { LocalPlayer *player = m_env.getLocalPlayer(); @@ -2377,7 +2382,7 @@ ClientActiveObject * Client::getSelectedActiveObject( std::vector objects; m_env.getActiveObjects(from_pos_f_on_map, max_d, objects); - + // Sort them. // After this, the closest object is the first in the array. std::sort(objects.begin(), objects.end()); @@ -2385,7 +2390,7 @@ ClientActiveObject * Client::getSelectedActiveObject( for(unsigned int i=0; i *selection_box = obj->getSelectionBox(); if(selection_box == NULL) continue; @@ -2493,13 +2498,13 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent) MapBlock *b = m_env.getMap().getBlockNoCreateNoEx(p); if(b == NULL) return; - + /* Create a task to update the mesh of the block */ - + MeshMakeData *data = new MeshMakeData(this); - + { //TimeTaker timer("data fill"); // Release: ~0ms @@ -2606,7 +2611,7 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font) assert(m_itemdef_received); assert(m_nodedef_received); assert(mediaReceived()); - + // Rebuild inherited images and recreate textures infostream<<"- Rebuilding images and textures"<rebuildImagesAndTextures(); @@ -2649,7 +2654,7 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font) // Start mesh update thread after setting up content definitions infostream<<"- Starting mesh update thread"< makeOriginalPacket( u32 packet_size = data.getSize() + header_size; SharedBuffer b(packet_size); - writeU8(&b[0], TYPE_ORIGINAL); - - memcpy(&b[header_size], *data, data.getSize()); - + writeU8(&(b[0]), TYPE_ORIGINAL); + if (data.getSize() > 0) { + memcpy(&(b[header_size]), *data, data.getSize()); + } return b; } @@ -1227,6 +1227,8 @@ void * ConnectionSendThread::Thread() PROFILE(std::stringstream ThreadIdentifier); PROFILE(ThreadIdentifier << "ConnectionSend: [" << m_connection->getDesc() << "]"); + porting::setThreadName("ConnectionSend"); + /* if stop is requested don't stop immediately but try to send all */ /* packets first */ while(!StopRequested() || packetsQueued()) { @@ -1955,6 +1957,8 @@ void * ConnectionReceiveThread::Thread() PROFILE(std::stringstream ThreadIdentifier); PROFILE(ThreadIdentifier << "ConnectionReceive: [" << m_connection->getDesc() << "]"); + porting::setThreadName("ConnectionReceive"); + #ifdef DEBUG_CONNECTION_KBPS u32 curtime = porting::getTimeMs(); u32 lasttime = curtime; @@ -2263,14 +2267,14 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, if(packetdata.getSize() < 1) throw InvalidIncomingDataException("packetdata.getSize() < 1"); - u8 type = readU8(&packetdata[0]); + u8 type = readU8(&(packetdata[0])); if(type == TYPE_CONTROL) { if(packetdata.getSize() < 2) throw InvalidIncomingDataException("packetdata.getSize() < 2"); - u8 controltype = readU8(&packetdata[1]); + u8 controltype = readU8(&(packetdata[1])); if( (controltype == CONTROLTYPE_ACK) && (peer_id <= MAX_UDP_PEERS)) @@ -2395,15 +2399,15 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, } else if(type == TYPE_ORIGINAL) { - if(packetdata.getSize() < ORIGINAL_HEADER_SIZE) + if(packetdata.getSize() <= ORIGINAL_HEADER_SIZE) throw InvalidIncomingDataException - ("packetdata.getSize() < ORIGINAL_HEADER_SIZE"); + ("packetdata.getSize() <= ORIGINAL_HEADER_SIZE"); LOG(dout_con<getDesc() <<"RETURNING TYPE_ORIGINAL to user" < payload(packetdata.getSize() - ORIGINAL_HEADER_SIZE); - memcpy(*payload, &packetdata[ORIGINAL_HEADER_SIZE], payload.getSize()); + memcpy(*payload, &(packetdata[ORIGINAL_HEADER_SIZE]), payload.getSize()); return payload; } else if(type == TYPE_SPLIT) diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 84ec3e143070..b70f8157fc3f 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1075,7 +1075,7 @@ class GenericCAO : public ClientActiveObject m_spritenode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS)); } } - + void step(float dtime, ClientEnvironment *env) { if(m_visuals_expired && m_smgr && m_irr){ diff --git a/src/emerge.cpp b/src/emerge.cpp index 0e805c95a3c9..8223692c9d7b 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -456,7 +456,6 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, return false; } - void *EmergeThread::Thread() { ThreadStarted(); log_register_thread("EmergeThread" + itos(id)); @@ -472,6 +471,8 @@ void *EmergeThread::Thread() { mapgen = emerge->mapgen[id]; enable_mapgen_debug_info = emerge->mapgen_debug_info; + porting::setThreadName("EmergeThread"); + while (!StopRequested()) try { if (!popBlockEmerge(&p, &flags)) { diff --git a/src/game.cpp b/src/game.cpp index 2b14b2c8e39f..8d691477c92c 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -313,7 +313,7 @@ PointedThing getPointedThing(Client *client, v3f player_position, // That didn't work, try to find a pointed at node - + v3s16 pos_i = floatToInt(player_position, BS); /*infostream<<"pos_i=("<0 ? a : 1); s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1); s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1); - + // Prevent signed number overflow if(yend==32767) yend=32766; @@ -461,9 +461,9 @@ void draw_load_screen(const std::wstring &text, IrrlichtDevice* device, } guienv->drawAll(); driver->endScene(); - + guitext->remove(); - + //return guitext; } @@ -530,7 +530,7 @@ class ProfilerGraph while(m_log.size() > m_log_max_size) m_log.erase(m_log.begin()); } - + void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver, gui::IGUIFont* font) const { @@ -579,7 +579,7 @@ class ProfilerGraph s32 graphh = 50; s32 textx = x_left + m_log_max_size + 15; s32 textx2 = textx + 200 - 15; - + // Draw background /*{ u32 num_graphs = m_meta.size(); @@ -588,7 +588,7 @@ class ProfilerGraph video::SColor bgcolor(120,0,0,0); driver->draw2DRectangle(bgcolor, rect, NULL); }*/ - + s32 meta_i = 0; for(std::map::const_iterator i = m_meta.begin(); i != m_meta.end(); i++){ @@ -674,7 +674,7 @@ class NodeDugEvent: public MtEvent public: v3s16 p; MapNode n; - + NodeDugEvent(v3s16 p, MapNode n): p(p), n(n) @@ -847,7 +847,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); float daynight_ratio_f = (float)daynight_ratio / 1000.0; services->setPixelShaderConstant("dayNightRatio", &daynight_ratio_f, 1); - + u32 animation_timer = porting::getTimeMs() % 100000; float animation_timer_f = (float)animation_timer / 100000.0; services->setPixelShaderConstant("animationTimer", &animation_timer_f, 1); @@ -1054,13 +1054,13 @@ void the_game(bool &kill, bool random_input, InputHandler *input, TextDest* current_textdest = 0; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); - + // Calculate text height using the font u32 text_height = font->getDimension(L"Random test string").Height; v2u32 last_screensize(0,0); v2u32 screensize = driver->getScreenSize(); - + /* Draw "Loading" screen */ @@ -1070,19 +1070,19 @@ void the_game(bool &kill, bool random_input, InputHandler *input, draw_load_screen(text, device, font,0,0); delete[] text; } - + // Create texture source IWritableTextureSource *tsrc = createTextureSource(device); - + // Create shader source IWritableShaderSource *shsrc = createShaderSource(device); - + // These will be filled by data received from the server // Create item definition manager IWritableItemDefManager *itemdef = createItemDefManager(); // Create node definition manager IWritableNodeDefManager *nodedef = createNodeDefManager(); - + // Sound fetcher (useful when testing) GameOnDemandSoundFetcher soundfetcher; @@ -1114,7 +1114,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, // Sound maker SoundMaker soundmaker(sound, nodedef); soundmaker.registerReceiver(&eventmgr); - + // Add chat log output for errors to be shown in chat LogOutputBuffer chat_log_error_buf(LMT_ERROR); @@ -1156,7 +1156,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } do{ // Client scope (breakable do-while(0)) - + /* Create client */ @@ -1167,9 +1167,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete[] text; } infostream<<"Creating client"<step(dtime); - + // End condition if(client.connectedAndInitialized()){ could_connect = true; @@ -1265,14 +1265,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, infostream<<"Connect aborted [Escape]"<step(dtime); - + // End condition if(client.mediaReceived() && client.itemdefReceived() && @@ -1366,7 +1366,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, infostream<<"Connect aborted [Escape]"<getBool("enable_clouds")) { @@ -1462,7 +1462,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, sky = new Sky(smgr->getRootSceneNode(), smgr, -1, client.getEnv().getLocalPlayer()); scene::ISceneNode* skybox = NULL; - + /* A copy of the local inventory */ @@ -1498,17 +1498,17 @@ void the_game(bool &kill, bool random_input, InputHandler *input, L"", core::rect(0,0,400,text_height*5+5) + v2s32(100,200), false, true); - + // Status text (displays info when showing and hiding GUI stuff, etc.) gui::IGUIStaticText *guitext_status = guienv->addStaticText( L"", core::rect(0,0,0,0), false, false); guitext_status->setVisible(false); - + std::wstring statustext; float statustext_time = 0; - + // Chat text gui::IGUIStaticText *guitext_chat = guienv->addStaticText( L"", @@ -1519,7 +1519,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, chat_backend.clearRecentChat(); // Chat backend and console GUIChatConsole *gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), -1, &chat_backend, &client); - + // Profiler text (size is updated when text is updated) gui::IGUIStaticText *guitext_profiler = guienv->addStaticText( L"", @@ -1528,7 +1528,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, guitext_profiler->setBackgroundColor(video::SColor(120,0,0,0)); guitext_profiler->setVisible(false); guitext_profiler->setWordWrap(true); - + /* Some statistics are collected in these */ @@ -1536,9 +1536,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input, u32 beginscenetime = 0; u32 scenetime = 0; u32 endscenetime = 0; - + float recent_turn_speed = 0.0; - + ProfilerGraph graph; // Initially clear the profiler Profiler::GraphValues dummyvalues; @@ -1607,7 +1607,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, LocalPlayer* player = client.getEnv().getLocalPlayer(); player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; - + /* HUD object */ @@ -1641,7 +1641,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, busytime_u32 = 0; busytime = busytime_u32 / 1000.0; } - + g_profiler->graphAdd("mainloop_other", busytime - (float)drawtime/1000.0f); // Necessary for device->getTimer()->getTime() @@ -1656,7 +1656,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, g_settings->getFloat("pause_fps_max") : g_settings->getFloat("fps_max"); u32 frametime_min = 1000./fps_max; - + if(busytime_u32 < frametime_min) { u32 sleeptime = frametime_min - busytime_u32; @@ -1672,7 +1672,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, Time difference calculation */ f32 dtime; // in seconds - + u32 time = device->getTimer()->getTime(); if(time > lasttime) dtime = (time - lasttime) / 1000.0; @@ -1689,7 +1689,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, if(object_hit_delay_timer >= 0) object_hit_delay_timer -= dtime; time_from_last_punch += dtime; - + g_profiler->add("Elapsed time", dtime); g_profiler->avg("FPS", 1./dtime); @@ -1718,7 +1718,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, jitter1_max = 0.0; } } - + /* Busytime average and jitter calculation */ @@ -1726,7 +1726,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, static f32 busytime_avg1 = 0.0; busytime_avg1 = busytime_avg1 * 0.98 + busytime * 0.02; f32 busytime_jitter1 = busytime - busytime_avg1; - + static f32 busytime_jitter1_max_sample = 0.0; static f32 busytime_jitter1_min_sample = 0.0; { @@ -1750,7 +1750,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Handle miscellaneous stuff */ - + if(client.accessDenied()) { error_message = L"Access denied. Reason: " @@ -1798,12 +1798,12 @@ void the_game(bool &kill, bool random_input, InputHandler *input, v2s32 displaycenter(screensize.X/2,screensize.Y/2); //bool screensize_changed = screensize != last_screensize; - + // Update HUD values hud.screensize = screensize; hud.displaycenter = displaycenter; hud.resizeHotbar(); - + // Hilight boxes collected during the loop and displayed std::vector hilightboxes; @@ -1835,7 +1835,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Direct handling of user input */ - + // Reset input if window not active or some menu is active if(device->isWindowActive() == false || noMenuActive() == false @@ -1872,7 +1872,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { infostream<<"the_game: " <<"Launching inventory"<isKeyDown(getKeySetting("keymap_jump")) && reset_jump_timer) { @@ -2156,7 +2156,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, new_playeritem = max_item; } } - + // Item selection for(u16 i=0; i<10; i++) { @@ -2206,7 +2206,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, Mouse and camera control NOTE: Do this before client.setPlayerControl() to not cause a camera lag of one frame */ - + float turn_amount = 0; if((device->isWindowActive() && noMenuActive()) || random_input) { @@ -2374,7 +2374,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, new GUIDeathScreen(guienv, guiroot, -1, &g_menumgr, respawner); menu->drop(); - + chat_backend.addMessage(L"", L"You died."); /* Handle visualization */ @@ -2477,7 +2477,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudadd.world_pos; continue; } - + HudElement *e = new HudElement; e->type = (HudElementType)event.hudadd.type; e->pos = *event.hudadd.pos; @@ -2490,7 +2490,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, e->align = *event.hudadd.align; e->offset = *event.hudadd.offset; e->world_pos = *event.hudadd.world_pos; - + if (id == nhudelem) player->hud.push_back(e); else @@ -2521,7 +2521,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudchange.sdata; continue; } - + HudElement* e = player->hud[id]; switch (event.hudchange.stat) { case HUD_STAT_POS: @@ -2555,7 +2555,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, e->world_pos = *event.hudchange.v3fdata; break; } - + delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; @@ -2602,7 +2602,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } } } - + //TimeTaker //timer2("//timer2"); /* @@ -2623,7 +2623,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, playeritem.getDefinition(itemdef); ToolCapabilities playeritem_toolcap = playeritem.getToolCapabilities(itemdef); - + /* Update camera */ @@ -2646,7 +2646,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, v3s16 camera_offset = camera.getOffset(); bool camera_offset_changed = (camera_offset != old_camera_offset); - + if(!disable_camera_update){ client.getEnv().getClientMap().updateCamera(camera_position, camera_direction, camera_fov, camera_offset); @@ -2657,7 +2657,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, clouds->updateCameraOffset(camera_offset); } } - + // Update sound listener sound->updateListener(camera.getCameraNode()->getPosition(), v3f(0,0,0), // velocity @@ -2670,7 +2670,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, */ { soundmaker.step(dtime); - + ClientMap &map = client.getEnv().getClientMap(); MapNode n = map.getNodeNoEx(player->getStandingNodePos()); soundmaker.m_player_step_sound = nodedef->get(n).sound_footstep; @@ -2679,9 +2679,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Calculate what block is the crosshair pointing to */ - + //u32 t1 = device->getTimer()->getRealTime(); - + f32 d = playeritem_def.range; // max. distance f32 d_hand = itemdef->get("").range; if(d < 0 && d_hand >= 0) @@ -2771,7 +2771,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Check information text of node */ - + ClientMap &map = client.getEnv().getClientMap(); NodeMetadata *meta = map.getNodeMetadata(nodepos); if(meta){ @@ -2783,11 +2783,11 @@ void the_game(bool &kill, bool random_input, InputHandler *input, infotext += narrow_to_wide(nodedef->get(n).name); } } - + /* Handle digging */ - + if(nodig_delay_timer <= 0.0 && input->getLeftState() && client.checkPrivilege("interact")) { @@ -2799,7 +2799,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, ldown_for_dig = true; } MapNode n = client.getEnv().getClientMap().getNode(nodepos); - + // NOTE: Similar piece of code exists on the server side for // cheat detection. // Get digging parameters @@ -2900,7 +2900,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, float mindelay = 0.15; if(nodig_delay_timer < mindelay) nodig_delay_timer = mindelay; - + // Send event to trigger sound MtEvent *e = new NodeDugEvent(nodepos, wasnode); gamedef->event()->put(e); @@ -2923,7 +2923,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { repeat_rightclick_timer = 0; infostream<<"Ground right-clicked"<getString("formspec") == "hack:sign_text_input" @@ -2931,7 +2931,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, && !input->isKeyDown(getKeySetting("keymap_sneak"))) { infostream<<"Launching metadata text input"<getPosition(); v3f dir = (objpos - player_position).normalize(); - + bool disable_send = selected_object->directReportPunch( dir, &playeritem, time_from_last_punch); time_from_last_punch = 0; @@ -3043,7 +3043,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } pointed_old = pointed; - + if(left_punch || input->getLeftClicked()) { camera.setDigging(0); // left click animation @@ -3054,7 +3054,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, input->resetLeftReleased(); input->resetRightReleased(); - + /* Calculate stuff for drawing */ @@ -3062,7 +3062,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Fog range */ - + if(draw_control.range_all) fog_range = 100000*BS; else { @@ -3091,7 +3091,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, daynight_ratio, (int)(old_brightness*255.5), &sunlight_seen) / 255.0; } - + time_of_day = client.getEnv().getTimeOfDayF(); float maxsm = 0.05; if(fabs(time_of_day - time_of_day_smooth) > maxsm && @@ -3105,10 +3105,10 @@ void the_game(bool &kill, bool random_input, InputHandler *input, else time_of_day_smooth = time_of_day_smooth * (1.0-todsm) + time_of_day * todsm; - + sky->update(time_of_day_smooth, time_brightness, direct_brightness, sunlight_seen); - + video::SColor bgcolor = sky->getBgColor(); video::SColor skycolor = sky->getSkyColor(); @@ -3125,18 +3125,18 @@ void the_game(bool &kill, bool random_input, InputHandler *input, clouds->setVisible(false); } } - + /* Update particles */ allparticles_step(dtime); allparticlespawners_step(dtime, client.getEnv()); - + /* Fog */ - + if(g_settings->getBool("enable_fog") && !force_fog_off) { driver->setFog( @@ -3165,9 +3165,6 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Update gui stuff (0ms) */ - - //TimeTaker guiupdatetimer("Gui updating"); - if(show_debug) { static float drawtime_avg = 0; @@ -3209,7 +3206,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { guitext->setVisible(false); } - + if(show_debug) { std::ostringstream os(std::ios_base::binary); @@ -3229,7 +3226,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { guitext2->setVisible(false); } - + { guitext_info->setText(infotext.c_str()); guitext_info->setVisible(show_hud && g_menumgr.menuCount() == 0); @@ -3275,7 +3272,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, guitext_status->enableOverrideColor(true); } } - + /* Get chat messages from client */ @@ -3320,7 +3317,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, /* Inventory */ - + if(client.getPlayerItem() != new_playeritem) { client.selectPlayerItem(new_playeritem); @@ -3329,7 +3326,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, { //infostream<<"Updating local inventory"<beginScene(false, true, bgcolor); @@ -3369,14 +3366,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, driver->beginScene(true, true, skycolor); beginscenetime = timer.stop(true); } - + //timer3.stop(); - + //infostream<<"smgr->drawAll()"<drawAll(); - + if(g_settings->getBool("anaglyph")) { irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition(); @@ -3458,14 +3455,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, scenetime = timer.stop(true); } - + { //TimeTaker timer9("auxiliary drawings"); // 0ms - + //timer9.stop(); //TimeTaker //timer10("//timer10"); - + video::SMaterial m; //m.Thickness = 10; m.Thickness = 3; @@ -3507,7 +3504,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, */ if (show_hud) hud.drawCrosshair(); - + } // timer //timer10.stop(); @@ -3532,7 +3529,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, driver->draw2DRectangle(color, core::rect(0,0,screensize.X,screensize.Y), NULL); - + damage_flash -= 100.0*dtime; } @@ -3592,7 +3589,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, if (sky) sky->drop(); clear_particles(); - + /* Draw a "shutting down" screen, which will be shown while the map generator and other stuff quits @@ -3641,7 +3638,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } - + if(!sound_is_dummy) delete sound; diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index f18473ee0014..972a009fd13c 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -226,7 +226,8 @@ bool GUIEngine::loadMainMenuScript() } else { infostream - << "GUIEngine: execution of custom menu failed!" + << "GUIEngine: execution of custom menu: \"" + << menuscript << "\" failed!" << std::endl << "\tfalling back to builtin menu" << std::endl; @@ -317,7 +318,7 @@ GUIEngine::~GUIEngine() } delete m_texture_source; - + if (m_cloud.clouds) m_cloud.clouds->drop(); } diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 4751978d7d3c..edeabaa315ce 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "gettime.h" #include "gettext.h" +#include "porting.h" #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -59,8 +60,6 @@ with this program; if not, write to the Free Software Foundation, Inc., << parts[b] << "\"" << std::endl; \ return; \ } - - /* GUIFormSpecMenu */ @@ -88,6 +87,12 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, current_keys_pending.key_enter = false; current_keys_pending.key_escape = false; + m_doubleclickdetect[0].time = 0; + m_doubleclickdetect[1].time = 0; + + m_doubleclickdetect[0].pos = v2s32(0,0); + m_doubleclickdetect[1].pos = v2s32(0,0); + } GUIFormSpecMenu::~GUIFormSpecMenu() @@ -102,23 +107,11 @@ GUIFormSpecMenu::~GUIFormSpecMenu() void GUIFormSpecMenu::removeChildren() { const core::list &children = getChildren(); - core::list children_copy; - for(core::list::ConstIterator - i = children.begin(); i != children.end(); i++) - { - children_copy.push_back(*i); - } - for(core::list::Iterator - i = children_copy.begin(); - i != children_copy.end(); i++) - { - (*i)->remove(); + + while(!children.empty()) { + (*children.getLast())->remove(); } - /*{ - gui::IGUIElement *e = getElementFromId(256); - if(e != NULL) - e->remove(); - }*/ + if(m_tooltip_element) { @@ -391,15 +384,14 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) std::wstring wlabel = narrow_to_wide(label.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), - L"", + wlabel, //Needed for displaying text on MSVC wlabel, 258+m_fields.size() ); spec.ftype = f_CheckBox; - spec.flabel = wlabel; //Needed for displaying text on MSVC gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this, spec.fid, spec.flabel.c_str()); @@ -517,7 +509,7 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element, std::wstring wlabel = narrow_to_wide(label.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), wlabel, L"", @@ -527,14 +519,14 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element, if(type == "button_exit") spec.is_exit = true; + m_fields.push_back(spec); gui::IGUIButton* e = Environment->addButton(rect, this, spec.fid, - spec.flabel.c_str()); + m_fields.back().flabel.c_str()); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } - m_fields.push_back(spec); return; } errorstream<< "Invalid button element(" << parts.size() << "): '" << element << "'" << std::endl; @@ -639,7 +631,7 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element) std::wstring fname_w = narrow_to_wide(name.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( fname_w, L"", L"", @@ -655,7 +647,6 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element) //now really show table GUITable *e = new GUITable(Environment, this, spec.fid, rect, m_tsrc); - e->drop(); // IGUIElement maintains the remaining reference if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -712,7 +703,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) std::wstring fname_w = narrow_to_wide(name.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( fname_w, L"", L"", @@ -728,7 +719,6 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) //now really show list GUITable *e = new GUITable(Environment, this, spec.fid, rect, m_tsrc); - e->drop(); // IGUIElement maintains the remaining reference if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -775,7 +765,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) std::wstring fname_w = narrow_to_wide(name.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( fname_w, L"", L"", @@ -836,7 +826,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) std::wstring wlabel = narrow_to_wide(label.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), wlabel, L"", @@ -913,7 +903,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data, std::wstring wlabel = narrow_to_wide(label.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), wlabel, narrow_to_wide(default_val.c_str()), @@ -928,7 +918,8 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data, else { spec.send = true; - gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + gui::IGUIEditBox *e = + Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1001,7 +992,7 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::wstring wlabel = narrow_to_wide(label.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), wlabel, narrow_to_wide(default_val.c_str()), @@ -1016,7 +1007,8 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, else { spec.send = true; - gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + gui::IGUIEditBox *e = + Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1087,12 +1079,13 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) std::wstring wlabel = narrow_to_wide(text.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( L"", wlabel, L"", 258+m_fields.size() ); + Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); m_fields.push_back(spec); return; @@ -1126,16 +1119,17 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) label += L"\n"; } - FieldSpec spec = FieldSpec( + FieldSpec spec( L"", label, L"", 258+m_fields.size() ); + m_fields.push_back(spec); gui::IGUIStaticText *t = - Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); + Environment->addStaticText((--m_fields.end())->flabel.c_str(), rect, false, true, this, spec.fid); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); - m_fields.push_back(spec); + return; } errorstream<< "Invalid vertlabel element(" << parts.size() << "): '" << element << "'" << std::endl; @@ -1173,9 +1167,9 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, if (parts[6] == "false") drawborder = false; } - + std::string pressed_image_name = ""; - + if ((parts.size() == 8)) { pressed_image_name = parts[7]; } @@ -1191,7 +1185,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, std::wstring wlabel = narrow_to_wide(label.c_str()); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), wlabel, narrow_to_wide(image_name.c_str()), @@ -1251,7 +1245,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) show_border = false; } - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), L"", L"", @@ -1276,14 +1270,10 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) } e->setNotClipped(true); + m_fields.push_back(spec); for (unsigned int i=0; i< buttons.size(); i++) { - wchar_t* wbutton = 0; - - std::wstring wlabel = narrow_to_wide(buttons[i]); //Needed for displaying text on windows - wbutton = (wchar_t*) wlabel.c_str(); - - e->addTab(wbutton,-1); + e->addTab(narrow_to_wide(buttons[i]).c_str(),-1); } if ((tab_index >= 0) && @@ -1291,7 +1281,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) (tab_index < (int) buttons.size())) e->setActiveTab(tab_index); - m_fields.push_back(spec); + return; } errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl; @@ -1336,7 +1326,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) std::string tooltip = item.getDefinition(idef).description; label = unescape_string(label); - FieldSpec spec = FieldSpec( + FieldSpec spec( narrow_to_wide(name.c_str()), narrow_to_wide(label.c_str()), narrow_to_wide(item_name.c_str()), @@ -1358,6 +1348,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) spec.rect=rect; if (tooltip!="") spec.tooltip=tooltip; + m_fields.push_back(spec); return; } @@ -1421,7 +1412,7 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) if ((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) { parseColor(parts[0], m_slotbg_n, false); parseColor(parts[1], m_slotbg_h, false); - + if (parts.size() >= 3) { if (parseColor(parts[2], m_slotbordercolor, false)) { m_slotborder = true; @@ -1612,6 +1603,11 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // Remove children removeChildren(); + for (u32 i = 0; i < m_tables.size(); ++i) { + GUITable *table = m_tables[i].second; + table->drop(); + } + mydata.size= v2s32(100,100); mydata.helptext_h = 15; mydata.screensize = screensize; @@ -1624,9 +1620,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // A proceed button is added if there is no size[] element mydata.bp_set = 0; - + /* Convert m_init_draw_spec to m_inventorylists */ - + m_inventorylists.clear(); m_images.clear(); m_backgrounds.clear(); @@ -1649,6 +1645,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_clipbackground = false; // Add tooltip { + assert(m_tooltip_element == NULL); // Note: parent != this so that the tooltip isn't clipped by the menu rectangle m_tooltip_element = Environment->addStaticText(L"",core::rect(0,0,110,18)); m_tooltip_element->enableOverrideColor(true); @@ -1706,7 +1703,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const { core::rect imgrect(0,0,imgsize.X,imgsize.Y); - + for(u32 i=0; igetSkin(); if (skin) font = skin->getFont(); - + Inventory *inv = m_invmgr->getInventory(s.inventoryloc); if(!inv){ infostream<<"GUIFormSpecMenu::drawList(): WARNING: " @@ -1754,9 +1751,9 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) < imgrect(0,0,imgsize.X,imgsize.Y); - + for(s32 i=0; igetSkin(); if (skin) font = skin->getFont(); - + Inventory *inv = m_invmgr->getInventory(m_selected_item->inventoryloc); assert(inv); InventoryList *list = inv->getList(m_selected_item->listname); @@ -1882,7 +1879,7 @@ void GUIFormSpecMenu::drawMenu() if (!skin) return; video::IVideoDriver* driver = Environment->getVideoDriver(); - + v2u32 screenSize = driver->getScreenSize(); core::rect allbg(0, 0, screenSize.X , screenSize.Y); if (m_bgfullscreen) @@ -1926,7 +1923,7 @@ void GUIFormSpecMenu::drawMenu() errorstream << "\t" << spec.name << std::endl; } } - + /* Draw Boxes */ @@ -1975,7 +1972,7 @@ void GUIFormSpecMenu::drawMenu() errorstream << "\t" << spec.name << std::endl; } } - + /* Draw item images */ @@ -2000,7 +1997,7 @@ void GUIFormSpecMenu::drawMenu() core::dimension2di(texture->getOriginalSize())), NULL/*&AbsoluteClippingRect*/, colors, true); } - + /* Draw items Phase 0: Item slot rectangles @@ -2017,7 +2014,7 @@ void GUIFormSpecMenu::drawMenu() Call base class */ gui::IGUIElement::draw(); - + /* Draw fields/buttons tooltips */ @@ -2200,40 +2197,43 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) current_keys_pending.key_escape = false; } - for(u32 i=0; i::iterator iter = m_fields.begin(); + iter != m_fields.end(); iter++) { - const FieldSpec &s = m_fields[i]; - if(s.send) + i++; + if(iter->send) { - if(s.ftype == f_Button) + std::string label = wide_to_narrow(iter->flabel); + std::string name = wide_to_narrow(iter->fname); + if(iter->ftype == f_Button) { - fields[wide_to_narrow(s.fname.c_str())] = wide_to_narrow(s.flabel.c_str()); + fields[name] = wide_to_narrow(iter->flabel); } - else if(s.ftype == f_Table) { - GUITable *table = getTable(s.fname); + else if(iter->ftype == f_Table) { + GUITable *table = getTable(iter->fname); if (table) { - fields[wide_to_narrow(s.fname.c_str())] - = table->checkEvent(); + fields[name] = table->checkEvent(); } } - else if(s.ftype == f_DropDown) { + else if(iter->ftype == f_DropDown) { // no dynamic cast possible due to some distributions shipped // without rtti support in irrlicht - IGUIElement * element = getElementFromId(s.fid); + IGUIElement * element = getElementFromId(iter->fid); gui::IGUIComboBox *e = NULL; if ((element) && (element->getType() == gui::EGUIET_COMBO_BOX)) { e = static_cast(element); } s32 selected = e->getSelected(); if (selected >= 0) { - fields[wide_to_narrow(s.fname.c_str())] = + fields[name] = wide_to_narrow(e->getItem(selected)); } } - else if (s.ftype == f_TabHeader) { + else if (iter->ftype == f_TabHeader) { // no dynamic cast possible due to some distributions shipped // without rtti support in irrlicht - IGUIElement * element = getElementFromId(s.fid); + IGUIElement * element = getElementFromId(iter->fid); gui::IGUITabControl *e = NULL; if ((element) && (element->getType() == gui::EGUIET_TAB_CONTROL)) { e = static_cast(element); @@ -2242,13 +2242,13 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) if (e != 0) { std::stringstream ss; ss << (e->getActiveTab() +1); - fields[wide_to_narrow(s.fname.c_str())] = ss.str(); + fields[name] = ss.str(); } } - else if (s.ftype == f_CheckBox) { + else if (iter->ftype == f_CheckBox) { // no dynamic cast possible due to some distributions shipped // without rtti support in irrlicht - IGUIElement * element = getElementFromId(s.fid); + IGUIElement * element = getElementFromId(iter->fid); gui::IGUICheckBox *e = NULL; if ((element) && (element->getType() == gui::EGUIET_CHECK_BOX)) { e = static_cast(element); @@ -2256,17 +2256,17 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) if (e != 0) { if (e->isChecked()) - fields[wide_to_narrow(s.fname.c_str())] = "true"; + fields[name] = "true"; else - fields[wide_to_narrow(s.fname.c_str())] = "false"; + fields[name] = "false"; } } else { - IGUIElement* e = getElementFromId(s.fid); + IGUIElement* e = getElementFromId(iter->fid); if(e != NULL) { - fields[wide_to_narrow(s.fname.c_str())] = wide_to_narrow(e->getText()); + fields[name] = wide_to_narrow(e->getText()); } } } @@ -2303,11 +2303,69 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) gui::IGUIElement *hovered = Environment->getRootGUIElement()->getElementFromPoint( core::position2d(x, y)); + if (hovered && isMyChild(hovered)) { hovered->OnEvent(event); return true; } } + + if (event.EventType == EET_MOUSE_INPUT_EVENT) { + s32 x = event.MouseInput.X; + s32 y = event.MouseInput.Y; + gui::IGUIElement *hovered = + Environment->getRootGUIElement()->getElementFromPoint( + core::position2d(x, y)); + + if (hovered != this) { + if (DoubleClickDetection(event)) { + return true; + } + } + } + return false; +} + +bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event) { + if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { + m_doubleclickdetect[0].pos = m_doubleclickdetect[1].pos; + m_doubleclickdetect[0].time = m_doubleclickdetect[1].time; + + m_doubleclickdetect[1].pos = m_pointer; + m_doubleclickdetect[1].time = getTimeMs(); + } + else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { + + u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, getTimeMs()); + if (delta < 400) { + + double distance = sqrt( + (m_doubleclickdetect[0].pos.X - m_doubleclickdetect[1].pos.X) * + (m_doubleclickdetect[0].pos.X - m_doubleclickdetect[1].pos.X) + + (m_doubleclickdetect[0].pos.Y - m_doubleclickdetect[1].pos.Y) * + (m_doubleclickdetect[0].pos.Y - m_doubleclickdetect[1].pos.Y)); + + if (distance < 30) { + + SEvent* translated = new SEvent(); + assert(translated != 0); + //translate doubleclick to escape + memset(translated,0,sizeof(SEvent)); + translated->EventType = irr::EET_KEY_INPUT_EVENT; + translated->KeyInput.Key = KEY_ESCAPE; + translated->KeyInput.Control = false; + translated->KeyInput.Shift = false; + translated->KeyInput.PressedDown = true; + translated->KeyInput.Char = 0; + OnEvent(*translated); + + // no need to send the key up event as we're already deleted + // and no one else did notice this event + delete translated; + return true; + } + } + } return false; } @@ -2360,7 +2418,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } return true; } - } if(event.EventType==EET_MOUSE_INPUT_EVENT && event.MouseInput.Event != EMIE_MOUSE_MOVED) @@ -2368,7 +2425,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) // Mouse event other than movement // Get selected item and hovered/clicked item (s) - updateSelectedItem(); ItemSpec s = getItemAtPos(m_pointer); @@ -2650,16 +2706,17 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) && isVisible()) { // find the element that was clicked - for(u32 i=0; igetID())) + for (std::vector::iterator iter = m_fields.begin(); + iter != m_fields.end(); iter ++) { + + std::string fieldname = wide_to_narrow(iter->flabel); + + if ((iter->ftype == f_TabHeader) && + (iter->fid == event.GUIEvent.Caller->getID())) { - s.send = true; + iter->send = true; acceptInput(); - s.send = false; + iter->send = false; return true; } } diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 6f7de158b505..d6227e9bb12e 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -143,7 +143,7 @@ class GUIFormSpecMenu : public GUIModalMenu v2s32 geom; bool scale; }; - + struct FieldSpec { FieldSpec() @@ -202,7 +202,7 @@ class GUIFormSpecMenu : public GUIModalMenu m_current_inventory_location = current_inventory_location; regenerateGui(m_screensize_old); } - + // form_src is deleted by this GUIFormSpecMenu void setFormSource(IFormSource *form_src) { @@ -231,7 +231,7 @@ class GUIFormSpecMenu : public GUIModalMenu Remove and re-add (or reposition) stuff */ void regenerateGui(v2u32 screensize); - + ItemSpec getItemAtPos(v2s32 p) const; void drawList(const ListDrawSpec &s, int phase); void drawSelectedItem(); @@ -260,7 +260,7 @@ class GUIFormSpecMenu : public GUIModalMenu v2s32 spacing; v2s32 imgsize; v2s32 offset; - + irr::IrrlichtDevice* m_device; InventoryManager *m_invmgr; IGameDef *m_gamedef; @@ -283,7 +283,7 @@ class GUIFormSpecMenu : public GUIModalMenu ItemSpec *m_selected_item; u32 m_selected_amount; bool m_selected_dragging; - + // WARNING: BLACK MAGIC // Used to guess and keep up with some special things the server can do. // If name is "", no guess exists. @@ -355,6 +355,15 @@ class GUIFormSpecMenu : public GUIModalMenu void parseBox(parserData* data,std::string element); void parseBackgroundColor(parserData* data,std::string element); void parseListColors(parserData* data,std::string element); + + + bool DoubleClickDetection(const SEvent event); + + struct clickpos { + v2s32 pos; + s32 time; + }; + clickpos m_doubleclickdetect[2]; }; class FormspecFormSource: public IFormSource diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 2eca363d7bb9..d3da69b73591 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -16,7 +16,6 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "socket.h" // for select() #include "porting.h" // for sleep_ms(), get_sysinfo() #include "httpfetch.h" @@ -566,6 +565,8 @@ class CurlFetchThread : public JThread log_register_thread("CurlFetchThread"); DSTACK(__FUNCTION_NAME); + porting::setThreadName("CurlFetchThread"); + CurlHandlePool pool; m_multi = curl_multi_init(); diff --git a/src/localplayer.cpp b/src/localplayer.cpp index a6f04849ab42..6ad2adf380ba 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -95,7 +95,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, /* Collision detection */ - + /* Check if player is in liquid (the oscillating value) */ @@ -173,7 +173,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, v3f lwn_f = intToFloat(m_sneak_node, BS); position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd); position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd); - + if(!is_climbing) { f32 min_y = lwn_f.Y + 0.5*BS; @@ -203,7 +203,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, */ bool touching_ground_was = touching_ground; touching_ground = result.touching_ground; - + //bool standing_on_unloaded = result.standing_on_unloaded; /* @@ -254,7 +254,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, f32 max_axis_distance_f = MYMAX( fabs(player_p2df.X-node_p2df.X), fabs(player_p2df.Y-node_p2df.Y)); - + if(distance_f > min_distance_f || max_axis_distance_f > 0.5*BS + sneak_max + 0.1*BS) continue; @@ -264,8 +264,9 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, if(nodemgr->get(map->getNode(p)).walkable == false) continue; // And the node above it has to be nonwalkable - if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true) + if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true) { continue; + } if (!physics_override_sneak_glitch) { if (nodemgr->get(map->getNode(p+v3s16(0,2,0))).walkable) continue; @@ -279,7 +280,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, min_distance_f = distance_f; new_sneak_node = p; } - + bool sneak_node_found = (min_distance_f < 100000.0*BS*0.9); m_sneak_node = new_sneak_node; @@ -292,12 +293,12 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, if(sneak_node_found && control.sneak) touching_ground = true; } - + /* Set new position */ setPosition(position); - + /* Report collisions */ @@ -345,7 +346,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, */ m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS); m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name; - + /* Check properties of the node on which the player is standing */ @@ -378,10 +379,10 @@ void LocalPlayer::applyControl(float dtime) v3f move_direction = v3f(0,0,1); move_direction.rotateXZBy(getYaw()); - + v3f speedH = v3f(0,0,0); // Horizontal (X, Z) v3f speedV = v3f(0,0,0); // Vertical (Y) - + bool fly_allowed = m_gamedef->checkLocalPrivilege("fly"); bool fast_allowed = m_gamedef->checkLocalPrivilege("fast"); @@ -393,7 +394,7 @@ void LocalPlayer::applyControl(float dtime) // Whether superspeed mode is used or not bool superspeed = false; - + if(g_settings->getBool("always_fly_fast") && free_move && fast_move) superspeed = true; @@ -403,7 +404,7 @@ void LocalPlayer::applyControl(float dtime) // If free movement and fast movement, always move fast if(free_move && fast_move) superspeed = true; - + // Auxiliary button 1 (E) if(control.aux1) { @@ -500,7 +501,7 @@ void LocalPlayer::applyControl(float dtime) if(control.jump) { if(free_move) - { + { if(g_settings->getBool("aux1_descends") || g_settings->getBool("always_fly_fast")) { if(fast_move) @@ -526,7 +527,7 @@ void LocalPlayer::applyControl(float dtime) { speedJ.Y = movement_speed_jump * physics_override_jump; setSpeed(speedJ); - + MtEvent *e = new SimpleTriggerEvent("PlayerJump"); m_gamedef->event()->put(e); } diff --git a/src/main.cpp b/src/main.cpp index e520027729c8..b0ec13c081a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,7 +41,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #endif #include "irrlicht.h" // createDevice - #include "main.h" #include "mainmenumanager.h" #include @@ -263,6 +262,7 @@ class MyEventReceiver : public IEventReceiver } else { keyIsDown.unset(event.KeyInput); } + return true; } if(event.EventType == irr::EET_MOUSE_INPUT_EVENT) @@ -1472,10 +1472,11 @@ int main(int argc, char *argv[]) bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; - if(random_input) + if(random_input) { input = new RandomInputHandler(); - else + } else { input = new RealInputHandler(device, &receiver); + } scene::ISceneManager* smgr = device->getSceneManager(); diff --git a/src/porting.cpp b/src/porting.cpp index b0a1843eb0b8..bcb8015976a7 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -190,11 +190,11 @@ bool threadBindToProcessor(threadid_t tid, int pnumber) { #elif defined(__sun) || defined(sun) - return processor_bind(P_LWPID, MAKE_LWPID_PTHREAD(tid), + return processor_bind(P_LWPID, MAKE_LWPID_PTHREAD(tid), pnumber, NULL) == 0; #elif defined(_AIX) - + return bindprocessor(BINDTHREAD, (tid_t)tid, pnumber) == 0; #elif defined(__hpux) || defined(hpux) @@ -203,11 +203,11 @@ bool threadBindToProcessor(threadid_t tid, int pnumber) { return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, &answer, pnumber, tid) == 0; - + #elif defined(__APPLE__) struct thread_affinity_policy tapol; - + thread_port_t threadport = pthread_mach_thread_np(tid); tapol.affinity_tag = pnumber + 1; return thread_policy_set(threadport, THREAD_AFFINITY_POLICY, @@ -232,21 +232,21 @@ bool threadSetPriority(threadid_t tid, int prio) { CloseHandle(hThread); return success; - + #else struct sched_param sparam; int policy; - + if (pthread_getschedparam(tid, &policy, &sparam) != 0) return false; - + int min = sched_get_priority_min(policy); int max = sched_get_priority_max(policy); sparam.sched_priority = min + prio * (max - min) / THREAD_PRIORITY_HIGHEST; return pthread_setschedparam(tid, policy, &sparam) == 0; - + #endif } @@ -476,7 +476,7 @@ void initializePaths() i != trylist.end(); i++) { const std::string &trypath = *i; - if(!fs::PathExists(trypath) || !fs::PathExists(trypath + "/builtin")){ + if(!fs::PathExists(trypath) || !fs::PathExists(trypath + DIR_DELIM + "builtin")){ dstream<<"WARNING: system-wide share not found at \"" < - + #define sleep_ms(x) Sleep(x) #else #include #include //for uintptr_t - + #if (defined(linux) || defined(__linux)) && !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif @@ -72,7 +72,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #endif #define sleep_ms(x) usleep(x*1000) - + #define THREAD_PRIORITY_LOWEST 0 #define THREAD_PRIORITY_BELOW_NORMAL 1 #define THREAD_PRIORITY_NORMAL 2 @@ -183,17 +183,17 @@ std::string get_sysinfo(); #define _WIN32_WINNT 0x0501 #endif #include - + inline u32 getTimeS() { return GetTickCount() / 1000; } - + inline u32 getTimeMs() { return GetTickCount(); } - + inline u32 getTimeUs() { LARGE_INTEGER freq, t; @@ -201,7 +201,7 @@ std::string get_sysinfo(); QueryPerformanceCounter(&t); return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000.0); } - + inline u32 getTimeNs() { LARGE_INTEGER freq, t; @@ -209,39 +209,39 @@ std::string get_sysinfo(); QueryPerformanceCounter(&t); return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000000.0); } - + #else // Posix #include #include - + inline u32 getTimeS() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec; } - + inline u32 getTimeMs() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec / 1000; } - + inline u32 getTimeUs() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; } - + inline u32 getTimeNs() { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); return ts.tv_sec * 1000000000 + ts.tv_nsec; } - + /*#include inline u32 getTimeMs() { @@ -266,6 +266,26 @@ inline u32 getTime(TimePrecision prec) return 0; } +inline u32 getDeltaMs(u32 old_time_ms,u32 new_time_ms) { + if (new_time_ms >= old_time_ms) { + return (new_time_ms - old_time_ms); + } + else { + return ((0xFFFFFFFF - old_time_ms) + new_time_ms); + } +} + +#ifdef WIN32 +// not supported on windows platform +#define setThreadName(a) +#else + +#include + +inline void setThreadName(const char* name) { + prctl(PR_SET_NAME,name); +} +#endif } // namespace porting diff --git a/src/server.cpp b/src/server.cpp index ba7ac1eceedc..2f7908e3352d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -99,6 +99,8 @@ void * ServerThread::Thread() ThreadStarted(); + porting::setThreadName("ServerThread"); + while(!StopRequested()) { try{ diff --git a/src/settings.h b/src/settings.h index 53e8d8ef5c85..cf220f9adf15 100644 --- a/src/settings.h +++ b/src/settings.h @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "filesys.h" +#include enum ValueType { @@ -575,7 +576,7 @@ class Settings u32 getFlagStr(std::string name, FlagDesc *flagdesc, u32 *flagmask) { std::string val = get(name); - return (isdigit(val[0])) ? stoi(val) : + return (std::isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc, flagmask); } diff --git a/src/tile.cpp b/src/tile.cpp index b8080c7084b9..78aa4d94659f 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -730,9 +730,6 @@ u32 TextureSource::getTextureIdDirect(const std::string &name) m_textureinfo_cache.push_back(ti); m_name_to_id[name] = id; - /*infostream<<"getTextureIdDirect(): " - <<"Returning id="<queryFeature(irr::video::EVDF_TEXTURE_NPOT)) { + core::dimension2d dim = image->getDimension(); + + + if ((dim.Height %2 != 0) || + (dim.Width %2 != 0)) { + errorstream << "TextureSource::generateImage " + << part_of_name << " size npot2 x=" << dim.Width + << " y=" << dim.Height << std::endl; + } + } + } + if(image == NULL) { if(part_of_name != ""){