diff options
author | Weblate <42@minetest.ru> | 2013-04-18 20:00:16 +0200 |
---|---|---|
committer | Weblate <42@minetest.ru> | 2013-04-18 20:00:16 +0200 |
commit | 9e6376bd95ba9309365b39b878ab2f499776437a (patch) | |
tree | a354a250daedf036cc36e33d3d1ebb9fafc4ac27 /src | |
parent | e385af7cc01d156164b85d10b00a7047a5372e66 (diff) | |
parent | e60eb32050a44d344795e4a1515a56038bb97e02 (diff) | |
download | minetest-9e6376bd95ba9309365b39b878ab2f499776437a.tar.gz minetest-9e6376bd95ba9309365b39b878ab2f499776437a.tar.bz2 minetest-9e6376bd95ba9309365b39b878ab2f499776437a.zip |
Merge remote branch 'origin/master'
Diffstat (limited to 'src')
53 files changed, 1648 insertions, 482 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9bef3289e..7ddeeb02e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -180,10 +180,26 @@ if(USE_FREETYPE) set(CGUITTFONT_LIBRARY cguittfont) endif(USE_FREETYPE) -# Do not use system-wide installation of Lua, because it'll likely be a -# different version and/or has different build options. -set(LUA_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lua/src") -set(LUA_LIBRARY "lua") + +find_library(LUA_LIBRARY luajit + NAMES luajit-5.1) +find_path(LUA_INCLUDE_DIR luajit.h + NAMES luajit.h + PATH_SUFFIXES luajit-2.0) +message (STATUS "LuaJIT library: ${LUA_LIBRARY}") +message (STATUS "LuaJIT headers: ${LUA_INCLUDE_DIR}") + +if(LUA_LIBRARY AND LUA_INCLUDE_DIR) + message (STATUS "LuaJIT found.") +else(LUA_LIBRARY AND LUA_INCLUDE_DIR) + message (STATUS "LuaJIT not found, using bundled Lua.") + set(LUA_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lua/src") + set(LUA_LIBRARY "lua") + add_subdirectory(lua) +endif(LUA_LIBRARY AND LUA_INCLUDE_DIR) + +mark_as_advanced(LUA_LIBRARY) +mark_as_advanced(LUA_INCLUDE_DIR) configure_file( "${PROJECT_SOURCE_DIR}/cmake_config.h.in" @@ -311,6 +327,7 @@ set(minetest_SRCS particles.cpp clientobject.cpp chat.cpp + hud.cpp guiMainMenu.cpp guiKeyChangeMenu.cpp guiMessageMenu.cpp @@ -601,11 +618,6 @@ if (BUILD_CLIENT AND USE_FREETYPE) add_subdirectory(cguittfont) endif (BUILD_CLIENT AND USE_FREETYPE) -if (LUA_FOUND) -else (LUA_FOUND) - add_subdirectory(lua) -endif (LUA_FOUND) - if (JSON_FOUND) else (JSON_FOUND) add_subdirectory(json) diff --git a/src/camera.cpp b/src/camera.cpp index 138b022c0..211ecfd70 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -67,9 +67,11 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, m_view_bobbing_anim(0), m_view_bobbing_state(0), m_view_bobbing_speed(0), + m_view_bobbing_fall(0), m_digging_anim(0), - m_digging_button(-1) + m_digging_button(-1), + m_dummymesh(createCubeMesh(v3f(1,1,1))) { //dstream<<__FUNCTION_NAME<<std::endl; @@ -84,13 +86,14 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, // all other 3D scene nodes and before the GUI. m_wieldmgr = smgr->createNewSceneManager(); m_wieldmgr->addCameraSceneNode(); - m_wieldnode = m_wieldmgr->addMeshSceneNode(createCubeMesh(v3f(1,1,1)), NULL); // need a dummy mesh + m_wieldnode = m_wieldmgr->addMeshSceneNode(m_dummymesh, NULL); // need a dummy mesh } Camera::~Camera() { - m_wieldnode->setMesh(NULL); m_wieldmgr->drop(); + + delete m_dummymesh; } bool Camera::successfullyCreated(std::wstring& error_message) @@ -132,6 +135,13 @@ inline f32 my_modf(f32 x) void Camera::step(f32 dtime) { + if(m_view_bobbing_fall > 0) + { + m_view_bobbing_fall -= 3 * dtime; + if(m_view_bobbing_fall <= 0) + m_view_bobbing_fall = -1; // Mark the effect as finished + } + if (m_view_bobbing_state != 0) { //f32 offset = dtime * m_view_bobbing_speed * 0.035; @@ -235,11 +245,28 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); - //Get camera tilt timer (hurt animation) + // Get camera tilt timer (hurt animation) float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75); + // Fall bobbing animation + float fall_bobbing = 0; + if(player->camera_impact >= 1) + { + if(m_view_bobbing_fall == -1) // Effect took place and has finished + player->camera_impact = m_view_bobbing_fall = 0; + else if(m_view_bobbing_fall == 0) // Initialize effect + m_view_bobbing_fall = 1; + + // Convert 0 -> 1 to 0 -> 1 -> 0 + fall_bobbing = m_view_bobbing_fall < 0.5 ? m_view_bobbing_fall * 2 : -(m_view_bobbing_fall - 0.5) * 2 + 1; + // Smoothen and invert the above + fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1; + // Amplify according to the intensity of the impact + fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5; + } + // Set head node transformation - m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength,0)); + m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0)); m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength)); m_headnode->updateAbsolutePosition(); diff --git a/src/camera.h b/src/camera.h index fc43d1176..0ed5c20d2 100644 --- a/src/camera.h +++ b/src/camera.h @@ -166,6 +166,8 @@ private: s32 m_view_bobbing_state; // Speed of view bobbing animation f32 m_view_bobbing_speed; + // Fall view bobbing + f32 m_view_bobbing_fall; // Digging animation frame (0 <= m_digging_anim < 1) f32 m_digging_anim; @@ -173,6 +175,9 @@ private: // If 0, left-click digging animation // If 1, right-click digging animation s32 m_digging_button; + + //dummymesh for camera + irr::scene::IAnimatedMesh* m_dummymesh; }; #endif diff --git a/src/client.cpp b/src/client.cpp index 1d5f8f472..03a710599 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -363,6 +363,15 @@ Client::~Client() for (std::list<MediaFetchThread*>::iterator i = m_media_fetch_threads.begin(); i != m_media_fetch_threads.end(); ++i) delete *i; + + // cleanup 3d model meshes on client shutdown + while (m_device->getSceneManager()->getMeshCache()->getMeshCount() != 0) { + scene::IAnimatedMesh * mesh = + m_device->getSceneManager()->getMeshCache()->getMeshByIndex(0); + + if (mesh != NULL) + m_device->getSceneManager()->getMeshCache()->removeMesh(mesh); + } } void Client::connect(Address address) @@ -976,16 +985,28 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) { verbosestream<<"Client: Storing model into Irrlicht: " <<"\""<<filename<<"\""<<std::endl; + scene::ISceneManager *smgr = m_device->getSceneManager(); + + //check if mesh was already cached + scene::IAnimatedMesh *mesh = + smgr->getMeshCache()->getMeshByName(filename.c_str()); + + if (mesh != NULL) { + errorstream << "Multiple models with name: " << filename.c_str() << + " found replacing previous model!" << std::endl; + + smgr->getMeshCache()->removeMesh(mesh); + mesh = 0; + } io::IFileSystem *irrfs = m_device->getFileSystem(); io::IReadFile *rfile = irrfs->createMemoryReadFile( *data_rw, data_rw.getSize(), filename.c_str()); assert(rfile); - scene::ISceneManager *smgr = m_device->getSceneManager(); - scene::IAnimatedMesh *mesh = smgr->getMesh(rfile); + mesh = smgr->getMesh(rfile); smgr->getMeshCache()->addMesh(filename.c_str(), mesh); - + rfile->drop(); return true; } @@ -2019,6 +2040,74 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) m_client_event_queue.push_back(event); } + else if(command == TOCLIENT_HUDADD) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + u8 type = readU8(is); + v2f pos = readV2F1000(is); + std::string name = deSerializeString(is); + v2f scale = readV2F1000(is); + std::string text = deSerializeString(is); + u32 number = readU32(is); + u32 item = readU32(is); + u32 dir = readU32(is); + + ClientEvent event; + event.type = CE_HUDADD; + event.hudadd.id = id; + event.hudadd.type = type; + event.hudadd.pos = new v2f(pos); + event.hudadd.name = new std::string(name); + event.hudadd.scale = new v2f(scale); + event.hudadd.text = new std::string(text); + event.hudadd.number = number; + event.hudadd.item = item; + event.hudadd.dir = dir; + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_HUDRM) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + + ClientEvent event; + event.type = CE_HUDRM; + event.hudrm.id = id; + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_HUDCHANGE) + { + std::string sdata; + v2f v2fdata; + u32 intdata = 0; + + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + u8 stat = (HudElementStat)readU8(is); + + if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE) + v2fdata = readV2F1000(is); + else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) + sdata = deSerializeString(is); + else + intdata = readU32(is); + + ClientEvent event; + event.type = CE_HUDCHANGE; + event.hudchange.id = id; + event.hudchange.stat = (HudElementStat)stat; + event.hudchange.v2fdata = new v2f(v2fdata); + event.hudchange.sdata = new std::string(sdata); + event.hudchange.data = intdata; + m_client_event_queue.push_back(event); + } else { infostream<<"Client: Ignoring unknown command " diff --git a/src/client.h b/src/client.h index 16cdc237f..f59588680 100644 --- a/src/client.h +++ b/src/client.h @@ -160,7 +160,10 @@ enum ClientEventType CE_SHOW_FORMSPEC, CE_SPAWN_PARTICLE, CE_ADD_PARTICLESPAWNER, - CE_DELETE_PARTICLESPAWNER + CE_DELETE_PARTICLESPAWNER, + CE_HUDADD, + CE_HUDRM, + CE_HUDCHANGE }; struct ClientEvent @@ -183,8 +186,8 @@ struct ClientEvent f32 camera_point_target_z; } deathscreen; struct{ - std::string* formspec; - std::string* formname; + std::string *formspec; + std::string *formname; } show_formspec; struct{ } textures_updated; @@ -217,6 +220,27 @@ struct ClientEvent struct{ u32 id; } delete_particlespawner; + struct{ + u32 id; + u8 type; + v2f *pos; + std::string *name; + v2f *scale; + std::string *text; + u32 number; + u32 item; + u32 dir; + } hudadd; + struct{ + u32 id; + } hudrm; + struct{ + u32 id; + HudElementStat stat; + v2f *v2fdata; + std::string *sdata; + u32 data; + } hudchange; }; }; diff --git a/src/clientserver.h b/src/clientserver.h index 8b1e0a7e4..6f7bb4402 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -90,9 +90,13 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed); sound_place added to ItemDefinition PROTOCOL_VERSION 19: GENERIC_CMD_SET_PHYSICS_OVERRIDE + PROTOCOL_VERSION 20: + TOCLIENT_HUD_ADD + TOCLIENT_HUD_RM + TOCLIENT_HUD_CHANGE */ -#define LATEST_PROTOCOL_VERSION 19 +#define LATEST_PROTOCOL_VERSION 20 // Server's supported network protocol range #define SERVER_PROTOCOL_VERSION_MIN 13 @@ -433,6 +437,39 @@ enum ToClientCommand u16 command u32 id */ + + TOCLIENT_HUDADD = 0x49, + /* + u16 command + u32 id + u8 type + v2f1000 pos + u32 len + u8[len] name + v2f1000 scale + u32 len2 + u8[len2] text + u32 number + u32 item + u32 dir + */ + + TOCLIENT_HUDRM = 0x50, + /* + u16 command + u32 id + */ + + TOCLIENT_HUDCHANGE = 0x51, + /* + u16 command + u32 id + u8 stat + [v2f1000 data | + u32 len + u8[len] data | + u32 data] + */ }; enum ToServerCommand diff --git a/src/collision.cpp b/src/collision.cpp index cd170196f..673966b6e 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -192,7 +192,7 @@ bool wouldCollideWithCeiling( collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, f32 pos_max_d, const aabb3f &box_0, f32 stepheight, f32 dtime, - v3f &pos_f, v3f &speed_f, v3f &accel_f) + v3f &pos_f, v3f &speed_f, v3f &accel_f,ActiveObject* self) { Map *map = &env->getMap(); //TimeTaker tt("collisionMoveSimple"); @@ -300,7 +300,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects); for (int i=0; i < clientobjects.size(); i++) { - objects.push_back((ActiveObject*)clientobjects[i].obj); + if ((self == 0) || (self != clientobjects[i].obj)) { + objects.push_back((ActiveObject*)clientobjects[i].obj); + } } } else @@ -314,7 +316,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++) { ServerActiveObject *current = s_env->getActiveObject(*iter); - objects.push_back((ActiveObject*)current); + if ((self == 0) || (self != current)) { + objects.push_back((ActiveObject*)current); + } } } } @@ -458,8 +462,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, if (is_object[nearest_boxindex]) { info.type = COLLISION_OBJECT; } - else + else { info.type = COLLISION_NODE; + } info.node_p = node_positions[nearest_boxindex]; info.bouncy = bouncy; info.old_speed = speed_f; diff --git a/src/collision.h b/src/collision.h index 117818456..77bf1f15d 100644 --- a/src/collision.h +++ b/src/collision.h @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class Map; class IGameDef; class Environment; +class ActiveObject; enum CollisionType { @@ -70,7 +71,7 @@ struct collisionMoveResult collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef, f32 pos_max_d, const aabb3f &box_0, f32 stepheight, f32 dtime, - v3f &pos_f, v3f &speed_f, v3f &accel_f); + v3f &pos_f, v3f &speed_f, v3f &accel_f,ActiveObject* self=0); #if 0 // This doesn't seem to work and isn't used diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 9738dc34c..f79d0d6f6 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1152,7 +1152,7 @@ public: v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(env,env->getGameDef(), pos_max_d, box, stepheight, dtime, - p_pos, p_velocity, p_acceleration); + p_pos, p_velocity, p_acceleration,this); // Apply results m_position = p_pos; m_velocity = p_velocity; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index e6c8c725c..3526ecbd2 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -502,7 +502,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(m_env,m_env->getGameDef(), pos_max_d, box, stepheight, dtime, - p_pos, p_velocity, p_acceleration); + p_pos, p_velocity, p_acceleration,this); // Apply results m_base_position = p_pos; m_velocity = p_velocity; diff --git a/src/emerge.cpp b/src/emerge.cpp index 499aaf291..049b3cc12 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -96,9 +96,20 @@ EmergeManager::~EmergeManager() { delete emergethread[i]; delete mapgen[i]; } + emergethread.clear(); + mapgen.clear(); + + for (unsigned int i = 0; i < ores.size(); i++) + delete ores[i]; + ores.clear(); + for (std::map<std::string, MapgenFactory *>::iterator iter = mglist.begin(); + iter != mglist.end(); iter ++) { + delete iter->second; + } + mglist.clear(); + delete biomedef; - delete params; } diff --git a/src/game.cpp b/src/game.cpp index 65feb50bf..a2d94ac0a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <IGUIStaticText.h> #include <IGUIFont.h> #include <IMaterialRendererServices.h> +#include "IMeshCache.h" #include "client.h" #include "server.h" #include "guiPauseMenu.h" @@ -58,6 +59,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "subgame.h" #include "quicktune_shortcutter.h" #include "clientmap.h" +#include "hud.h" #include "sky.h" #include "sound.h" #if USE_SOUND @@ -227,137 +229,6 @@ public: std::string m_formspec; FormspecFormSource** m_game_formspec; }; -/* - Hotbar draw routine -*/ -void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, - IGameDef *gamedef, - v2s32 centerlowerpos, s32 imgsize, s32 itemcount, - Inventory *inventory, s32 halfheartcount, u16 playeritem) -{ - InventoryList *mainlist = inventory->getList("main"); - if(mainlist == NULL) - { - errorstream<<"draw_hotbar(): mainlist == NULL"<<std::endl; - return; - } - - s32 padding = imgsize/12; - //s32 height = imgsize + padding*2; - s32 width = itemcount*(imgsize+padding*2); - - // Position of upper left corner of bar - v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2); - - // Draw background color - /*core::rect<s32> barrect(0,0,width,height); - barrect += pos; - video::SColor bgcolor(255,128,128,128); - driver->draw2DRectangle(bgcolor, barrect, NULL);*/ - - core::rect<s32> imgrect(0,0,imgsize,imgsize); - - for(s32 i=0; i<itemcount; i++) - { - const ItemStack &item = mainlist->getItem(i); - - core::rect<s32> rect = imgrect + pos - + v2s32(padding+i*(imgsize+padding*2), padding); - - if(playeritem == i) - { - video::SColor c_outside(255,255,0,0); - //video::SColor c_outside(255,0,0,0); - //video::SColor c_inside(255,192,192,192); - s32 x1 = rect.UpperLeftCorner.X; - s32 y1 = rect.UpperLeftCorner.Y; - s32 x2 = rect.LowerRightCorner.X; - s32 y2 = rect.LowerRightCorner.Y; - // Black base borders - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y1 - padding), - v2s32(x2 + padding, y1) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y2), - v2s32(x2 + padding, y2 + padding) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x2, y1), - v2s32(x2 + padding, y2) - ), NULL); - /*// Light inside borders - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y1 - padding/2), - v2s32(x2 + padding/2, y1) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y2), - v2s32(x2 + padding/2, y2 + padding/2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x2, y1), - v2s32(x2 + padding/2, y2) - ), NULL); - */ - } - - video::SColor bgcolor2(128,0,0,0); - driver->draw2DRectangle(bgcolor2, rect, NULL); - drawItemStack(driver, font, item, rect, NULL, gamedef); - } - - /* - Draw hearts - */ - video::ITexture *heart_texture = - gamedef->getTextureSource()->getTextureRaw("heart.png"); - if(heart_texture) - { - v2s32 p = pos + v2s32(0, -20); - for(s32 i=0; i<halfheartcount/2; i++) - { - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect<s32> rect(0,0,16,16); - rect += p; - driver->draw2DImage(heart_texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), - core::dimension2di(heart_texture->getOriginalSize())), - NULL, colors, true); - p += v2s32(16,0); - } - if(halfheartcount % 2 == 1) - { - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect<s32> rect(0,0,16/2,16); - rect += p; - core::dimension2di srcd(heart_texture->getOriginalSize()); - srcd.Width /= 2; - driver->draw2DImage(heart_texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), srcd), - NULL, colors, true); - p += v2s32(16,0); - } - } -} /* Check if a node is pointable @@ -943,14 +814,8 @@ void the_game( // Calculate text height using the font u32 text_height = font->getDimension(L"Random test string").Height; - v2u32 screensize(0,0); v2u32 last_screensize(0,0); - screensize = driver->getScreenSize(); - - const s32 hotbar_itemcount = 8; - //const s32 hotbar_imagesize = 36; - //const s32 hotbar_imagesize = 64; - s32 hotbar_imagesize = 48; + v2u32 screensize = driver->getScreenSize(); /* Draw "Loading" screen @@ -992,6 +857,9 @@ void the_game( sound_is_dummy = true; } + Server *server = NULL; + + try{ // Event manager EventManager eventmgr; @@ -1007,9 +875,8 @@ void the_game( /* Create server. - SharedPtr will delete it when it goes out of scope. */ - SharedPtr<Server> server; + if(address == ""){ draw_load_screen(L"Creating server...", driver, font); infostream<<"Creating server"<<std::endl; @@ -1018,7 +885,6 @@ void the_game( server->start(port); } - try{ do{ // Client scope (breakable do-while(0)) /* @@ -1373,6 +1239,12 @@ void the_game( LocalPlayer* player = client.getEnv().getLocalPlayer(); player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; + + /* + HUD object + */ + Hud hud(driver, guienv, font, text_height, + gamedef, player, &local_inventory); for(;;) { @@ -1546,13 +1418,11 @@ void the_game( v2s32 displaycenter(screensize.X/2,screensize.Y/2); //bool screensize_changed = screensize != last_screensize; - // Resize hotbar - if(screensize.Y <= 800) - hotbar_imagesize = 32; - else if(screensize.Y <= 1280) - hotbar_imagesize = 48; - else - hotbar_imagesize = 64; + + // Update HUD values + hud.screensize = screensize; + hud.displaycenter = displaycenter; + hud.resizeHotbar(); // Hilight boxes collected during the loop and displayed std::vector<aabb3f> hilightboxes; @@ -1916,7 +1786,7 @@ void the_game( { s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1, - hotbar_itemcount-1); + hud.hotbar_itemcount-1); if(wheel < 0) { @@ -1940,7 +1810,7 @@ void the_game( const KeyPress *kp = NumberKey + (i + 1) % 10; if(input->wasKeyDown(*kp)) { - if(i < PLAYER_INVENTORY_SIZE && i < hotbar_itemcount) + if(i < PLAYER_INVENTORY_SIZE && i < hud.hotbar_itemcount) { new_playeritem = i; @@ -2227,6 +2097,83 @@ void the_game( { delete_particlespawner (event.delete_particlespawner.id); } + else if (event.type == CE_HUDADD) + { + u32 id = event.hudadd.id; + size_t nhudelem = player->hud.size(); + if (id > nhudelem || (id < nhudelem && player->hud[id])) { + delete event.hudadd.pos; + delete event.hudadd.name; + delete event.hudadd.scale; + delete event.hudadd.text; + continue; + } + + HudElement *e = new HudElement; + e->type = (HudElementType)event.hudadd.type; + e->pos = *event.hudadd.pos; + e->name = *event.hudadd.name; + e->scale = *event.hudadd.scale; + e->text = *event.hudadd.text; + e->number = event.hudadd.number; + e->item = event.hudadd.item; + e->dir = event.hudadd.dir; + + if (id == nhudelem) + player->hud.push_back(e); + else + player->hud[id] = e; + + delete event.hudadd.pos; + delete event.hudadd.name; + delete event.hudadd.scale; + delete event.hudadd.text; + } + else if (event.type == CE_HUDRM) + { + u32 id = event.hudrm.id; + if (id < player->hud.size() && player->hud[id]) { + delete player->hud[id]; + player->hud[id] = NULL; + } + } + else if (event.type == CE_HUDCHANGE) + { + u32 id = event.hudchange.id; + if (id >= player->hud.size() || !player->hud[id]) { + delete event.hudchange.v2fdata; + delete event.hudchange.sdata; + continue; + } + + HudElement* e = player->hud[id]; + switch (event.hudchange.stat) { + case HUD_STAT_POS: + e->pos = *event.hudchange.v2fdata; + break; + case HUD_STAT_NAME: + e->name = *event.hudchange.sdata; + break; + case HUD_STAT_SCALE: + e->scale = *event.hudchange.v2fdata; + break; + case HUD_STAT_TEXT: + e->text = *event.hudchange.sdata; + break; + case HUD_STAT_NUMBER: + e->number = event.hudchange.data; + break; + case HUD_STAT_ITEM: + e->item = event.hudchange.data; + break; + case HUD_STAT_DIR: + e->dir = event.hudchange.data; + break; + } + + delete event.hudchange.v2fdata; + delete event.hudchange.sdata; + } } } @@ -3003,7 +2950,6 @@ void the_game( */ TimeTaker tt_draw("mainloop: draw"); - { TimeTaker timer("beginScene"); @@ -3107,26 +3053,8 @@ void the_game( driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); - if(show_hud) - { - v3f selectionbox_color = g_settings->getV3F("selectionbox_color"); - u32 selectionbox_color_r = rangelim(myround(selectionbox_color.X), 0, 255); - u32 selectionbox_color_g = rangelim(myround(selectionbox_color.Y), 0, 255); - u32 selectionbox_color_b = rangelim(myround(selectionbox_color.Z), 0, 255); - - for(std::vector<aabb3f>::const_iterator - i = hilightboxes.begin(); - i != hilightboxes.end(); i++) - { - /*infostream<<"hilightbox min=" - <<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")" - <<" max=" - <<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->MaxEdge.Z<<")" - <<std::endl;*/ - driver->draw3DBox(*i, video::SColor(255,selectionbox_color_r,selectionbox_color_g,selectionbox_color_b)); - } - } - + if (show_hud) + hud.drawSelectionBoxes(hilightboxes); /* Wielded tool */ @@ -3154,22 +3082,9 @@ void the_game( /* Draw crosshair */ - if(show_hud) - { - v3f crosshair_color = g_settings->getV3F("crosshair_color"); - u32 crosshair_color_r = rangelim(myround(crosshair_color.X), 0, 255); - u32 crosshair_color_g = rangelim(myround(crosshair_color.Y), 0, 255); - u32 crosshair_color_b = rangelim(myround(crosshair_color.Z), 0, 255); - u32 crosshair_alpha = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255); - - driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0), - displaycenter + core::vector2d<s32>(10,0), - video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); - driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10), - displaycenter + core::vector2d<s32>(0,10), - video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); - } - + if (show_hud) + hud.drawCrosshair(); + } // timer //timer10.stop(); @@ -3179,11 +3094,9 @@ void the_game( /* Draw hotbar */ - if(show_hud) + if (show_hud) { - draw_hotbar(driver, font, gamedef, - v2s32(displaycenter.X, screensize.Y), - hotbar_imagesize, hotbar_itemcount, &local_inventory, + hud.drawHotbar(v2s32(displaycenter.X, screensize.Y), client.getHP(), client.getPlayerItem()); } @@ -3211,6 +3124,12 @@ void the_game( } /* + Draw lua hud items + */ + if (show_hud) + hud.drawLuaElements(); + + /* Draw gui */ // 0-1ms @@ -3258,11 +3177,11 @@ void the_game( /* Drop stuff */ - if(clouds) + if (clouds) clouds->drop(); - if(gui_chat_console) + if (gui_chat_console) gui_chat_console->drop(); - clear_particles (); + clear_particles(); /* Draw a "shutting down" screen, which will be shown while the map @@ -3290,14 +3209,44 @@ void the_game( L" running a different version of Minetest."; errorstream<<wide_to_narrow(error_message)<<std::endl; } + catch(ServerError &e) + { + error_message = narrow_to_wide(e.what()); + errorstream<<wide_to_narrow(error_message)<<std::endl; + } + catch(ModError &e) + { + errorstream<<e.what()<<std::endl; + error_message = narrow_to_wide(e.what()) + wgettext("\nCheck debug.txt for details."); + } + + if(!sound_is_dummy) delete sound; + //has to be deleted first to stop all server threads + delete server; + delete tsrc; delete shsrc; delete nodedef; delete itemdef; + + //extended resource accounting + infostream << "Irrlicht resources after cleanup:" << std::endl; + infostream << "\tRemaining meshes : " + << device->getSceneManager()->getMeshCache()->getMeshCount() << std::endl; + infostream << "\tRemaining textures : " + << driver->getTextureCount() << std::endl; + for (unsigned int i = 0; i < driver->getTextureCount(); i++ ) { + irr::video::ITexture* texture = driver->getTextureByIndex(i); + infostream << "\t\t" << i << ":" << texture->getName().getPath().c_str() + << std::endl; + } + infostream << "\tRemaining materials: " + << driver-> getMaterialRendererCount () + << " (note: irrlicht doesn't support removing renderers)"<< std::endl; } diff --git a/src/guiConfigureWorld.cpp b/src/guiConfigureWorld.cpp index 080691222..b2debfbd2 100644 --- a/src/guiConfigureWorld.cpp +++ b/src/guiConfigureWorld.cpp @@ -120,11 +120,12 @@ GUIConfigureWorld::GUIConfigureWorld(gui::IGUIEnvironment* env, } if(!m_new_mod_names.empty()) { + wchar_t* text = wgettext("Warning: Some mods are not configured yet.\n" + "They will be enabled by default when you save the configuration. "); GUIMessageMenu *menu = - new GUIMessageMenu(Environment, Parent, -1, m_menumgr, - wgettext("Warning: Some mods are not configured yet.\n" - "They will be enabled by default when you save the configuration. ")); + new GUIMessageMenu(Environment, Parent, -1, m_menumgr, text); menu->drop(); + delete[] text; } @@ -139,10 +140,11 @@ GUIConfigureWorld::GUIConfigureWorld(gui::IGUIEnvironment* env, } if(!missing_mods.empty()) { + wchar_t* text = wgettext("Warning: Some configured mods are missing.\n" + "Their setting will be removed when you save the configuration. "); GUIMessageMenu *menu = - new GUIMessageMenu(Environment, Parent, -1, m_menumgr, - wgettext("Warning: Some configured mods are missing.\n" - "Their setting will be removed when you save the configuration. ")); + new GUIMessageMenu(Environment, Parent, -1, m_menumgr, text); + delete[] text; for(std::set<std::string>::iterator it = missing_mods.begin(); it != missing_mods.end(); ++it) m_settings.remove("load_mod_"+(*it)); @@ -203,30 +205,36 @@ void GUIConfigureWorld::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 200, 20); rect += v2s32(0, 25) + topleft; + wchar_t* text = wgettext("enabled"); m_enabled_checkbox = Environment->addCheckBox(false, rect, this, GUI_ID_ENABLED_CHECKBOX, - wgettext("enabled")); + text); + delete[] text; m_enabled_checkbox->setVisible(false); } { core::rect<s32> rect(0, 0, 85, 30); rect = rect + v2s32(0, 25) + topleft; + wchar_t* text = wgettext("Enable All"); m_enableall = Environment->addButton(rect, this, GUI_ID_ENABLEALL, - wgettext("Enable All")); + text); + delete[] text; m_enableall->setVisible(false); } { core::rect<s32> rect(0, 0, 85, 30); rect = rect + v2s32(115, 25) + topleft; - m_disableall = Environment->addButton(rect, this, GUI_ID_DISABLEALL, - wgettext("Disable All")); + wchar_t* text = wgettext("Disable All"); + m_disableall = Environment->addButton(rect, this, GUI_ID_DISABLEALL, text ); + delete[] text; m_disableall->setVisible(false); } { core::rect<s32> rect(0, 0, 200, 20); rect += v2s32(0, 60) + topleft; - Environment->addStaticText(wgettext("depends on:"), - rect, false, false, this, -1); + wchar_t* text = wgettext("depends on:"); + Environment->addStaticText(text, rect, false, false, this, -1); + delete[] text; } { core::rect<s32> rect(0, 0, 200, 85); @@ -237,8 +245,9 @@ void GUIConfigureWorld::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 200, 20); rect += v2s32(0, 175) + topleft; - Environment->addStaticText(wgettext("is required by:"), - rect, false, false, this, -1); + wchar_t* text = wgettext("is required by:"); + Environment->addStaticText( text, rect, false, false, this, -1); + delete[] text; } { core::rect<s32> rect(0, 0, 200, 85); @@ -258,14 +267,16 @@ void GUIConfigureWorld::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 120, 30); rect = rect + v2s32(330, 270) - topleft; - Environment->addButton(rect, this, GUI_ID_CANCEL, - wgettext("Cancel")); + wchar_t* text = wgettext("Cancel"); + Environment->addButton(rect, this, GUI_ID_CANCEL, text); + delete[] text; } { core::rect<s32> rect(0, 0, 120, 30); rect = rect + v2s32(460, 270) - topleft; - Environment->addButton(rect, this, GUI_ID_SAVE, - wgettext("Save")); + wchar_t* text = wgettext("Save"); + Environment->addButton(rect, this, GUI_ID_SAVE, text); + delete[] text; } changeCtype("C"); @@ -389,17 +400,21 @@ bool GUIConfigureWorld::OnEvent(const SEvent& event) // bug in the text-size calculation. if the trailing // spaces are removed from the message text, the // message gets wrapped and parts of it are cut off: + wchar_t* text = wgettext("Configuration saved. "); GUIMessageMenu *menu = new GUIMessageMenu(Environment, Parent, -1, m_menumgr, - wgettext("Configuration saved. ")); + text ); + delete[] text; menu->drop(); ModConfiguration modconf(m_wspec.path); if(!modconf.isConsistent()) { - GUIMessageMenu *menu = + wchar_t* text = wgettext("Warning: Configuration not consistent. "); + GUIMessageMenu *menu = new GUIMessageMenu(Environment, Parent, -1, m_menumgr, - wgettext("Warning: Configuration not consistent. ")); + text ); + delete[] text; menu->drop(); } diff --git a/src/guiConfirmMenu.cpp b/src/guiConfirmMenu.cpp index 70e33c760..86b230506 100644 --- a/src/guiConfirmMenu.cpp +++ b/src/guiConfirmMenu.cpp @@ -116,14 +116,18 @@ void GUIConfirmMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, bw, 30); rect = rect + v2s32(size.X/2-bw/2-(bw/2+5), size.Y/2-30/2+5 + msg_h/2); + wchar_t* text = wgettext("Yes"); Environment->addButton(rect, this, GUI_ID_YES, - wgettext("Yes")); + text); + delete[] text; } { core::rect<s32> rect(0, 0, bw, 30); rect = rect + v2s32(size.X/2-bw/2+(bw/2+5), size.Y/2-30/2+5 + msg_h/2); + wchar_t* text = wgettext("No"); Environment->addButton(rect, this, GUI_ID_NO, - wgettext("No")); + text); + delete[] text; } changeCtype("C"); } diff --git a/src/guiCreateWorld.cpp b/src/guiCreateWorld.cpp index 8ac3fb17c..09b18fb3c 100644 --- a/src/guiCreateWorld.cpp +++ b/src/guiCreateWorld.cpp @@ -113,8 +113,9 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 100, 20); rect += v2s32(0, 5) + topleft; - Environment->addStaticText(wgettext("World name"), - rect, false, true, this, -1); + wchar_t* text = wgettext("World name"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } { core::rect<s32> rect(0, 0, 300, 30); @@ -132,8 +133,9 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 100, 20); rect += v2s32(0, 40+5) + topleft; - Environment->addStaticText(wgettext("Game"), - rect, false, true, this, -1); + wchar_t* text = wgettext("Game"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } { core::rect<s32> rect(0, 0, 300, 80); @@ -155,14 +157,18 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 120, 30); rect = rect + v2s32(170, 140) + topleft; + wchar_t* text = wgettext("Create"); Environment->addButton(rect, this, GUI_ID_CREATE, - wgettext("Create")); + text); + delete[] text; } { core::rect<s32> rect(0, 0, 120, 30); rect = rect + v2s32(300, 140) + topleft; + wchar_t* text = wgettext("Cancel"); Environment->addButton(rect, this, GUI_ID_CANCEL, - wgettext("Cancel")); + text); + delete [] text; } changeCtype("C"); } diff --git a/src/guiDeathScreen.cpp b/src/guiDeathScreen.cpp index ba329e3be..dfdce3f8d 100644 --- a/src/guiDeathScreen.cpp +++ b/src/guiDeathScreen.cpp @@ -93,15 +93,19 @@ void GUIDeathScreen::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 400, 50); rect = rect + v2s32(size.X/2-400/2, size.Y/2-50/2-25); - Environment->addStaticText(wgettext("You died."), rect, false, + wchar_t* text = wgettext("You died."); + Environment->addStaticText(text, rect, false, true, this, 256); + delete[] text; } { core::rect<s32> rect(0, 0, 140, 30); rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25); + wchar_t* text = wgettext("Respawn"); gui::IGUIElement *e = Environment->addButton(rect, this, 257, - wgettext("Respawn")); + text); + delete[] text; Environment->setFocus(e); } changeCtype("C"); diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 1754422d0..6ada77698 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -581,6 +581,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) size.Y-rect.getHeight()-5); const wchar_t *text = wgettext("Left click: Move all items, Right click: Move single item"); Environment->addStaticText(text, rect, false, true, this, 256); + delete[] text; changeCtype("C"); } // If there's fields, add a Proceed button @@ -604,7 +605,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) v2s32 size = DesiredRect.getSize(); rect = core::rect<s32>(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y+30); - Environment->addButton(rect, this, 257, wgettext("Proceed")); + wchar_t* text = wgettext("Proceed"); + Environment->addButton(rect, this, 257, text); + delete[] text; } changeCtype("C"); } diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 4569f3d9d..c660ed870 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -75,6 +75,13 @@ GUIModalMenu(env, parent, id, menumgr) GUIKeyChangeMenu::~GUIKeyChangeMenu() { removeChildren(); + + for (std::vector<key_setting*>::iterator iter = key_settings.begin(); + iter != key_settings.end(); iter ++) { + delete[] (*iter)->button_name; + delete (*iter); + } + key_settings.clear(); } void GUIKeyChangeMenu::removeChildren() @@ -111,8 +118,10 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) core::rect < s32 > rect(0, 0, 600, 40); rect += topleft + v2s32(25, 3); //gui::IGUIStaticText *t = - Environment->addStaticText(wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)"), + wchar_t* text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } @@ -132,7 +141,9 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); - k->button = Environment->addButton(rect, this, k->id, wgettext(k->key.name())); + wchar_t* text = wgettext(k->key.name()); + k->button = Environment->addButton(rect, this, k->id, text ); + delete[] text; } if(i + 1 == KMaxButtonPerColumns) offset = v2s32(250, 60); @@ -147,8 +158,10 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, option_w, 30); rect += topleft + v2s32(option_x, option_y); + wchar_t* text = wgettext("\"Use\" = climb down"); Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this, - GUI_ID_CB_AUX1_DESCENDS, wgettext("\"Use\" = climb down")); + GUI_ID_CB_AUX1_DESCENDS, text); + delete[] text; } offset += v2s32(0, 25); } @@ -160,8 +173,10 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, option_w, 30); rect += topleft + v2s32(option_x, option_y); + wchar_t* text = wgettext("Double tap \"jump\" to toggle fly"); Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this, - GUI_ID_CB_DOUBLETAP_JUMP, wgettext("Double tap \"jump\" to toggle fly")); + GUI_ID_CB_DOUBLETAP_JUMP, text); + delete[] text; } offset += v2s32(0, 25); } @@ -169,14 +184,18 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40); + wchar_t* text = wgettext("Save"); Environment->addButton(rect, this, GUI_ID_BACK_BUTTON, - wgettext("Save")); + text); + delete[] text; } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40); + wchar_t* text = wgettext("Cancel"); Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, - wgettext("Cancel")); + text ); + delete[] text; } changeCtype("C"); @@ -230,7 +249,9 @@ bool GUIKeyChangeMenu::resetMenu() key_setting *k = key_settings.at(i); if(k->id == activeKey) { - k->button->setText(wgettext(k->key.name())); + wchar_t* text = wgettext(k->key.name()); + k->button->setText(text); + delete[] text; break; } } @@ -266,8 +287,10 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) { core::rect < s32 > rect(0, 0, 600, 40); rect += v2s32(0, 0) + v2s32(25, 30); - this->key_used_text = Environment->addStaticText(wgettext("Key already in use"), + wchar_t* text = wgettext("Key already in use"); + this->key_used_text = Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; //infostream << "Key already in use" << std::endl; } @@ -284,7 +307,9 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) } assert(k); k->key = kp; - k->button->setText(wgettext(k->key.name())); + wchar_t* text = wgettext(k->key.name()); + k->button->setText(text); + delete[] text; this->key_used.push_back(kp); @@ -344,7 +369,9 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) resetMenu(); shift_down = false; activeKey = event.GUIEvent.Caller->getID(); - k->button->setText(wgettext("press key")); + wchar_t* text = wgettext("press key"); + k->button->setText(text); + delete[] text; this->key_used.erase(std::remove(this->key_used.begin(), this->key_used.end(), k->key), this->key_used.end()); break; @@ -357,11 +384,12 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) return Parent ? Parent->OnEvent(event) : false; } -void GUIKeyChangeMenu::add_key(int id, std::string button_name, std::string setting_name) +void GUIKeyChangeMenu::add_key(int id, wchar_t* button_name, std::string setting_name) { key_setting *k = new key_setting; k->id = id; - k->button_name = wgettext(button_name.c_str()); + + k->button_name = button_name; k->setting_name = setting_name; k->key = getKeySetting(k->setting_name.c_str()); key_settings.push_back(k); @@ -369,21 +397,21 @@ void GUIKeyChangeMenu::add_key(int id, std::string button_name, std::string sett void GUIKeyChangeMenu::init_keys() { - this->add_key(GUI_ID_KEY_FORWARD_BUTTON, gettext("Forward"), "keymap_forward"); - this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, gettext("Backward"), "keymap_backward"); - this->add_key(GUI_ID_KEY_LEFT_BUTTON, gettext("Left"), "keymap_left"); - this->add_key(GUI_ID_KEY_RIGHT_BUTTON, gettext("Right"), "keymap_right"); - this->add_key(GUI_ID_KEY_USE_BUTTON, gettext("Use"), "keymap_special1"); - this->add_key(GUI_ID_KEY_JUMP_BUTTON, gettext("Jump"), "keymap_jump"); - this->add_key(GUI_ID_KEY_SNEAK_BUTTON, gettext("Sneak"), "keymap_sneak"); - this->add_key(GUI_ID_KEY_DROP_BUTTON, gettext("Drop"), "keymap_drop"); - this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, gettext("Inventory"), "keymap_inventory"); - this->add_key(GUI_ID_KEY_CHAT_BUTTON, gettext("Chat"), "keymap_chat"); - this->add_key(GUI_ID_KEY_CMD_BUTTON, gettext("Command"), "keymap_cmd"); - this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, gettext("Console"), "keymap_console"); - this->add_key(GUI_ID_KEY_FLY_BUTTON, gettext("Toggle fly"), "keymap_freemove"); - this->add_key(GUI_ID_KEY_FAST_BUTTON, gettext("Toggle fast"), "keymap_fastmove"); - this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, gettext("Toggle noclip"), "keymap_noclip"); - this->add_key(GUI_ID_KEY_RANGE_BUTTON, gettext("Range select"), "keymap_rangeselect"); - this->add_key(GUI_ID_KEY_DUMP_BUTTON, gettext("Print stacks"), "keymap_print_debug_stacks"); + this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); + this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); + this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); + this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); + this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1"); + this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); + this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); + this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); + this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); + this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); + this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); + this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); + this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); + this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); + this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); + this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); + this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks"); } diff --git a/src/guiKeyChangeMenu.h b/src/guiKeyChangeMenu.h index 2b498676b..833514c1d 100644 --- a/src/guiKeyChangeMenu.h +++ b/src/guiKeyChangeMenu.h @@ -64,7 +64,7 @@ private: bool resetMenu(); - void add_key(int id, std::string setting_name, std::string button_name); + void add_key(int id, wchar_t* button_name, std::string setting_name); bool shift_down; diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 1e3083577..431b40e63 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -89,7 +89,9 @@ struct CreateWorldDestMainMenu : public CreateWorldDest std::string name_narrow = wide_to_narrow(name); if(!string_allowed_blacklist(name_narrow, WORLDNAME_BLACKLISTED_CHARS)) { - m_menu->displayMessageMenu(wgettext("Cannot create world: Name contains invalid characters")); + wchar_t* text = wgettext("Cannot create world: Name contains invalid characters"); + m_menu->displayMessageMenu(text); + delete[] text; return; } std::vector<WorldSpec> worlds = getAvailableWorlds(); @@ -98,7 +100,9 @@ struct CreateWorldDestMainMenu : public CreateWorldDest { if((*i).name == name_narrow) { - m_menu->displayMessageMenu(wgettext("Cannot create world: A world by this name already exists")); + wchar_t* text = wgettext("Cannot create world: A world by this name already exists"); + m_menu->displayMessageMenu(text); + delete[] text; return; } } @@ -280,12 +284,24 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += m_topleft_client + v2s32(0, -30); gui::IGUITabControl *e = Environment->addTabControl( rect, this, true, true, GUI_ID_TAB_CONTROL); - e->addTab(wgettext("Singleplayer")); - e->addTab(wgettext("Multiplayer")); - e->addTab(wgettext("Advanced")); - e->addTab(wgettext("Settings")); - e->addTab(wgettext("Credits")); + wchar_t* text = wgettext("Singleplayer"); + e->addTab(text); + delete[] text; + text = wgettext("Multiplayer"); + e->addTab(text); + delete[] text; + text = wgettext("Advanced"); + e->addTab(text); + delete[] text; + text = wgettext("Settings"); + e->addTab(text); + delete[] text; + text = wgettext("Credits"); + e->addTab(text); + delete[] text; + e->setActiveTab(m_data->selected_tab); + } if(m_data->selected_tab == TAB_SINGLEPLAYER) @@ -313,9 +329,11 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, world_sel_w-4, 20); rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20); + wchar_t* text = wgettext("Select World:"); /*gui::IGUIStaticText *e =*/ Environment->addStaticText( - wgettext("Select World:"), + text, rect, false, true, this, -1); + delete[] text; /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/ } { @@ -335,23 +353,29 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0); + wchar_t* text = wgettext("Delete"); Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON, - wgettext("Delete")); + text); + delete[] text; } // Create world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0); + wchar_t* text = wgettext("New"); Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON, - wgettext("New")); + text); + delete[] text; } // Configure world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2, world_sel_y+world_sel_h+0); + wchar_t* text = wgettext("Configure"); Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON, - wgettext("Configure")); + text); + delete[] text; } // Start game button { @@ -365,8 +389,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, bw, 30); rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw, world_sel_y+world_sel_h+30+bs); + wchar_t* text = wgettext("Play"); Environment->addButton(rect, this, - GUI_ID_JOIN_GAME_BUTTON, wgettext("Play")); + GUI_ID_JOIN_GAME_BUTTON, text); + delete[] text; } // Options s32 option_x = 50; @@ -376,14 +402,18 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*0); + wchar_t* text = wgettext("Creative Mode"); Environment->addCheckBox(m_data->creative_mode, rect, this, - GUI_ID_CREATIVE_CB, wgettext("Creative Mode")); + GUI_ID_CREATIVE_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*1); + wchar_t* text = wgettext("Enable Damage"); Environment->addCheckBox(m_data->enable_damage, rect, this, - GUI_ID_DAMAGE_CB, wgettext("Enable Damage")); + GUI_ID_DAMAGE_CB, text); + delete[] text; } changeCtype("C"); } @@ -402,9 +432,11 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) // Nickname + password { core::rect<s32> rect(0, 0, 110, 20); + wchar_t* text = wgettext("Name/Password"); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6); - Environment->addStaticText(wgettext("Name/Password"), + Environment->addStaticText(text, rect, false, true, this, -1); + delete [] text; } changeCtype("C"); { @@ -467,8 +499,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6); - Environment->addStaticText(wgettext("Address/Port"), + wchar_t* text = wgettext("Address/Port"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete [] text; } changeCtype("C"); { @@ -493,13 +527,17 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 260, 30); rect += m_topleft_client + v2s32(50, 180); + wchar_t* text = wgettext("Show Public"); gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE, - wgettext("Show Public")); + text); + delete[] text; e->setIsPushButton(true); if (m_data->selected_serverlist == SERVERLIST_PUBLIC) { - e->setText(wgettext("Show Favorites")); + wchar_t* text = wgettext("Show Favorites"); + e->setText(text); e->setPressed(); + delete[] text; } } #endif @@ -507,18 +545,23 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(50+260+10, 180); + wchar_t* text = wgettext("Delete"); gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE, - wgettext("Delete")); + text); if (m_data->selected_serverlist == SERVERLIST_PUBLIC) // Hidden when on public list e->setVisible(false); + + delete [] text; } // Start game button { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-130-30, m_size_client.Y-25-15); + wchar_t* text = wgettext("Connect"); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, - wgettext("Connect")); + text); + delete[] text; } changeCtype("C"); } @@ -538,8 +581,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 35+6); - Environment->addStaticText(wgettext("Name/Password"), + wchar_t* text = wgettext("Name/Password"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete [] text; } changeCtype("C"); { @@ -565,8 +610,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 75+6); - Environment->addStaticText(wgettext("Address/Port"), + wchar_t* text = wgettext("Address/Port"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } changeCtype("C"); { @@ -588,16 +635,20 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 400, 20); rect += m_topleft_client + v2s32(160+30, 75+35); - Environment->addStaticText(wgettext("Leave address blank to start a local server."), + wchar_t* text = wgettext("Leave address blank to start a local server."); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } // Start game button { core::rect<s32> rect(0, 0, 180, 30); rect += m_topleft_client + v2s32(m_size_client.X-180-30, m_size_client.Y-30-20); + wchar_t* text = wgettext("Start Game / Connect"); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, - wgettext("Start Game / Connect")); + text); + delete[] text; } /* Server section @@ -615,36 +666,46 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 20); + wchar_t* text = wgettext("Creative Mode"); Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB, - wgettext("Creative Mode")); + text); + delete[] text; } { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 40); + wchar_t* text = wgettext("Enable Damage"); Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB, - wgettext("Enable Damage")); + text); + delete[] text; } #if USE_CURL { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 60); + wchar_t* text = wgettext("Public"); Environment->addCheckBox(m_data->enable_public, rect, this, GUI_ID_PUBLIC_CB, - wgettext("Public")); + text); + delete[] text; } #endif // Delete world button { core::rect<s32> rect(0, 0, 130, 30); rect += m_topleft_server + v2s32(30+20+250+20, 90); + wchar_t* text = wgettext("Delete world"); Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON, - wgettext("Delete world")); + text ); + delete[] text; } // Create world button { core::rect<s32> rect(0, 0, 130, 30); rect += m_topleft_server + v2s32(30+20+250+20+140, 90); + wchar_t* text = wgettext("Create world"); Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON, - wgettext("Create world")); + text ); + delete[] text; } // World selection listbox { @@ -677,26 +738,34 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y); + wchar_t* text = wgettext("Fancy trees"); Environment->addCheckBox(m_data->fancy_trees, rect, this, - GUI_ID_FANCYTREE_CB, wgettext("Fancy trees")); + GUI_ID_FANCYTREE_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20); + wchar_t* text = wgettext("Smooth Lighting"); Environment->addCheckBox(m_data->smooth_lighting, rect, this, - GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting")); + GUI_ID_SMOOTH_LIGHTING_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*2); + wchar_t* text = wgettext("3D Clouds"); Environment->addCheckBox(m_data->clouds_3d, rect, this, - GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds")); + GUI_ID_3D_CLOUDS_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*3); + wchar_t* text = wgettext("Opaque water"); Environment->addCheckBox(m_data->opaque_water, rect, this, - GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water")); + GUI_ID_OPAQUE_WATER_CB, text); + delete[] text; } @@ -705,58 +774,74 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y); + wchar_t* text = wgettext("Mip-Mapping"); Environment->addCheckBox(m_data->mip_map, rect, this, - GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping")); + GUI_ID_MIPMAP_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y+20); + wchar_t* text = wgettext("Anisotropic Filtering"); Environment->addCheckBox(m_data->anisotropic_filter, rect, this, - GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering")); + GUI_ID_ANISOTROPIC_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y+20*2); + wchar_t* text = wgettext("Bi-Linear Filtering"); Environment->addCheckBox(m_data->bilinear_filter, rect, this, - GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering")); + GUI_ID_BILINEAR_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y+20*3); + wchar_t* text = wgettext("Tri-Linear Filtering"); Environment->addCheckBox(m_data->trilinear_filter, rect, this, - GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering")); + GUI_ID_TRILINEAR_CB, text); + delete[] text; } // shader/on demand image loading/particles settings { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y); + wchar_t* text = wgettext("Shaders"); Environment->addCheckBox(m_data->enable_shaders, rect, this, - GUI_ID_SHADERS_CB, wgettext("Shaders")); + GUI_ID_SHADERS_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w+20+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y+20); + wchar_t* text = wgettext("Preload item visuals"); Environment->addCheckBox(m_data->preload_item_visuals, rect, this, - GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals")); + GUI_ID_PRELOAD_ITEM_VISUALS_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w+20+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2); + wchar_t* text = wgettext("Enable Particles"); Environment->addCheckBox(m_data->enable_particles, rect, this, - GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles")); + GUI_ID_ENABLE_PARTICLES_CB, text); + delete[] text; } { core::rect<s32> rect(0, 0, option_w+20+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*3); + wchar_t* text = wgettext("Finite liquid"); Environment->addCheckBox(m_data->liquid_finite, rect, this, - GUI_ID_LIQUID_FINITE_CB, wgettext("Finite liquid")); + GUI_ID_LIQUID_FINITE_CB, text); + delete[] text; } // Key change button @@ -765,8 +850,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) /*rect += m_topleft_client + v2s32(m_size_client.X-120-30, m_size_client.Y-30-20);*/ rect += m_topleft_client + v2s32(option_x, option_y+120); + wchar_t* text = wgettext("Change keys"); Environment->addButton(rect, this, - GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys")); + GUI_ID_CHANGE_KEYS_BUTTON, text); + delete[] text; } changeCtype("C"); } @@ -1080,9 +1167,11 @@ bool GUIMainMenu::OnEvent(const SEvent& event) readInput(&cur); if (getTab() == TAB_MULTIPLAYER && cur.address == L"") { + wchar_t* text = wgettext("Address required."); (new GUIMessageMenu(env, parent, -1, menumgr, - wgettext("Address required.")) + text) )->drop(); + delete[] text; return true; } acceptInput(); @@ -1098,9 +1187,11 @@ bool GUIMainMenu::OnEvent(const SEvent& event) MainMenuData cur; readInput(&cur); if(cur.selected_world == -1){ + wchar_t* text = wgettext("Cannot delete world: Nothing selected"); (new GUIMessageMenu(env, parent, -1, menumgr, - wgettext("Cannot delete world: Nothing selected")) + text) )->drop(); + delete[] text; } else { WorldSpec spec = m_data->worlds[cur.selected_world]; // Get files and directories involved @@ -1110,12 +1201,16 @@ bool GUIMainMenu::OnEvent(const SEvent& event) // Launch confirmation dialog ConfirmDestDeleteWorld *dest = new ConfirmDestDeleteWorld(spec, this, paths); - std::wstring text = wgettext("Delete world"); + wchar_t* text1 = wgettext("Delete world"); + wchar_t* text2 = wgettext("Files to be deleted"); + std::wstring text = text1; text += L" \""; text += narrow_to_wide(spec.name); text += L"\"?\n\n"; - text += wgettext("Files to be deleted"); + text += text2; text += L":\n"; + delete[] text1; + delete[] text2; for(u32 i=0; i<paths.size(); i++){ if(i == 3){ text += L"..."; break; } text += narrow_to_wide(paths[i]) + L"\n"; @@ -1128,10 +1223,12 @@ bool GUIMainMenu::OnEvent(const SEvent& event) case GUI_ID_CREATE_WORLD_BUTTON: { std::vector<SubgameSpec> games = getAvailableGames(); if(games.size() == 0){ + wchar_t* text = wgettext("Cannot create world: No games found"); GUIMessageMenu *menu = new GUIMessageMenu(env, parent, -1, menumgr, - wgettext("Cannot create world: No games found")); + text); menu->drop(); + delete[] text; } else { CreateWorldDest *dest = new CreateWorldDestMainMenu(this); GUICreateWorld *menu = new GUICreateWorld(env, parent, -1, @@ -1145,9 +1242,11 @@ bool GUIMainMenu::OnEvent(const SEvent& event) readInput(&cur); if(cur.selected_world == -1) { + wchar_t* text = wgettext("Cannot configure world: Nothing selected"); (new GUIMessageMenu(env, parent, -1, menumgr, - wgettext("Cannot configure world: Nothing selected")) + text) )->drop(); + delete[] text; } else { @@ -1180,8 +1279,12 @@ bool GUIMainMenu::OnEvent(const SEvent& event) if (m_data->selected_serverlist == SERVERLIST_PUBLIC) // switch to favorite list { m_data->servers = ServerList::getLocal(); - togglebutton->setText(wgettext("Show Public")); - title->setText(wgettext("Favorites:")); + wchar_t* text1 = wgettext("Show Public"); + wchar_t* text2 = wgettext("Favorites:"); + togglebutton->setText(text1); + title->setText(text2); + delete[] text1; + delete[] text2; deletebutton->setVisible(true); updateGuiServerList(); serverlist->setSelected(0); @@ -1190,8 +1293,12 @@ bool GUIMainMenu::OnEvent(const SEvent& event) else // switch to online list { m_data->servers = ServerList::getOnline(); - togglebutton->setText(wgettext("Show Favorites")); - title->setText(wgettext("Public Server List:")); + wchar_t* text1 = wgettext("Show Favorites"); + wchar_t* text2 = wgettext("Public Server List:"); + togglebutton->setText(text1); + title->setText(text2); + delete[] text1; + delete[] text2; deletebutton->setVisible(false); updateGuiServerList(); serverlist->setSelected(0); @@ -1261,8 +1368,10 @@ void GUIMainMenu::deleteWorld(const std::vector<std::string> &paths) // Delete files bool did = fs::DeletePaths(paths); if(!did){ + wchar_t* text = wgettext("Failed to delete all world files"); GUIMessageMenu *menu = new GUIMessageMenu(env, parent, - -1, menumgr, wgettext("Failed to delete all world files")); + -1, menumgr, text); + delete[] text; menu->drop(); } // Quit menu to refresh it diff --git a/src/guiMessageMenu.cpp b/src/guiMessageMenu.cpp index abb31cf2d..c6592e51c 100644 --- a/src/guiMessageMenu.cpp +++ b/src/guiMessageMenu.cpp @@ -104,10 +104,12 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, bw, 30); rect = rect + v2s32(size.X/2-bw/2, size.Y/2-30/2+5 + msg_h/2); + wchar_t* text = wgettext("Proceed"); gui::IGUIElement *e = Environment->addButton(rect, this, 257, - wgettext("Proceed")); + text); Environment->setFocus(e); + delete[] text; } changeCtype("C"); } diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp index e4b77b611..a4d16444d 100644 --- a/src/guiPasswordChange.cpp +++ b/src/guiPasswordChange.cpp @@ -105,8 +105,9 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 110, 20); rect += topleft_client + v2s32(35, ypos+6); - Environment->addStaticText(wgettext("Old Password"), - rect, false, true, this, -1); + wchar_t* text = wgettext("Old Password"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } changeCtype("C"); { @@ -122,8 +123,9 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 110, 20); rect += topleft_client + v2s32(35, ypos+6); - Environment->addStaticText(wgettext("New Password"), - rect, false, true, this, -1); + wchar_t* text = wgettext("New Password"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } changeCtype("C"); { @@ -138,8 +140,9 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 110, 20); rect += topleft_client + v2s32(35, ypos+6); - Environment->addStaticText(wgettext("Confirm Password"), - rect, false, true, this, -1); + wchar_t* text = wgettext("Confirm Password"); + Environment->addStaticText(text, rect, false, true, this, -1); + delete[] text; } changeCtype("C"); { @@ -155,18 +158,22 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 140, 30); rect = rect + v2s32(size.X/2-140/2, ypos); - Environment->addButton(rect, this, ID_change, wgettext("Change")); + wchar_t* text = wgettext("Change"); + Environment->addButton(rect, this, ID_change, text); + delete[] text; } ypos += 50; { core::rect<s32> rect(0, 0, 300, 20); rect += topleft_client + v2s32(35, ypos); + wchar_t* text = wgettext("Passwords do not match!"); IGUIElement *e = Environment->addStaticText( - wgettext("Passwords do not match!"), + text, rect, false, true, this, ID_message); e->setVisible(false); + delete[] text; } changeCtype("C"); diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index dc95eef5b..b57b4a1d1 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -119,8 +119,10 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); + wchar_t* text = wgettext("Continue"); Environment->addButton(rect, this, 256, - wgettext("Continue")); + text); + delete[] text; } btn_y += btn_height + btn_gap; if(!m_simple_singleplayer_mode) @@ -128,48 +130,58 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); + wchar_t* text = wgettext("Change Password"); Environment->addButton(rect, this, 261, - wgettext("Change Password")); + text); + delete[] text; } btn_y += btn_height + btn_gap; } { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); + wchar_t* text = wgettext("Sound Volume"); Environment->addButton(rect, this, 262, - wgettext("Sound Volume")); + text); + delete[] text; } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); + wchar_t* text = wgettext("Exit to Menu"); Environment->addButton(rect, this, 260, - wgettext("Exit to Menu")); + text); + delete[] text; } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); + wchar_t* text = wgettext("Exit to OS"); Environment->addButton(rect, this, 257, - wgettext("Exit to OS")); + text); + delete[] text; } { core::rect<s32> rect(0, 0, 180, 240); rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); - Environment->addStaticText(chartowchar_t(gettext( - "Default Controls:\n" - "- WASD: Walk\n" - "- Mouse left: dig/hit\n" - "- Mouse right: place/use\n" - "- Mouse wheel: select item\n" - "- 0...9: select item\n" - "- Shift: sneak\n" - "- R: Toggle viewing all loaded chunks\n" - "- I: Inventory menu\n" - "- ESC: This menu\n" - "- T: Chat\n" - )), rect, false, true, this, 258); + wchar_t* text = wgettext("Default Controls:\n" + "- WASD: Walk\n" + "- Mouse left: dig/hit\n" + "- Mouse right: place/use\n" + "- Mouse wheel: select item\n" + "- 0...9: select item\n" + "- Shift: sneak\n" + "- R: Toggle viewing all loaded chunks\n" + "- I: Inventory menu\n" + "- ESC: This menu\n" + "- T: Chat\n" + ); + Environment->addStaticText(text, rect, false, true, this, 258); + delete[] text; + } { core::rect<s32> rect(0, 0, 180, 220); diff --git a/src/guiTextInputMenu.cpp b/src/guiTextInputMenu.cpp index f4e3bb5ba..c15eeedc5 100644 --- a/src/guiTextInputMenu.cpp +++ b/src/guiTextInputMenu.cpp @@ -127,8 +127,10 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 140, 30); rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25); + wchar_t* text = wgettext("Proceed"); Environment->addButton(rect, this, 257, - wgettext("Proceed")); + text); + delete[] text; } changeCtype("C"); } diff --git a/src/guiVolumeChange.cpp b/src/guiVolumeChange.cpp index cfb89da1c..4e92b82c2 100644 --- a/src/guiVolumeChange.cpp +++ b/src/guiVolumeChange.cpp @@ -105,8 +105,10 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 120, 20); rect = rect + v2s32(size.X/2-60, size.Y/2-35); - Environment->addStaticText(wgettext("Sound Volume: "), rect, false, + wchar_t* text = wgettext("Sound Volume: "); + Environment->addStaticText(text, rect, false, true, this, ID_soundText1); + delete[] text; } { core::rect<s32> rect(0, 0, 30, 20); @@ -117,8 +119,10 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 80, 30); rect = rect + v2s32(size.X/2-80/2, size.Y/2+55); + wchar_t* text = wgettext("Exit"); Environment->addButton(rect, this, ID_soundExitButton, - wgettext("Exit")); + text); + delete[] text; } { core::rect<s32> rect(0, 0, 300, 20); diff --git a/src/hud.cpp b/src/hud.cpp new file mode 100644 index 000000000..349c55add --- /dev/null +++ b/src/hud.cpp @@ -0,0 +1,291 @@ +/* +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2010-2013 blue42u, Jonathon Anderson <anderjon@umail.iu.edu> +Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +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 <IGUIStaticText.h> + +#include "guiFormSpecMenu.h" +#include "main.h" +#include "util/numeric.h" +#include "log.h" +#include "client.h" +#include "hud.h" + + +Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, + gui::IGUIFont *font, u32 text_height, IGameDef *gamedef, + LocalPlayer *player, Inventory *inventory) { + this->driver = driver; + this->guienv = guienv; + this->font = font; + this->text_height = text_height; + this->gamedef = gamedef; + this->player = player; + this->inventory = inventory; + + screensize = v2u32(0, 0); + displaycenter = v2s32(0, 0); + hotbar_imagesize = 48; + hotbar_itemcount = 8; + + v3f crosshair_color = g_settings->getV3F("crosshair_color"); + u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255); + u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255); + u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255); + u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255); + crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b); + + v3f selectionbox_color = g_settings->getV3F("selectionbox_color"); + u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255); + u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255); + u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255); + selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b); +} + + +//NOTE: selectitem = 0 -> no selected; selectitem 1-based +void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount, + InventoryList *mainlist, u16 selectitem, u16 direction) +{ + s32 padding = imgsize / 12; + s32 height = imgsize + padding * 2; + s32 width = itemcount * (imgsize + padding * 2); + if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) { + width = imgsize + padding * 2; + height = itemcount * (imgsize + padding * 2); + } + s32 fullimglen = imgsize + padding * 2; + + // Position of upper left corner of bar + v2s32 pos = upperleftpos; + + // Draw background color + /*core::rect<s32> barrect(0,0,width,height); + barrect += pos; + video::SColor bgcolor(255,128,128,128); + driver->draw2DRectangle(bgcolor, barrect, NULL);*/ + + core::rect<s32> imgrect(0, 0, imgsize, imgsize); + + for (s32 i = 0; i < itemcount; i++) + { + const ItemStack &item = mainlist->getItem(i); + + v2s32 steppos; + switch (direction) { + case HUD_DIR_RIGHT_LEFT: + steppos = v2s32(-(padding + i * fullimglen), padding); + break; + case HUD_DIR_TOP_BOTTOM: + steppos = v2s32(padding, padding + i * fullimglen); + break; + case HUD_DIR_BOTTOM_TOP: + steppos = v2s32(padding, -(padding + i * fullimglen)); + break; + default: + steppos = v2s32(padding + i * fullimglen, padding); + } + + core::rect<s32> rect = imgrect + pos + steppos; + + if (selectitem == i + 1) + { + video::SColor c_outside(255,255,0,0); + //video::SColor c_outside(255,0,0,0); + //video::SColor c_inside(255,192,192,192); + s32 x1 = rect.UpperLeftCorner.X; + s32 y1 = rect.UpperLeftCorner.Y; + s32 x2 = rect.LowerRightCorner.X; + s32 y2 = rect.LowerRightCorner.Y; + // Black base borders + driver->draw2DRectangle(c_outside, + core::rect<s32>( + v2s32(x1 - padding, y1 - padding), + v2s32(x2 + padding, y1) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect<s32>( + v2s32(x1 - padding, y2), + v2s32(x2 + padding, y2 + padding) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect<s32>( + v2s32(x1 - padding, y1), + v2s32(x1, y2) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect<s32>( + v2s32(x2, y1), + v2s32(x2 + padding, y2) + ), NULL); + /*// Light inside borders + driver->draw2DRectangle(c_inside, + core::rect<s32>( + v2s32(x1 - padding/2, y1 - padding/2), + v2s32(x2 + padding/2, y1) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect<s32>( + v2s32(x1 - padding/2, y2), + v2s32(x2 + padding/2, y2 + padding/2) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect<s32>( + v2s32(x1 - padding/2, y1), + v2s32(x1, y2) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect<s32>( + v2s32(x2, y1), + v2s32(x2 + padding/2, y2) + ), NULL); + */ + } + + video::SColor bgcolor2(128, 0, 0, 0); + driver->draw2DRectangle(bgcolor2, rect, NULL); + drawItemStack(driver, font, item, rect, NULL, gamedef); + } +} + + +void Hud::drawLuaElements() { + for (size_t i = 0; i != player->hud.size(); i++) { + HudElement *e = player->hud[i]; + if (!e) + continue; + + v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y); + switch (e->type) { + case HUD_ELEM_IMAGE: { + video::ITexture *texture = + gamedef->getTextureSource()->getTextureRaw(e->text); + if (!texture) + continue; + + const video::SColor color(255, 255, 255, 255); + const video::SColor colors[] = {color, color, color, color}; + core::dimension2di imgsize(texture->getOriginalSize()); + core::rect<s32> rect(0, 0, imgsize.Width * e->scale.X, + imgsize.Height * e->scale.X); + rect += pos; + driver->draw2DImage(texture, rect, + core::rect<s32>(core::position2d<s32>(0,0), imgsize), + NULL, colors, true); + break; } + case HUD_ELEM_TEXT: { + video::SColor color(255, (e->number >> 16) & 0xFF, + (e->number >> 8) & 0xFF, + (e->number >> 0) & 0xFF); + core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y); + font->draw(narrow_to_wide(e->text).c_str(), size + pos, color); + break; } + case HUD_ELEM_STATBAR: + drawStatbar(pos, e->text, e->number); + break; + case HUD_ELEM_INVENTORY: { + InventoryList *inv = inventory->getList(e->text); + drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir); + break; } + default: + infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << + "of hud element ID " << i << " due to unrecognized type" << std::endl; + } + } +} + + +void Hud::drawStatbar(v2s32 upperleftpos, std::string texture, s32 count) { + video::ITexture *stat_texture = + gamedef->getTextureSource()->getTextureRaw(texture); + if (!stat_texture) + return; + + v2s32 p = upperleftpos; + for (s32 i = 0; i < count / 2; i++) + { + core::dimension2di srcd(stat_texture->getOriginalSize()); + const video::SColor color(255, 255, 255, 255); + const video::SColor colors[] = {color, color, color, color}; + core::rect<s32> rect(0, 0, srcd.Width, srcd.Height); + rect += p; + driver->draw2DImage(stat_texture, rect, + core::rect<s32>(core::position2d<s32>(0, 0), srcd), + NULL, colors, true); + p += v2s32(srcd.Width, 0); + } + + if (count % 2 == 1) + { + core::dimension2di srcd(stat_texture->getOriginalSize()); + const video::SColor color(255, 255, 255, 255); + const video::SColor colors[] = {color, color, color, color}; + core::rect<s32> rect(0, 0, srcd.Width / 2, srcd.Height); + rect += p; + srcd.Width /= 2; + driver->draw2DImage(stat_texture, rect, + core::rect<s32>(core::position2d<s32>(0, 0), srcd), + NULL, colors, true); + p += v2s32(srcd.Width * 2, 0); + } +} + + +void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) { + InventoryList *mainlist = inventory->getList("main"); + if (mainlist == NULL) { + errorstream << "draw_hotbar(): mainlist == NULL" << std::endl; + return; + } + + s32 padding = hotbar_imagesize / 12; + s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2); + v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2); + + drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0); + drawStatbar(pos + v2s32(0, -20), "heart.png", halfheartcount); +} + + +void Hud::drawCrosshair() { + driver->draw2DLine(displaycenter - v2s32(10,0), + displaycenter + v2s32(10, 0), crosshair_argb); + driver->draw2DLine(displaycenter - v2s32(0,10), + displaycenter + v2s32(0, 10), crosshair_argb); +} + + +void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) { + for (std::vector<aabb3f>::const_iterator + i = hilightboxes.begin(); + i != hilightboxes.end(); i++) { + driver->draw3DBox(*i, selectionbox_argb); + } +} + + +void Hud::resizeHotbar() { + if (screensize.Y <= 800) + hotbar_imagesize = 32; + else if (screensize.Y <= 1280) + hotbar_imagesize = 48; + else + hotbar_imagesize = 64; +} diff --git a/src/hud.h b/src/hud.h new file mode 100644 index 000000000..7e00a94e3 --- /dev/null +++ b/src/hud.h @@ -0,0 +1,116 @@ +/* +Minetest +Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +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. +*/ + +#ifndef HUD_HEADER +#define HUD_HEADER + +#include "irrlichttypes_extrabloated.h" + +#define HUD_DIR_LEFT_RIGHT 0 +#define HUD_DIR_RIGHT_LEFT 1 +#define HUD_DIR_TOP_BOTTOM 2 +#define HUD_DIR_BOTTOM_TOP 3 + +class Player; + +enum HudElementType { + HUD_ELEM_IMAGE = 0, + HUD_ELEM_TEXT = 1, + HUD_ELEM_STATBAR = 2, + HUD_ELEM_INVENTORY = 3 +}; + +enum HudElementStat { + HUD_STAT_POS, + HUD_STAT_NAME, + HUD_STAT_SCALE, + HUD_STAT_TEXT, + HUD_STAT_NUMBER, + HUD_STAT_ITEM, + HUD_STAT_DIR +}; + +struct HudElement { + HudElementType type; + v2f pos; + std::string name; + v2f scale; + std::string text; + u32 number; + u32 item; + u32 dir; +}; + + +inline u32 hud_get_free_id(Player *player) { + size_t size = player->hud.size(); + for (size_t i = 0; i != size; i++) { + if (!player->hud[i]) + return i; + } + return size; +} + +#ifndef SERVER + +#include <deque> + +#include <IGUIFont.h> + +#include "gamedef.h" +#include "inventory.h" +#include "localplayer.h" + +class Hud { +public: + video::IVideoDriver *driver; + gui::IGUIEnvironment *guienv; + gui::IGUIFont *font; + u32 text_height; + IGameDef *gamedef; + LocalPlayer *player; + Inventory *inventory; + + v2u32 screensize; + v2s32 displaycenter; + s32 hotbar_imagesize; + s32 hotbar_itemcount; + + video::SColor crosshair_argb; + video::SColor selectionbox_argb; + + Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, + gui::IGUIFont *font, u32 text_height, IGameDef *gamedef, + LocalPlayer *player, Inventory *inventory); + + void drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount, + InventoryList *mainlist, u16 selectitem, u16 direction); + void drawLuaElements(); + void drawStatbar(v2s32 upperleftpos, std::string texture, s32 count); + + void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem); + void resizeHotbar(); + + void drawCrosshair(); + void drawSelectionBoxes(std::vector<aabb3f> &hilightboxes); +}; + +#endif + +#endif diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 72ce0e654..784919ae2 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -226,8 +226,15 @@ class CItemDefManager: public IWritableItemDefManager public: CItemDefManager() { + for (std::map<std::string, ItemDefinition*>::iterator iter = + m_item_definitions.begin(); iter != m_item_definitions.end(); + iter ++) { + delete iter->second; + } + m_item_definitions.clear(); #ifndef SERVER m_main_thread = get_current_thread_id(); + m_driver = NULL; #endif clear(); @@ -241,7 +248,16 @@ public: { ClientCached *cc = *i; cc->wield_mesh->drop(); + delete cc; + } + + if (m_driver != NULL) { + for (unsigned int i = 0; i < m_extruded_textures.size(); i++) { + m_driver->removeTexture(m_extruded_textures[i]); + } + m_extruded_textures.clear(); } + m_driver = NULL; #endif } virtual const ItemDefinition& get(const std::string &name_) const @@ -290,6 +306,10 @@ public: return m_item_definitions.find(name) != m_item_definitions.end(); } #ifndef SERVER +private: + static video::IVideoDriver * m_driver; + static std::vector<video::ITexture*> m_extruded_textures; +public: ClientCached* createClientCachedDirect(const std::string &name, IGameDef *gamedef) const { @@ -328,11 +348,7 @@ public: } // Create a wield mesh - if(cc->wield_mesh != NULL) - { - cc->wield_mesh->drop(); - cc->wield_mesh = NULL; - } + assert(cc->wield_mesh == NULL); if(def->type == ITEM_NODE && def->wield_image == "") { need_node_mesh = true; @@ -432,20 +448,27 @@ public: tsrc->getTextureRaw(f.tiledef[0].name); } } + else + { + if (m_driver == 0) + m_driver = driver; + + m_extruded_textures.push_back(cc->inventory_texture); + } /* Use the node mesh as the wield mesh */ - if(cc->wield_mesh == NULL) - { - // Scale to proper wield mesh proportions - scaleMesh(node_mesh, v3f(30.0, 30.0, 30.0) - * def->wield_scale); - cc->wield_mesh = node_mesh; - cc->wield_mesh->grab(); - } - // falling outside of here deletes node_mesh + // Scale to proper wield mesh proportions + scaleMesh(node_mesh, v3f(30.0, 30.0, 30.0) + * def->wield_scale); + + cc->wield_mesh = node_mesh; + cc->wield_mesh->grab(); + + //no way reference count can be smaller than 2 in this place! + assert(cc->wield_mesh->getReferenceCount() >= 2); } // Put in cache @@ -658,3 +681,8 @@ IWritableItemDefManager* createItemDefManager() return new CItemDefManager(); } +#ifndef SERVER +//TODO very very very dirty hack! +video::IVideoDriver * CItemDefManager::m_driver = 0; +std::vector<video::ITexture*> CItemDefManager::m_extruded_textures; +#endif diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 9c70c8b2f..6b7b0943c 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -329,6 +329,9 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, if(!touching_ground_was && touching_ground){ MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround"); m_gamedef->event()->put(e); + + // Set camera impact value to be used for view bobbing + camera_impact = getSpeed().Y * -1; } { diff --git a/src/localplayer.h b/src/localplayer.h index 9ac2bc682..8c3041c04 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -59,6 +59,8 @@ public: float last_yaw; unsigned int last_keyPressed; + float camera_impact; + private: // This is used for determining the sneaking range v3s16 m_sneak_node; diff --git a/src/main.cpp b/src/main.cpp index 08af6a37d..eef65cdb2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1501,7 +1501,9 @@ int main(int argc, char *argv[]) while(device->run() && kill == false) { // Set the window caption - device->setWindowCaption((std::wstring(L"Minetest [")+wgettext("Main Menu")+L"]").c_str()); + wchar_t* text = wgettext("Main Menu"); + device->setWindowCaption((std::wstring(L"Minetest [")+text+L"]").c_str()); + delete[] text; // This is used for catching disconnects try @@ -1902,16 +1904,6 @@ int main(int argc, char *argv[]) error_message = wgettext("Connection error (timed out?)"); errorstream<<wide_to_narrow(error_message)<<std::endl; } - catch(ServerError &e) - { - error_message = narrow_to_wide(e.what()); - errorstream<<wide_to_narrow(error_message)<<std::endl; - } - catch(ModError &e) - { - errorstream<<e.what()<<std::endl; - error_message = narrow_to_wide(e.what()) + wgettext("\nCheck debug.txt for details."); - } #ifdef NDEBUG catch(std::exception &e) { diff --git a/src/map.cpp b/src/map.cpp index a8201f3ee..c4884a45a 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2494,6 +2494,8 @@ ServerMap::~ServerMap() delete chunk; } #endif + + delete m_mgparams; } bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 22488bc4c..0646a8826 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -94,7 +94,7 @@ void Ore::resolveNodeNames(INodeDefManager *ndef) { } -void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { +void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { int in_range = 0; in_range |= (nmin.Y <= height_max && nmax.Y >= height_min); @@ -105,9 +105,6 @@ void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { resolveNodeNames(mg->ndef); - MapNode n_ore(ore); - ManualMapVoxelManipulator *vm = mg->vm; - PseudoRandom pr(blockseed); int ymin, ymax; if (in_range & ORE_RANGE_MIRROR) { @@ -120,6 +117,17 @@ void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { if (clust_size >= ymax - ymin + 1) return; + nmin.Y = ymin; + nmax.Y = ymax; + generate(mg->vm, mg->seed, blockseed, nmin, nmax); +} + + +void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed, + u32 blockseed, v3s16 nmin, v3s16 nmax) { + PseudoRandom pr(blockseed); + MapNode n_ore(ore, 0, ore_param2); + int volume = (nmax.X - nmin.X + 1) * (nmax.Y - nmin.Y + 1) * (nmax.Z - nmin.Z + 1); @@ -129,10 +137,10 @@ void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { for (int i = 0; i != nclusters; i++) { int x0 = pr.range(nmin.X, nmax.X - csize + 1); - int y0 = pr.range(ymin, ymax - csize + 1); + int y0 = pr.range(nmin.Y, nmax.Y - csize + 1); int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); - if (np && (NoisePerlin3D(np, x0, y0, z0, mg->seed) < nthresh)) + if (np && (NoisePerlin3D(np, x0, y0, z0, seed) < nthresh)) continue; for (int z1 = 0; z1 != csize; z1++) @@ -149,53 +157,25 @@ void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { } -void OreSheet::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { - int in_range = 0; - - in_range |= (nmin.Y <= height_max && nmax.Y >= height_min); - if (flags & OREFLAG_ABSHEIGHT) - in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1; - if (!in_range) - return; - - resolveNodeNames(mg->ndef); - - MapNode n_ore(ore); - ManualMapVoxelManipulator *vm = mg->vm; +void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed, + u32 blockseed, v3s16 nmin, v3s16 nmax) { PseudoRandom pr(blockseed + 4234); - int ymin, ymax; - - if (in_range & ORE_RANGE_MIRROR) { - ymin = MYMAX(nmin.Y, -height_max); - ymax = MYMIN(nmax.Y, -height_min); - } else { - ymin = MYMAX(nmin.Y, height_min); - ymax = MYMIN(nmax.Y, height_max); - } - - if (clust_size >= ymax - ymin + 1) - return; - - int x0 = nmin.X; - int z0 = nmin.Z; - - int x1 = nmax.X; - int z1 = nmax.Z; + MapNode n_ore(ore, 0, ore_param2); int max_height = clust_size; - int y_start = pr.range(ymin, ymax - max_height); + int y_start = pr.range(nmin.Y, nmax.Y - max_height); if (!noise) { int sx = nmax.X - nmin.X + 1; int sz = nmax.Z - nmin.Z + 1; noise = new Noise(np, 0, sx, sz); } - noise->seed = mg->seed + y_start; - noise->perlinMap2D(x0, z0); + noise->seed = seed + y_start; + noise->perlinMap2D(nmin.X, nmin.Z); int index = 0; - for (int z = z0; z != z1; z++) - for (int x = x0; x != x1; x++) { + for (int z = nmin.Z; z <= nmax.Z; z++) + for (int x = nmin.X; x <= nmax.X; x++) { float noiseval = noise->result[index++]; if (noiseval < nthresh) continue; diff --git a/src/mapgen.h b/src/mapgen.h index e708f23b1..17136a137 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -120,7 +120,6 @@ class Ore { public: std::string ore_name; std::string wherein_name; - content_t ore; content_t wherein; // the node to be replaced u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing at a node @@ -128,6 +127,7 @@ public: s16 clust_size; // how large (in nodes) a chunk of ore is s16 height_min; s16 height_max; + u8 ore_param2; // to set node-specific attributes u32 flags; // attributes for this ore float nthresh; // threshhold for noise at which an ore is placed NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering) @@ -141,15 +141,19 @@ public: } void resolveNodeNames(INodeDefManager *ndef); - virtual void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) = 0; + void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + virtual void generate(ManualMapVoxelManipulator *vm, int seed, + u32 blockseed, v3s16 nmin, v3s16 nmax) = 0; }; class OreScatter : public Ore { - void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + virtual void generate(ManualMapVoxelManipulator *vm, int seed, + u32 blockseed, v3s16 nmin, v3s16 nmax); }; class OreSheet : public Ore { - void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + virtual void generate(ManualMapVoxelManipulator *vm, int seed, + u32 blockseed, v3s16 nmin, v3s16 nmax); }; Ore *createOre(OreType type); diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 4a037bb85..2e44d7b4a 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -467,7 +467,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) { // Generate the registered ores for (unsigned int i = 0; i != emerge->ores.size(); i++) { Ore *ore = emerge->ores[i]; - ore->generate(this, blockseed + i, node_min, node_max); + ore->placeOre(this, blockseed + i, node_min, node_max); } // Calculate lighting diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 6aecfe310..8aad37f73 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -180,7 +180,7 @@ void MapgenV7::makeChunk(BlockMakeData *data) { for (size_t i = 0; i != emerge->ores.size(); i++) { Ore *ore = emerge->ores[i]; - ore->generate(this, blockseed + i, node_min, node_max); + ore->placeOre(this, blockseed + i, node_min, node_max); } //printf("makeChunk: %dms\n", t.stop()); diff --git a/src/mesh.cpp b/src/mesh.cpp index c2e6bcaa4..da0dbe442 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -246,6 +246,8 @@ static scene::IAnimatedMesh* extrudeARGB(u32 twidth, u32 theight, u8 *data) } } + delete[] solidity; + // Add to mesh scene::SMesh *mesh = new scene::SMesh(); mesh->addMeshBuffer(buf); diff --git a/src/pathfinder.cpp b/src/pathfinder.cpp index c7621177e..0d1cfe476 100644 --- a/src/pathfinder.cpp +++ b/src/pathfinder.cpp @@ -687,9 +687,8 @@ bool pathfinder::update_all_costs( v3s16 ipos, if ((g_pos2.totalcost < 0) || (g_pos2.totalcost > new_cost)) { - int old_cost = g_pos2.totalcost; DEBUG_OUT(LVL "Pathfinder: updating path at: "<< - PPOS(ipos2) << " from: " << old_cost << " to "<< + PPOS(ipos2) << " from: " << g_pos2.totalcost << " to "<< new_cost << std::endl); if (update_all_costs(ipos2,invert(directions[i]), new_cost,level)) { @@ -847,9 +846,8 @@ bool pathfinder::update_cost_heuristic( v3s16 ipos, if ((g_pos2.totalcost < 0) || (g_pos2.totalcost > new_cost)) { - int old_cost = g_pos2.totalcost; DEBUG_OUT(LVL "Pathfinder: updating path at: "<< - PPOS(ipos2) << " from: " << old_cost << " to "<< + PPOS(ipos2) << " from: " << g_pos2.totalcost << " to "<< new_cost << " srcdir=" << PPOS(invert(direction))<< std::endl); if (update_cost_heuristic(ipos2,invert(direction), diff --git a/src/player.h b/src/player.h index d95e535ff..d0e50d2c3 100644 --- a/src/player.h +++ b/src/player.h @@ -87,6 +87,7 @@ class Map; class IGameDef; struct CollisionInfo; class PlayerSAO; +class HudElement; class Player { @@ -242,6 +243,8 @@ public: } u32 keyPressed; + + std::vector<HudElement *> hud; protected: IGameDef *m_gamedef; @@ -253,6 +256,7 @@ protected: v3f m_position; }; + /* Player on the server */ diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 0227c6a19..8d472e6b8 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -670,6 +670,7 @@ static int l_register_ore(lua_State *L) } ore->ore_name = getstringfield_default(L, index, "ore", ""); + ore->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0); ore->wherein_name = getstringfield_default(L, index, "wherein", ""); ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1); ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1); diff --git a/src/scriptapi_craft.cpp b/src/scriptapi_craft.cpp index 183eeb840..459908237 100644 --- a/src/scriptapi_craft.cpp +++ b/src/scriptapi_craft.cpp @@ -330,8 +330,7 @@ int l_get_craft_result(lua_State *L) // get_craft_recipe(result item) int l_get_craft_recipe(lua_State *L) { - int k = 0; - char tmp[20]; + int k = 1; int input_i = 1; std::string o_item = luaL_checkstring(L,input_i); @@ -351,8 +350,7 @@ int l_get_craft_recipe(lua_State *L) { continue; } - sprintf(tmp,"%d",k); - lua_pushstring(L,tmp); + lua_pushinteger(L,k); lua_pushstring(L,i->name.c_str()); lua_settable(L, -3); } @@ -383,9 +381,7 @@ int l_get_craft_recipe(lua_State *L) // get_all_craft_recipes(result item) int l_get_all_craft_recipes(lua_State *L) { - char tmp[20]; - int input_i = 1; - std::string o_item = luaL_checkstring(L,input_i); + std::string o_item = luaL_checkstring(L,1); IGameDef *gdef = get_server(L); ICraftDefManager *cdef = gdef->cdef(); CraftInput input; @@ -402,7 +398,7 @@ int l_get_all_craft_recipes(lua_State *L) int table_insert = lua_gettop(L); lua_newtable(L); int table = lua_gettop(L); - for(std::vector<CraftDefinition*>::const_iterator + for (std::vector<CraftDefinition*>::const_iterator i = recipes_list.begin(); i != recipes_list.end(); i++) { @@ -411,28 +407,29 @@ int l_get_all_craft_recipes(lua_State *L) tmpout.time = 0; CraftDefinition *def = *i; tmpout = def->getOutput(input, gdef); - if(tmpout.item.substr(0,output.item.length()) == output.item) + std::string query = tmpout.item; + char *fmtpos, *fmt = &query[0]; + if (strtok_r(fmt, " ", &fmtpos) == output.item) { input = def->getInput(output, gdef); lua_pushvalue(L, table_insert); lua_pushvalue(L, table); lua_newtable(L); - int k = 0; + int k = 1; lua_newtable(L); for(std::vector<ItemStack>::const_iterator i = input.items.begin(); i != input.items.end(); i++, k++) { - if (i->empty()) continue; - sprintf(tmp,"%d",k); - lua_pushstring(L,tmp); - lua_pushstring(L,i->name.c_str()); + if (i->empty()) + continue; + lua_pushinteger(L, k); + lua_pushstring(L, i->name.c_str()); lua_settable(L, -3); } lua_setfield(L, -2, "items"); setintfield(L, -1, "width", input.width); - switch (input.method) - { + switch (input.method) { case CRAFT_METHOD_NORMAL: lua_pushstring(L,"normal"); break; @@ -446,8 +443,10 @@ int l_get_all_craft_recipes(lua_State *L) lua_pushstring(L,"unknown"); } lua_setfield(L, -2, "type"); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + lua_pushstring(L, &tmpout.item[0]); + lua_setfield(L, -2, "output"); + if (lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); } } return 1; diff --git a/src/scriptapi_env.cpp b/src/scriptapi_env.cpp index 9bf7f0b55..efed58e66 100644 --- a/src/scriptapi_env.cpp +++ b/src/scriptapi_env.cpp @@ -662,9 +662,11 @@ int EnvRef::l_line_of_sight(lua_State *L) { v3f pos2 = checkFloatPos(L, 2); //read step size from lua if(lua_isnumber(L, 3)) - stepsize = lua_tonumber(L, 3); + stepsize = lua_tonumber(L, 3); - return (env->line_of_sight(pos1,pos2,stepsize)); + lua_pushboolean(L, env->line_of_sight(pos1,pos2,stepsize)); + + return 1; } int EnvRef::l_find_path(lua_State *L) diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp index 05433a598..531bb7a58 100644 --- a/src/scriptapi_object.cpp +++ b/src/scriptapi_object.cpp @@ -26,6 +26,30 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "scriptapi_item.h" #include "scriptapi_entity.h" #include "scriptapi_common.h" +#include "hud.h" + + +struct EnumString es_HudElementType[] = +{ + {HUD_ELEM_IMAGE, "image"}, + {HUD_ELEM_TEXT, "text"}, + {HUD_ELEM_STATBAR, "statbar"}, + {HUD_ELEM_INVENTORY, "inventory"}, + {0, NULL}, +}; + +struct EnumString es_HudElementStat[] = +{ + {HUD_STAT_POS, "pos"}, + {HUD_STAT_NAME, "name"}, + {HUD_STAT_SCALE, "scale"}, + {HUD_STAT_TEXT, "text"}, + {HUD_STAT_NUMBER, "number"}, + {HUD_STAT_ITEM, "item"}, + {HUD_STAT_DIR, "direction"}, + {0, NULL}, +}; + /* ObjectRef @@ -700,6 +724,165 @@ int ObjectRef::l_get_player_control_bits(lua_State *L) return 1; } +// hud_add(self, form) +int ObjectRef::l_hud_add(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + HudElement *elem = new HudElement; + + elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type", + es_HudElementType, HUD_ELEM_TEXT); + + lua_getfield(L, 2, "position"); + elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "scale"); + elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + elem->name = getstringfield_default(L, 2, "name", ""); + elem->text = getstringfield_default(L, 2, "text", ""); + elem->number = getintfield_default(L, 2, "number", 0); + elem->item = getintfield_default(L, 2, "item", 0); + elem->dir = getintfield_default(L, 2, "dir", 0); + + u32 id = get_server(L)->hudAdd(player, elem); + if (id == (u32)-1) { + delete elem; + return 0; + } + + lua_pushnumber(L, id); + return 1; +} + +// hud_remove(self, id) +int ObjectRef::l_hud_remove(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = -1; + if (!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + if (!get_server(L)->hudRemove(player, id)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + +// hud_change(self, id, stat, data) +int ObjectRef::l_hud_change(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = -1; + if (!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + HudElementStat stat = (HudElementStat)getenumfield(L, 3, "stat", + es_HudElementStat, HUD_STAT_NUMBER); + + if (id >= player->hud.size()) + return 0; + + void *value = NULL; + HudElement *e = player->hud[id]; + if (!e) + return 0; + + switch (stat) { + case HUD_STAT_POS: + e->pos = read_v2f(L, 4); + value = &e->pos; + break; + case HUD_STAT_NAME: + e->name = lua_tostring(L, 4); + value = &e->name; + break; + case HUD_STAT_SCALE: + e->scale = read_v2f(L, 4); + value = &e->scale; + break; + case HUD_STAT_TEXT: + e->text = lua_tostring(L, 4); + value = &e->text; + break; + case HUD_STAT_NUMBER: + e->number = lua_tonumber(L, 4); + value = &e->number; + break; + case HUD_STAT_ITEM: + e->item = lua_tonumber(L, 4); + value = &e->item; + break; + case HUD_STAT_DIR: + e->dir = lua_tonumber(L, 4); + value = &e->dir; + } + + get_server(L)->hudChange(player, id, stat, value); + + lua_pushboolean(L, true); + return 1; +} + +// hud_get(self, id) +int ObjectRef::l_hud_get(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = lua_tonumber(L, -1); + if (id >= player->hud.size()) + return 0; + + HudElement *e = player->hud[id]; + if (!e) + return 0; + + lua_newtable(L); + + lua_pushstring(L, es_HudElementType[(u8)e->type].str); + lua_setfield(L, -2, "type"); + + push_v2f(L, e->pos); + lua_setfield(L, -2, "position"); + + lua_pushstring(L, e->name.c_str()); + lua_setfield(L, -2, "name"); + + push_v2f(L, e->scale); + lua_setfield(L, -2, "scale"); + + lua_pushstring(L, e->text.c_str()); + lua_setfield(L, -2, "text"); + + lua_pushnumber(L, e->number); + lua_setfield(L, -2, "number"); + + lua_pushnumber(L, e->item); + lua_setfield(L, -2, "item"); + + lua_pushnumber(L, e->dir); + lua_setfield(L, -2, "dir"); + + return 1; +} ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) @@ -807,6 +990,12 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, get_inventory_formspec), luamethod(ObjectRef, get_player_control), luamethod(ObjectRef, get_player_control_bits), + luamethod(ObjectRef, hud_add), + luamethod(ObjectRef, hud_remove), + luamethod(ObjectRef, hud_change), + luamethod(ObjectRef, hud_get), + //luamethod(ObjectRef, hud_lock_next_bar), + //luamethod(ObjectRef, hud_unlock_bar), {0,0} }; diff --git a/src/scriptapi_object.h b/src/scriptapi_object.h index a44016933..fd46f2cf6 100644 --- a/src/scriptapi_object.h +++ b/src/scriptapi_object.h @@ -190,6 +190,18 @@ private: // get_player_control_bits(self) static int l_get_player_control_bits(lua_State *L); + // hud_add(self, id, form) + static int l_hud_add(lua_State *L); + + // hud_rm(self, id) + static int l_hud_remove(lua_State *L); + + // hud_change(self, id, stat, data) + static int l_hud_change(lua_State *L); + + // hud_get(self, id) + static int l_hud_get(lua_State *L); + public: ObjectRef(ServerActiveObject *object); diff --git a/src/scriptapi_types.cpp b/src/scriptapi_types.cpp index 01a9b3bc3..f30451108 100644 --- a/src/scriptapi_types.cpp +++ b/src/scriptapi_types.cpp @@ -42,6 +42,15 @@ void push_v3f(lua_State *L, v3f p) lua_setfield(L, -2, "z"); } +void push_v2f(lua_State *L, v2f p) +{ + lua_newtable(L); + lua_pushnumber(L, p.X); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, p.Y); + lua_setfield(L, -2, "y"); +} + v2s16 read_v2s16(lua_State *L, int index) { v2s16 p; diff --git a/src/scriptapi_types.h b/src/scriptapi_types.h index 1eeed66df..dd0b125e6 100644 --- a/src/scriptapi_types.h +++ b/src/scriptapi_types.h @@ -81,6 +81,7 @@ std::vector<aabb3f> void push_v3s16 (lua_State *L, v3s16 p); void pushFloatPos (lua_State *L, v3f p); void push_v3f (lua_State *L, v3f p); +void push_v2f (lua_State *L, v2f p); MapNode readnode(lua_State *L, int index, INodeDefManager *ndef); diff --git a/src/server.cpp b/src/server.cpp index 05075a72c..241826ba2 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -904,6 +904,9 @@ Server::~Server() */ stop(); + //shutdown all emerge threads first! + delete m_emerge; + /* Delete clients */ @@ -923,7 +926,6 @@ Server::~Server() // Delete things in the reverse order of creation delete m_env; delete m_rollback; - delete m_emerge; delete m_event; delete m_itemdef; delete m_nodedef; @@ -3447,7 +3449,9 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message) // Send as reliable m_con.Send(peer_id, 0, data, true); } -void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname) + +void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, + const std::string formname) { DSTACK(__FUNCTION_NAME); @@ -3468,7 +3472,9 @@ void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, co } // Spawns a particle on peer with peer_id -void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture) +void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, + float expirationtime, float size, bool collisiondetection, + std::string texture) { DSTACK(__FUNCTION_NAME); @@ -3490,7 +3496,9 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat } // Spawns a particle on all peers -void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture) +void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, + float expirationtime, float size, bool collisiondetection, + std::string texture) { for(std::map<u16, RemoteClient*>::iterator i = m_clients.begin(); @@ -3593,6 +3601,76 @@ void Server::SendDeleteParticleSpawnerAll(u32 id) } } +void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_HUDADD); + writeU32(os, id); + writeU8(os, (u8)form->type); + writeV2F1000(os, form->pos); + os << serializeString(form->name); + writeV2F1000(os, form->scale); + os << serializeString(form->text); + writeU32(os, form->number); + writeU32(os, form->item); + writeU32(os, form->dir); + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + +void Server::SendHUDRemove(u16 peer_id, u32 id) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_HUDRM); + writeU32(os, id); + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + +void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_HUDCHANGE); + writeU32(os, id); + writeU8(os, (u8)stat); + switch (stat) { + case HUD_STAT_POS: + case HUD_STAT_SCALE: + writeV2F1000(os, *(v2f *)value); + break; + case HUD_STAT_NAME: + case HUD_STAT_TEXT: + os << serializeString(*(std::string *)value); + break; + case HUD_STAT_NUMBER: + case HUD_STAT_ITEM: + case HUD_STAT_DIR: + default: + writeU32(os, *(u32 *)value); + break; + } + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8 *)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + void Server::BroadcastChatMessage(const std::wstring &message) { for(std::map<u16, RemoteClient*>::iterator @@ -4546,6 +4624,39 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c return true; } +u32 Server::hudAdd(Player *player, HudElement *form) { + if (!player) + return -1; + + u32 id = hud_get_free_id(player); + if (id < player->hud.size()) + player->hud[id] = form; + else + player->hud.push_back(form); + + SendHUDAdd(player->peer_id, id, form); + return id; +} + +bool Server::hudRemove(Player *player, u32 id) { + if (!player || id >= player->hud.size() || !player->hud[id]) + return false; + + delete player->hud[id]; + player->hud[id] = NULL; + + SendHUDRemove(player->peer_id, id); + return true; +} + +bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) { + if (!player) + return false; + + SendHUDChange(player->peer_id, id, stat, data); + return true; +} + void Server::notifyPlayers(const std::wstring msg) { BroadcastChatMessage(msg); diff --git a/src/server.h b/src/server.h index ea1cb79af..52606b0cb 100644 --- a/src/server.h +++ b/src/server.h @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "inventory.h" #include "ban.h" +#include "hud.h" #include "gamedef.h" #include "serialization.h" // For SER_FMT_VER_INVALID #include "mods.h" @@ -51,6 +52,7 @@ class EventManager; class PlayerSAO; class IRollbackManager; class EmergeManager; +//struct HudElement; class ServerError : public std::exception { @@ -534,6 +536,11 @@ public: } bool showFormspec(const char *name, const std::string &formspec, const std::string &formname); + + u32 hudAdd(Player *player, HudElement *element); + bool hudRemove(Player *player, u32 id); + bool hudChange(Player *player, u32 id, HudElementStat stat, void *value); + private: // con::PeerHandler implementation. @@ -573,6 +580,9 @@ private: void SendPlayerPrivileges(u16 peer_id); void SendPlayerInventoryFormspec(u16 peer_id); void SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname); + void SendHUDAdd(u16 peer_id, u32 id, HudElement *form); + void SendHUDRemove(u16 peer_id, u32 id); + void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value); /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than diff --git a/src/shader.cpp b/src/shader.cpp index a224c82bb..62b7c99a9 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -388,6 +388,12 @@ ShaderSource::ShaderSource(IrrlichtDevice *device): ShaderSource::~ShaderSource() { //m_shader_callback->drop(); + + for (std::vector<IShaderConstantSetter*>::iterator iter = m_global_setters.begin(); + iter != m_global_setters.end(); iter++) { + delete *iter; + } + m_global_setters.clear(); } u32 ShaderSource::getShaderId(const std::string &name) diff --git a/src/shader.h b/src/shader.h index a7367eaff..a62569602 100644 --- a/src/shader.h +++ b/src/shader.h @@ -49,6 +49,7 @@ struct ShaderInfo video::E_MATERIAL_TYPE material; ShaderInfo(): name(""), material(video::EMT_SOLID) {} + virtual ~ShaderInfo() {} }; /* diff --git a/src/sound_openal.cpp b/src/sound_openal.cpp index cc5261eae..0cfbc2798 100644 --- a/src/sound_openal.cpp +++ b/src/sound_openal.cpp @@ -271,6 +271,16 @@ public: m_context = NULL; alcCloseDevice(m_device); m_device = NULL; + + for (std::map<std::string, std::vector<SoundBuffer*> >::iterator i = m_buffers.begin(); + i != m_buffers.end(); i++) { + for (std::vector<SoundBuffer*>::iterator iter = (*i).second.begin(); + iter != (*i).second.end(); iter++) { + delete *iter; + } + (*i).second.clear(); + } + m_buffers.clear(); infostream<<"Audio: Deinitialized."<<std::endl; } diff --git a/src/test.cpp b/src/test.cpp index d18bd8b93..d1f53f880 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1781,5 +1781,7 @@ void run_tests() errorstream<<"run_tests() aborting."<<std::endl; abort(); } + delete idef; + delete ndef; } diff --git a/src/tile.cpp b/src/tile.cpp index c5e8a2a9d..39f47962e 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -201,6 +201,13 @@ struct SourceAtlasPointer class SourceImageCache { public: + ~SourceImageCache() { + for(std::map<std::string, video::IImage*>::iterator iter = m_images.begin(); + iter != m_images.end(); iter++) { + iter->second->drop(); + } + m_images.clear(); + } void insert(const std::string &name, video::IImage *img, bool prefer_local, video::IVideoDriver *driver) { @@ -209,23 +216,28 @@ public: std::map<std::string, video::IImage*>::iterator n; n = m_images.find(name); if(n != m_images.end()){ - video::IImage *oldimg = n->second; - if(oldimg) - oldimg->drop(); + if(n->second) + n->second->drop(); } + + video::IImage* toadd = img; + bool need_to_grab = true; + // Try to use local texture instead if asked to if(prefer_local){ std::string path = getTexturePath(name.c_str()); if(path != ""){ video::IImage *img2 = driver->createImageFromFile(path.c_str()); if(img2){ - m_images[name] = img2; - return; + toadd = img2; + need_to_grab = false; } } } - img->grab(); - m_images[name] = img; + + if (need_to_grab) + toadd->grab(); + m_images[name] = toadd; } video::IImage* get(const std::string &name) { @@ -254,8 +266,7 @@ public: infostream<<"SourceImageCache::getOrLoad(): Loading path \""<<path <<"\""<<std::endl; video::IImage *img = driver->createImageFromFile(path.c_str()); - // Even if could not be loaded, put as NULL - //m_images[name] = img; + if(img){ m_images[name] = img; img->grab(); // Grab for caller @@ -274,7 +285,7 @@ class TextureSource : public IWritableTextureSource { public: TextureSource(IrrlichtDevice *device); - ~TextureSource(); + virtual ~TextureSource(); /* Example case: @@ -454,6 +465,28 @@ TextureSource::TextureSource(IrrlichtDevice *device): TextureSource::~TextureSource() { + video::IVideoDriver* driver = m_device->getVideoDriver(); + + unsigned int textures_before = driver->getTextureCount(); + + for (std::vector<SourceAtlasPointer>::iterator iter = + m_atlaspointer_cache.begin(); iter != m_atlaspointer_cache.end(); + iter++) + { + video::ITexture *t = driver->getTexture(iter->name.c_str()); + + //cleanup texture + if (t) + driver->removeTexture(t); + + //cleanup source image + if (iter->atlas_img) + iter->atlas_img->drop(); + } + m_atlaspointer_cache.clear(); + + infostream << "~TextureSource() "<< textures_before << "/" + << driver->getTextureCount() << std::endl; } u32 TextureSource::getTextureId(const std::string &name) @@ -1205,7 +1238,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, core::dimension2d<u32> dim = image->getDimension(); baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); image->copyTo(baseimg); - image->drop(); } // Else blit on base. else @@ -1224,9 +1256,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, video::SColor(255,255,255,255), NULL);*/ blit_with_alpha(image, baseimg, pos_from, pos_to, dim); - // Drop image - image->drop(); } + //cleanup + image->drop(); } else { @@ -1630,6 +1662,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim); assert(image); + //cleanup texture + driver->removeTexture(rtt); + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); if(image) |