diff --git a/data/builtin.lua b/data/builtin.lua
index a3276192190013eb1f59ab8cd06e8ed22dee59f6..b14ffa3b469ca4d6bae156589c1d931df21f3bb8 100644
--- a/data/builtin.lua
+++ b/data/builtin.lua
@@ -166,14 +166,4 @@ minetest.registered_on_generateds, minetest.register_on_generated = make_registr
 minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
 minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
 
-minetest.on_chat_message = function(name, message)
-	for i,func in ipairs(minetest.registered_on_chat_messages) do
-		local ate = func(name, message)
-		if ate then
-			return true
-		end
-	end
-	return false
-end
-
 -- END
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index fb1b58f5d76e077477e4f68e2071bf954729e7ed..a91122543447c0ff26173eb0d045bfce34e5ee9f 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -1548,18 +1548,28 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
 	assert(lua_checkstack(L, 20));
 	StackUnroller stack_unroller(L);
 
-	// Get minetest.on_chat_message builtin function
+	// Get minetest.registered_on_chat_messages
 	lua_getglobal(L, "minetest");
-	lua_getfield(L, -1, "on_chat_message");
-	luaL_checktype(L, -1, LUA_TFUNCTION);
-
-	// Call function
-	lua_pushstring(L, name.c_str());
-	lua_pushstring(L, message.c_str());
-	if(lua_pcall(L, 2, 1, 0))
-		script_error(L, "error: %s\n", lua_tostring(L, -1));
-	bool ate = lua_toboolean(L, -1);
-	return ate;
+	lua_getfield(L, -1, "registered_on_chat_messages");
+	luaL_checktype(L, -1, LUA_TTABLE);
+	int table = lua_gettop(L);
+	// Foreach
+	lua_pushnil(L);
+	while(lua_next(L, table) != 0){
+		// key at index -2 and value at index -1
+		luaL_checktype(L, -1, LUA_TFUNCTION);
+		// Call function
+		lua_pushstring(L, name.c_str());
+		lua_pushstring(L, message.c_str());
+		if(lua_pcall(L, 2, 1, 0))
+			script_error(L, "error: %s\n", lua_tostring(L, -1));
+		bool ate = lua_toboolean(L, -1);
+		lua_pop(L, 1);
+		if(ate)
+			return true;
+		// value removed, keep key for next iteration
+	}
+	return false;
 }
 
 /*