From 7c0e707cf1d0031788567bfec66f6c13ec901cdc Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 7 Apr 2013 21:21:17 -0400 Subject: [PATCH 01/26] Add param2 field for ores, some minor fixes and misc. code cleanup --- src/mapgen.cpp | 64 ++++++++++++++++------------------------------- src/mapgen.h | 12 ++++++--- src/mapgen_v6.cpp | 2 +- src/mapgen_v7.cpp | 2 +- src/scriptapi.cpp | 1 + 5 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 22488bc4..0646a882 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 e708f23b..17136a13 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 4a037bb8..2e44d7b4 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 6aecfe31..8aad37f7 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/scriptapi.cpp b/src/scriptapi.cpp index 0227c6a1..8d472e6b 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); From e1146396bc043782b288226c027bc28857ccf4d2 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 20:33:00 +0200 Subject: [PATCH 02/26] fix mesh leak in camera class --- src/camera.cpp | 8 +++++--- src/camera.h | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 138b022c..735a8d1e 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -69,7 +69,8 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, m_view_bobbing_speed(0), m_digging_anim(0), - m_digging_button(-1) + m_digging_button(-1), + m_dummymesh(createCubeMesh(v3f(1,1,1))) { //dstream<<__FUNCTION_NAME<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) diff --git a/src/camera.h b/src/camera.h index fc43d117..989dcb71 100644 --- a/src/camera.h +++ b/src/camera.h @@ -173,6 +173,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 From 3b684d306c74f012cb066e6b256325edaefbf470 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 20:13:21 +0200 Subject: [PATCH 03/26] fix 3d model mesh leak --- src/client.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 1d5f8f47..4b14125c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -363,6 +363,15 @@ Client::~Client() for (std::list::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,14 +985,26 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) { verbosestream<<"Client: Storing model into Irrlicht: " <<"\""<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); return true; From 5743ef4e6480897bc0a27d19b2dee0de93f6931c Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 22:19:53 +0200 Subject: [PATCH 04/26] fix huge texture leak in tiledef fix minor glitches too --- src/tile.cpp | 57 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/tile.cpp b/src/tile.cpp index c5e8a2a9..80db32ad 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -201,6 +201,13 @@ struct SourceAtlasPointer class SourceImageCache { public: + ~SourceImageCache() { + for(std::map::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::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 \""<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,27 @@ TextureSource::TextureSource(IrrlichtDevice *device): TextureSource::~TextureSource() { + video::IVideoDriver* driver = m_device->getVideoDriver(); + + unsigned int textures_before = driver->getTextureCount(); + + for (std::vector::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 + 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 +1237,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, core::dimension2d dim = image->getDimension(); baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); image->copyTo(baseimg); - image->drop(); } // Else blit on base. else @@ -1224,9 +1255,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 { From 7a32698312bcca7dc4e82de80df659418a2b5b3b Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 22:02:57 +0200 Subject: [PATCH 05/26] fix memory leak in itemdef cleanup useless code --- src/itemdef.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 72ce0e65..bb294699 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -226,6 +226,12 @@ class CItemDefManager: public IWritableItemDefManager public: CItemDefManager() { + for (std::map::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(); #endif @@ -241,6 +247,7 @@ public: { ClientCached *cc = *i; cc->wield_mesh->drop(); + delete cc; } #endif } @@ -328,11 +335,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; @@ -436,16 +439,16 @@ public: /* 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 From 2bdff11d5472e4e5299c4e4e25e128b0869367a8 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 21:42:54 +0200 Subject: [PATCH 06/26] fix memory leak on shader shutdown --- src/shader.cpp | 6 ++++++ src/shader.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/shader.cpp b/src/shader.cpp index a224c82b..62b7c99a 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::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 a7367eaf..a6256960 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() {} }; /* From cd27c8ef5df35edd2cc606291f3f7985a61d41d5 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 19:41:12 +0200 Subject: [PATCH 07/26] replace Server smart pointer with conventional one to gain control over dtor call order --- src/game.cpp | 22 +++++++++++++++++++--- src/main.cpp | 10 ---------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 65feb50b..4f6eb472 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -992,6 +992,9 @@ void the_game( sound_is_dummy = true; } + Server *server = NULL; + + try{ // Event manager EventManager eventmgr; @@ -1007,9 +1010,8 @@ void the_game( /* Create server. - SharedPtr will delete it when it goes out of scope. */ - SharedPtr server; + if(address == ""){ draw_load_screen(L"Creating server...", driver, font); infostream<<"Creating server"<start(port); } - try{ do{ // Client scope (breakable do-while(0)) /* @@ -3290,10 +3291,25 @@ void the_game( L" running a different version of Minetest."; errorstream< Date: Sun, 7 Apr 2013 19:15:17 +0200 Subject: [PATCH 08/26] fix memory leaks introduced by invalid gettext usage --- src/guiConfigureWorld.cpp | 57 ++++++---- src/guiConfirmMenu.cpp | 8 +- src/guiCreateWorld.cpp | 18 ++-- src/guiDeathScreen.cpp | 8 +- src/guiFormSpecMenu.cpp | 5 +- src/guiKeyChangeMenu.cpp | 86 ++++++++++----- src/guiKeyChangeMenu.h | 2 +- src/guiMainMenu.cpp | 215 ++++++++++++++++++++++++++++---------- src/guiMessageMenu.cpp | 4 +- src/guiPasswordChange.cpp | 23 ++-- src/guiPauseMenu.cpp | 48 +++++---- src/guiTextInputMenu.cpp | 4 +- src/guiVolumeChange.cpp | 8 +- src/main.cpp | 4 +- 14 files changed, 344 insertions(+), 146 deletions(-) diff --git a/src/guiConfigureWorld.cpp b/src/guiConfigureWorld.cpp index 08069122..b2debfbd 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::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 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 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 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 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 rect(0, 0, 200, 85); @@ -237,8 +245,9 @@ void GUIConfigureWorld::regenerateGui(v2u32 screensize) { core::rect 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 rect(0, 0, 200, 85); @@ -258,14 +267,16 @@ void GUIConfigureWorld::regenerateGui(v2u32 screensize) { core::rect 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 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 70e33c76..86b23050 100644 --- a/src/guiConfirmMenu.cpp +++ b/src/guiConfirmMenu.cpp @@ -116,14 +116,18 @@ void GUIConfirmMenu::regenerateGui(v2u32 screensize) { core::rect 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 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 8ac3fb17..09b18fb3 100644 --- a/src/guiCreateWorld.cpp +++ b/src/guiCreateWorld.cpp @@ -113,8 +113,9 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) { core::rect 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 rect(0, 0, 300, 30); @@ -132,8 +133,9 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) { core::rect 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 rect(0, 0, 300, 80); @@ -155,14 +157,18 @@ void GUICreateWorld::regenerateGui(v2u32 screensize) { core::rect 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 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 ba329e3b..dfdce3f8 100644 --- a/src/guiDeathScreen.cpp +++ b/src/guiDeathScreen.cpp @@ -93,15 +93,19 @@ void GUIDeathScreen::regenerateGui(v2u32 screensize) { core::rect 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 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 1754422d..6ada7769 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(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 4569f3d9..c660ed87 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -75,6 +75,13 @@ GUIModalMenu(env, parent, id, menumgr) GUIKeyChangeMenu::~GUIKeyChangeMenu() { removeChildren(); + + for (std::vector::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 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 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 2b498676..833514c1 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 1e308357..431b40e6 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 &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 abb31cf2..c6592e51 100644 --- a/src/guiMessageMenu.cpp +++ b/src/guiMessageMenu.cpp @@ -104,10 +104,12 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize) { core::rect 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 e4b77b61..a4d16444 100644 --- a/src/guiPasswordChange.cpp +++ b/src/guiPasswordChange.cpp @@ -105,8 +105,9 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) { core::rect 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 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 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 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 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 dc95eef5..b57b4a1d 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -119,8 +119,10 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) { core::rect 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 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 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 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 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 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 rect(0, 0, 180, 220); diff --git a/src/guiTextInputMenu.cpp b/src/guiTextInputMenu.cpp index f4e3bb5b..c15eeedc 100644 --- a/src/guiTextInputMenu.cpp +++ b/src/guiTextInputMenu.cpp @@ -127,8 +127,10 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize) { core::rect 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 cfb89da1..4e92b82c 100644 --- a/src/guiVolumeChange.cpp +++ b/src/guiVolumeChange.cpp @@ -105,8 +105,10 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) { core::rect 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 rect(0, 0, 30, 20); @@ -117,8 +119,10 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) { core::rect 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 rect(0, 0, 300, 20); diff --git a/src/main.cpp b/src/main.cpp index b0cabfe8..eef65cdb 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 From abe74ea5ea820403450725ee0ddcc44b07cbe098 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 19:47:34 +0200 Subject: [PATCH 09/26] fix inventory image texture leak --- src/tile.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tile.cpp b/src/tile.cpp index 80db32ad..3bfb4bb8 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -1661,6 +1661,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) From 10502b59bce198f8ccbdb6e3d154b25873b9406d Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 20:22:06 +0200 Subject: [PATCH 10/26] addon extended resource accounting --- src/game.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/game.cpp b/src/game.cpp index 4f6eb472..aae88fe9 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 #include #include +#include "IMeshCache.h" #include "client.h" #include "server.h" #include "guiPauseMenu.h" @@ -3314,6 +3315,21 @@ void the_game( 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; } From 0d26bb36aff7d4b76b0b8df3bd475954bc3867ba Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 20:39:59 +0200 Subject: [PATCH 11/26] fix memory leak in loadMedia --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index 4b14125c..64b01a5a 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1006,7 +1006,7 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) mesh = smgr->getMesh(rfile); smgr->getMeshCache()->addMesh(filename.c_str(), mesh); - + rfile->drop(); return true; } From e7247c1a66e2a61d5b4a97d9cab02194b97de53b Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 21:17:26 +0200 Subject: [PATCH 12/26] fix memory leak on sound shutdown --- src/sound_openal.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sound_openal.cpp b/src/sound_openal.cpp index cc5261ea..0cfbc279 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 >::iterator i = m_buffers.begin(); + i != m_buffers.end(); i++) { + for (std::vector::iterator iter = (*i).second.begin(); + iter != (*i).second.end(); iter++) { + delete *iter; + } + (*i).second.clear(); + } + m_buffers.clear(); infostream<<"Audio: Deinitialized."< Date: Sun, 7 Apr 2013 20:35:48 +0200 Subject: [PATCH 13/26] Use system wide LuaJIT if aviable. --- builtin/serialize.lua | 2 +- src/CMakeLists.txt | 29 ++++++++++++++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/builtin/serialize.lua b/builtin/serialize.lua index ecb2438e..61b923ce 100644 --- a/builtin/serialize.lua +++ b/builtin/serialize.lua @@ -197,7 +197,7 @@ local function unit_test() unitTest("test 1b", unittest_input.cat.speed == unittest_output.cat.speed) unitTest("test 1c", unittest_input.dog.sound == unittest_output.dog.sound) - unittest_input = {escapechars="\n\r\t\v\\\"\'\[\]", noneuropean="θשׁ٩∂"} + unittest_input = {escapechars="\n\r\t\v\\\"\'", noneuropean="θשׁ٩∂"} unittest_output = minetest.deserialize(minetest.serialize(unittest_input)) unitTest("test 3a", unittest_input.escapechars == unittest_output.escapechars) unitTest("test 3b", unittest_input.noneuropean == unittest_output.noneuropean) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9bef3289..62bb42b9 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" @@ -601,11 +617,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) From 58fd39de35fc541ee6f50cc7b85ff29ab749778a Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 20:00:25 +0200 Subject: [PATCH 14/26] fix extruded items texture leak --- src/itemdef.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/itemdef.cpp b/src/itemdef.cpp index bb294699..784919ae 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -234,6 +234,7 @@ public: m_item_definitions.clear(); #ifndef SERVER m_main_thread = get_current_thread_id(); + m_driver = NULL; #endif clear(); @@ -249,6 +250,14 @@ public: 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 @@ -297,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 m_extruded_textures; +public: ClientCached* createClientCachedDirect(const std::string &name, IGameDef *gamedef) const { @@ -435,6 +448,13 @@ 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 @@ -661,3 +681,8 @@ IWritableItemDefManager* createItemDefManager() return new CItemDefManager(); } +#ifndef SERVER +//TODO very very very dirty hack! +video::IVideoDriver * CItemDefManager::m_driver = 0; +std::vector CItemDefManager::m_extruded_textures; +#endif From 04c3b17c780f78fcaa23af8187b5e5e30ff8fcab Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 7 Apr 2013 22:27:27 +0200 Subject: [PATCH 15/26] fix various memory leaks --- src/mesh.cpp | 2 ++ src/server.cpp | 4 +++- src/test.cpp | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index c2e6bcaa..da0dbe44 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/server.cpp b/src/server.cpp index 05075a72..b7287c91 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; diff --git a/src/test.cpp b/src/test.cpp index d18bd8b9..d1f53f88 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1781,5 +1781,7 @@ void run_tests() errorstream<<"run_tests() aborting."< Date: Sun, 7 Apr 2013 21:01:19 +0200 Subject: [PATCH 16/26] fix emergemanager memory leaks --- src/emerge.cpp | 16 +++++++++++++++- src/map.cpp | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/emerge.cpp b/src/emerge.cpp index 499aaf29..9d3f94d4 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -96,9 +96,23 @@ EmergeManager::~EmergeManager() { delete emergethread[i]; delete mapgen[i]; } + emergethread.clear(); + + for (unsigned int i = 0; i < mapgen.size(); i++) + delete mapgen[i]; + mapgen.clear(); + + for (unsigned int i = 0; i < ores.size(); i++) + delete ores[i]; + ores.clear(); + for (std::map::iterator iter = mglist.begin(); + iter != mglist.end(); iter ++) { + delete iter->second; + } + mglist.clear(); + delete biomedef; - delete params; } diff --git a/src/map.cpp b/src/map.cpp index a8201f3e..c4884a45 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) From 6e4fdf37baaeaf1048210e5519822ebd68dd413b Mon Sep 17 00:00:00 2001 From: sapier Date: Tue, 9 Apr 2013 23:16:13 +0200 Subject: [PATCH 17/26] fix objects colliding with its own collision boxes --- src/collision.cpp | 13 +++++++++---- src/collision.h | 3 ++- src/content_cao.cpp | 2 +- src/content_sao.cpp | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/collision.cpp b/src/collision.cpp index cd170196..673966b6 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::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 11781845..77bf1f15 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 9738dc34..f79d0d6f 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 e6c8c725..3526ecbd 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; From dda2071cc083db2770044db85174a8629a7598b7 Mon Sep 17 00:00:00 2001 From: sapier Date: Tue, 9 Apr 2013 20:33:59 +0200 Subject: [PATCH 18/26] fix bug in scriptapi line_of_sight fix warnings for pathfinder debug traces --- src/pathfinder.cpp | 6 ++---- src/scriptapi_env.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pathfinder.cpp b/src/pathfinder.cpp index c7621177..0d1cfe47 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/scriptapi_env.cpp b/src/scriptapi_env.cpp index 9bf7f0b5..efed58e6 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) From e7f5cdf9d4cbe17a2a42015e072a791659b3886b Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Thu, 11 Apr 2013 03:36:38 +0200 Subject: [PATCH 19/26] Bugfixes to get_craft_recipe and get_all_craft_recipes. Improvements to get_all_craft_recipes (see api doc) --- doc/lua_api.txt | 21 +++++++++++++++++---- src/scriptapi_craft.cpp | 35 +++++++++++++++++------------------ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 285f3d20..b29c5037 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1002,10 +1002,23 @@ minetest.get_craft_recipe(output) -> input ^ input.items = for example { stack 1, stack 2, stack 3, stack 4, stack 5, stack 6, stack 7, stack 8, stack 9 } ^ input.items = nil if no recipe found -minetest.get_all_craft_recipes(output) -> table or nil -^ returns table with all registered recipes for output item (node) -^ returns nil if no recipe was found -^ table entries have same format as minetest.get_craft_recipe +minetest.get_all_craft_recipes(query item) -> table or nil +^ returns indexed table with all registered recipes for query item (node) + or nil if no recipe was found + recipe entry table: + { + method = 'normal' or 'cooking' or 'fuel' + width = 0-3, 0 means shapeless recipe + items = indexed [1-9] table with recipe items + output = string with item name and quantity + } + Example query for default:gold_ingot will return table: + { + 1={type = "cooking", width = 3, output = "default:gold_ingot", + items = {1 = "default:gold_lump"}}, + 2={type = "normal", width = 1, output = "default:gold_ingot 9", + items = {1 = "default:goldblock"}} + } minetest.handle_node_drops(pos, drops, digger) ^ drops: list of itemstrings ^ Handles drops from nodes after digging: Default action is to put them into diff --git a/src/scriptapi_craft.cpp b/src/scriptapi_craft.cpp index 183eeb84..45990823 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::const_iterator + for (std::vector::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::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; From 17cfb1850d35148b9e2445dfdd160a164d02ebf9 Mon Sep 17 00:00:00 2001 From: proller Date: Thu, 11 Apr 2013 20:18:34 +0400 Subject: [PATCH 20/26] Fix masterserver javascript: adjustable output id --- util/master/index.html | 2 +- util/master/list.js | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/util/master/index.html b/util/master/index.html index 63ee5c70..328dd893 100644 --- a/util/master/index.html +++ b/util/master/index.html @@ -5,7 +5,7 @@ Minetest server list -
+
diff --git a/util/master/list.js b/util/master/list.js index 990bb6de..98f5ad49 100644 --- a/util/master/list.js +++ b/util/master/list.js @@ -1,3 +1,5 @@ +var master_root, output_to; + function e(s) { if (typeof s === "undefined") s = ''; return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); //mc" @@ -39,7 +41,7 @@ function human_time(t, abs) { function success(r) { if (!r || !r.list) return; - var h = ''; + var h = '
ip[:port]clients/maxversion gameidnamedescflagsuptimeping
'; for (var i = 0; i < r.list.length; ++i) { var s = r.list[i]; if (!s) continue; @@ -60,9 +62,8 @@ function success(r) { h += ''; } h += '
ip[:port]clients/maxversion gameidnamedescriptionflagsuptimeping
' - jQuery('#table').html(h); + jQuery(output_to || '#servers_table').html(h); } -var master_root; function get() { jQuery.getJSON((master_root || '') + 'list', success); From 7cd5eb4c77de9fda4946de7e1c2384d0c2a0253e Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Sun, 7 Apr 2013 15:41:33 -1000 Subject: [PATCH 21/26] Swing the camera down when the player lands on the ground, based on the velocity the surface is hit with. --- src/camera.cpp | 29 +++++++++++++++++++++++++++-- src/camera.h | 2 ++ src/localplayer.cpp | 3 +++ src/localplayer.h | 2 ++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 735a8d1e..211ecfd7 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -67,6 +67,7 @@ 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), @@ -134,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; @@ -237,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 989dcb71..0ed5c20d 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; diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 9c70c8b2..6b7b0943 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 9ac2bc68..8c3041c0 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; From ce901f4c4ca97dee5ab0a3a0d3e14cf7f1cf0154 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Fri, 12 Apr 2013 17:20:05 -0400 Subject: [PATCH 22/26] Fix double free, null texture drop --- src/emerge.cpp | 3 --- src/tile.cpp | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/emerge.cpp b/src/emerge.cpp index 9d3f94d4..049b3cc1 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -97,9 +97,6 @@ EmergeManager::~EmergeManager() { delete mapgen[i]; } emergethread.clear(); - - for (unsigned int i = 0; i < mapgen.size(); i++) - delete mapgen[i]; mapgen.clear(); for (unsigned int i = 0; i < ores.size(); i++) diff --git a/src/tile.cpp b/src/tile.cpp index 3bfb4bb8..39f47962 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -480,7 +480,8 @@ TextureSource::~TextureSource() driver->removeTexture(t); //cleanup source image - iter->atlas_img->drop(); + if (iter->atlas_img) + iter->atlas_img->drop(); } m_atlaspointer_cache.clear(); From 9e0bb94460f38efa0458a1493ffd785b7b96a352 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Sun, 14 Apr 2013 03:06:24 -0400 Subject: [PATCH 23/26] Remove old Makefile(that is what git is for) --- old/Makefile.bak | 90 ------------------------------------------------ 1 file changed, 90 deletions(-) delete mode 100644 old/Makefile.bak diff --git a/old/Makefile.bak b/old/Makefile.bak deleted file mode 100644 index 8ba03f9b..00000000 --- a/old/Makefile.bak +++ /dev/null @@ -1,90 +0,0 @@ -# Makefile for Irrlicht Examples -# It's usually sufficient to change just the target name and source file list -# and be sure that CXX is set to a valid compiler -SOURCE_FILES = porting.cpp guiMessageMenu.cpp materials.cpp guiTextInputMenu.cpp guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp - -DEBUG_TARGET = debugtest -DEBUG_SOURCES = $(addprefix src/, $(SOURCE_FILES)) -DEBUG_BUILD_DIR = debugbuild -DEBUG_OBJECTS = $(addprefix $(DEBUG_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) - -FAST_TARGET = fasttest -FAST_SOURCES = $(addprefix src/, $(SOURCE_FILES)) -FAST_BUILD_DIR = fastbuild -FAST_OBJECTS = $(addprefix $(FAST_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) - -SERVER_TARGET = server -SERVER_SOURCE_FILES = porting.cpp materials.cpp defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp -SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES)) -SERVER_BUILD_DIR = serverbuild -SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o)) - -IRRLICHTPATH = ../irrlicht/irrlicht-1.7.1 -JTHREADPATH = ../jthread/jthread-1.2.1 - - -all: fast - -ifeq ($(HOSTTYPE), x86_64) -LIBSELECT=64 -endif - -debug: CXXFLAGS = -Wall -g -O1 -debug: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DDEBUG -DRUN_IN_PLACE -debug: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L$(IRRLICHTPATH)/lib/Linux -L$(JTHREADPATH)/src/.libs -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -ljthread -lz - -fast: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686 -fast: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DUNITTEST_DISABLE -DRUN_IN_PLACE -fast: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L$(IRRLICHTPATH)/lib/Linux -L$(JTHREADPATH)/src/.libs -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -ljthread -lz - -server: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686 -server: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DSERVER -DUNITTEST_DISABLE -DRUN_IN_PLACE -server: LDFLAGS = -L$(JTHREADPATH)/src/.libs -ljthread -lz -lpthread - -DEBUG_DESTPATH = bin/$(DEBUG_TARGET) -FAST_DESTPATH = bin/$(FAST_TARGET) -SERVER_DESTPATH = bin/$(SERVER_TARGET) - -# Build commands - -debug: $(DEBUG_BUILD_DIR) $(DEBUG_DESTPATH) -fast: $(FAST_BUILD_DIR) $(FAST_DESTPATH) -server: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH) - -$(DEBUG_BUILD_DIR): - mkdir -p $(DEBUG_BUILD_DIR) -$(FAST_BUILD_DIR): - mkdir -p $(FAST_BUILD_DIR) -$(SERVER_BUILD_DIR): - mkdir -p $(SERVER_BUILD_DIR) - -$(DEBUG_DESTPATH): $(DEBUG_OBJECTS) - $(CXX) -o $@ $(DEBUG_OBJECTS) $(LDFLAGS) - -$(FAST_DESTPATH): $(FAST_OBJECTS) - $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS) - -$(SERVER_DESTPATH): $(SERVER_OBJECTS) - $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) - -$(DEBUG_BUILD_DIR)/%.o: src/%.cpp - $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) - -$(FAST_BUILD_DIR)/%.o: src/%.cpp - $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) - -$(SERVER_BUILD_DIR)/%.o: src/%.cpp - $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) - -clean: clean_debug clean_fast clean_server - -clean_debug: - @$(RM) $(DEBUG_OBJECTS) $(DEBUG_DESTPATH) - -clean_fast: - @$(RM) $(FAST_OBJECTS) $(FAST_DESTPATH) - -clean_server: - @$(RM) $(SERVER_OBJECTS) $(SERVER_DESTPATH) - -.PHONY: all all_win32 clean clean_debug clean_win32 clean_fast clean_server From 49f6e347f01f72e8854308d5a54aaae337489555 Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Thu, 11 Apr 2013 13:23:38 -0500 Subject: [PATCH 24/26] Lua HUD --- doc/lua_api.txt | 32 ++++- src/client.cpp | 67 ++++++++++ src/client.h | 26 +++- src/clientserver.h | 39 +++++- src/game.cpp | 261 ++++++++++++++++++++++++++++++++++++++- src/player.h | 16 +++ src/scriptapi_object.cpp | 209 +++++++++++++++++++++++++++++++ src/scriptapi_object.h | 29 +++++ src/scriptapi_types.cpp | 9 ++ src/scriptapi_types.h | 1 + src/server.cpp | 179 +++++++++++++++++++++++++++ src/server.h | 10 ++ 12 files changed, 873 insertions(+), 5 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index b29c5037..d4d078e2 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1379,7 +1379,20 @@ Player-only: (no-op for other objects) modifies per-player walking speed, jump height, and gravity. Values default to 1 and act as offsets to the physics settings in minetest.conf. nil will keep the current setting. - +- hud_add(id, hud definition) + ^ id is used for later reference + ^ If this id has already been used, it will reset its drawform +- hud_rm(id): remove an id from the lua hud +- hud_change(id, stat, value): change a value of a previously added element + ^ stat/table key: 0/position, 1/name, 2/scale, 3/text, 4/number, + ^ 5/item, 6/dir +- hud_get_next_id(): get the next available id for a hud element +- hud_lock_next_bar(right): add a non-conflicting statbar + ^ if right, will claim spot on right side, rather then left + ^ returns element id on success, false otherwise +- hud_unlock_bar(id): remove a non-conflicting statbar + ^ id is the value returned by calling hud_lock_next_bar() + InvRef: Reference to an inventory methods: - is_empty(listname): return true if list is empty @@ -1802,3 +1815,20 @@ Detached inventory callbacks ^ No return value } +HUD Definition (hud_add) +{ + type = "I", -- One of "I"(image), "S"(statbar), + ^ "T"(text), "i"(inv) + position = {x=0.5, y=0.5}, -- Left corner position + name = "", + scale = {x=2, y=2}, + text = "", + ^ Used as texture name for statbars and images, and as list name + ^ for inv + number = 2, + ^ Used as stat for statbar, and as # of items for inv + item = 3, -- Selected item in inv. 0 -> no item selected + dir = 0, + ^ dir/inv direction: 0/left-right, 1/right-left, + ^ 2/top-bottom, 3/bottom-top +} diff --git a/src/client.cpp b/src/client.cpp index 64b01a5a..1f8b9cac 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2040,6 +2040,73 @@ 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); + core::vector2df pos = readV2F1000(is); + std::string name = deSerializeString(is); + core::vector2df 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 datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + u8 stat = readU8(is); + core::vector2df v2fdata; + std::string sdata; + u32 data = 0; + if(stat == 0 || stat == 2) { + v2fdata = readV2F1000(is); + } else if(stat == 1 || stat == 3) { + sdata = deSerializeString(is); + } else { + data = readU32(is); + } + + ClientEvent event; + event.type = CE_HUDCHANGE; + event.hudchange.id = id; + event.hudchange.stat = stat; + event.hudchange.v2fdata = new v2f(v2fdata); + event.hudchange.sdata = new std::string(sdata); + event.hudchange.data = data; + m_client_event_queue.push_back(event); + } else { infostream<<"Client: Ignoring unknown command " diff --git a/src/client.h b/src/client.h index 16cdc237..696385a9 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 @@ -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; + u8 stat; + v2f* v2fdata; + std::string* sdata; + u32 data; + } hudchange; }; }; diff --git a/src/clientserver.h b/src/clientserver.h index 8b1e0a7e..6f7bb440 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -90,9 +90,13 @@ SharedBuffer 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/game.cpp b/src/game.cpp index aae88fe9..046b7bdb 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -228,6 +228,154 @@ public: std::string m_formspec; FormspecFormSource** m_game_formspec; }; + +/* + Item draw routine +*/ +void draw_item(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef, + v2s32 upperleftpos, s32 imgsize, s32 itemcount, + InventoryList *mainlist, u16 selectitem, unsigned short int direction) + //NOTE: selectitem = 0 -> no selected; selectitem 1-based + //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top +{ + s32 padding = imgsize/12; + s32 height = imgsize + padding*2; + s32 width = itemcount*(imgsize+padding*2); + if(direction == 2 or direction == 3){ + 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 barrect(0,0,width,height); + barrect += pos; + video::SColor bgcolor(255,128,128,128); + driver->draw2DRectangle(bgcolor, barrect, NULL);*/ + + core::rect imgrect(0,0,imgsize,imgsize); + + for(s32 i=0; igetItem(i); + + v2s32 steppos; + if(direction == 1){ + steppos = v2s32(-(padding+i*fullimglen), padding); + } else if(direction == 2) { + steppos = v2s32(padding, padding+i*fullimglen); + } else if(direction == 3) { + steppos = v2s32(padding, -(padding+i*fullimglen)); + } else { + steppos = v2s32(padding+i*fullimglen, padding); + } + core::rect 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( + v2s32(x1 - padding, y1 - padding), + v2s32(x2 + padding, y1) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect( + v2s32(x1 - padding, y2), + v2s32(x2 + padding, y2 + padding) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect( + v2s32(x1 - padding, y1), + v2s32(x1, y2) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect( + v2s32(x2, y1), + v2s32(x2 + padding, y2) + ), NULL); + /*// Light inside borders + driver->draw2DRectangle(c_inside, + core::rect( + v2s32(x1 - padding/2, y1 - padding/2), + v2s32(x2 + padding/2, y1) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect( + v2s32(x1 - padding/2, y2), + v2s32(x2 + padding/2, y2 + padding/2) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect( + v2s32(x1 - padding/2, y1), + v2s32(x1, y2) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect( + 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); + } +} + +/* + Statbar draw routine +*/ +void draw_statbar(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef, + v2s32 upperleftpos, std::string texture, s32 count) + //NOTE: selectitem = 0 -> no selected; selectitem 1-based + //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top +{ + video::ITexture *stat_texture = + gamedef->getTextureSource()->getTextureRaw(texture); + if(stat_texture) + { + v2s32 p = upperleftpos; + for(s32 i=0; igetOriginalSize()); + const video::SColor color(255,255,255,255); + const video::SColor colors[] = {color,color,color,color}; + core::rect rect(0,0,srcd.Width,srcd.Height); + rect += p; + driver->draw2DImage(stat_texture, rect, + core::rect(core::position2d(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 rect(0,0,srcd.Width/2,srcd.Height); + rect += p; + srcd.Width /= 2; + driver->draw2DImage(stat_texture, rect, + core::rect(core::position2d(0,0), srcd), + NULL, colors, true); + p += v2s32(srcd.Width*2,0); + } + } +} + /* Hotbar draw routine */ @@ -242,7 +390,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, errorstream<<"draw_hotbar(): mainlist == NULL"<draw2DRectangle(bgcolor2, rect, NULL); drawItemStack(driver, font, item, rect, NULL, gamedef); } - +#else + s32 padding = imgsize/12; + s32 width = itemcount*(imgsize+padding*2); + v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2); + draw_item(driver, font, gamedef, pos, imgsize, itemcount, + mainlist, playeritem + 1, 0); +#endif +#if 0 /* Draw hearts */ @@ -358,6 +513,10 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, p += v2s32(16,0); } } +#else + draw_statbar(driver, font, gamedef, pos + v2s32(0, -20), + "heart.png", halfheartcount); +#endif } /* @@ -2229,6 +2388,45 @@ void the_game( { delete_particlespawner (event.delete_particlespawner.id); } + else if (event.type == CE_HUDADD) + { + HudElement* e = new HudElement; + e->type = 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; + player->hud[event.hudadd.id] = e; + delete(event.hudadd.pos); + delete(event.hudadd.name); + delete(event.hudadd.scale); + delete(event.hudadd.text); + } + else if (event.type == CE_HUDRM) + { + player->hud.erase(event.hudrm.id); + } + else if (event.type == CE_HUDCHANGE) + { + HudElement* e = player->hud[event.hudchange.id]; + if(event.hudchange.stat == 0) + e->pos = *event.hudchange.v2fdata; + else if(event.hudchange.stat == 1) + e->name = *event.hudchange.sdata; + else if(event.hudchange.stat == 2) + e->scale = *event.hudchange.v2fdata; + else if(event.hudchange.stat == 3) + e->text = *event.hudchange.sdata; + else if(event.hudchange.stat == 4) + e->number = event.hudchange.data; + else if(event.hudchange.stat == 5) + e->item = event.hudchange.data; + else if(event.hudchange.stat == 6) + e->dir = event.hudchange.data; + } } } @@ -3212,12 +3410,71 @@ void the_game( player->hurt_tilt_strength = 0; } + /* + Draw lua hud items + */ + std::deque luaguitexts; + if(show_hud) + { + for(std::map::iterator it = player->hud.begin(); + it != player->hud.end(); ++it) + { + HudElement* e = it->second; + v2f posp(e->pos * v2f(screensize.X, screensize.Y)); + core::vector2d pos(posp.X, posp.Y); + if(e->type == 'I'){ //Img + video::ITexture *texture = + gamedef->getTextureSource()->getTextureRaw(e->text); + const video::SColor color(255,255,255,255); + const video::SColor colors[] = {color,color,color,color}; + core::dimension2di imgsize(texture->getOriginalSize()); + core::rect rect(0, 0, imgsize.Width*e->scale.X, + imgsize.Height*e->scale.X); + rect += pos; + driver->draw2DImage(texture, rect, + core::rect(core::position2d(0,0), imgsize), + NULL, colors, true); + } else if(e->type == 'T') { //Text + std::wstring t; + t.assign(e->text.begin(), e->text.end()); + gui::IGUIStaticText *luaguitext = guienv->addStaticText( + t.c_str(), + core::rect(0, 0, e->scale.X, text_height*(e->scale.Y))+pos, + false, false); + luaguitexts.push_back(luaguitext); + } else if(e->type == 'S') { //Statbar + draw_statbar(driver, font, gamedef, pos, e->text, e->number); + } else if(e->type == 's') { //Non-conflict Statbar + v2s32 p(displaycenter.X - 143, screensize.Y - 76); + p.X += e->pos.X*173; + p.Y += e->pos.X*20; + p.Y -= e->pos.Y*20; + draw_statbar(driver, font, gamedef, p, e->text, e->number); + } else if(e->type == 'i') { //Inv + InventoryList* inv = local_inventory.getList(e->text); + draw_item(driver, font, gamedef, pos, hotbar_imagesize, + e->number, inv, e->item, e->dir); + } else { + actionstream<<"luadraw: ignoring drawform "<second<< + "of key "<first<<" due to incorrect command."<drawAll(); + /* + Remove lua-texts + */ + for(std::deque::iterator it = luaguitexts.begin(); + it != luaguitexts.end(); ++it) + (*it)->remove(); + /* End scene */ diff --git a/src/player.h b/src/player.h index d95e535f..fc80769c 100644 --- a/src/player.h +++ b/src/player.h @@ -87,6 +87,7 @@ class Map; class IGameDef; struct CollisionInfo; class PlayerSAO; +struct HudElement; class Player { @@ -243,6 +244,9 @@ public: u32 keyPressed; + std::map hud; + std::map hud_bars; + protected: IGameDef *m_gamedef; @@ -253,6 +257,18 @@ protected: v3f m_position; }; +struct HudElement { + u8 type; + core::vector2df pos; + std::string name; + + core::vector2df scale; + std::string text; + u32 number; + u32 item; + u32 dir; +}; + /* Player on the server */ diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp index 05433a59..8f92ca43 100644 --- a/src/scriptapi_object.cpp +++ b/src/scriptapi_object.cpp @@ -700,6 +700,209 @@ 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; + + u32 id = hud_get_next_id(L); + HudElement* form = new HudElement; + std::string SS = getstringfield_default(L, 3, "type", "I"); + form->type = SS[0]; + lua_getfield(L, 3, "position"); + if(lua_istable(L, -1)) + form->pos = read_v2f(L, -1); + else + form->pos = v2f(); + lua_pop(L, 1); + form->name = getstringfield_default(L, 3, "name", ""); + + lua_getfield(L, 3, "scale"); + if(lua_istable(L, -1)) + form->scale = read_v2f(L, -1); + else + form->scale = v2f(); + lua_pop(L, 1); + + form->text = getstringfield_default(L, 3, "text", ""); + form->number = getintfield_default(L, 3, "number", 0); + form->item = getintfield_default(L, 3, "item", 0); + form->dir = getintfield_default(L, 3, "dir", 0); + + get_server(L)->hudadd(player->getName(), id, form); + player->hud[id] = form; + lua_pushnumber(L, id); + return 1; +} + +// hud_rm(self, id) +int ObjectRef::l_hud_rm(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); + get_server(L)->hudrm(player->getName(), id); + player->hud.at(id)->type = (u8)NULL; + 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); + u8 stat = -1; + if(!lua_isnil(L, 3)) + stat = lua_tonumber(L, 3); + if(stat == 0 || stat == 2) { + get_server(L)->hudchange(player->getName(), id, stat, read_v2f(L, 4)); + } else if(stat == 1 || stat == 3) { + get_server(L)->hudchange(player->getName(), id, stat, lua_tostring(L, 4)); + } else { + get_server(L)->hudchange(player->getName(), id, stat, lua_tonumber(L, 4)); + } + + HudElement* e = player->hud[id]; + switch(stat) { + case HUD_STAT_POS: e->pos = read_v2f(L, 4); + case HUD_STAT_NAME: e->name = lua_tostring(L, 4); + case HUD_STAT_SCALE: e->scale = read_v2f(L, 4); + case HUD_STAT_TEXT: e->text = lua_tostring(L, 4); + case HUD_STAT_NUMBER: e->number = lua_tonumber(L, 4); + case HUD_STAT_ITEM: e->item = lua_tonumber(L, 4); + case HUD_STAT_DIR: e->dir = lua_tonumber(L, 4); + } + + lua_pushboolean(L, true); + return 1; +} + +u32 ObjectRef::hud_get_next_id(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + + for(std::map::iterator it=player->hud.begin(); + it!=player->hud.end();it++) { + if(it->second->type == (u8)NULL) { + return it->first; + } + } + return player->hud.size(); +} + +// 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; + + HudElement* e = player->hud.at(lua_tonumber(L, -1)); + lua_newtable(L); + lua_pushstring(L, std::string(1, e->type).c_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; +} + +// hud_lock_next_bar(self, texture, right) +// return id on success, false otherwise +int ObjectRef::l_hud_lock_next_bar(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + + bool right = false; + if(!lua_isnil(L, 2)) + right = lua_toboolean(L, 2); + v2f pos(0, 0); + u8 i = 0; + if(right) + pos.X = 1; + i += 3; + for(u8 it = 0; it < 4; it++) { + if(player->hud_bars.count(i+it) == 1) { + if(it == 3) { + lua_pushboolean(L, false); + return 1; + } + } else { + i += it; + pos.Y = it; + break; + } + } + HudElement* form = new HudElement; + form->type = 's'; + form->pos = pos; + form->name = ""; + form->scale = v2f(); + form->text = ""; + form->number = 0; + form->item = 0; + form->dir = 0; + + u32 id = hud_get_next_id(L); + get_server(L)->hudadd(player->getName(), id, form); + player->hud[id] = form; + player->hud_bars[i] = id; + lua_pushnumber(L, id); + return 1; +} + +// hud_unlock_bar(self, id) +int ObjectRef::l_hud_unlock_bar(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + + u32 id = 0; + if(!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + for(std::map::iterator it=player->hud_bars.begin(); + it!=player->hud_bars.end();it++) { + if(it->second == id) { + player->hud_bars.erase(it->first); + get_server(L)->hudrm(player->getName(), id); + player->hud.at(id)->type = (u8)NULL; + lua_pushboolean(L, true); + return 1; + } + } + lua_pushboolean(L, false); + return 1; +} ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) @@ -807,6 +1010,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_rm), + 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 a4401693..6df4366b 100644 --- a/src/scriptapi_object.h +++ b/src/scriptapi_object.h @@ -29,6 +29,14 @@ extern "C" { #include "content_sao.h" #include "player.h" +#define HUD_STAT_POS 0 +#define HUD_STAT_NAME 1 +#define HUD_STAT_SCALE 2 +#define HUD_STAT_TEXT 3 +#define HUD_STAT_NUMBER 4 +#define HUD_STAT_ITEM 5 +#define HUD_STAT_DIR 6 + /* ObjectRef */ @@ -190,6 +198,27 @@ 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_rm(lua_State *L); + + // hud_change(self, id, stat, data) + static int l_hud_change(lua_State *L); + + // hud_get_next_id(self) + static u32 hud_get_next_id(lua_State *L); + + // hud_get(self, id) + static int l_hud_get(lua_State *L); + + // hud_lock_next_bar(self, right) + static int l_hud_lock_next_bar(lua_State *L); + + // hud_unlock_bar(self, id) + static int l_hud_unlock_bar(lua_State *L); + public: ObjectRef(ServerActiveObject *object); diff --git a/src/scriptapi_types.cpp b/src/scriptapi_types.cpp index 01a9b3bc..f3045110 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 1eeed66d..dd0b125e 100644 --- a/src/scriptapi_types.h +++ b/src/scriptapi_types.h @@ -81,6 +81,7 @@ std::vector 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 b7287c91..a9632c93 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3595,6 +3595,115 @@ void Server::SendDeleteParticleSpawnerAll(u32 id) } } +void Server::SendHUDAdd(u16 peer_id, const u32 id, HudElement* form) +{ + DSTACK(__FUNCTION_NAME); + + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOCLIENT_HUDADD); + os.write((char*)buf, 2); + writeU32(os, id); + writeU8(os, form->type); + writeV2F1000(os, form->pos); + os<name); + writeV2F1000(os, form->scale); + os<text); + writeU32(os, form->number); + writeU32(os, form->item); + writeU32(os, form->dir); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + +void Server::SendHUDRm(u16 peer_id, const u32 id) +{ + DSTACK(__FUNCTION_NAME); + + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOCLIENT_HUDRM); + os.write((char*)buf, 2); + writeU32(os, id); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + +void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data) +{ + DSTACK(__FUNCTION_NAME); + + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOCLIENT_HUDCHANGE); + os.write((char*)buf, 2); + writeU32(os, id); + writeU8(os, stat); + writeV2F1000(os, data); + + // Make data buffer + std::string s = os.str(); + SharedBuffer ddata((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, ddata, true); +} + +void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data) +{ + DSTACK(__FUNCTION_NAME); + + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOCLIENT_HUDCHANGE); + os.write((char*)buf, 2); + writeU32(os, id); + writeU8(os, stat); + os< ddata((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, ddata, true); +} + +void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data) +{ + DSTACK(__FUNCTION_NAME); + + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOCLIENT_HUDCHANGE); + os.write((char*)buf, 2); + writeU32(os, id); + writeU8(os, stat); + writeU32(os, data); + + // Make data buffer + std::string s = os.str(); + SharedBuffer ddata((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, ddata, true); +} + void Server::BroadcastChatMessage(const std::wstring &message) { for(std::map::iterator @@ -4548,6 +4657,76 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c return true; } +bool Server::hudadd(const char *playername, const u32 &id, HudElement* form) +{ + Player *player = m_env->getPlayer(playername); + + if(!player) + { + infostream<<"hudadd: couldn't find player:"<peer_id, id, form); + return true; +} + +bool Server::hudrm(const char *playername, const u32 &id) +{ + Player *player = m_env->getPlayer(playername); + + if(!player) + { + infostream<<"hudrm: couldn't find player:"<peer_id, id); + return true; +} + +bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, v2f data) +{ + Player *player = m_env->getPlayer(playername); + + if(!player) + { + infostream<<"hudchange: couldn't find player:"<peer_id, id, stat, data); + return true; +} + +bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, std::string data) +{ + Player *player = m_env->getPlayer(playername); + + if(!player) + { + infostream<<"hudchange: couldn't find player:"<peer_id, id, stat, data); + return true; +} + +bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, u32 data) +{ + Player *player = m_env->getPlayer(playername); + + if(!player) + { + infostream<<"hudchange: couldn't find 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 ea1cb79a..ef0c45a6 100644 --- a/src/server.h +++ b/src/server.h @@ -534,6 +534,11 @@ public: } bool showFormspec(const char *name, const std::string &formspec, const std::string &formname); + bool hudadd(const char *pname, const u32 &id, HudElement *element); + bool hudrm(const char *pname, const u32 &id); + bool hudchange(const char *pname, const u32 &id, const u8 &stat, v2f data); + bool hudchange(const char *pname, const u32 &id, const u8 &stat, std::string data); + bool hudchange(const char *pname, const u32 &id, const u8 &stat, u32 data); private: // con::PeerHandler implementation. @@ -573,6 +578,11 @@ 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, const u32 id, HudElement* form); + void SendHUDRm(u16 peer_id, const u32 id); + void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data); + void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data); + void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data); /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than From 666aae359310483b7ad0f2bba1f4c31d8a58c737 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 13 Apr 2013 18:20:22 -0400 Subject: [PATCH 25/26] Split HUD code off to hud.cpp, make into a class, extensive Lua HUD modification --- doc/lua_api.txt | 73 ++++-- src/CMakeLists.txt | 1 + src/client.cpp | 73 +++--- src/client.h | 28 +-- src/game.cpp | 516 +++++++-------------------------------- src/hud.cpp | 291 ++++++++++++++++++++++ src/hud.h | 116 +++++++++ src/player.h | 18 +- src/scriptapi_object.cpp | 266 ++++++++++---------- src/scriptapi_object.h | 19 +- src/server.cpp | 188 +++++--------- src/server.h | 20 +- 12 files changed, 793 insertions(+), 816 deletions(-) create mode 100644 src/hud.cpp create mode 100644 src/hud.h diff --git a/doc/lua_api.txt b/doc/lua_api.txt index d4d078e2..44b2a0b6 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -401,6 +401,43 @@ Currently supported flags: absheight Also produce this same ore between the height range of -height_max and -height_min. Useful for having ore in sky realms without having to duplicate ore entries. +HUD element types +------------------- +The position field is used for all element types. +To account for differing resolutions, the position coordinates are the percentage of the screen, +ranging in value from 0 to 1. +The name field is not yet used, but should contain a description of what the HUD element represents. +Below are the specific uses for fields in each type; fields not listed for that type are ignored. + +Note: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages. + +- image + Displays an image on the HUD. + - scale: The scale of the image, with 1 being the original texture size. + Only the X coordinate scale is used. + - text: The name of the texture that is displayed. +- text + Displays text on the HUD. + - scale: Defines the bounding rectangle of the text. + A value such as {x=100, y=100} should work. + - text: The text to be displayed in the HUD element. + - number: An integer containing the RGB value of the color used to draw the text. + Specify 0xFFFFFF for white text, 0xFF0000 for red, and so on. +- statbar + Displays a horizontal bar made up of half-images. + - text: The name of the texture that is used. + - number: The number of half-textures that are displayed. + If odd, will end with a vertically center-split texture. +- inventory + - text: The name of the inventory list to be displayed. + - number: Number of items in the inventory to be displayed. + - item: Position of item that is selected. + - direction: Direction in which the inventory list is drawn. + 0 draws from left to right, + 1 draws from right to left, + 2 draws from top to bottom, and + 3 draws from bottom to top. + Representations of simple things -------------------------------- Position/vector: @@ -1379,19 +1416,11 @@ Player-only: (no-op for other objects) modifies per-player walking speed, jump height, and gravity. Values default to 1 and act as offsets to the physics settings in minetest.conf. nil will keep the current setting. -- hud_add(id, hud definition) - ^ id is used for later reference - ^ If this id has already been used, it will reset its drawform -- hud_rm(id): remove an id from the lua hud -- hud_change(id, stat, value): change a value of a previously added element - ^ stat/table key: 0/position, 1/name, 2/scale, 3/text, 4/number, - ^ 5/item, 6/dir -- hud_get_next_id(): get the next available id for a hud element -- hud_lock_next_bar(right): add a non-conflicting statbar - ^ if right, will claim spot on right side, rather then left - ^ returns element id on success, false otherwise -- hud_unlock_bar(id): remove a non-conflicting statbar - ^ id is the value returned by calling hud_lock_next_bar() +- hud_add(hud definition): add a HUD element described by HUD def, returns ID number on success +- hud_remove(id): remove the HUD element of the specified id +- hud_change(id, stat, value): change a value of a previously added HUD element + ^ element stat values: position, name, scale, text, number, item, dir +- hud_get(id): gets the HUD element definition structure of the specified ID InvRef: Reference to an inventory methods: @@ -1815,20 +1844,18 @@ Detached inventory callbacks ^ No return value } -HUD Definition (hud_add) +HUD Definition (hud_add, hud_get) { - type = "I", -- One of "I"(image), "S"(statbar), - ^ "T"(text), "i"(inv) - position = {x=0.5, y=0.5}, -- Left corner position + type = "image", + ^ type of HUD element, can be either of "image", "text", "statbar", or "inventory" + position = {x=0.5, y=0.5}, + ^ Left corner position of element name = "", scale = {x=2, y=2}, text = "", - ^ Used as texture name for statbars and images, and as list name - ^ for inv number = 2, - ^ Used as stat for statbar, and as # of items for inv - item = 3, -- Selected item in inv. 0 -> no item selected + item = 3, + ^ Selected item in inventory. 0 for no item selected. dir = 0, - ^ dir/inv direction: 0/left-right, 1/right-left, - ^ 2/top-bottom, 3/bottom-top + ^ Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62bb42b9..7ddeeb02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -327,6 +327,7 @@ set(minetest_SRCS particles.cpp clientobject.cpp chat.cpp + hud.cpp guiMainMenu.cpp guiKeyChangeMenu.cpp guiMessageMenu.cpp diff --git a/src/client.cpp b/src/client.cpp index 1f8b9cac..03a71059 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2042,35 +2042,35 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } else if(command == TOCLIENT_HUDADD) { - std::string datastring((char*)&data[2], datasize-2); + std::string datastring((char *)&data[2], datasize - 2); std::istringstream is(datastring, std::ios_base::binary); - u32 id = readU32(is); - u8 type = readU8(is); - core::vector2df pos = readV2F1000(is); - std::string name = deSerializeString(is); - core::vector2df scale = readV2F1000(is); - std::string text = deSerializeString(is); - u32 number = readU32(is); - u32 item = readU32(is); - u32 dir = readU32(is); + 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.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; + 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::string datastring((char *)&data[2], datasize - 2); std::istringstream is(datastring, std::ios_base::binary); u32 id = readU32(is); @@ -2081,30 +2081,31 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) m_client_event_queue.push_back(event); } else if(command == TOCLIENT_HUDCHANGE) - { - std::string datastring((char*)&data[2], datasize-2); + { + 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 = readU8(is); - core::vector2df v2fdata; - std::string sdata; - u32 data = 0; - if(stat == 0 || stat == 2) { + u32 id = readU32(is); + u8 stat = (HudElementStat)readU8(is); + + if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE) v2fdata = readV2F1000(is); - } else if(stat == 1 || stat == 3) { + else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) sdata = deSerializeString(is); - } else { - data = readU32(is); - } - + else + intdata = readU32(is); + ClientEvent event; event.type = CE_HUDCHANGE; - event.hudchange.id = id; - event.hudchange.stat = stat; + 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 = data; + event.hudchange.sdata = new std::string(sdata); + event.hudchange.data = intdata; m_client_event_queue.push_back(event); } else diff --git a/src/client.h b/src/client.h index 696385a9..f5958868 100644 --- a/src/client.h +++ b/src/client.h @@ -186,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; @@ -221,24 +221,24 @@ struct ClientEvent 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; + 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; - u8 stat; - v2f* v2fdata; - std::string* sdata; + HudElementStat stat; + v2f *v2fdata; + std::string *sdata; u32 data; } hudchange; }; diff --git a/src/game.cpp b/src/game.cpp index 046b7bdb..a2d94ac0 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -59,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 @@ -229,296 +230,6 @@ public: FormspecFormSource** m_game_formspec; }; -/* - Item draw routine -*/ -void draw_item(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef, - v2s32 upperleftpos, s32 imgsize, s32 itemcount, - InventoryList *mainlist, u16 selectitem, unsigned short int direction) - //NOTE: selectitem = 0 -> no selected; selectitem 1-based - //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top -{ - s32 padding = imgsize/12; - s32 height = imgsize + padding*2; - s32 width = itemcount*(imgsize+padding*2); - if(direction == 2 or direction == 3){ - 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 barrect(0,0,width,height); - barrect += pos; - video::SColor bgcolor(255,128,128,128); - driver->draw2DRectangle(bgcolor, barrect, NULL);*/ - - core::rect imgrect(0,0,imgsize,imgsize); - - for(s32 i=0; igetItem(i); - - v2s32 steppos; - if(direction == 1){ - steppos = v2s32(-(padding+i*fullimglen), padding); - } else if(direction == 2) { - steppos = v2s32(padding, padding+i*fullimglen); - } else if(direction == 3) { - steppos = v2s32(padding, -(padding+i*fullimglen)); - } else { - steppos = v2s32(padding+i*fullimglen, padding); - } - core::rect 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( - v2s32(x1 - padding, y1 - padding), - v2s32(x2 + padding, y1) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect( - v2s32(x1 - padding, y2), - v2s32(x2 + padding, y2 + padding) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect( - v2s32(x1 - padding, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect( - v2s32(x2, y1), - v2s32(x2 + padding, y2) - ), NULL); - /*// Light inside borders - driver->draw2DRectangle(c_inside, - core::rect( - v2s32(x1 - padding/2, y1 - padding/2), - v2s32(x2 + padding/2, y1) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect( - v2s32(x1 - padding/2, y2), - v2s32(x2 + padding/2, y2 + padding/2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect( - v2s32(x1 - padding/2, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect( - 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); - } -} - -/* - Statbar draw routine -*/ -void draw_statbar(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef, - v2s32 upperleftpos, std::string texture, s32 count) - //NOTE: selectitem = 0 -> no selected; selectitem 1-based - //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top -{ - video::ITexture *stat_texture = - gamedef->getTextureSource()->getTextureRaw(texture); - if(stat_texture) - { - v2s32 p = upperleftpos; - for(s32 i=0; igetOriginalSize()); - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect rect(0,0,srcd.Width,srcd.Height); - rect += p; - driver->draw2DImage(stat_texture, rect, - core::rect(core::position2d(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 rect(0,0,srcd.Width/2,srcd.Height); - rect += p; - srcd.Width /= 2; - driver->draw2DImage(stat_texture, rect, - core::rect(core::position2d(0,0), srcd), - NULL, colors, true); - p += v2s32(srcd.Width*2,0); - } - } -} - -/* - 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"< barrect(0,0,width,height); - barrect += pos; - video::SColor bgcolor(255,128,128,128); - driver->draw2DRectangle(bgcolor, barrect, NULL);*/ - - core::rect imgrect(0,0,imgsize,imgsize); - - for(s32 i=0; igetItem(i); - - core::rect 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( - v2s32(x1 - padding, y1 - padding), - v2s32(x2 + padding, y1) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect( - v2s32(x1 - padding, y2), - v2s32(x2 + padding, y2 + padding) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect( - v2s32(x1 - padding, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect( - v2s32(x2, y1), - v2s32(x2 + padding, y2) - ), NULL); - /*// Light inside borders - driver->draw2DRectangle(c_inside, - core::rect( - v2s32(x1 - padding/2, y1 - padding/2), - v2s32(x2 + padding/2, y1) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect( - v2s32(x1 - padding/2, y2), - v2s32(x2 + padding/2, y2 + padding/2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect( - v2s32(x1 - padding/2, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect( - 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); - } -#else - s32 padding = imgsize/12; - s32 width = itemcount*(imgsize+padding*2); - v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2); - draw_item(driver, font, gamedef, pos, imgsize, itemcount, - mainlist, playeritem + 1, 0); -#endif -#if 0 - /* - 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 rect(0,0,16,16); - rect += p; - driver->draw2DImage(heart_texture, rect, - core::rect(core::position2d(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 rect(0,0,16/2,16); - rect += p; - core::dimension2di srcd(heart_texture->getOriginalSize()); - srcd.Width /= 2; - driver->draw2DImage(heart_texture, rect, - core::rect(core::position2d(0,0), srcd), - NULL, colors, true); - p += v2s32(16,0); - } - } -#else - draw_statbar(driver, font, gamedef, pos + v2s32(0, -20), - "heart.png", halfheartcount); -#endif -} - /* Check if a node is pointable */ @@ -1103,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 @@ -1534,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(;;) { @@ -1707,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 hilightboxes; @@ -2077,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) { @@ -2101,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; @@ -2390,8 +2099,18 @@ void the_game( } else if (event.type == CE_HUDADD) { - HudElement* e = new HudElement; - e->type = event.hudadd.type; + 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; @@ -2399,33 +2118,61 @@ void the_game( e->number = event.hudadd.number; e->item = event.hudadd.item; e->dir = event.hudadd.dir; - player->hud[event.hudadd.id] = e; - delete(event.hudadd.pos); - delete(event.hudadd.name); - delete(event.hudadd.scale); - delete(event.hudadd.text); + + 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) { - player->hud.erase(event.hudrm.id); + 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) { - HudElement* e = player->hud[event.hudchange.id]; - if(event.hudchange.stat == 0) - e->pos = *event.hudchange.v2fdata; - else if(event.hudchange.stat == 1) - e->name = *event.hudchange.sdata; - else if(event.hudchange.stat == 2) - e->scale = *event.hudchange.v2fdata; - else if(event.hudchange.stat == 3) - e->text = *event.hudchange.sdata; - else if(event.hudchange.stat == 4) - e->number = event.hudchange.data; - else if(event.hudchange.stat == 5) - e->item = event.hudchange.data; - else if(event.hudchange.stat == 6) - e->dir = event.hudchange.data; + 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; } } } @@ -3203,7 +2950,6 @@ void the_game( */ TimeTaker tt_draw("mainloop: draw"); - { TimeTaker timer("beginScene"); @@ -3307,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::const_iterator - i = hilightboxes.begin(); - i != hilightboxes.end(); i++) - { - /*infostream<<"hilightbox min=" - <<"("<MinEdge.X<<","<MinEdge.Y<<","<MinEdge.Z<<")" - <<" max=" - <<"("<MaxEdge.X<<","<MaxEdge.Y<<","<MaxEdge.Z<<")" - <draw3DBox(*i, video::SColor(255,selectionbox_color_r,selectionbox_color_g,selectionbox_color_b)); - } - } - + if (show_hud) + hud.drawSelectionBoxes(hilightboxes); /* Wielded tool */ @@ -3354,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(10,0), - displaycenter + core::vector2d(10,0), - video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); - driver->draw2DLine(displaycenter - core::vector2d(0,10), - displaycenter + core::vector2d(0,10), - video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); - } - + if (show_hud) + hud.drawCrosshair(); + } // timer //timer10.stop(); @@ -3379,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()); } @@ -3413,54 +3126,8 @@ void the_game( /* Draw lua hud items */ - std::deque luaguitexts; - if(show_hud) - { - for(std::map::iterator it = player->hud.begin(); - it != player->hud.end(); ++it) - { - HudElement* e = it->second; - v2f posp(e->pos * v2f(screensize.X, screensize.Y)); - core::vector2d pos(posp.X, posp.Y); - if(e->type == 'I'){ //Img - video::ITexture *texture = - gamedef->getTextureSource()->getTextureRaw(e->text); - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::dimension2di imgsize(texture->getOriginalSize()); - core::rect rect(0, 0, imgsize.Width*e->scale.X, - imgsize.Height*e->scale.X); - rect += pos; - driver->draw2DImage(texture, rect, - core::rect(core::position2d(0,0), imgsize), - NULL, colors, true); - } else if(e->type == 'T') { //Text - std::wstring t; - t.assign(e->text.begin(), e->text.end()); - gui::IGUIStaticText *luaguitext = guienv->addStaticText( - t.c_str(), - core::rect(0, 0, e->scale.X, text_height*(e->scale.Y))+pos, - false, false); - luaguitexts.push_back(luaguitext); - } else if(e->type == 'S') { //Statbar - draw_statbar(driver, font, gamedef, pos, e->text, e->number); - } else if(e->type == 's') { //Non-conflict Statbar - v2s32 p(displaycenter.X - 143, screensize.Y - 76); - p.X += e->pos.X*173; - p.Y += e->pos.X*20; - p.Y -= e->pos.Y*20; - draw_statbar(driver, font, gamedef, p, e->text, e->number); - } else if(e->type == 'i') { //Inv - InventoryList* inv = local_inventory.getList(e->text); - draw_item(driver, font, gamedef, pos, hotbar_imagesize, - e->number, inv, e->item, e->dir); - } else { - actionstream<<"luadraw: ignoring drawform "<second<< - "of key "<first<<" due to incorrect command."<drawAll(); - /* - Remove lua-texts - */ - for(std::deque::iterator it = luaguitexts.begin(); - it != luaguitexts.end(); ++it) - (*it)->remove(); - /* End scene */ @@ -3517,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 diff --git a/src/hud.cpp b/src/hud.cpp new file mode 100644 index 00000000..349c55ad --- /dev/null +++ b/src/hud.cpp @@ -0,0 +1,291 @@ +/* +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola +Copyright (C) 2010-2013 blue42u, Jonathon Anderson +Copyright (C) 2010-2013 kwolekr, Ryan Kwolek + +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 + +#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 barrect(0,0,width,height); + barrect += pos; + video::SColor bgcolor(255,128,128,128); + driver->draw2DRectangle(bgcolor, barrect, NULL);*/ + + core::rect 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 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( + v2s32(x1 - padding, y1 - padding), + v2s32(x2 + padding, y1) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect( + v2s32(x1 - padding, y2), + v2s32(x2 + padding, y2 + padding) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect( + v2s32(x1 - padding, y1), + v2s32(x1, y2) + ), NULL); + driver->draw2DRectangle(c_outside, + core::rect( + v2s32(x2, y1), + v2s32(x2 + padding, y2) + ), NULL); + /*// Light inside borders + driver->draw2DRectangle(c_inside, + core::rect( + v2s32(x1 - padding/2, y1 - padding/2), + v2s32(x2 + padding/2, y1) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect( + v2s32(x1 - padding/2, y2), + v2s32(x2 + padding/2, y2 + padding/2) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect( + v2s32(x1 - padding/2, y1), + v2s32(x1, y2) + ), NULL); + driver->draw2DRectangle(c_inside, + core::rect( + 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 rect(0, 0, imgsize.Width * e->scale.X, + imgsize.Height * e->scale.X); + rect += pos; + driver->draw2DImage(texture, rect, + core::rect(core::position2d(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 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 rect(0, 0, srcd.Width, srcd.Height); + rect += p; + driver->draw2DImage(stat_texture, rect, + core::rect(core::position2d(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 rect(0, 0, srcd.Width / 2, srcd.Height); + rect += p; + srcd.Width /= 2; + driver->draw2DImage(stat_texture, rect, + core::rect(core::position2d(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 &hilightboxes) { + for (std::vector::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 00000000..7e00a94e --- /dev/null +++ b/src/hud.h @@ -0,0 +1,116 @@ +/* +Minetest +Copyright (C) 2010-2013 kwolekr, Ryan Kwolek + +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 + +#include + +#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 &hilightboxes); +}; + +#endif + +#endif diff --git a/src/player.h b/src/player.h index fc80769c..d0e50d2c 100644 --- a/src/player.h +++ b/src/player.h @@ -87,7 +87,7 @@ class Map; class IGameDef; struct CollisionInfo; class PlayerSAO; -struct HudElement; +class HudElement; class Player { @@ -243,9 +243,8 @@ public: } u32 keyPressed; - - std::map hud; - std::map hud_bars; + + std::vector hud; protected: IGameDef *m_gamedef; @@ -257,17 +256,6 @@ protected: v3f m_position; }; -struct HudElement { - u8 type; - core::vector2df pos; - std::string name; - - core::vector2df scale; - std::string text; - u32 number; - u32 item; - u32 dir; -}; /* Player on the server diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp index 8f92ca43..531bb7a5 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 @@ -705,205 +729,161 @@ int ObjectRef::l_hud_add(lua_State *L) { ObjectRef *ref = checkobject(L, 1); Player *player = getplayer(ref); - if(player == NULL) return 0; + if (player == NULL) + return 0; - u32 id = hud_get_next_id(L); - HudElement* form = new HudElement; - std::string SS = getstringfield_default(L, 3, "type", "I"); - form->type = SS[0]; - lua_getfield(L, 3, "position"); - if(lua_istable(L, -1)) - form->pos = read_v2f(L, -1); - else - form->pos = v2f(); + 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); - form->name = getstringfield_default(L, 3, "name", ""); - - lua_getfield(L, 3, "scale"); - if(lua_istable(L, -1)) - form->scale = read_v2f(L, -1); - else - form->scale = v2f(); + + 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); - form->text = getstringfield_default(L, 3, "text", ""); - form->number = getintfield_default(L, 3, "number", 0); - form->item = getintfield_default(L, 3, "item", 0); - form->dir = getintfield_default(L, 3, "dir", 0); + u32 id = get_server(L)->hudAdd(player, elem); + if (id == (u32)-1) { + delete elem; + return 0; + } - get_server(L)->hudadd(player->getName(), id, form); - player->hud[id] = form; lua_pushnumber(L, id); return 1; } -// hud_rm(self, id) -int ObjectRef::l_hud_rm(lua_State *L) +// 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; + if (player == NULL) + return 0; u32 id = -1; - if(!lua_isnil(L, 2)) + if (!lua_isnil(L, 2)) id = lua_tonumber(L, 2); - get_server(L)->hudrm(player->getName(), id); - player->hud.at(id)->type = (u8)NULL; + + 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; + if (player == NULL) + return 0; u32 id = -1; - if(!lua_isnil(L, 2)) + if (!lua_isnil(L, 2)) id = lua_tonumber(L, 2); - u8 stat = -1; - if(!lua_isnil(L, 3)) - stat = lua_tonumber(L, 3); - if(stat == 0 || stat == 2) { - get_server(L)->hudchange(player->getName(), id, stat, read_v2f(L, 4)); - } else if(stat == 1 || stat == 3) { - get_server(L)->hudchange(player->getName(), id, stat, lua_tostring(L, 4)); - } else { - get_server(L)->hudchange(player->getName(), id, stat, lua_tonumber(L, 4)); - } - - HudElement* e = player->hud[id]; - switch(stat) { - case HUD_STAT_POS: e->pos = read_v2f(L, 4); - case HUD_STAT_NAME: e->name = lua_tostring(L, 4); - case HUD_STAT_SCALE: e->scale = read_v2f(L, 4); - case HUD_STAT_TEXT: e->text = lua_tostring(L, 4); - case HUD_STAT_NUMBER: e->number = lua_tonumber(L, 4); - case HUD_STAT_ITEM: e->item = lua_tonumber(L, 4); - case HUD_STAT_DIR: e->dir = lua_tonumber(L, 4); + + 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; } -u32 ObjectRef::hud_get_next_id(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - - for(std::map::iterator it=player->hud.begin(); - it!=player->hud.end();it++) { - if(it->second->type == (u8)NULL) { - return it->first; - } - } - return player->hud.size(); -} - // 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; + if (player == NULL) + return 0; - HudElement* e = player->hud.at(lua_tonumber(L, -1)); + 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, std::string(1, e->type).c_str()); + + 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; } -// hud_lock_next_bar(self, texture, right) -// return id on success, false otherwise -int ObjectRef::l_hud_lock_next_bar(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - - bool right = false; - if(!lua_isnil(L, 2)) - right = lua_toboolean(L, 2); - v2f pos(0, 0); - u8 i = 0; - if(right) - pos.X = 1; - i += 3; - for(u8 it = 0; it < 4; it++) { - if(player->hud_bars.count(i+it) == 1) { - if(it == 3) { - lua_pushboolean(L, false); - return 1; - } - } else { - i += it; - pos.Y = it; - break; - } - } - HudElement* form = new HudElement; - form->type = 's'; - form->pos = pos; - form->name = ""; - form->scale = v2f(); - form->text = ""; - form->number = 0; - form->item = 0; - form->dir = 0; - - u32 id = hud_get_next_id(L); - get_server(L)->hudadd(player->getName(), id, form); - player->hud[id] = form; - player->hud_bars[i] = id; - lua_pushnumber(L, id); - return 1; -} - -// hud_unlock_bar(self, id) -int ObjectRef::l_hud_unlock_bar(lua_State *L) -{ - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - - u32 id = 0; - if(!lua_isnil(L, 2)) - id = lua_tonumber(L, 2); - - for(std::map::iterator it=player->hud_bars.begin(); - it!=player->hud_bars.end();it++) { - if(it->second == id) { - player->hud_bars.erase(it->first); - get_server(L)->hudrm(player->getName(), id); - player->hud.at(id)->type = (u8)NULL; - lua_pushboolean(L, true); - return 1; - } - } - lua_pushboolean(L, false); - return 1; -} - ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) { @@ -1011,11 +991,11 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, get_player_control), luamethod(ObjectRef, get_player_control_bits), luamethod(ObjectRef, hud_add), - luamethod(ObjectRef, hud_rm), + luamethod(ObjectRef, hud_remove), luamethod(ObjectRef, hud_change), luamethod(ObjectRef, hud_get), - luamethod(ObjectRef, hud_lock_next_bar), - luamethod(ObjectRef, hud_unlock_bar), + //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 6df4366b..fd46f2cf 100644 --- a/src/scriptapi_object.h +++ b/src/scriptapi_object.h @@ -29,14 +29,6 @@ extern "C" { #include "content_sao.h" #include "player.h" -#define HUD_STAT_POS 0 -#define HUD_STAT_NAME 1 -#define HUD_STAT_SCALE 2 -#define HUD_STAT_TEXT 3 -#define HUD_STAT_NUMBER 4 -#define HUD_STAT_ITEM 5 -#define HUD_STAT_DIR 6 - /* ObjectRef */ @@ -202,23 +194,14 @@ private: static int l_hud_add(lua_State *L); // hud_rm(self, id) - static int l_hud_rm(lua_State *L); + static int l_hud_remove(lua_State *L); // hud_change(self, id, stat, data) static int l_hud_change(lua_State *L); - // hud_get_next_id(self) - static u32 hud_get_next_id(lua_State *L); - // hud_get(self, id) static int l_hud_get(lua_State *L); - // hud_lock_next_bar(self, right) - static int l_hud_lock_next_bar(lua_State *L); - - // hud_unlock_bar(self, id) - static int l_hud_unlock_bar(lua_State *L); - public: ObjectRef(ServerActiveObject *object); diff --git a/src/server.cpp b/src/server.cpp index a9632c93..241826ba 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3449,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); @@ -3470,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); @@ -3492,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::iterator i = m_clients.begin(); @@ -3595,22 +3601,18 @@ void Server::SendDeleteParticleSpawnerAll(u32 id) } } -void Server::SendHUDAdd(u16 peer_id, const u32 id, HudElement* form) +void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form) { - DSTACK(__FUNCTION_NAME); - std::ostringstream os(std::ios_base::binary); - u8 buf[12]; // Write command - writeU16(buf, TOCLIENT_HUDADD); - os.write((char*)buf, 2); + writeU16(os, TOCLIENT_HUDADD); writeU32(os, id); - writeU8(os, form->type); + writeU8(os, (u8)form->type); writeV2F1000(os, form->pos); - os<name); + os << serializeString(form->name); writeV2F1000(os, form->scale); - os<text); + os << serializeString(form->text); writeU32(os, form->number); writeU32(os, form->item); writeU32(os, form->dir); @@ -3622,16 +3624,12 @@ void Server::SendHUDAdd(u16 peer_id, const u32 id, HudElement* form) m_con.Send(peer_id, 0, data, true); } -void Server::SendHUDRm(u16 peer_id, const u32 id) +void Server::SendHUDRemove(u16 peer_id, u32 id) { - DSTACK(__FUNCTION_NAME); - std::ostringstream os(std::ios_base::binary); - u8 buf[12]; // Write command - writeU16(buf, TOCLIENT_HUDRM); - os.write((char*)buf, 2); + writeU16(os, TOCLIENT_HUDRM); writeU32(os, id); // Make data buffer @@ -3641,67 +3639,36 @@ void Server::SendHUDRm(u16 peer_id, const u32 id) m_con.Send(peer_id, 0, data, true); } -void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data) +void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value) { - DSTACK(__FUNCTION_NAME); - std::ostringstream os(std::ios_base::binary); - u8 buf[12]; // Write command - writeU16(buf, TOCLIENT_HUDCHANGE); - os.write((char*)buf, 2); + writeU16(os, TOCLIENT_HUDCHANGE); writeU32(os, id); - writeU8(os, stat); - writeV2F1000(os, data); + 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 ddata((u8*)s.c_str(), s.size()); + SharedBuffer data((u8 *)s.c_str(), s.size()); // Send as reliable - m_con.Send(peer_id, 0, ddata, true); -} - -void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data) -{ - DSTACK(__FUNCTION_NAME); - - std::ostringstream os(std::ios_base::binary); - u8 buf[12]; - - // Write command - writeU16(buf, TOCLIENT_HUDCHANGE); - os.write((char*)buf, 2); - writeU32(os, id); - writeU8(os, stat); - os< ddata((u8*)s.c_str(), s.size()); - // Send as reliable - m_con.Send(peer_id, 0, ddata, true); -} - -void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data) -{ - DSTACK(__FUNCTION_NAME); - - std::ostringstream os(std::ios_base::binary); - u8 buf[12]; - - // Write command - writeU16(buf, TOCLIENT_HUDCHANGE); - os.write((char*)buf, 2); - writeU32(os, id); - writeU8(os, stat); - writeU32(os, data); - - // Make data buffer - std::string s = os.str(); - SharedBuffer ddata((u8*)s.c_str(), s.size()); - // Send as reliable - m_con.Send(peer_id, 0, ddata, true); + m_con.Send(peer_id, 0, data, true); } void Server::BroadcastChatMessage(const std::wstring &message) @@ -4657,71 +4624,34 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c return true; } -bool Server::hudadd(const char *playername, const u32 &id, HudElement* form) -{ - Player *player = m_env->getPlayer(playername); - - if(!player) - { - infostream<<"hudadd: couldn't find 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::hudrm(const char *playername, const u32 &id) -{ - Player *player = m_env->getPlayer(playername); - - if(!player) - { - infostream<<"hudrm: couldn't find player:"<peer_id, id); - return true; -} - -bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, v2f data) -{ - Player *player = m_env->getPlayer(playername); - - if(!player) - { - infostream<<"hudchange: couldn't find player:"<peer_id, id, stat, data); - return true; -} - -bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, std::string data) -{ - Player *player = m_env->getPlayer(playername); - - if(!player) - { - infostream<<"hudchange: couldn't find player:"<peer_id, id, stat, data); - return true; -} - -bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, u32 data) -{ - Player *player = m_env->getPlayer(playername); - - if(!player) - { - infostream<<"hudchange: couldn't find player:"<peer_id, id, stat, data); return true; diff --git a/src/server.h b/src/server.h index ef0c45a6..52606b0c 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,11 +536,11 @@ public: } bool showFormspec(const char *name, const std::string &formspec, const std::string &formname); - bool hudadd(const char *pname, const u32 &id, HudElement *element); - bool hudrm(const char *pname, const u32 &id); - bool hudchange(const char *pname, const u32 &id, const u8 &stat, v2f data); - bool hudchange(const char *pname, const u32 &id, const u8 &stat, std::string data); - bool hudchange(const char *pname, const u32 &id, const u8 &stat, u32 data); + + 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. @@ -578,11 +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, const u32 id, HudElement* form); - void SendHUDRm(u16 peer_id, const u32 id); - void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data); - void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data); - void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data); + 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 From e60eb32050a44d344795e4a1515a56038bb97e02 Mon Sep 17 00:00:00 2001 From: LS-Steeef Date: Thu, 18 Apr 2013 16:30:11 +0300 Subject: [PATCH 26/26] Add dutch translation --- po/du/minetest.po | 776 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 776 insertions(+) create mode 100644 po/du/minetest.po diff --git a/po/du/minetest.po b/po/du/minetest.po new file mode 100644 index 00000000..b2024d8a --- /dev/null +++ b/po/du/minetest.po @@ -0,0 +1,776 @@ +# SOME DESCRIPTIVE TITLE. DUTCH TRANSLATION +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-03-30 19:56+0100\n" +"PO-Revision-Date: 2013-04-18 15:28+0100\n" +"Last-Translator: LS-Steeef \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.5\n" +"Language: dutch\n" + +#: src/guiConfigureWorld.cpp:125 +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" +"Let op: Nog niet alle mods zijn geconfigueerd. \n" +"De mods zullen automatisch worden ingeschakeld als je de configuratie " +"bewaard." + +#: src/guiConfigureWorld.cpp:144 +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" +"LEt op: Sommige ingestelde mods zijn vermist.\n" +"Hun instellingen worden verwijderd als je de configuratie opslaat." + +#: src/guiConfigureWorld.cpp:208 +msgid "enabled" +msgstr "ingeschakeld" + +#: src/guiConfigureWorld.cpp:215 +msgid "Enable All" +msgstr "Allen inschakelen" + +#: src/guiConfigureWorld.cpp:222 +msgid "Disable All" +msgstr "Allen uitschakelen" + +#: src/guiConfigureWorld.cpp:228 +msgid "depends on:" +msgstr "heeft nodig:" + +#: src/guiConfigureWorld.cpp:240 +msgid "is required by:" +msgstr "is benodigd voor:" + +#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 +#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 +msgid "Cancel" +msgstr "Annuleer" + +#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 +msgid "Save" +msgstr "Bewaar" + +#: src/guiConfigureWorld.cpp:394 +msgid "Configuration saved. " +msgstr "Instellingen bewaard." + +#: src/guiConfigureWorld.cpp:402 +msgid "Warning: Configuration not consistent. " +msgstr "Waarschuwing: Instellingen niet consistent." + +#: src/guiConfirmMenu.cpp:120 +msgid "Yes" +msgstr "Ja" + +#: src/guiConfirmMenu.cpp:126 +msgid "No" +msgstr "Nee" + +#: src/guiCreateWorld.cpp:116 +msgid "World name" +msgstr "Naam wereld" + +#: src/guiCreateWorld.cpp:135 +msgid "Game" +msgstr "Spel" + +#: src/guiCreateWorld.cpp:159 +msgid "Create" +msgstr "Maak aan" + +#: src/guiDeathScreen.cpp:96 +msgid "You died." +msgstr "Je bent gestorven." + +#: src/guiDeathScreen.cpp:104 +msgid "Respawn" +msgstr "Respawn" + +#: src/guiFormSpecMenu.cpp:582 +msgid "Left click: Move all items, Right click: Move single item" +msgstr "" +"Linkermuisknop: Verplaats alle items. Rechtermuisknop: Verplaats één item." + +#: src/guiFormSpecMenu.cpp:607 src/guiMessageMenu.cpp:109 +#: src/guiTextInputMenu.cpp:131 +msgid "Proceed" +msgstr "Volgende" + +#: src/guiKeyChangeMenu.cpp:114 +msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" +msgstr "Sneltoetsen." + +#: src/guiKeyChangeMenu.cpp:151 +msgid "\"Use\" = climb down" +msgstr "\"Use\" = Omlaag klimmen" + +#: src/guiKeyChangeMenu.cpp:164 +msgid "Double tap \"jump\" to toggle fly" +msgstr "Dubbelklik op \"jump\" om te vliegen" + +#: src/guiKeyChangeMenu.cpp:269 +msgid "Key already in use" +msgstr "Toets is al in gebruik" + +#: src/guiKeyChangeMenu.cpp:347 +msgid "press key" +msgstr "druk op" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Vooruit" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Achteruit" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Links" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Rechts" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Gebruikwn" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Springen" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Kruipen" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "Weggooien" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Rugzak" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Chat" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "Opdracht" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "Console" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Vliegen aan/uit" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Snel bewegen aan/uit" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "Noclip aan/uit" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Range instellen" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "Print stacks" + +#: src/guiMainMenu.cpp:92 +msgid "Cannot create world: Name contains invalid characters" +msgstr "Kan geen nieuwe wereld aanmaken: de naam bevat onjuiste tekens." + +#: src/guiMainMenu.cpp:101 +msgid "Cannot create world: A world by this name already exists" +msgstr "Kan geen nieuwe wereld aanmaken: De naam bestaat al." + +#: src/guiMainMenu.cpp:283 +msgid "Singleplayer" +msgstr "Singleplayer" + +#: src/guiMainMenu.cpp:284 +msgid "Multiplayer" +msgstr "Multiplayer" + +#: src/guiMainMenu.cpp:285 +msgid "Advanced" +msgstr "Geavanceerd" + +#: src/guiMainMenu.cpp:286 +msgid "Settings" +msgstr "Instellingen" + +#: src/guiMainMenu.cpp:287 +msgid "Credits" +msgstr "Credits" + +#: src/guiMainMenu.cpp:317 +msgid "Select World:" +msgstr "Selecteer Wereld:" + +#: src/guiMainMenu.cpp:339 src/guiMainMenu.cpp:511 src/keycode.cpp:229 +msgid "Delete" +msgstr "Verwijderen" + +#: src/guiMainMenu.cpp:346 +msgid "New" +msgstr "Nieuw" + +#: src/guiMainMenu.cpp:354 +msgid "Configure" +msgstr "Instellingen" + +#: src/guiMainMenu.cpp:369 src/keycode.cpp:248 +msgid "Play" +msgstr "Speel!" + +#: src/guiMainMenu.cpp:380 src/guiMainMenu.cpp:619 +msgid "Creative Mode" +msgstr "Creative Modus" + +#: src/guiMainMenu.cpp:386 src/guiMainMenu.cpp:625 +msgid "Enable Damage" +msgstr "Schade inschakelen" + +#: src/guiMainMenu.cpp:406 src/guiMainMenu.cpp:541 +msgid "Name/Password" +msgstr "Naam/Wachtwoord" + +#: src/guiMainMenu.cpp:442 src/guiMainMenu.cpp:459 src/guiMainMenu.cpp:1184 +msgid "Favorites:" +msgstr "Favourieten:" + +#: src/guiMainMenu.cpp:450 src/guiMainMenu.cpp:1194 +msgid "Public Server List:" +msgstr "Publieke Server lijst:" + +#: src/guiMainMenu.cpp:470 src/guiMainMenu.cpp:568 +msgid "Address/Port" +msgstr "IP-Adres/Poort" + +#: src/guiMainMenu.cpp:497 src/guiMainMenu.cpp:1183 +msgid "Show Public" +msgstr "Publieke server" + +#: src/guiMainMenu.cpp:501 src/guiMainMenu.cpp:1193 +msgid "Show Favorites" +msgstr "Favourieten" + +#: src/guiMainMenu.cpp:521 +msgid "Connect" +msgstr "Verbinden" + +#: src/guiMainMenu.cpp:591 +msgid "Leave address blank to start a local server." +msgstr "Laat het adres leeg om een lokale server te starten." + +#: src/guiMainMenu.cpp:600 +msgid "Start Game / Connect" +msgstr "Start het spel / Verbind" + +#: src/guiMainMenu.cpp:632 +msgid "Public" +msgstr "Publiek" + +#: src/guiMainMenu.cpp:640 src/guiMainMenu.cpp:1113 +msgid "Delete world" +msgstr "Verwijder wereld" + +#: src/guiMainMenu.cpp:647 +msgid "Create world" +msgstr "Maak wereld aan" + +#: src/guiMainMenu.cpp:681 +msgid "Fancy trees" +msgstr "Mooie bomen" + +#: src/guiMainMenu.cpp:687 +msgid "Smooth Lighting" +msgstr "Mooie verlichting" + +#: src/guiMainMenu.cpp:693 +msgid "3D Clouds" +msgstr "3D wolken" + +#: src/guiMainMenu.cpp:699 +msgid "Opaque water" +msgstr "Doorzichtig water" + +#: src/guiMainMenu.cpp:709 +msgid "Mip-Mapping" +msgstr "Mip-Mapping" + +#: src/guiMainMenu.cpp:716 +msgid "Anisotropic Filtering" +msgstr "Bi-Linear Filtering" + +#: src/guiMainMenu.cpp:723 +msgid "Bi-Linear Filtering" +msgstr "Bi-Linear Filtering" + +#: src/guiMainMenu.cpp:730 +msgid "Tri-Linear Filtering" +msgstr "Tri-Linear Filtering" + +#: src/guiMainMenu.cpp:738 +msgid "Shaders" +msgstr "Shaders" + +#: src/guiMainMenu.cpp:745 +msgid "Preload item visuals" +msgstr "Preload item visuals" + +#: src/guiMainMenu.cpp:752 +msgid "Enable Particles" +msgstr "Enable Particles" + +#: src/guiMainMenu.cpp:759 +msgid "Finite liquid" +msgstr "Finite liquid" + +#: src/guiMainMenu.cpp:769 +msgid "Change keys" +msgstr "Sneltoetsen veranderen" + +#: src/guiMainMenu.cpp:1084 +msgid "Address required." +msgstr "IP-adres nodig." + +#: src/guiMainMenu.cpp:1102 +msgid "Cannot delete world: Nothing selected" +msgstr "Kan niets verwijderen: Geen wereld geselecteerd." + +#: src/guiMainMenu.cpp:1117 +msgid "Files to be deleted" +msgstr "Deze bestanden worden verwijderd" + +#: src/guiMainMenu.cpp:1133 +msgid "Cannot create world: No games found" +msgstr "Kan geen wereld aanmaken: Geen games gevonden" + +#: src/guiMainMenu.cpp:1149 +msgid "Cannot configure world: Nothing selected" +msgstr "Kan instellingen niet aanpassen: Niets geselecteerd" + +#: src/guiMainMenu.cpp:1256 +msgid "Failed to delete all world files" +msgstr "Niet alle bestanden zijn verwijderd" + +#: src/guiPasswordChange.cpp:108 +msgid "Old Password" +msgstr "Huidig wachtwoord" + +#: src/guiPasswordChange.cpp:125 +msgid "New Password" +msgstr "Nieuw wachtwoord" + +#: src/guiPasswordChange.cpp:141 +msgid "Confirm Password" +msgstr "Herhaal wachtwoord" + +#: src/guiPasswordChange.cpp:158 +msgid "Change" +msgstr "Veranderen" + +#: src/guiPasswordChange.cpp:167 +msgid "Passwords do not match!" +msgstr "Wachtwoorden zijn niet gelijk!" + +#: src/guiPauseMenu.cpp:123 +msgid "Continue" +msgstr "Volgende" + +#: src/guiPauseMenu.cpp:132 +msgid "Change Password" +msgstr "Verander wachtwoord" + +#: src/guiPauseMenu.cpp:140 +msgid "Sound Volume" +msgstr "Volume" + +#: src/guiPauseMenu.cpp:147 +msgid "Exit to Menu" +msgstr "Exit naar menu" + +#: src/guiPauseMenu.cpp:154 +msgid "Exit to OS" +msgstr "Afsluiten" + +#: src/guiPauseMenu.cpp:161 +msgid "" +"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" +msgstr "" +"Default Besturing:\n" +"- WASD: Lopen\n" +"- Linkermuisknop: Graaf/Sla\n" +"- Rechtmuisknop: Plaats/Gebruik\n" +"- Muiswiel: selecteer item\n" +"- 0...9: selecteer item\n" +"- Shift: kruipen\n" +"- R: Toggle viewing all loaded chunks\n" +"- I: Rugzak\n" +"- ESC: Menu\n" +"- T: Chat\n" + +#: src/guiVolumeChange.cpp:108 +msgid "Sound Volume: " +msgstr "Volume:" + +#: src/guiVolumeChange.cpp:121 +msgid "Exit" +msgstr "Exit" + +#: src/keycode.cpp:223 +msgid "Left Button" +msgstr "Linkermuisknop" + +#: src/keycode.cpp:223 +msgid "Middle Button" +msgstr "Muiswielknop" + +#: src/keycode.cpp:223 +msgid "Right Button" +msgstr "Rechtmuisknop" + +#: src/keycode.cpp:223 +msgid "X Button 1" +msgstr "X knop 1" + +#: src/keycode.cpp:224 +msgid "Back" +msgstr "Terug" + +#: src/keycode.cpp:224 +msgid "Clear" +msgstr "Wissen" + +#: src/keycode.cpp:224 +msgid "Return" +msgstr "Return" + +#: src/keycode.cpp:224 +msgid "Tab" +msgstr "Tab" + +#: src/keycode.cpp:224 +msgid "X Button 2" +msgstr "X knop 2" + +#: src/keycode.cpp:225 +msgid "Capital" +msgstr "Kapitaal" + +#: src/keycode.cpp:225 +msgid "Control" +msgstr "Control" + +#: src/keycode.cpp:225 +msgid "Kana" +msgstr "Kana" + +#: src/keycode.cpp:225 +msgid "Menu" +msgstr "Menu" + +#: src/keycode.cpp:225 +msgid "Pause" +msgstr "Pauze" + +#: src/keycode.cpp:225 +msgid "Shift" +msgstr "Shift" + +#: src/keycode.cpp:226 +msgid "Convert" +msgstr "Converteren" + +#: src/keycode.cpp:226 +msgid "Escape" +msgstr "Escape" + +#: src/keycode.cpp:226 +msgid "Final" +msgstr "Final" + +#: src/keycode.cpp:226 +msgid "Junja" +msgstr "Junja" + +#: src/keycode.cpp:226 +msgid "Kanji" +msgstr "Kanji" + +#: src/keycode.cpp:226 +msgid "Nonconvert" +msgstr "Nonconvert" + +#: src/keycode.cpp:227 +msgid "Accept" +msgstr "Accepteren" + +#: src/keycode.cpp:227 +msgid "End" +msgstr "End" + +#: src/keycode.cpp:227 +msgid "Home" +msgstr "Home" + +#: src/keycode.cpp:227 +msgid "Mode Change" +msgstr "Modus veranderen" + +#: src/keycode.cpp:227 +msgid "Next" +msgstr "Volgende" + +#: src/keycode.cpp:227 +msgid "Prior" +msgstr "Eerste" + +#: src/keycode.cpp:227 +msgid "Space" +msgstr "Spatie" + +#: src/keycode.cpp:228 +msgid "Down" +msgstr "Omlaag" + +#: src/keycode.cpp:228 +msgid "Execute" +msgstr "Uitvoeren" + +#: src/keycode.cpp:228 +msgid "Print" +msgstr "Print" + +#: src/keycode.cpp:228 +msgid "Select" +msgstr "Selecteren" + +#: src/keycode.cpp:228 +msgid "Up" +msgstr "Omhoog" + +#: src/keycode.cpp:229 +msgid "Help" +msgstr "Help" + +#: src/keycode.cpp:229 +msgid "Insert" +msgstr "Insert" + +#: src/keycode.cpp:229 +msgid "Snapshot" +msgstr "Screenshot" + +#: src/keycode.cpp:232 +msgid "Left Windows" +msgstr "Linker Windowstoets" + +#: src/keycode.cpp:233 +msgid "Apps" +msgstr "Apps" + +#: src/keycode.cpp:233 +msgid "Numpad 0" +msgstr "Numpad 0" + +#: src/keycode.cpp:233 +msgid "Numpad 1" +msgstr "Numpad 1" + +#: src/keycode.cpp:233 +msgid "Right Windows" +msgstr "Rechter Windowstoets" + +#: src/keycode.cpp:233 +msgid "Sleep" +msgstr "Slaapknop" + +#: src/keycode.cpp:234 +msgid "Numpad 2" +msgstr "Numpad 2" + +#: src/keycode.cpp:234 +msgid "Numpad 3" +msgstr "Numpad 3" + +#: src/keycode.cpp:234 +msgid "Numpad 4" +msgstr "Numpad 4" + +#: src/keycode.cpp:234 +msgid "Numpad 5" +msgstr "Numpad 5" + +#: src/keycode.cpp:234 +msgid "Numpad 6" +msgstr "Numpad 6" + +#: src/keycode.cpp:234 +msgid "Numpad 7" +msgstr "Numpad 7" + +#: src/keycode.cpp:235 +msgid "Numpad *" +msgstr "Numpad *" + +#: src/keycode.cpp:235 +msgid "Numpad +" +msgstr "Numpad +" + +#: src/keycode.cpp:235 +msgid "Numpad -" +msgstr "Numpad -" + +#: src/keycode.cpp:235 +msgid "Numpad /" +msgstr "Numpad /" + +#: src/keycode.cpp:235 +msgid "Numpad 8" +msgstr "Numpad 8" + +#: src/keycode.cpp:235 +msgid "Numpad 9" +msgstr "Numpad 9" + +#: src/keycode.cpp:239 +msgid "Num Lock" +msgstr "Num Lock" + +#: src/keycode.cpp:239 +msgid "Scroll Lock" +msgstr "Scroll Lock" + +#: src/keycode.cpp:240 +msgid "Left Shift" +msgstr "Linker Shift" + +#: src/keycode.cpp:240 +msgid "Right Shift" +msgstr "Rechter Shift" + +#: src/keycode.cpp:241 +msgid "Left Control" +msgstr "Linker Ctrl" + +#: src/keycode.cpp:241 +msgid "Left Menu" +msgstr "Linker Menu" + +#: src/keycode.cpp:241 +msgid "Right Control" +msgstr "Rechter Ctrl" + +#: src/keycode.cpp:241 +msgid "Right Menu" +msgstr "Rechter Menu" + +#: src/keycode.cpp:243 +msgid "Comma" +msgstr "Komma" + +#: src/keycode.cpp:243 +msgid "Minus" +msgstr "Min" + +#: src/keycode.cpp:243 +msgid "Period" +msgstr "Punt" + +#: src/keycode.cpp:243 +msgid "Plus" +msgstr "Plus" + +#: src/keycode.cpp:247 +msgid "Attn" +msgstr "Attn" + +#: src/keycode.cpp:247 +msgid "CrSel" +msgstr "CrSel" + +#: src/keycode.cpp:248 +msgid "Erase OEF" +msgstr "Erase OEF" + +#: src/keycode.cpp:248 +msgid "ExSel" +msgstr "ExSel" + +#: src/keycode.cpp:248 +msgid "OEM Clear" +msgstr "OEM Clear" + +#: src/keycode.cpp:248 +msgid "PA1" +msgstr "PA1" + +#: src/keycode.cpp:248 +msgid "Zoom" +msgstr "Zoom" + +#: src/main.cpp:1506 +msgid "Main Menu" +msgstr "Hoofdmenu" + +#: src/main.cpp:1830 +msgid "Failed to initialize world" +msgstr "Laden van wereld is mislukt" + +#: src/main.cpp:1842 +msgid "No world selected and no address provided. Nothing to do." +msgstr "Geen wereld en adres geselecteerd. Niks te doen." + +#: src/main.cpp:1850 +msgid "Could not find or load game \"" +msgstr "Kan niet de game laden of vinden." + +#: src/main.cpp:1864 +msgid "Invalid gamespec." +msgstr "Onjuiste gamespec." + +#: src/main.cpp:1904 +msgid "Connection error (timed out?)" +msgstr "Connection error (timed out?)" + +#: src/main.cpp:1915 +msgid "" +"\n" +"Check debug.txt for details." +msgstr "" +"\n" +"Check debug.txt for details."