diff --git a/src/content_nodemeta.h b/src/content_nodemeta.h
index e20334312fd8a12d1a1a1cc5b8efe1c183f0d1ff..da5639e72ab4dd0b5fcf1cae8abbd59ec79aa62a 100644
--- a/src/content_nodemeta.h
+++ b/src/content_nodemeta.h
@@ -36,8 +36,9 @@ class SignNodeMetadata : public NodeMetadata
 	virtual void serializeBody(std::ostream &os);
 	virtual std::string infoText();
 
-	std::string getText(){ return m_text; }
-	void setText(std::string t){ m_text = t; }
+	virtual bool allowsTextInput(){ return true; }
+	virtual std::string getText(){ return m_text; }
+	virtual void setText(const std::string &t){ m_text = t; }
 
 private:
 	std::string m_text;
diff --git a/src/game.cpp b/src/game.cpp
index 30bd1bcf7fce04ea9a59a6c491ed5b2cc18b0724..638ad91556226d0aefe3abf25a46adf093328d61 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -43,12 +43,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gettext.h"
 #include "log.h"
 #include "filesys.h"
-// Needed for writing to signs (CONTENT_SIGN_WALL)
-// TODO: A generic way for handling such should be created
-#include "content_mapnode.h"
-// Needed for sign text input
-// TODO: A generic way for handling such should be created
-#include "content_nodemeta.h"
 // Needed for determining pointing to nodes
 #include "mapnode_contentfeatures.h"
 
@@ -115,9 +109,9 @@ struct TextDestChat : public TextDest
 	Client *m_client;
 };
 
-struct TextDestSignNode : public TextDest
+struct TextDestNodeMetadata : public TextDest
 {
-	TextDestSignNode(v3s16 p, Client *client)
+	TextDestNodeMetadata(v3s16 p, Client *client)
 	{
 		m_p = p;
 		m_client = client;
@@ -1784,23 +1778,22 @@ void the_game(
 					menu->setDrawSpec(draw_spec);
 					menu->drop();
 				}
-				else if(meta && meta->typeId() == CONTENT_SIGN_WALL && !random_input)
+				// If metadata provides text input, activate text input
+				else if(meta && meta->allowsTextInput() && !random_input)
 				{
-					infostream<<"Sign node right-clicked"<<std::endl;
-					
-					SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;
+					infostream<<"Launching metadata text input"<<std::endl;
 					
 					// Get a new text for it
 
-					TextDest *dest = new TextDestSignNode(nodepos, &client);
+					TextDest *dest = new TextDestNodeMetadata(nodepos, &client);
 
-					std::wstring wtext =
-							narrow_to_wide(signmeta->getText());
+					std::wstring wtext = narrow_to_wide(meta->getText());
 
 					(new GUITextInputMenu(guienv, guiroot, -1,
 							&g_menumgr, dest,
 							wtext))->drop();
 				}
+				// Otherwise report right click to server
 				else
 				{
 					client.groundAction(1, nodepos, neighbourpos, g_selected_item);
diff --git a/src/nodemetadata.h b/src/nodemetadata.h
index d81ade96cf434e8dbc5fc406679f44d1f535a199..5b2f129a1b1574febb574b5c8f2918d6a2c35835 100644
--- a/src/nodemetadata.h
+++ b/src/nodemetadata.h
@@ -25,16 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iostream>
 
 /*
-	Used for storing:
+	NodeMetadata stores arbitary amounts of data for special blocks.
+	Used for furnaces, chests and signs.
 
-	Oven:
-		- Item that is being burned
-		- Burning time
-		- Item stack that is being heated
-		- Result item stack
-	
-	Sign:
-		- Text
+	There are two interaction methods: inventory menu and text input.
+	Only one can be used for a single metadata, thus only inventory OR
+	text input should exist in a metadata.
 */
 
 class Inventory;
@@ -67,8 +63,10 @@ class NodeMetadata
 	virtual std::string getInventoryDrawSpecString(){return "";}
 	// primarily used for locking chests, but others can play too
 	virtual std::string getOwner(){ return std::string(""); }
-	virtual void setOwner(std::string t){  }
-
+	virtual void setOwner(std::string t){}
+	virtual bool allowsTextInput(){ return false; }
+	virtual std::string getText(){ return ""; }
+	virtual void setText(const std::string &t){}
 protected:
 	static void registerType(u16 id, Factory f);
 private: