diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua
index 4acf8d83f366485f624204f3d3e9ce60068a7096..c69d26454c92ac3b26c3d57ad62870742ea33970 100644
--- a/data/mods/default/init.lua
+++ b/data/mods/default/init.lua
@@ -107,10 +107,19 @@
 -- minetest.chat_send_all(text)
 -- minetest.chat_send_player(name, text)
 -- minetest.get_player_privs(name) -> set of privs
+--
 -- stackstring_take_item(stackstring) -> stackstring, item
 -- stackstring_put_item(stackstring, item) -> stackstring, success
 -- stackstring_put_stackstring(stackstring, stackstring) -> stackstring, success
 --
+-- minetest.digprop_constanttime(time)
+-- minetest.digprop_stonelike(toughness)
+-- minetest.digprop_dirtlike(toughness)
+-- minetest.digprop_gravellike(toughness)
+-- minetest.digprop_woodlike(toughness)
+-- minetest.digprop_leaveslike(toughness)
+-- minetest.digprop_glasslike(toughness)
+--
 -- Global objects:
 -- minetest.env - environment reference
 --
diff --git a/data/mods/legacy/init.lua b/data/mods/legacy/init.lua
index c50cfb6a2139553825d3a1cccc6e257135930295..a51931e419c9778a73af629bcbc38599a051e970 100644
--- a/data/mods/legacy/init.lua
+++ b/data/mods/legacy/init.lua
@@ -1,6 +1,46 @@
 -- legacy (Minetest 0.4 mod)
 -- Provides as much backwards-compatibility as feasible
 
+minetest.alias_node("stone", "default:stone")
+minetest.alias_node("dirt_with_grass", "default:dirt_with_grass")
+minetest.alias_node("dirt_with_grass_footsteps", "default:dirt_with_grass_footsteps")
+minetest.alias_node("dirt", "default:dirt")
+minetest.alias_node("sand", "default:sand")
+minetest.alias_node("gravel", "default:gravel")
+minetest.alias_node("sandstone", "default:sandstone")
+minetest.alias_node("clay", "default:clay")
+minetest.alias_node("brick", "default:brick")
+minetest.alias_node("tree", "default:tree")
+minetest.alias_node("jungletree", "default:jungletree")
+minetest.alias_node("junglegrass", "default:junglegrass")
+minetest.alias_node("leaves", "default:leaves")
+minetest.alias_node("cactus", "default:cactus")
+minetest.alias_node("papyrus", "default:papyrus")
+minetest.alias_node("bookshelf", "default:bookshelf")
+minetest.alias_node("glass", "default:glass")
+minetest.alias_node("wooden_fence", "default:fence_wood")
+minetest.alias_node("rail", "default:rail")
+minetest.alias_node("ladder", "default:ladder")
+minetest.alias_node("wood", "default:wood")
+minetest.alias_node("mese", "default:mese")
+minetest.alias_node("cloud", "default:cloud")
+minetest.alias_node("water_flowing", "default:water_flowing")
+minetest.alias_node("water_source", "default:water_source")
+minetest.alias_node("lava_flowing", "default:lava_flowing")
+minetest.alias_node("lava_source", "default:lava_source")
+minetest.alias_node("torch", "default:torch")
+minetest.alias_node("sign_wall", "default:sign_wall")
+minetest.alias_node("chest", "default:chest")
+minetest.alias_node("locked_chest", "default:chest_locked")
+minetest.alias_node("cobble", "default:cobble")
+minetest.alias_node("mossycobble", "default:mossycobble")
+minetest.alias_node("steelblock", "default:steelblock")
+minetest.alias_node("nyancat", "default:nyancat")
+minetest.alias_node("nyancat_rainbow", "default:nyancat_rainbow")
+minetest.alias_node("sapling", "default:sapling")
+minetest.alias_node("apple", "default:apple")
+
+--[[
 WATER_ALPHA = 160
 WATER_VISC = 1
 LAVA_VISC = 7
@@ -1016,5 +1056,5 @@ function on_dignode(p, node)
 	nodeupdate(p)
 end
 minetest.register_on_dignode(on_dignode)
-
+--]]
 -- END
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 9f2d4f0af4552dbfc129d58a7f6b74704549a5dc..e2e5616f174ecb29ea87c585a3af61c78a910b20 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -398,8 +398,18 @@ class CNodeDefManager: public IWritableNodeDefManager
 	{
 		return get(n.getContent());
 	}
-	virtual bool getId(const std::string &name, content_t &result) const
+	virtual bool getId(const std::string &name_, content_t &result) const
 	{
+		std::string name = name_;
+		// Convert name according to possible alias
+		std::map<std::string, std::string>::const_iterator i;
+		i = m_aliases.find(name);
+		if(i != m_aliases.end()){
+			/*infostream<<"ndef: alias active: "<<name<<" -> "<<i->second
+					<<std::endl;*/
+			name = i->second;
+		}
+		// Get id
 		return m_name_id_mapping.getId(name, result);
 	}
 	virtual content_t getId(const std::string &name) const
@@ -438,6 +448,12 @@ class CNodeDefManager: public IWritableNodeDefManager
 		m_content_features[c] = def;
 		if(def.name != "")
 			m_name_id_mapping.set(c, def.name);
+
+		// Remove conflicting alias if it exists
+		bool alias_removed = (m_aliases.erase(def.name) != 0);
+		if(alias_removed)
+			infostream<<"ndef: erased alias "<<def.name
+					<<" because node was defined"<<std::endl;
 	}
 	virtual content_t set(const std::string &name,
 			const ContentFeatures &def)
@@ -476,6 +492,19 @@ class CNodeDefManager: public IWritableNodeDefManager
 		f.material.diggability = DIGGABLE_NORMAL;
 		return set(name, f);
 	}
+	virtual void setAlias(const std::string &name,
+			const std::string &convert_to)
+	{
+		content_t id;
+		if(getId(name, id)){
+			infostream<<"ndef: not setting alias "<<name<<" -> "<<convert_to
+					<<": "<<name<<" is already defined"<<std::endl;
+			return;
+		}
+		infostream<<"ndef: setting alias "<<name<<" -> "<<convert_to
+				<<std::endl;
+		m_aliases[name] = convert_to;
+	}
 	virtual void updateTextures(ITextureSource *tsrc)
 	{
 #ifndef SERVER
@@ -639,8 +668,12 @@ class CNodeDefManager: public IWritableNodeDefManager
 		}
 	}
 private:
+	// Features indexed by id
 	ContentFeatures m_content_features[MAX_CONTENT+1];
+	// A mapping for fast converting back and forth between names and ids
 	NameIdMapping m_name_id_mapping;
+	// Aliases for loading legacy crap
+	std::map<std::string, std::string> m_aliases;
 };
 
 IWritableNodeDefManager* createNodeDefManager()
diff --git a/src/nodedef.h b/src/nodedef.h
index e0b5c864c44a7dbc7ccd1bd19bc204a773be4311..f69b66c9f46d4eab4485f917aad3108120c9b1db 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -279,6 +279,11 @@ class IWritableNodeDefManager : public INodeDefManager
 			const ContentFeatures &def)=0;
 	// If returns CONTENT_IGNORE, could not allocate id
 	virtual content_t allocateDummy(const std::string &name)=0;
+	// Set an alias so that nodes named <name> will load as <convert_to>.
+	// Alias is not set if <name> has already been defined.
+	// Alias will be removed if <name> is defined at a later point of time.
+	virtual void setAlias(const std::string &name,
+			const std::string &convert_to)=0;
 
 	/*
 		Update tile textures to latest return values of TextueSource.
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 624ca5d85dec60fd18b5143a3242f8f085d11c91..c5574dd8ec9ad1a91481a439bedac6d9872cedb4 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -1122,6 +1122,24 @@ static int l_register_node(lua_State *L)
 	return 0; /* number of results */
 }
 
+// alias_node(name, convert_to_name)
+static int l_alias_node(lua_State *L)
+{
+	std::string name = luaL_checkstring(L, 1);
+	std::string convert_to = luaL_checkstring(L, 2);
+
+	// Get server from registry
+	lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
+	Server *server = (Server*)lua_touserdata(L, -1);
+	// And get the writable node definition manager from the server
+	IWritableNodeDefManager *nodedef =
+			server->getWritableNodeDefManager();
+	
+	nodedef->setAlias(name, convert_to);
+	
+	return 0; /* number of results */
+}
+
 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
 static int l_register_craft(lua_State *L)
 {
@@ -1274,6 +1292,7 @@ static const struct luaL_Reg minetest_f [] = {
 	{"register_node", l_register_node},
 	{"register_craft", l_register_craft},
 	{"register_abm", l_register_abm},
+	{"alias_node", l_alias_node},
 	{"setting_get", l_setting_get},
 	{"setting_getbool", l_setting_getbool},
 	{"chat_send_all", l_chat_send_all},