From 15c7460edaa279b96c235ec8bc4ae9bad5739e66 Mon Sep 17 00:00:00 2001 From: sapier Date: Thu, 25 Sep 2014 19:54:02 +0200 Subject: [PATCH 01/18] Fix chat lines not word wrapped correct --- src/game.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 45b879ff2..a8f6bc992 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1102,8 +1102,16 @@ static void updateChat(Client& client, f32 dtime, bool show_debug, if (show_debug) chat_y += line_height; - core::rect rect(10, chat_y, font->getDimension(recent_chat.c_str()).Width +10, - chat_y + (recent_chat_count * line_height)); + // first pass to calculate height of text to be set + s32 width = std::min(font->getDimension(recent_chat.c_str()).Width + 10, + porting::getWindowSize().X - 20); + core::rect rect(10, chat_y, width, chat_y + porting::getWindowSize().Y); + guitext_chat->setRelativePosition(rect); + + //now use real height of text and adjust rect according to this size + rect = core::rect(10, chat_y, width, + chat_y + guitext_chat->getTextHeight()); + guitext_chat->setRelativePosition(rect); // Don't show chat if disabled or empty or profiler is enabled From 121e8cc2a145591000282548ef07dbc70af7c6fc Mon Sep 17 00:00:00 2001 From: sapier Date: Thu, 25 Sep 2014 20:33:17 +0200 Subject: [PATCH 02/18] Fix totally messed up 3d modes interlaced/topbottom/sidebyside --- src/drawscene.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/drawscene.cpp b/src/drawscene.cpp index 2080ccb73..20c2e22be 100644 --- a/src/drawscene.cpp +++ b/src/drawscene.cpp @@ -132,14 +132,15 @@ void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud, } void init_texture(video::IVideoDriver* driver, const v2u32& screensize, - video::ITexture** texture) + video::ITexture** texture, const char* name) { if (*texture != NULL) { driver->removeTexture(*texture); } *texture = driver->addRenderTargetTexture( - core::dimension2d(screensize.X, screensize.Y)); + core::dimension2d(screensize.X, screensize.Y), name, + irr::video::ECF_A8R8G8B8); } video::ITexture* draw_image(const v2u32& screensize, @@ -156,13 +157,16 @@ video::ITexture* draw_image(const v2u32& screensize, video::ITexture* image = NULL; if (screensize != last_screensize) { - init_texture(driver, screensize, &images[1]); - image = images[1]; - init_texture(driver, screensize, &images[0]); - image = images[0]; + init_texture(driver, screensize, &images[1], "mt_drawimage_img1"); + init_texture(driver, screensize, &images[0], "mt_drawimage_img2"); last_screensize = screensize; } + if (psign == RIGHT) + image = images[1]; + else + image = images[0]; + driver->setRenderTarget(image, true, true, irr::video::SColor(255, skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue())); @@ -205,7 +209,7 @@ video::ITexture* draw_hud(video::IVideoDriver* driver, const v2u32& screensize, video::SColor skycolor, gui::IGUIEnvironment* guienv, Camera& camera ) { static video::ITexture* image = NULL; - init_texture(driver, screensize, &image); + init_texture(driver, screensize, &image, "mt_drawimage_hud"); driver->setRenderTarget(image, true, true, irr::video::SColor(255,0,0,0)); From b75e7148c2c6ad9a602d78d7ec6356273e3a4214 Mon Sep 17 00:00:00 2001 From: BlockMen Date: Sun, 28 Sep 2014 08:44:05 +0200 Subject: [PATCH 03/18] Fix multilined description in tooltips (fixes #1688) --- src/guiFormSpecMenu.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 1c8b63299..cbba313bc 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -2141,10 +2141,10 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) // Draw tooltip std::string tooltip_text = ""; - if(hovering && !m_selected_item) + if (hovering && !m_selected_item) tooltip_text = item.getDefinition(m_gamedef->idef()).description; - if(tooltip_text != "") - { + if (tooltip_text != "") { + std::vector tt_rows = split(tooltip_text,'\n'); m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor); m_tooltip_element->setOverrideColor(m_default_tooltip_color); m_tooltip_element->setVisible(true); @@ -2153,7 +2153,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) s32 tooltip_x = m_pointer.X + m_btn_height; s32 tooltip_y = m_pointer.Y + m_btn_height; s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; - s32 tooltip_height = m_tooltip_element->getTextHeight() + 5; + s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5; m_tooltip_element->setRelativePosition(core::rect( core::position2d(tooltip_x, tooltip_y), core::dimension2d(tooltip_width, tooltip_height))); From 61ed56f916f71a708b56260d7cba2160e8166529 Mon Sep 17 00:00:00 2001 From: BlockMen Date: Sun, 28 Sep 2014 10:10:43 +0200 Subject: [PATCH 04/18] Standardize tooltip row detection --- src/guiFormSpecMenu.cpp | 11 +++-------- src/util/string.h | 10 ++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index cbba313bc..f50fd15e5 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -2144,7 +2144,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) if (hovering && !m_selected_item) tooltip_text = item.getDefinition(m_gamedef->idef()).description; if (tooltip_text != "") { - std::vector tt_rows = split(tooltip_text,'\n'); + std::vector tt_rows = str_split(tooltip_text, '\n'); m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor); m_tooltip_element->setOverrideColor(m_default_tooltip_color); m_tooltip_element->setVisible(true); @@ -2376,13 +2376,8 @@ void GUIFormSpecMenu::drawMenu() s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; if (tooltip_x + tooltip_width > (s32)screenSize.X) tooltip_x = (s32)screenSize.X - tooltip_width - m_btn_height; - int lines_count = 1; - size_t i = 0; - while ((i = m_tooltips[iter->fname].tooltip.find("\n", i)) != std::string::npos) { - lines_count++; - i += 2; - } - s32 tooltip_height = m_tooltip_element->getTextHeight() * lines_count + 5; + std::vector tt_rows = str_split(m_tooltips[iter->fname].tooltip, '\n'); + s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5; m_tooltip_element->setRelativePosition(core::rect( core::position2d(tooltip_x, tooltip_y), core::dimension2d(tooltip_width, tooltip_height))); diff --git a/src/util/string.h b/src/util/string.h index 98d23b161..54a5a458e 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -113,6 +113,16 @@ inline std::vector str_split(const std::wstring &str, wchar_t deli return parts; } +inline std::vector str_split(const std::string &str, char delimiter) { + + std::vector parts; + std::stringstream sstr(str); + std::string part; + while(std::getline(sstr, part, delimiter)) + parts.push_back(part); + return parts; +} + inline std::string lowercase(const std::string &s) { std::string s2; From db5aff832ba929c567564bfd9ee7bb6d7ef03a05 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 24 Jul 2014 11:51:07 +0200 Subject: [PATCH 05/18] Use round if falling node is misplaced Fixes: http://i.imgur.com/arAWw1i.png (middle-right) --- builtin/game/falling.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 8f3b41d5a..0e45a4375 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -43,7 +43,6 @@ core.register_entity(":__builtin:falling_node", { on_activate = function(self, staticdata) self.object:set_armor_groups({immortal=1}) - --self.object:setacceleration({x=0, y=-10, z=0}) self:set_node({name=staticdata}) end, @@ -102,8 +101,12 @@ core.register_entity(":__builtin:falling_node", { core.add_node(np, self.node) self.object:remove() nodeupdate(np) - else - -- Do nothing + return + end + local vel = self.object:getvelocity() + if vector.equals(vel, {x=0,y=0,z=0}) then + local npos = self.object:getpos() + self.object:setpos(vector.round(npos)) end end }) @@ -175,7 +178,7 @@ function nodeupdate_single(p, delay) if delay then core.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false) else - n.level = core.env:get_node_level(p) + n.level = core.get_node_level(p) core.remove_node(p) spawn_falling_node(p, n) nodeupdate(p) From 47abe25fe7d87ef3f15ec8d1e5a9ece51819a606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Mart=C3=ADnez?= Date: Tue, 30 Sep 2014 10:57:28 -0300 Subject: [PATCH 06/18] updatepo.sh: Find all files --- util/updatepo.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/util/updatepo.sh b/util/updatepo.sh index fc463f8bc..29d1f2fb1 100755 --- a/util/updatepo.sh +++ b/util/updatepo.sh @@ -48,7 +48,11 @@ cd .. # directory at the top level. You a recent enough xgettext that supports # --package-name potfile=po/minetest.pot -xgettext --package-name=minetest -kN_ -kwgettext -kfgettext -F -n -o $potfile src/*.cpp src/*.h builtin/*.lua +xgettext --package-name=minetest \ + -kN_ -kwgettext -kfgettext \ + -F -n -o $potfile \ + `find src/ -name '*.cpp' -o -name '*.h'` \ + `find builtin/ -name '*.lua'` # Now iterate on all languages and create the po file if missing, or update it # if it exists already From b37bff72f17c46b3bf6ba55a4084edf58bd3df78 Mon Sep 17 00:00:00 2001 From: sapier Date: Wed, 1 Oct 2014 22:18:29 +0200 Subject: [PATCH 07/18] Fix android build using hardcoded path for data instead of using the one fetched by android api on init. Fix android missing version information --- src/config.h | 5 +++++ src/porting.cpp | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config.h b/src/config.h index 510c5ef1e..f1aef03aa 100644 --- a/src/config.h +++ b/src/config.h @@ -74,5 +74,10 @@ #define VERSION_EXTRA_STRING CMAKE_VERSION_EXTRA_STRING #endif +#ifdef __ANDROID__ + #include "android_version.h" + #define VERSION_STRING CMAKE_VERSION_STRING +#endif + #endif diff --git a/src/porting.cpp b/src/porting.cpp index ad942b0bc..2fc5d0364 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -480,7 +480,7 @@ void initializePaths() bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME); trylist.push_back(bindir + DIR_DELIM + ".."); #ifdef __ANDROID__ - trylist.push_back(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME); + trylist.push_back(path_user); #endif for(std::list::const_iterator i = trylist.begin(); @@ -502,8 +502,6 @@ void initializePaths() } #ifndef __ANDROID__ path_user = std::string(getenv("HOME")) + DIR_DELIM + "." + PROJECT_NAME; -#else - path_user = std::string(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME DIR_DELIM); #endif /* From cd0df0d5e7051763c7ac6ca20a0f2960e0dda83a Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Sun, 3 Aug 2014 16:19:07 -0400 Subject: [PATCH 08/18] Simplify player modification checks --- src/client.cpp | 4 +--- src/environment.cpp | 4 ++-- src/localplayer.cpp | 4 ++-- src/localplayer.h | 4 ++-- src/player.cpp | 23 +++++++++++------------ src/player.h | 36 +++++++++++------------------------- src/server.cpp | 3 +-- 7 files changed, 30 insertions(+), 48 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 5a276e306..4a00283ee 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -270,9 +270,7 @@ Client::Client( Add local player */ { - Player *player = new LocalPlayer(this); - - player->updateName(playername); + Player *player = new LocalPlayer(this, playername); m_env.addPlayer(player); } diff --git a/src/environment.cpp b/src/environment.cpp index 66898f012..4106ecdf5 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -449,11 +449,11 @@ Player *ServerEnvironment::loadPlayer(const std::string &playername) bool newplayer = false; bool found = false; if (!player) { - player = new RemotePlayer(m_gamedef); + player = new RemotePlayer(m_gamedef, playername.c_str()); newplayer = true; } - RemotePlayer testplayer(m_gamedef); + RemotePlayer testplayer(m_gamedef, ""); std::string path = players_path + playername; for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) { // Open file and deserialize diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 1a238cb47..84b7c1146 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -33,8 +33,8 @@ with this program; if not, write to the Free Software Foundation, Inc., LocalPlayer */ -LocalPlayer::LocalPlayer(IGameDef *gamedef): - Player(gamedef), +LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name): + Player(gamedef, name), parent(0), isAttached(false), overridePosition(v3f(0,0,0)), diff --git a/src/localplayer.h b/src/localplayer.h index bfe476b70..16830f3ec 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -32,14 +32,14 @@ enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local class LocalPlayer : public Player { public: - LocalPlayer(IGameDef *gamedef); + LocalPlayer(IGameDef *gamedef, const char *name); virtual ~LocalPlayer(); bool isLocal() const { return true; } - + ClientActiveObject *parent; bool isAttached; diff --git a/src/player.cpp b/src/player.cpp index 8e5f56199..a8f95bb99 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -28,8 +28,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "filesys.h" #include "log.h" +#include "porting.h" // strlcpy -Player::Player(IGameDef *gamedef): + +Player::Player(IGameDef *gamedef, const char *name): touching_ground(false), in_liquid(false), in_liquid_stable(false), @@ -52,20 +54,16 @@ Player::Player(IGameDef *gamedef): m_speed(0,0,0), m_position(0,0,0), m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30), - m_last_pitch(0), - m_last_yaw(0), - m_last_pos(0,0,0), - m_last_hp(PLAYER_MAX_HP), - m_last_inventory(gamedef->idef()) + m_dirty(false) { - updateName(""); + strlcpy(m_name, name, PLAYERNAME_SIZE); + inventory.clear(); inventory.addList("main", PLAYER_INVENTORY_SIZE); InventoryList *craft = inventory.addList("craft", 9); craft->setWidth(3); inventory.addList("craftpreview", 1); inventory.addList("craftresult", 1); - m_last_inventory = inventory; // Can be redefined via Lua inventory_formspec = "size[8,7.5]" @@ -207,7 +205,7 @@ void Player::deSerialize(std::istream &is, std::string playername) //args.getS32("version"); // Version field value not used std::string name = args.get("name"); - updateName(name.c_str()); + strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); setPitch(args.getFloat("pitch")); setYaw(args.getFloat("yaw")); setPosition(args.getV3F("position")); @@ -238,8 +236,7 @@ void Player::deSerialize(std::istream &is, std::string playername) } } - // Set m_last_* - checkModified(); + m_dirty = false; } u32 Player::addHud(HudElement *toadd) @@ -290,7 +287,7 @@ void RemotePlayer::save(std::string savedir) */ // A player to deserialize files into to check their names - RemotePlayer testplayer(m_gamedef); + RemotePlayer testplayer(m_gamedef, ""); savedir += DIR_DELIM; std::string path = savedir + m_name; @@ -302,6 +299,7 @@ void RemotePlayer::save(std::string savedir) if (!fs::safeWriteToFile(path, ss.str())) { infostream << "Failed to write " << path << std::endl; } + m_dirty = false; return; } // Open file and deserialize @@ -319,6 +317,7 @@ void RemotePlayer::save(std::string savedir) if (!fs::safeWriteToFile(path, ss.str())) { infostream << "Failed to write " << path << std::endl; } + m_dirty = false; return; } path = savedir + m_name + itos(i); diff --git a/src/player.h b/src/player.h index 93197d374..174f14728 100644 --- a/src/player.h +++ b/src/player.h @@ -95,7 +95,7 @@ class Player { public: - Player(IGameDef *gamedef); + Player(IGameDef *gamedef, const char *name); virtual ~Player() = 0; virtual void move(f32 dtime, Environment *env, f32 pos_max_d) @@ -142,16 +142,19 @@ public: virtual void setPosition(const v3f &position) { + m_dirty = true; m_position = position; } void setPitch(f32 pitch) { + m_dirty = true; m_pitch = pitch; } virtual void setYaw(f32 yaw) { + m_dirty = true; m_yaw = yaw; } @@ -172,6 +175,7 @@ public: virtual void setBreath(u16 breath) { + m_dirty = true; m_breath = breath; } @@ -185,11 +189,6 @@ public: return (m_yaw + 90.) * core::DEGTORAD; } - void updateName(const char *name) - { - snprintf(m_name, PLAYERNAME_SIZE, "%s", name); - } - const char * getName() const { return m_name; @@ -225,19 +224,7 @@ public: bool checkModified() { - if(m_last_hp != hp || m_last_pitch != m_pitch || - m_last_pos != m_position || m_last_yaw != m_yaw || - !(inventory == m_last_inventory)) - { - m_last_hp = hp; - m_last_pitch = m_pitch; - m_last_pos = m_position; - m_last_yaw = m_yaw; - m_last_inventory = inventory; - return true; - } else { - return false; - } + return m_dirty; } bool touching_ground; @@ -316,11 +303,7 @@ protected: v3f m_position; core::aabbox3d m_collisionbox; - f32 m_last_pitch; - f32 m_last_yaw; - v3f m_last_pos; - u16 m_last_hp; - Inventory m_last_inventory; + bool m_dirty; std::vector hud; }; @@ -332,7 +315,10 @@ protected: class RemotePlayer : public Player { public: - RemotePlayer(IGameDef *gamedef): Player(gamedef), m_sao(0) {} + RemotePlayer(IGameDef *gamedef, const char *name): + Player(gamedef, name), + m_sao(NULL) + {} virtual ~RemotePlayer() {} void save(std::string savedir); diff --git a/src/server.cpp b/src/server.cpp index 262970c09..4f4763ea4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -5038,8 +5038,7 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id) // Create player if it doesn't exist if (!player) { newplayer = true; - player = new RemotePlayer(this); - player->updateName(name); + player = new RemotePlayer(this, name); /* Set player position */ infostream<<"Server: Finding spawn place for player \"" < Date: Thu, 28 Aug 2014 20:22:19 -0400 Subject: [PATCH 09/18] Only set player dirty flag if values change --- src/player.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/player.h b/src/player.h index 174f14728..aa38996a5 100644 --- a/src/player.h +++ b/src/player.h @@ -142,19 +142,22 @@ public: virtual void setPosition(const v3f &position) { - m_dirty = true; + if (position != m_position) + m_dirty = true; m_position = position; } void setPitch(f32 pitch) { - m_dirty = true; + if (pitch != m_pitch) + m_dirty = true; m_pitch = pitch; } virtual void setYaw(f32 yaw) { - m_dirty = true; + if (yaw != m_yaw) + m_dirty = true; m_yaw = yaw; } @@ -175,7 +178,8 @@ public: virtual void setBreath(u16 breath) { - m_dirty = true; + if (breath != m_breath) + m_dirty = true; m_breath = breath; } From e9c9b66ae92f4b95061d2b93e5db182d0c80b526 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Tue, 2 Sep 2014 12:53:20 -0400 Subject: [PATCH 10/18] Make players check inventory modification properly --- src/environment.cpp | 1 + src/inventory.cpp | 7 +++++++ src/inventory.h | 14 +++++++++++++- src/player.cpp | 8 ++++---- src/player.h | 11 +++++++++-- src/server.cpp | 7 +++++-- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/environment.cpp b/src/environment.cpp index 4106ecdf5..8977ee673 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -478,6 +478,7 @@ Player *ServerEnvironment::loadPlayer(const std::string &playername) if (newplayer) { addPlayer(player); } + player->setModified(false); return player; } diff --git a/src/inventory.cpp b/src/inventory.cpp index 4766524dd..cecef01a0 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -831,6 +831,7 @@ Inventory::~Inventory() void Inventory::clear() { + m_dirty = true; for(u32 i=0; iaddItem(newitem); } - + + bool checkModified() const + { + return m_dirty; + } + + void setModified(const bool x) + { + m_dirty = x; + } + private: // -1 if not found const s32 getListIndex(const std::string &name) const; std::vector m_lists; IItemDefManager *m_itemdef; + bool m_dirty; }; #endif diff --git a/src/player.cpp b/src/player.cpp index a8f95bb99..13866e5f5 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -64,6 +64,7 @@ Player::Player(IGameDef *gamedef, const char *name): craft->setWidth(3); inventory.addList("craftpreview", 1); inventory.addList("craftresult", 1); + inventory.setModified(false); // Can be redefined via Lua inventory_formspec = "size[8,7.5]" @@ -203,6 +204,7 @@ void Player::deSerialize(std::istream &is, std::string playername) playername + " not found!"); } + m_dirty = true; //args.getS32("version"); // Version field value not used std::string name = args.get("name"); strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); @@ -235,8 +237,6 @@ void Player::deSerialize(std::istream &is, std::string playername) inventory.getList("craftresult")->changeItem(0, ItemStack()); } } - - m_dirty = false; } u32 Player::addHud(HudElement *toadd) @@ -299,7 +299,7 @@ void RemotePlayer::save(std::string savedir) if (!fs::safeWriteToFile(path, ss.str())) { infostream << "Failed to write " << path << std::endl; } - m_dirty = false; + setModified(false); return; } // Open file and deserialize @@ -317,7 +317,7 @@ void RemotePlayer::save(std::string savedir) if (!fs::safeWriteToFile(path, ss.str())) { infostream << "Failed to write " << path << std::endl; } - m_dirty = false; + setModified(false); return; } path = savedir + m_name + itos(i); diff --git a/src/player.h b/src/player.h index aa38996a5..a5cc7123f 100644 --- a/src/player.h +++ b/src/player.h @@ -226,9 +226,16 @@ public: void serialize(std::ostream &os); void deSerialize(std::istream &is, std::string playername); - bool checkModified() + bool checkModified() const { - return m_dirty; + return m_dirty || inventory.checkModified(); + } + + void setModified(const bool x) + { + m_dirty = x; + if (x == false) + inventory.setModified(x); } bool touching_ground; diff --git a/src/server.cpp b/src/server.cpp index 4f4763ea4..6afe600ed 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -5039,13 +5039,16 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id) if (!player) { newplayer = true; player = new RemotePlayer(this, name); - /* Set player position */ + // Set player position infostream<<"Server: Finding spawn place for player \"" <getServerMap()); player->setPosition(pos); - /* Add player to environment */ + // Make sure the player is saved + player->setModified(true); + + // Add player to environment m_env->addPlayer(player); } From f48f6869303ab331600efaf9ec5796c238180106 Mon Sep 17 00:00:00 2001 From: BlockMen Date: Sat, 27 Sep 2014 18:16:26 +0200 Subject: [PATCH 11/18] Add optional framed glasslike drawtype --- builtin/mainmenu/tab_settings.lua | 20 ++++++++++---------- doc/lua_api.txt | 6 ++++-- minetest.conf.example | 2 ++ src/content_mapblock.cpp | 4 ++++ src/defaultsettings.cpp | 1 + src/nodedef.cpp | 10 ++++++++++ src/nodedef.h | 4 +++- src/script/cpp_api/s_node.cpp | 1 + src/shader.cpp | 3 ++- 9 files changed, 37 insertions(+), 14 deletions(-) diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index d97dd0051..630267478 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -132,18 +132,18 @@ local function formspec(tabview, name, tabdata) local tab_string = "vertlabel[0,-0.25;" .. fgettext("SETTINGS") .. "]" .. "box[0.75,0;3.25,4;#999999]" .. - "checkbox[1,0;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";" - .. dump(core.setting_getbool("new_style_leaves")) .. "]".. - "checkbox[1,0.5;cb_smooth_lighting;".. fgettext("Smooth Lighting") + "checkbox[1,0;cb_smooth_lighting;".. fgettext("Smooth Lighting") .. ";".. dump(core.setting_getbool("smooth_lighting")) .. "]".. + "checkbox[1,0.5;cb_particles;".. fgettext("Enable Particles") .. ";" + .. dump(core.setting_getbool("enable_particles")) .. "]".. "checkbox[1,1;cb_3d_clouds;".. fgettext("3D Clouds") .. ";" .. dump(core.setting_getbool("enable_3d_clouds")) .. "]".. - "checkbox[1,1.5;cb_opaque_water;".. fgettext("Opaque Water") .. ";" + "checkbox[1,1.5;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";" + .. dump(core.setting_getbool("new_style_leaves")) .. "]".. + "checkbox[1,2.0;cb_opaque_water;".. fgettext("Opaque Water") .. ";" .. dump(core.setting_getbool("opaque_water")) .. "]".. - "checkbox[1,2.0;cb_pre_ivis;".. fgettext("Preload item visuals") .. ";" - .. dump(core.setting_getbool("preload_item_visuals")) .. "]".. - "checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";" - .. dump(core.setting_getbool("enable_particles")) .. "]".. + "checkbox[1,2.5;cb_connected_glass;".. fgettext("Connected Glass") .. ";" + .. dump(core.setting_getbool("connected_glass")) .. "]".. "dropdown[1,3.25;3;dd_video_driver;" .. video_driver_string .. ";" .. current_video_driver_idx .. "]" .. "tooltip[dd_video_driver;" .. @@ -259,8 +259,8 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) end return true end - if fields["cb_pre_ivis"] then - core.setting_set("preload_item_visuals", fields["cb_pre_ivis"]) + if fields["cb_connected_glass"] then + core.setting_set("connected_glass", fields["cb_connected_glass"]) return true end if fields["cb_particles"] then diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 0cdca506f..4c3a9d074 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -406,8 +406,7 @@ Nodes can also contain extra data. See "Node Metadata". Node drawtypes --------------- -There are a bunch of different looking node types. These are mostly just -copied from Minetest 0.3; more may be made in the future. +There are a bunch of different looking node types. Look for examples in games/minimal or games/minetest_game. @@ -417,6 +416,7 @@ Look for examples in games/minimal or games/minetest_game. - flowingliquid - glasslike - glasslike_framed +- glasslike_framed_optional - allfaces - allfaces_optional - torchlike @@ -427,6 +427,8 @@ Look for examples in games/minimal or games/minetest_game. - raillike - nodebox -- See below. EXPERIMENTAL +*_optional drawtypes need less rendering time if deactivated (always client side) + Node boxes ----------- Node selection boxes are defined using "node boxes" diff --git a/minetest.conf.example b/minetest.conf.example index 689596fc0..3e7689c76 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -101,6 +101,8 @@ #liquid_update = 1.0 # Enable nice leaves; disable for speed #new_style_leaves = true +# Connects glass if supported by node +#connected_glass = false # Enable smooth lighting with simple ambient occlusion; # disable for speed or for different looks. #smooth_lighting = true diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 6d7a69bb8..c84e75ac0 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -794,6 +794,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data, collector.append(tile, vertices, 4, indices, 6); } break;} + case NDT_GLASSLIKE_FRAMED_OPTIONAL: + // This is always pre-converted to something else + assert(0); + break; case NDT_GLASSLIKE_FRAMED: { static const v3s16 dirs[6] = { diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index ccde6b577..dc4a59be3 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -100,6 +100,7 @@ void set_default_settings(Settings *settings) settings->setDefault("view_bobbing", "true"); settings->setDefault("new_style_water", "false"); settings->setDefault("new_style_leaves", "true"); + settings->setDefault("connected_glass", "false"); settings->setDefault("smooth_lighting", "true"); settings->setDefault("texture_path", ""); settings->setDefault("shader_path", ""); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 31156ce68..8a5cff3bf 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -607,6 +607,7 @@ public: bool new_style_water = g_settings->getBool("new_style_water"); bool new_style_leaves = g_settings->getBool("new_style_leaves"); + bool connected_glass = g_settings->getBool("connected_glass"); bool opaque_water = g_settings->getBool("opaque_water"); bool enable_shaders = g_settings->getBool("enable_shaders"); bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); @@ -666,6 +667,15 @@ public: f->solidness = 0; f->visual_solidness = 1; break; + case NDT_GLASSLIKE_FRAMED_OPTIONAL: + f->solidness = 0; + f->visual_solidness = 1; + if (connected_glass) { + f->drawtype = NDT_GLASSLIKE_FRAMED; + } else { + f->drawtype = NDT_GLASSLIKE; + } + break; case NDT_ALLFACES: f->solidness = 0; f->visual_solidness = 1; diff --git a/src/nodedef.h b/src/nodedef.h index 262f4bc4e..b737e0237 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -149,7 +149,9 @@ enum NodeDrawType NDT_GLASSLIKE_FRAMED, // Glass-like, draw connected frames and all all // visible faces // uses 2 textures, one for frames, second for faces - NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes + NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes, + NDT_GLASSLIKE_FRAMED_OPTIONAL, // enabled -> connected, disabled -> Glass-like + // uses 2 textures, one for frames, second for faces }; #define CF_SPECIAL_COUNT 6 diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index 2b8d02d74..8c9b46c2a 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -35,6 +35,7 @@ struct EnumString ScriptApiNode::es_DrawType[] = {NDT_FLOWINGLIQUID, "flowingliquid"}, {NDT_GLASSLIKE, "glasslike"}, {NDT_GLASSLIKE_FRAMED, "glasslike_framed"}, + {NDT_GLASSLIKE_FRAMED_OPTIONAL, "glasslike_framed_optional"}, {NDT_ALLFACES, "allfaces"}, {NDT_ALLFACES_OPTIONAL, "allfaces_optional"}, {NDT_TORCHLIKE, "torchlike"}, diff --git a/src/shader.cpp b/src/shader.cpp index cf3bbd761..167045804 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -645,7 +645,8 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype, "NDT_RAILLIKE", "NDT_NODEBOX", "NDT_GLASSLIKE_FRAMED", - "NDT_FIRELIKE" + "NDT_FIRELIKE", + "NDT_GLASSLIKE_FRAMED_OPTIONAL" }; for (int i = 0; i < 14; i++){ From 5baf379f40537060a1d5111905c7702d4563ee5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Mart=C3=ADnez?= Date: Thu, 2 Oct 2014 13:30:32 -0300 Subject: [PATCH 12/18] Add better documentation for alternate drop definition to lua_api.txt. --- doc/lua_api.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4c3a9d074..4db0dc40f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2423,7 +2423,6 @@ Node definition (register_node) diggable = true, -- If false, can never be dug climbable = false, -- If true, can be climbed on (ladder) buildable_to = false, -- If true, placed nodes can replace this node - drop = "", -- alternatively drop = { max_items = ..., items = { ... } } liquidtype = "none", -- "none"/"source"/"flowing" liquid_alternative_flowing = "", -- Flowing version of source liquid liquid_alternative_source = "", -- Source version of flowing liquid @@ -2446,6 +2445,17 @@ Node definition (register_node) dug = , place = , }, + drop = "", -- Name of dropped node when dug. Default is the node itself. + -- Alternatively: + drop = { + max_items = 1, -- Maximum number of items to drop. + items = { -- Choose max_items randomly from this list. + { + items = {"foo:bar", "baz:frob"}, -- Choose one item randomly from this list. + rarity = 1, -- Probability of getting is 1 / rarity. + }, + }, + }, on_construct = func(pos), ^ Node constructor; always called after adding node From 01ce57ade534f83d80bbb1f0c48630891b338237 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Fri, 3 Oct 2014 03:16:43 -0400 Subject: [PATCH 13/18] Clean up nodedef.cpp --- src/nodedef.cpp | 1144 ++++++++++++++++++++++++----------------------- 1 file changed, 583 insertions(+), 561 deletions(-) diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 8a5cff3bf..92e4b59b3 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -370,592 +370,612 @@ void ContentFeatures::deSerialize(std::istream &is) CNodeDefManager */ -class CNodeDefManager: public IWritableNodeDefManager -{ +class CNodeDefManager: public IWritableNodeDefManager { public: - void clear() - { - m_content_features.clear(); - m_name_id_mapping.clear(); - m_name_id_mapping_with_aliases.clear(); - m_group_to_items.clear(); - m_next_id = 0; + CNodeDefManager(); + virtual ~CNodeDefManager(); + void clear(); + virtual IWritableNodeDefManager *clone(); + virtual const ContentFeatures& get(content_t c) const; + virtual const ContentFeatures& get(const MapNode &n) const; + virtual bool getId(const std::string &name, content_t &result) const; + virtual content_t getId(const std::string &name) const; + virtual void getIds(const std::string &name, std::set &result) const; + virtual const ContentFeatures& get(const std::string &name) const; + content_t allocateId(); + virtual content_t set(const std::string &name, const ContentFeatures &def); + virtual content_t allocateDummy(const std::string &name); + virtual void updateAliases(IItemDefManager *idef); + virtual void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc); + void serialize(std::ostream &os, u16 protocol_version); + void deSerialize(std::istream &is); - u32 initial_length = 0; - initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1); - initial_length = MYMAX(initial_length, CONTENT_AIR + 1); - initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1); - m_content_features.resize(initial_length); - - // Set CONTENT_UNKNOWN - { - ContentFeatures f; - f.name = "unknown"; - // Insert directly into containers - content_t c = CONTENT_UNKNOWN; - m_content_features[c] = f; - addNameIdMapping(c, f.name); - } - - // Set CONTENT_AIR - { - ContentFeatures f; - f.name = "air"; - f.drawtype = NDT_AIRLIKE; - f.param_type = CPT_LIGHT; - f.light_propagates = true; - f.sunlight_propagates = true; - f.walkable = false; - f.pointable = false; - f.diggable = false; - f.buildable_to = true; - f.is_ground_content = true; - // Insert directly into containers - content_t c = CONTENT_AIR; - m_content_features[c] = f; - addNameIdMapping(c, f.name); - } - - // Set CONTENT_IGNORE - { - ContentFeatures f; - f.name = "ignore"; - f.drawtype = NDT_AIRLIKE; - f.param_type = CPT_NONE; - f.light_propagates = false; - f.sunlight_propagates = false; - f.walkable = false; - f.pointable = false; - f.diggable = false; - f.buildable_to = true; // A way to remove accidental CONTENT_IGNOREs - f.is_ground_content = true; - // Insert directly into containers - content_t c = CONTENT_IGNORE; - m_content_features[c] = f; - addNameIdMapping(c, f.name); - } - } - CNodeDefManager() - { - clear(); - } - virtual ~CNodeDefManager() - { - } - virtual IWritableNodeDefManager* clone() - { - CNodeDefManager *mgr = new CNodeDefManager(); - *mgr = *this; - return mgr; - } - virtual const ContentFeatures& get(content_t c) const - { - if(c < m_content_features.size()) - return m_content_features[c]; - else - return m_content_features[CONTENT_UNKNOWN]; - } - virtual const ContentFeatures& get(const MapNode &n) const - { - return get(n.getContent()); - } - virtual bool getId(const std::string &name, content_t &result) const - { - std::map::const_iterator - i = m_name_id_mapping_with_aliases.find(name); - if(i == m_name_id_mapping_with_aliases.end()) - return false; - result = i->second; - return true; - } - virtual content_t getId(const std::string &name) const - { - content_t id = CONTENT_IGNORE; - getId(name, id); - return id; - } - virtual void getIds(const std::string &name, std::set &result) - const - { - //TimeTaker t("getIds", NULL, PRECISION_MICRO); - if(name.substr(0,6) != "group:"){ - content_t id = CONTENT_IGNORE; - if(getId(name, id)) - result.insert(id); - return; - } - std::string group = name.substr(6); - - std::map::const_iterator - i = m_group_to_items.find(group); - if (i == m_group_to_items.end()) - return; - - const GroupItems &items = i->second; - for (GroupItems::const_iterator j = items.begin(); - j != items.end(); ++j) { - if ((*j).second != 0) - result.insert((*j).first); - } - //printf("getIds: %dus\n", t.stop()); - } - virtual const ContentFeatures& get(const std::string &name) const - { - content_t id = CONTENT_UNKNOWN; - getId(name, id); - return get(id); - } - // returns CONTENT_IGNORE if no free ID found - content_t allocateId() - { - for(content_t id = m_next_id; - id >= m_next_id; // overflow? - ++id){ - while(id >= m_content_features.size()){ - m_content_features.push_back(ContentFeatures()); - } - const ContentFeatures &f = m_content_features[id]; - if(f.name == ""){ - m_next_id = id + 1; - return id; - } - } - // If we arrive here, an overflow occurred in id. - // That means no ID was found - return CONTENT_IGNORE; - } - // IWritableNodeDefManager - virtual content_t set(const std::string &name, - const ContentFeatures &def) - { - assert(name != ""); - assert(name == def.name); - - // Don't allow redefining ignore (but allow air and unknown) - if(name == "ignore"){ - infostream<<"NodeDefManager: WARNING: Ignoring " - <<"CONTENT_IGNORE redefinition"<first; - - std::map::iterator - j = m_group_to_items.find(group_name); - if (j == m_group_to_items.end()) { - m_group_to_items[group_name].push_back( - std::make_pair(id, i->second)); - } else { - GroupItems &items = j->second; - items.push_back(std::make_pair(id, i->second)); - } - } - return id; - } - virtual content_t allocateDummy(const std::string &name) - { - assert(name != ""); - ContentFeatures f; - f.name = name; - return set(name, f); - } - virtual void updateAliases(IItemDefManager *idef) - { - std::set all = idef->getAll(); - m_name_id_mapping_with_aliases.clear(); - for(std::set::iterator - i = all.begin(); i != all.end(); i++) - { - std::string name = *i; - std::string convert_to = idef->getAlias(name); - content_t id; - if(m_name_id_mapping.getId(convert_to, id)) - { - m_name_id_mapping_with_aliases.insert( - std::make_pair(name, id)); - } - } - } - virtual void updateTextures(ITextureSource *tsrc, - IShaderSource *shdsrc) - { +private: + void addNameIdMapping(content_t i, std::string name); #ifndef SERVER - infostream<<"CNodeDefManager::updateTextures(): Updating " - <<"textures in node definitions"<getBool("new_style_water"); - bool new_style_leaves = g_settings->getBool("new_style_leaves"); - bool connected_glass = g_settings->getBool("connected_glass"); - bool opaque_water = g_settings->getBool("opaque_water"); - bool enable_shaders = g_settings->getBool("enable_shaders"); - bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); - bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); - - for(u32 i=0; itiledef[j]; - if(tiledef[j].name == "") - tiledef[j].name = "unknown_node.png"; - } - - bool is_liquid = false; - bool is_water_surface = false; - - u8 material_type; - material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA; - - switch(f->drawtype){ - default: - case NDT_NORMAL: - f->solidness = 2; - break; - case NDT_AIRLIKE: - f->solidness = 0; - break; - case NDT_LIQUID: - assert(f->liquid_type == LIQUID_SOURCE); - if(opaque_water) - f->alpha = 255; - if(new_style_water){ - f->solidness = 0; - } else { - f->solidness = 1; - f->backface_culling = false; - } - is_liquid = true; - break; - case NDT_FLOWINGLIQUID: - assert(f->liquid_type == LIQUID_FLOWING); - f->solidness = 0; - if(opaque_water) - f->alpha = 255; - is_liquid = true; - break; - case NDT_GLASSLIKE: - f->solidness = 0; - f->visual_solidness = 1; - break; - case NDT_GLASSLIKE_FRAMED: - f->solidness = 0; - f->visual_solidness = 1; - break; - case NDT_GLASSLIKE_FRAMED_OPTIONAL: - f->solidness = 0; - f->visual_solidness = 1; - if (connected_glass) { - f->drawtype = NDT_GLASSLIKE_FRAMED; - } else { - f->drawtype = NDT_GLASSLIKE; - } - break; - case NDT_ALLFACES: - f->solidness = 0; - f->visual_solidness = 1; - break; - case NDT_ALLFACES_OPTIONAL: - if(new_style_leaves){ - f->drawtype = NDT_ALLFACES; - f->solidness = 0; - f->visual_solidness = 1; - } else { - f->drawtype = NDT_NORMAL; - f->solidness = 2; - for(u32 i=0; i<6; i++){ - tiledef[i].name += std::string("^[noalpha"); - } - } - if (f->waving == 1) - material_type = TILE_MATERIAL_WAVING_LEAVES; - break; - case NDT_PLANTLIKE: - f->solidness = 0; - f->backface_culling = false; - if (f->waving == 1) - material_type = TILE_MATERIAL_WAVING_PLANTS; - break; - case NDT_FIRELIKE: - f->backface_culling = false; - case NDT_TORCHLIKE: - case NDT_SIGNLIKE: - case NDT_FENCELIKE: - case NDT_RAILLIKE: - case NDT_NODEBOX: - f->solidness = 0; - break; - } - - if (is_liquid){ - material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT; - if (f->name == "default:water_source") - is_water_surface = true; - } - u32 tile_shader[6]; - for(u16 j=0; j<6; j++) - tile_shader[j] = shdsrc->getShader("nodes_shader",material_type, f->drawtype); - - if (is_water_surface) - tile_shader[0] = shdsrc->getShader("water_surface_shader",material_type, f->drawtype); - - // Tiles (fill in f->tiles[]) - for(u16 j = 0; j < 6; j++){ - // Shader - f->tiles[j].shader_id = tile_shader[j]; - // Texture - f->tiles[j].texture = tsrc->getTexture( - tiledef[j].name, - &f->tiles[j].texture_id); - // Normal texture - if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion)) - f->tiles[j].normal_texture = tsrc->getNormalTexture(tiledef[j].name); - // Alpha - f->tiles[j].alpha = f->alpha; - // Material type - f->tiles[j].material_type = material_type; - // Material flags - f->tiles[j].material_flags = 0; - if(f->backface_culling) - f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; - if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES) - f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; - // Animation parameters - int frame_count = 1; - if(f->tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { - // Get texture size to determine frame count by - // aspect ratio - v2u32 size = f->tiles[j].texture->getOriginalSize(); - int frame_height = (float)size.X / - (float)tiledef[j].animation.aspect_w * - (float)tiledef[j].animation.aspect_h; - frame_count = size.Y / frame_height; - int frame_length_ms = 1000.0 * - tiledef[j].animation.length / frame_count; - f->tiles[j].animation_frame_count = frame_count; - f->tiles[j].animation_frame_length_ms = frame_length_ms; - } - if(frame_count == 1) { - f->tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; - } else { - std::ostringstream os(std::ios::binary); - for (int i = 0; i < frame_count; i++) { - FrameSpec frame; - os.str(""); - os<getTexture(os.str(), &frame.texture_id); - if (f->tiles[j].normal_texture) - frame.normal_texture = tsrc->getNormalTexture(os.str()); - f->tiles[j].frames[i]=frame; - } - } - } - // Special tiles (fill in f->special_tiles[]) - for(u16 j=0; jspecial_tiles[j].shader_id = tile_shader[j]; - // Texture - f->special_tiles[j].texture = tsrc->getTexture( - f->tiledef_special[j].name, - &f->special_tiles[j].texture_id); - // Normal texture - if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion)) - f->special_tiles[j].normal_texture = tsrc->getNormalTexture(f->tiledef_special[j].name); - // Alpha - f->special_tiles[j].alpha = f->alpha; - // Material type - f->special_tiles[j].material_type = material_type; - // Material flags - f->special_tiles[j].material_flags = 0; - if(f->tiledef_special[j].backface_culling) - f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; - if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES) - f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; - // Animation parameters - int frame_count = 1; - if(f->special_tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { - // Get texture size to determine frame count by - // aspect ratio - v2u32 size = f->special_tiles[j].texture->getOriginalSize(); - int frame_height = (float)size.X / - (float)f->tiledef_special[j].animation.aspect_w * - (float)f->tiledef_special[j].animation.aspect_h; - frame_count = size.Y / frame_height; - int frame_length_ms = 1000.0 * - f->tiledef_special[j].animation.length / frame_count; - f->special_tiles[j].animation_frame_count = frame_count; - f->special_tiles[j].animation_frame_length_ms = frame_length_ms; - } - if(frame_count == 1) { - f->special_tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; - } else { - std::ostringstream os(std::ios::binary); - for (int i = 0; i < frame_count; i++) { - FrameSpec frame; - os.str(""); - os<tiledef_special[j].name<<"^[verticalframe:"<getTexture(os.str(), &frame.texture_id); - if (f->special_tiles[j].normal_texture) - frame.normal_texture = tsrc->getNormalTexture(os.str()); - f->special_tiles[j].frames[i]=frame; - } - } - } - } + void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef, + u32 shader_id, bool use_normal_texture, u8 alpha, u8 material_type); #endif - } - void serialize(std::ostream &os, u16 protocol_version) - { - writeU8(os, 1); // version - u16 count = 0; - std::ostringstream os2(std::ios::binary); - for(u32 i = 0; i < m_content_features.size(); i++) - { - if(i == CONTENT_IGNORE || i == CONTENT_AIR - || i == CONTENT_UNKNOWN) - continue; - ContentFeatures *f = &m_content_features[i]; - if(f->name == "") - continue; - writeU16(os2, i); - // Wrap it in a string to allow different lengths without - // strict version incompatibilities - std::ostringstream wrapper_os(std::ios::binary); - f->serialize(wrapper_os, protocol_version); - os2< count); // must not overflow - count++; - } - writeU16(os, count); - os<= m_content_features.size()) - m_content_features.resize((u32)(i) + 1); - m_content_features[i] = f; - addNameIdMapping(i, f.name); - verbosestream<<"deserialized "< m_content_features; + // A mapping for fast converting back and forth between names and ids NameIdMapping m_name_id_mapping; + // Like m_name_id_mapping, but only from names to ids, and includes // item aliases too. Updated by updateAliases() // Note: Not serialized. + std::map m_name_id_mapping_with_aliases; + // A mapping from groups to a list of content_ts (and their levels) // that belong to it. Necessary for a direct lookup in getIds(). // Note: Not serialized. std::map m_group_to_items; + // Next possibly free id content_t m_next_id; }; -IWritableNodeDefManager* createNodeDefManager() + +CNodeDefManager::CNodeDefManager() +{ + clear(); +} + + +CNodeDefManager::~CNodeDefManager() +{ +} + + +void CNodeDefManager::clear() +{ + m_content_features.clear(); + m_name_id_mapping.clear(); + m_name_id_mapping_with_aliases.clear(); + m_group_to_items.clear(); + m_next_id = 0; + + u32 initial_length = 0; + initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1); + initial_length = MYMAX(initial_length, CONTENT_AIR + 1); + initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1); + m_content_features.resize(initial_length); + + // Set CONTENT_UNKNOWN + { + ContentFeatures f; + f.name = "unknown"; + // Insert directly into containers + content_t c = CONTENT_UNKNOWN; + m_content_features[c] = f; + addNameIdMapping(c, f.name); + } + + // Set CONTENT_AIR + { + ContentFeatures f; + f.name = "air"; + f.drawtype = NDT_AIRLIKE; + f.param_type = CPT_LIGHT; + f.light_propagates = true; + f.sunlight_propagates = true; + f.walkable = false; + f.pointable = false; + f.diggable = false; + f.buildable_to = true; + f.is_ground_content = true; + // Insert directly into containers + content_t c = CONTENT_AIR; + m_content_features[c] = f; + addNameIdMapping(c, f.name); + } + + // Set CONTENT_IGNORE + { + ContentFeatures f; + f.name = "ignore"; + f.drawtype = NDT_AIRLIKE; + f.param_type = CPT_NONE; + f.light_propagates = false; + f.sunlight_propagates = false; + f.walkable = false; + f.pointable = false; + f.diggable = false; + f.buildable_to = true; // A way to remove accidental CONTENT_IGNOREs + f.is_ground_content = true; + // Insert directly into containers + content_t c = CONTENT_IGNORE; + m_content_features[c] = f; + addNameIdMapping(c, f.name); + } +} + + +IWritableNodeDefManager *CNodeDefManager::clone() +{ + CNodeDefManager *mgr = new CNodeDefManager(); + *mgr = *this; + return mgr; +} + + +const ContentFeatures& CNodeDefManager::get(content_t c) const +{ + if (c < m_content_features.size()) + return m_content_features[c]; + else + return m_content_features[CONTENT_UNKNOWN]; +} + + +const ContentFeatures& CNodeDefManager::get(const MapNode &n) const +{ + return get(n.getContent()); +} + + +bool CNodeDefManager::getId(const std::string &name, content_t &result) const +{ + std::map::const_iterator + i = m_name_id_mapping_with_aliases.find(name); + if(i == m_name_id_mapping_with_aliases.end()) + return false; + result = i->second; + return true; +} + + +content_t CNodeDefManager::getId(const std::string &name) const +{ + content_t id = CONTENT_IGNORE; + getId(name, id); + return id; +} + + +void CNodeDefManager::getIds(const std::string &name, std::set &result) + const +{ + //TimeTaker t("getIds", NULL, PRECISION_MICRO); + if (name.substr(0,6) != "group:") { + content_t id = CONTENT_IGNORE; + if(getId(name, id)) + result.insert(id); + return; + } + std::string group = name.substr(6); + + std::map::const_iterator + i = m_group_to_items.find(group); + if (i == m_group_to_items.end()) + return; + + const GroupItems &items = i->second; + for (GroupItems::const_iterator j = items.begin(); + j != items.end(); ++j) { + if ((*j).second != 0) + result.insert((*j).first); + } + //printf("getIds: %dus\n", t.stop()); +} + + +const ContentFeatures& CNodeDefManager::get(const std::string &name) const +{ + content_t id = CONTENT_UNKNOWN; + getId(name, id); + return get(id); +} + + +// returns CONTENT_IGNORE if no free ID found +content_t CNodeDefManager::allocateId() +{ + for (content_t id = m_next_id; + id >= m_next_id; // overflow? + ++id) { + while (id >= m_content_features.size()) { + m_content_features.push_back(ContentFeatures()); + } + const ContentFeatures &f = m_content_features[id]; + if (f.name == "") { + m_next_id = id + 1; + return id; + } + } + // If we arrive here, an overflow occurred in id. + // That means no ID was found + return CONTENT_IGNORE; +} + + +// IWritableNodeDefManager +content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &def) +{ + assert(name != ""); + assert(name == def.name); + + // Don't allow redefining ignore (but allow air and unknown) + if (name == "ignore") { + infostream << "NodeDefManager: WARNING: Ignoring " + "CONTENT_IGNORE redefinition"<first; + + std::map::iterator + j = m_group_to_items.find(group_name); + if (j == m_group_to_items.end()) { + m_group_to_items[group_name].push_back( + std::make_pair(id, i->second)); + } else { + GroupItems &items = j->second; + items.push_back(std::make_pair(id, i->second)); + } + } + return id; +} + + +content_t CNodeDefManager::allocateDummy(const std::string &name) +{ + assert(name != ""); + ContentFeatures f; + f.name = name; + return set(name, f); +} + + +void CNodeDefManager::updateAliases(IItemDefManager *idef) +{ + std::set all = idef->getAll(); + m_name_id_mapping_with_aliases.clear(); + for (std::set::iterator + i = all.begin(); i != all.end(); i++) { + std::string name = *i; + std::string convert_to = idef->getAlias(name); + content_t id; + if (m_name_id_mapping.getId(convert_to, id)) { + m_name_id_mapping_with_aliases.insert( + std::make_pair(name, id)); + } + } +} + + +void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc) +{ +#ifndef SERVER + infostream << "CNodeDefManager::updateTextures(): Updating " + "textures in node definitions" << std::endl; + + bool new_style_water = g_settings->getBool("new_style_water"); + bool new_style_leaves = g_settings->getBool("new_style_leaves"); + bool connected_glass = g_settings->getBool("connected_glass"); + bool opaque_water = g_settings->getBool("opaque_water"); + bool enable_shaders = g_settings->getBool("enable_shaders"); + bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); + bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); + + bool use_normal_texture = enable_shaders && + (enable_bumpmapping || enable_parallax_occlusion); + + for (u32 i = 0; i < m_content_features.size(); i++) { + ContentFeatures *f = &m_content_features[i]; + + // Figure out the actual tiles to use + TileDef tiledef[6]; + for (u32 j = 0; j < 6; j++) { + tiledef[j] = f->tiledef[j]; + if (tiledef[j].name == "") + tiledef[j].name = "unknown_node.png"; + } + + bool is_liquid = false; + bool is_water_surface = false; + + u8 material_type = (f->alpha == 255) ? + TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA; + + switch (f->drawtype) { + default: + case NDT_NORMAL: + f->solidness = 2; + break; + case NDT_AIRLIKE: + f->solidness = 0; + break; + case NDT_LIQUID: + assert(f->liquid_type == LIQUID_SOURCE); + if (opaque_water) + f->alpha = 255; + if (new_style_water){ + f->solidness = 0; + } else { + f->solidness = 1; + f->backface_culling = false; + } + is_liquid = true; + break; + case NDT_FLOWINGLIQUID: + assert(f->liquid_type == LIQUID_FLOWING); + f->solidness = 0; + if (opaque_water) + f->alpha = 255; + is_liquid = true; + break; + case NDT_GLASSLIKE: + f->solidness = 0; + f->visual_solidness = 1; + break; + case NDT_GLASSLIKE_FRAMED: + f->solidness = 0; + f->visual_solidness = 1; + break; + case NDT_GLASSLIKE_FRAMED_OPTIONAL: + f->solidness = 0; + f->visual_solidness = 1; + f->drawtype = connected_glass ? NDT_GLASSLIKE_FRAMED : NDT_GLASSLIKE; + break; + case NDT_ALLFACES: + f->solidness = 0; + f->visual_solidness = 1; + break; + case NDT_ALLFACES_OPTIONAL: + if (new_style_leaves) { + f->drawtype = NDT_ALLFACES; + f->solidness = 0; + f->visual_solidness = 1; + } else { + f->drawtype = NDT_NORMAL; + f->solidness = 2; + for (u32 i = 0; i < 6; i++) + tiledef[i].name += std::string("^[noalpha"); + } + if (f->waving == 1) + material_type = TILE_MATERIAL_WAVING_LEAVES; + break; + case NDT_PLANTLIKE: + f->solidness = 0; + f->backface_culling = false; + if (f->waving == 1) + material_type = TILE_MATERIAL_WAVING_PLANTS; + break; + case NDT_FIRELIKE: + f->backface_culling = false; + case NDT_TORCHLIKE: + case NDT_SIGNLIKE: + case NDT_FENCELIKE: + case NDT_RAILLIKE: + case NDT_NODEBOX: + f->solidness = 0; + break; + } + + if (is_liquid) { + material_type = (f->alpha == 255) ? + TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT; + if (f->name == "default:water_source") + is_water_surface = true; + } + + u32 tile_shader[6]; + for (u16 j = 0; j < 6; j++) { + tile_shader[j] = shdsrc->getShader("nodes_shader", + material_type, f->drawtype); + } + + if (is_water_surface) { + tile_shader[0] = shdsrc->getShader("water_surface_shader", + material_type, f->drawtype); + } + + // Tiles (fill in f->tiles[]) + for (u16 j = 0; j < 6; j++) { + fillTileAttribs(tsrc, &f->tiles[j], &tiledef[j], tile_shader[j], + use_normal_texture, f->alpha, material_type); + } + + // Special tiles (fill in f->special_tiles[]) + for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) { + fillTileAttribs(tsrc, &f->special_tiles[j], &f->tiledef_special[j], + tile_shader[j], use_normal_texture, f->alpha, material_type); + } + } +#endif +} + + +#ifndef SERVER +void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, + TileDef *tiledef, u32 shader_id, bool use_normal_texture, + u8 alpha, u8 material_type) +{ + tile->shader_id = shader_id; + tile->texture = tsrc->getTexture(tiledef->name, &tile->texture_id); + tile->alpha = alpha; + tile->material_type = material_type; + + // Normal texture + if (use_normal_texture) + tile->normal_texture = tsrc->getNormalTexture(tiledef->name); + + // Material flags + tile->material_flags = 0; + if (tiledef->backface_culling) + tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; + if (tiledef->animation.type == TAT_VERTICAL_FRAMES) + tile->material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + + // Animation parameters + int frame_count = 1; + if (tile->material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { + // Get texture size to determine frame count by aspect ratio + v2u32 size = tile->texture->getOriginalSize(); + int frame_height = (float)size.X / + (float)tiledef->animation.aspect_w * + (float)tiledef->animation.aspect_h; + frame_count = size.Y / frame_height; + int frame_length_ms = 1000.0 * tiledef->animation.length / frame_count; + tile->animation_frame_count = frame_count; + tile->animation_frame_length_ms = frame_length_ms; + } + + if (frame_count == 1) { + tile->material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } else { + std::ostringstream os(std::ios::binary); + for (int i = 0; i < frame_count; i++) { + FrameSpec frame; + + os.str(""); + os << tiledef->name << "^[verticalframe:" + << frame_count << ":" << i; + + frame.texture = tsrc->getTexture(os.str(), &frame.texture_id); + if (tile->normal_texture) + frame.normal_texture = tsrc->getNormalTexture(os.str()); + tile->frames[i] = frame; + } + } +} +#endif + + +void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version) +{ + writeU8(os, 1); // version + u16 count = 0; + std::ostringstream os2(std::ios::binary); + for (u32 i = 0; i < m_content_features.size(); i++) { + if (i == CONTENT_IGNORE || i == CONTENT_AIR + || i == CONTENT_UNKNOWN) + continue; + ContentFeatures *f = &m_content_features[i]; + if (f->name == "") + continue; + writeU16(os2, i); + // Wrap it in a string to allow different lengths without + // strict version incompatibilities + std::ostringstream wrapper_os(std::ios::binary); + f->serialize(wrapper_os, protocol_version); + os2< count); // must not overflow + count++; + } + writeU16(os, count); + os << serializeLongString(os2.str()); +} + + +void CNodeDefManager::deSerialize(std::istream &is) +{ + clear(); + int version = readU8(is); + if (version != 1) + throw SerializationError("unsupported NodeDefinitionManager version"); + u16 count = readU16(is); + std::istringstream is2(deSerializeLongString(is), std::ios::binary); + ContentFeatures f; + for (u16 n = 0; n < count; n++) { + u16 i = readU16(is2); + + // Read it from the string wrapper + std::string wrapper = deSerializeString(is2); + std::istringstream wrapper_is(wrapper, std::ios::binary); + f.deSerialize(wrapper_is); + + // Check error conditions + if (i == CONTENT_IGNORE || i == CONTENT_AIR || i == CONTENT_UNKNOWN) { + infostream << "NodeDefManager::deSerialize(): WARNING: " + "not changing builtin node " << i << std::endl; + continue; + } + if (f.name == "") { + infostream << "NodeDefManager::deSerialize(): WARNING: " + "received empty name" << std::endl; + continue; + } + + // Ignore aliases + u16 existing_id; + if (m_name_id_mapping.getId(f.name, existing_id) && i != existing_id) { + infostream << "NodeDefManager::deSerialize(): WARNING: " + "already defined with different ID: " << f.name << std::endl; + continue; + } + + // All is ok, add node definition with the requested ID + if (i >= m_content_features.size()) + m_content_features.resize((u32)(i) + 1); + m_content_features[i] = f; + addNameIdMapping(i, f.name); + verbosestream << "deserialized " << f.name << std::endl; + } +} + + +void CNodeDefManager::addNameIdMapping(content_t i, std::string name) +{ + m_name_id_mapping.set(i, name); + m_name_id_mapping_with_aliases.insert(std::make_pair(name, i)); +} + + +IWritableNodeDefManager *createNodeDefManager() { return new CNodeDefManager(); } -/* - Serialization of old ContentFeatures formats -*/ +//// Serialization of old ContentFeatures formats void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) { - if(protocol_version == 13) + if (protocol_version == 13) { writeU8(os, 5); // version os<first); writeS16(os, i->second); } writeU8(os, drawtype); writeF1000(os, visual_scale); writeU8(os, 6); - for(u32 i = 0; i < 6; i++) + for (u32 i = 0; i < 6; i++) tiledef[i].serialize(os, protocol_version); //CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24 writeU8(os, 2); - for(u32 i = 0; i < 2; i++){ + for (u32 i = 0; i < 2; i++) tiledef_special[i].serialize(os, protocol_version); - } writeU8(os, alpha); writeU8(os, post_effect_color.getAlpha()); writeU8(os, post_effect_color.getRed()); @@ -990,21 +1010,20 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) writeU8(os, 6); // version os<first); writeS16(os, i->second); } writeU8(os, drawtype); writeF1000(os, visual_scale); writeU8(os, 6); - for(u32 i = 0; i < 6; i++) + for (u32 i = 0; i < 6; i++) tiledef[i].serialize(os, protocol_version); //CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24 writeU8(os, 2); - for(u32 i = 0; i < 2; i++){ + for (u32 i = 0; i < 2; i++) tiledef_special[i].serialize(os, protocol_version); - } writeU8(os, alpha); writeU8(os, post_effect_color.getAlpha()); writeU8(os, post_effect_color.getRed()); @@ -1040,12 +1059,14 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) writeU8(os, leveled); writeU8(os, liquid_range); } else - throw SerializationError("ContentFeatures::serialize(): Unsupported version requested"); + throw SerializationError("ContentFeatures::serialize(): " + "Unsupported version requested"); } + void ContentFeatures::deSerializeOld(std::istream &is, int version) { - if(version == 5) // In PROTOCOL_VERSION 13 + if (version == 5) // In PROTOCOL_VERSION 13 { name = deSerializeString(is); groups.clear(); @@ -1057,13 +1078,13 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version) } drawtype = (enum NodeDrawType)readU8(is); visual_scale = readF1000(is); - if(readU8(is) != 6) + if (readU8(is) != 6) throw SerializationError("unsupported tile count"); - for(u32 i=0; i<6; i++) + for (u32 i = 0; i < 6; i++) tiledef[i].deSerialize(is); - if(readU8(is) != CF_SPECIAL_COUNT) + if (readU8(is) != CF_SPECIAL_COUNT) throw SerializationError("unsupported CF_SPECIAL_COUNT"); - for(u32 i=0; i Date: Fri, 3 Oct 2014 03:49:06 -0400 Subject: [PATCH 14/18] Fix misc. style issues --- src/nodedef.cpp | 6 ++++-- src/tile.h | 10 ++++++---- src/util/string.cpp | 5 ++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 92e4b59b3..ce1515fd2 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -536,8 +536,8 @@ content_t CNodeDefManager::getId(const std::string &name) const } -void CNodeDefManager::getIds(const std::string &name, std::set &result) - const +void CNodeDefManager::getIds(const std::string &name, + std::set &result) const { //TimeTaker t("getIds", NULL, PRECISION_MICRO); if (name.substr(0,6) != "group:") { @@ -768,6 +768,8 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc break; case NDT_FIRELIKE: f->backface_culling = false; + f->solidness = 0; + break; case NDT_TORCHLIKE: case NDT_SIGNLIKE: case NDT_FENCELIKE: diff --git a/src/tile.h b/src/tile.h index 78aaef00e..f4dc572e7 100644 --- a/src/tile.h +++ b/src/tile.h @@ -229,7 +229,7 @@ struct TileSpec // Sets everything else except the texture in the material void applyMaterialOptions(video::SMaterial &material) const { - switch(material_type){ + switch (material_type) { case TILE_MATERIAL_BASIC: material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; break; @@ -247,14 +247,16 @@ struct TileSpec break; case TILE_MATERIAL_WAVING_PLANTS: material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - break; + break; } - material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false; + material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) + ? true : false; } void applyMaterialOptionsWithShaders(video::SMaterial &material) const { - material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false; + material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) + ? true : false; } u32 texture_id; diff --git a/src/util/string.cpp b/src/util/string.cpp index 92a4735c4..5ba97afd5 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -30,7 +30,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../porting.h" #ifdef __ANDROID__ -const wchar_t* wide_chars = L" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; +const wchar_t* wide_chars = + L" !\"#$%&'()*+,-./0123456789:;<=>?@" + L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" + L"abcdefghijklmnopqrstuvwxyz{|}~"; int wctomb(char *s, wchar_t wc) { From 0920f55eb4224fdac1dfb363ef0864fc26162406 Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Fri, 3 Oct 2014 15:33:32 +0200 Subject: [PATCH 15/18] Fix broken plantlike drawtype. --- src/nodedef.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/nodedef.cpp b/src/nodedef.cpp index ce1515fd2..895761f59 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -394,7 +394,8 @@ private: void addNameIdMapping(content_t i, std::string name); #ifndef SERVER void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef, - u32 shader_id, bool use_normal_texture, u8 alpha, u8 material_type); + u32 shader_id, bool use_normal_texture, u8 alpha, u8 material_type, + bool backface_culling); #endif // Features indexed by id @@ -800,13 +801,13 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc // Tiles (fill in f->tiles[]) for (u16 j = 0; j < 6; j++) { fillTileAttribs(tsrc, &f->tiles[j], &tiledef[j], tile_shader[j], - use_normal_texture, f->alpha, material_type); + use_normal_texture, f->alpha, material_type, f->backface_culling); } // Special tiles (fill in f->special_tiles[]) for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) { fillTileAttribs(tsrc, &f->special_tiles[j], &f->tiledef_special[j], - tile_shader[j], use_normal_texture, f->alpha, material_type); + tile_shader[j], use_normal_texture, f->alpha, material_type, f->backface_culling); } } #endif @@ -816,7 +817,7 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc #ifndef SERVER void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef, u32 shader_id, bool use_normal_texture, - u8 alpha, u8 material_type) + u8 alpha, u8 material_type, bool backface_culling) { tile->shader_id = shader_id; tile->texture = tsrc->getTexture(tiledef->name, &tile->texture_id); @@ -829,7 +830,7 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, // Material flags tile->material_flags = 0; - if (tiledef->backface_culling) + if (backface_culling) tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; if (tiledef->animation.type == TAT_VERTICAL_FRAMES) tile->material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; From b9cb196d494c60016a509ffe17ce2077e98ceac6 Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Fri, 3 Oct 2014 16:03:14 +0200 Subject: [PATCH 16/18] Bugfix: dont highlight (0,0,0) when theres no node pointed. --- src/game.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index a8f6bc992..12bc695a6 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2786,8 +2786,13 @@ void the_game(bool &kill, bool random_input, InputHandler *input, if(pointed != pointed_old) { infostream<<"Pointing at "<getBool("enable_node_highlighting")) - client.setHighlighted(pointed.node_undersurface, show_hud); + if (g_settings->getBool("enable_node_highlighting")) { + if (pointed.type == POINTEDTHING_NODE) { + client.setHighlighted(pointed.node_undersurface, show_hud); + } else { + client.setHighlighted(pointed.node_undersurface, false); + } + } } /* From 173beeee65289464d2541c44f753d21cd1fa3155 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Fri, 3 Oct 2014 11:20:29 -0400 Subject: [PATCH 17/18] Fix special tile backspace culling --- src/nodedef.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 895761f59..f1a7ad694 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -394,8 +394,8 @@ private: void addNameIdMapping(content_t i, std::string name); #ifndef SERVER void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef, - u32 shader_id, bool use_normal_texture, u8 alpha, u8 material_type, - bool backface_culling); + u32 shader_id, bool use_normal_texture, bool backface_culling, + u8 alpha, u8 material_type); #endif // Features indexed by id @@ -801,13 +801,14 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc // Tiles (fill in f->tiles[]) for (u16 j = 0; j < 6; j++) { fillTileAttribs(tsrc, &f->tiles[j], &tiledef[j], tile_shader[j], - use_normal_texture, f->alpha, material_type, f->backface_culling); + use_normal_texture, f->backface_culling, f->alpha, material_type); } // Special tiles (fill in f->special_tiles[]) for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) { fillTileAttribs(tsrc, &f->special_tiles[j], &f->tiledef_special[j], - tile_shader[j], use_normal_texture, f->alpha, material_type, f->backface_culling); + tile_shader[j], use_normal_texture, + f->tiledef_special[j].backface_culling, f->alpha, material_type); } } #endif @@ -817,7 +818,7 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc #ifndef SERVER void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef, u32 shader_id, bool use_normal_texture, - u8 alpha, u8 material_type, bool backface_culling) + bool backface_culling, u8 alpha, u8 material_type) { tile->shader_id = shader_id; tile->texture = tsrc->getTexture(tiledef->name, &tile->texture_id); From 28438bba27168289be59a26d3ae55e3f3658d8d3 Mon Sep 17 00:00:00 2001 From: BlockMen Date: Fri, 3 Oct 2014 06:11:21 +0200 Subject: [PATCH 18/18] Add [colorize modifier --- doc/lua_api.txt | 32 +++++++++------- src/guiFormSpecMenu.cpp | 81 +++++------------------------------------ src/guiFormSpecMenu.h | 3 -- src/guiTable.cpp | 14 +++---- src/tile.cpp | 41 ++++++++++++++++++++- src/util/string.cpp | 63 ++++++++++++++++++++++++++++++++ src/util/string.h | 3 +- 7 files changed, 138 insertions(+), 99 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4db0dc40f..131a63fa5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -262,6 +262,10 @@ Advanced texture modifiers: Apply a mask to the base image. The mask is applied using binary AND. + [colorize: + Colorize the textures with given color + as ColorString + Sounds ------- Only OGG Vorbis files are supported. @@ -985,16 +989,16 @@ list[;;,;,;] ^ Show an inventory list listcolors[;] -^ Sets background color of slots in HEX-Color format +^ Sets background color of slots as ColorString ^ Sets background color of slots on mouse hovering listcolors[;;] -^ Sets background color of slots in HEX-Color format +^ Sets background color of slots as ColorString ^ Sets background color of slots on mouse hovering ^ Sets color of slots border listcolors[;;;;] -^ Sets background color of slots in HEX-Color format +^ Sets background color of slots as ColorString ^ Sets background color of slots on mouse hovering ^ Sets color of slots border ^ Sets default background color of tooltips @@ -1002,8 +1006,8 @@ listcolors[;;;;;;,] ^ Adds tooltip for an element -^ tooltip background color in HEX-Color format (optional) -^ tooltip font color in HEX-Color format (optional) +^ tooltip background color as ColorString (optional) +^ tooltip font color as ColorString (optional) image[,;,;] @@ -1015,7 +1019,7 @@ item_image[,;,;] ^ Position and size units are inventory slots bgcolor[;] -^ Sets background color of formspec in HEX-Color format +^ Sets background color of formspec as ColorString ^ If true the background color is drawn fullscreen (does not effect the size of the formspec) background[,;,;] @@ -1136,7 +1140,7 @@ box[,;,;] ^ simple colored semitransparent box ^ x and y position the box relative to the top left of the menu ^ w and h are the size of box -^ color in HEX-Color format +^ color as ColorString dropdown[,;;;,, ...,;] ^ show a dropdown field @@ -1182,15 +1186,15 @@ table[,;,;;,,...,;] tableoptions[;;...] ^ sets options for table[]: ^ color=#RRGGBB -^^ default text color (HEX-Color), defaults to #FFFFFF +^^ default text color (ColorString), defaults to #FFFFFF ^ background=#RRGGBB -^^ table background color (HEX-Color), defaults to #000000 +^^ table background color (ColorString), defaults to #000000 ^ border= ^^ should the table be drawn with a border? (default true) ^ highlight=#RRGGBB -^^ highlight background color (HEX-Color), defaults to #466432 +^^ highlight background color (ColorString), defaults to #466432 ^ highlight_text=#RRGGBB -^^ highlight text color (HEX-Color), defaults to #FFFFFF +^^ highlight text color (ColorString), defaults to #FFFFFF ^ opendepth= ^^ all subtrees up to depth < value are open (default value = 0) ^^ only useful when there is a column of type "tree" @@ -1200,7 +1204,7 @@ tablecolumns[,,,...;,,;...] ^ types: text, image, color, indent, tree ^^ text: show cell contents as text ^^ image: cell contents are an image index, use column options to define images -^^ color: cell contents are a HEX-Color and define color of following cell +^^ color: cell contents are a ColorString and define color of following cell ^^ indent: cell contents are a number and define indentation of following cell ^^ tree: same as indent, but user can open and close subtrees (treeview-like) ^ column options: @@ -1231,8 +1235,8 @@ Inventory location: - "nodemeta:,,": Any node metadata - "detached:": A detached inventory -HEX-Color ---------- +ColorString +----------- #RGB ^ defines a color in hexadecimal format #RGBA diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index f50fd15e5..2439de7fa 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" #include "settings.h" #include "client.h" +#include "util/string.h" // for parseColorString() #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -1575,7 +1576,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element) video::SColor tmp_color; - if (parseColor(parts[2], tmp_color, false)) { + if (parseColorString(parts[2], tmp_color, false)) { BoxDrawSpec spec(pos, geom, tmp_color); m_boxes.push_back(spec); @@ -1595,7 +1596,7 @@ void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element) if (((parts.size() == 1) || (parts.size() == 2)) || ((parts.size() > 2) && (m_formspec_version > FORMSPEC_API_VERSION))) { - parseColor(parts[0],m_bgcolor,false); + parseColorString(parts[0],m_bgcolor,false); if (parts.size() == 2) { std::string fullscreen = parts[1]; @@ -1613,20 +1614,20 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) if (((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) || ((parts.size() > 5) && (m_formspec_version > FORMSPEC_API_VERSION))) { - parseColor(parts[0], m_slotbg_n, false); - parseColor(parts[1], m_slotbg_h, false); + parseColorString(parts[0], m_slotbg_n, false); + parseColorString(parts[1], m_slotbg_h, false); if (parts.size() >= 3) { - if (parseColor(parts[2], m_slotbordercolor, false)) { + if (parseColorString(parts[2], m_slotbordercolor, false)) { m_slotborder = true; } } if (parts.size() == 5) { video::SColor tmp_color; - if (parseColor(parts[3], tmp_color, false)) + if (parseColorString(parts[3], tmp_color, false)) m_default_tooltip_bgcolor = tmp_color; - if (parseColor(parts[4], tmp_color, false)) + if (parseColorString(parts[4], tmp_color, false)) m_default_tooltip_color = tmp_color; } return; @@ -1644,7 +1645,7 @@ void GUIFormSpecMenu::parseTooltip(parserData* data, std::string element) } else if (parts.size() == 4) { std::string name = parts[0]; video::SColor tmp_color1, tmp_color2; - if ( parseColor(parts[2], tmp_color1, false) && parseColor(parts[3], tmp_color2, false) ) { + if ( parseColorString(parts[2], tmp_color1, false) && parseColorString(parts[3], tmp_color2, false) ) { m_tooltips[narrow_to_wide(name.c_str())] = TooltipSpec (parts[1], tmp_color1, tmp_color2); return; } @@ -3388,67 +3389,3 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id) } return L""; } - -bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color, - bool quiet) -{ - const char *hexpattern = NULL; - if (value[0] == '#') { - if (value.size() == 9) - hexpattern = "#RRGGBBAA"; - else if (value.size() == 7) - hexpattern = "#RRGGBB"; - else if (value.size() == 5) - hexpattern = "#RGBA"; - else if (value.size() == 4) - hexpattern = "#RGB"; - } - - if (hexpattern) { - assert(strlen(hexpattern) == value.size()); - video::SColor outcolor(255, 255, 255, 255); - for (size_t pos = 0; pos < value.size(); ++pos) { - // '#' in the pattern means skip that character - if (hexpattern[pos] == '#') - continue; - - // Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A' - // Read one or two digits, depending on hexpattern - unsigned char c1, c2; - if (hexpattern[pos+1] == hexpattern[pos]) { - // Two digits, e.g. hexpattern == "#RRGGBB" - if (!hex_digit_decode(value[pos], c1) || - !hex_digit_decode(value[pos+1], c2)) - goto fail; - ++pos; - } - else { - // One digit, e.g. hexpattern == "#RGB" - if (!hex_digit_decode(value[pos], c1)) - goto fail; - c2 = c1; - } - u32 colorpart = ((c1 & 0x0f) << 4) | (c2 & 0x0f); - - // Update outcolor with newly read color part - if (hexpattern[pos] == 'R') - outcolor.setRed(colorpart); - else if (hexpattern[pos] == 'G') - outcolor.setGreen(colorpart); - else if (hexpattern[pos] == 'B') - outcolor.setBlue(colorpart); - else if (hexpattern[pos] == 'A') - outcolor.setAlpha(colorpart); - } - - color = outcolor; - return true; - } - - // Optionally, named colors could be implemented here - -fail: - if (!quiet) - errorstream<<"Invalid color: \""< &content, cell->content_index = allocString(s.substr(2)); } else if (s[0] == '#' && s.size() >= 7 && - GUIFormSpecMenu::parseColor( + parseColorString( s.substr(0,7), cell->color, false)) { // single # for color cell->color_defined = true; @@ -211,15 +211,15 @@ void GUITable::setTable(const TableOptions &options, const std::string &name = options[k].name; const std::string &value = options[k].value; if (name == "color") - GUIFormSpecMenu::parseColor(value, m_color, false); + parseColorString(value, m_color, false); else if (name == "background") - GUIFormSpecMenu::parseColor(value, m_background, false); + parseColorString(value, m_background, false); else if (name == "border") m_border = is_yes(value); else if (name == "highlight") - GUIFormSpecMenu::parseColor(value, m_highlight, false); + parseColorString(value, m_highlight, false); else if (name == "highlight_text") - GUIFormSpecMenu::parseColor(value, m_highlight_text, false); + parseColorString(value, m_highlight_text, false); else if (name == "opendepth") opendepth = stoi(value); else @@ -416,7 +416,7 @@ void GUITable::setTable(const TableOptions &options, else if (columntype == COLUMN_TYPE_COLOR) { for (s32 i = 0; i < rowcount; ++i) { video::SColor cellcolor(255, 255, 255, 255); - if (GUIFormSpecMenu::parseColor(content[i * colcount + j], cellcolor, true)) + if (parseColorString(content[i * colcount + j], cellcolor, true)) rows[i].colors.push_back(std::make_pair(cellcolor, j+span)); } } diff --git a/src/tile.cpp b/src/tile.cpp index ebef77fb9..fa2f4c84e 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gamedef.h" #include "strfnd.h" +#include "util/string.h" // for parseColorString() #ifdef __ANDROID__ #include @@ -1588,10 +1589,46 @@ bool TextureSource::generateImagePart(std::string part_of_name, << filename << "\"."; } } + /* + [colorize:color + Overlays image with given color + color = color as ColorString + */ + else if (part_of_name.substr(0,10) == "[colorize:") { + Strfnd sf(part_of_name); + sf.next(":"); + std::string color_str = sf.next(":"); + + if (baseimg == NULL) { + errorstream << "generateImagePart(): baseimg != NULL " + << "for part_of_name=\"" << part_of_name + << "\", cancelling." << std::endl; + return false; + } + + video::SColor color; + if (!parseColorString(color_str, color, false)) + return false; + + core::dimension2d dim = baseimg->getDimension(); + video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim); + + if (!img) { + errorstream << "generateImagePart(): Could not create image " + << "for part_of_name=\"" << part_of_name + << "\", cancelling." << std::endl; + return false; + } + + img->fill(video::SColor(color)); + // Overlay the colored image + blit_with_alpha_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim); + img->drop(); + } else { - errorstream<<"generateImagePart(): Invalid " - " modification: \""< #include @@ -303,3 +304,65 @@ u64 read_seed(const char *str) return num; } + +bool parseColorString(const std::string &value, video::SColor &color, bool quiet) +{ + const char *hexpattern = NULL; + video::SColor outcolor(255, 255, 255, 255); + + if (value[0] == '#') { + if (value.size() == 9) + hexpattern = "#RRGGBBAA"; + else if (value.size() == 7) + hexpattern = "#RRGGBB"; + else if (value.size() == 5) + hexpattern = "#RGBA"; + else if (value.size() == 4) + hexpattern = "#RGB"; + } + + if (!hexpattern) + goto fail; + + assert(strlen(hexpattern) == value.size()); + for (size_t pos = 0; pos < value.size(); ++pos) { + // '#' in the pattern means skip that character + if (hexpattern[pos] == '#') + continue; + + // Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A' + // Read one or two digits, depending on hexpattern + unsigned char c1, c2; + if (hexpattern[pos+1] == hexpattern[pos]) { + // Two digits, e.g. hexpattern == "#RRGGBB" + if (!hex_digit_decode(value[pos], c1) || + !hex_digit_decode(value[pos+1], c2)) + goto fail; + ++pos; + } else { + // One digit, e.g. hexpattern == "#RGB" + if (!hex_digit_decode(value[pos], c1)) + goto fail; + c2 = c1; + } + u32 colorpart = ((c1 & 0x0f) << 4) | (c2 & 0x0f); + + // Update outcolor with newly read color part + if (hexpattern[pos] == 'R') + outcolor.setRed(colorpart); + else if (hexpattern[pos] == 'G') + outcolor.setGreen(colorpart); + else if (hexpattern[pos] == 'B') + outcolor.setBlue(colorpart); + else if (hexpattern[pos] == 'A') + outcolor.setAlpha(colorpart); + } + + color = outcolor; + return true; + +fail: + if (!quiet) + errorstream << "Invalid color: \"" << value << "\"" << std::endl; + return false; +} diff --git a/src/util/string.h b/src/util/string.h index 54a5a458e..e46fbf4e9 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef UTIL_STRING_HEADER #define UTIL_STRING_HEADER -#include "../irrlichttypes.h" +#include "irrlichttypes_bloated.h" #include #include #include @@ -349,6 +349,7 @@ std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask); size_t mystrlcpy(char *dst, const char *src, size_t size); char *mystrtok_r(char *s, const char *sep, char **lasts); u64 read_seed(const char *str); +bool parseColorString(const std::string &value, video::SColor &color, bool quiet); #endif