diff --git a/mods/CORE/_mcl_autogroup/depends.txt b/mods/CORE/_mcl_autogroup/depends.txt
index e69de29bb..2c9bbaec7 100644
--- a/mods/CORE/_mcl_autogroup/depends.txt
+++ b/mods/CORE/_mcl_autogroup/depends.txt
@@ -0,0 +1 @@
+mcl_autogroup
diff --git a/mods/CORE/_mcl_autogroup/init.lua b/mods/CORE/_mcl_autogroup/init.lua
index aabfa5906..7c1deecf4 100644
--- a/mods/CORE/_mcl_autogroup/init.lua
+++ b/mods/CORE/_mcl_autogroup/init.lua
@@ -1,169 +1,273 @@
---[[ Mining times. Yeah, mining times … Alright, this is going to be FUN!
+--[[
+This mod implements a HACK to make 100% sure the digging times of all tools
+match Minecraft's perfectly.  The digging times system of Minetest is very
+different, so this weird group trickery has to be used.  In Minecraft, each
+block has a hardness and the actual Minecraft digging time is determined by
+this:
 
-This mod does include a HACK to make 100% sure the digging times of all tools match Minecraft's perfectly.
-The digging times system of Minetest is very different, so this weird group trickery has to be used.
-In Minecraft, each block has a hardness and the actual Minecraft digging time is determined by this:
 1) The block's hardness
-2) The tool being used
-3) Whether the tool is considered as “eligible” for the block
+2) The tool being used (the tool_multiplier and its efficiency level)
+3) Whether the tool is considered as "eligible" for the block
    (e.g. only diamond pick eligible for obsidian)
-See Minecraft Wiki <http://minecraft.gamepedia.com/Minecraft_Wiki> for more information.
 
-In MineClone 2, all diggable node have the hardness set in the custom field “_mcl_hardness” (0 by default).
-The nodes are also required to specify the “eligible” tools in groups like “pickaxey”, “shovely”, etc.
-This mod then calculates the real digging time based on the node meta data. The real digging times
-are then added into mcl_autogroup.digtimes where the table indices are group rating and the values are the
-digging times in seconds. These digging times can be then added verbatim into the tool definitions.
+See Minecraft Wiki <http://minecraft.gamepedia.com/Minecraft_Wiki> for more
+information.
 
-Example:
-mcl_autogroup.digtimes.pickaxey_dig_diamond[1] = 0.2
+How the mod is used
+===================
 
-→ This means that when a node has been assigned the group “pickaxey_dig_diamond=1”, it can be dug by the
-diamond pickaxe in 0.2 seconds.
+In MineClone 2, all diggable node have the hardness set in the custom field
+"_mcl_hardness" (0 by default).  Digging groups are registered using the
+following code:
 
+    mcl_autogroup.register_digtime_group("pickaxey", { levels = 5 })
+    mcl_autogroup.register_digtime_group("shovely")
+    mcl_autogroup.register_digtime_group("shovely")
 
+The first line registers "pickaxey" as a digging group.  The "levels" field
+indicates that the digging group have 5 levels (in this case one for each
+material of a pickaxe).  The second line registers "shovely" as a digging group
+which does not have separate levels (if the "levels" field is not set it
+defaults to 0).
 
-This strange setup with mcl_autogroup has been done to minimize the amount of required digging times
-a single tool needs to use. If this is not being done, the loading time will increase considerably
-(>10s).
+Nodes indicate that they belong to a particular digging group by being member of
+the digging group in their node definition.  "mcl_core:dirt" for example has
+shovely=1 in its groups.  If the digging group has multiple levels the value of
+the group indicates which digging level the node requires.
+"mcl_core:stone_with_gold" for example has pickaxey=3 because it requires a
+pickaxe of level 3 to be mined.
 
-]]
+For tools to be able to dig nodes of the digging groups they need to use the
+"mcl_autogroups.get_groupcaps" function to get the groupcaps.  See
+"mcl_tools/init.lua" for examples of this.
 
-local materials = { "wood", "gold", "stone", "iron", "diamond" }
-local basegroups = { "pickaxey", "axey", "shovely" }
-local minigroups = { "handy", "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
-local divisors = {
-	["wood"] = 2,
-	["gold"] = 12,
-	["stone"] = 4,
-	["iron"] = 6,
-	["diamond"] = 8,
-	["handy"] = 1,
-	["shearsy"] = 15,
-	["swordy"] = 1.5,
-	["shearsy_wool"] = 5,
-	["swordy_cobweb"] = 15,
-}
-local max_efficiency_level = 5
+Information about the mod
+=========================
 
-mcl_autogroup = {}
-mcl_autogroup.digtimes = {}
-mcl_autogroup.creativetimes = {}	-- Copy of digtimes, except that all values are 0. Used for creative mode
+The mod is also split up into two mods, mcl_autogroups and _mcl_autogroups.
+mcl_autogroups contains the API functions used to register custom digging
+groups.  _mcl_autogroups contains parts of the mod which need to be executed
+after loading all other mods.
+--]]
 
-for m=1, #materials do
-	for g=1, #basegroups do
-		mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m]] = {}
-		mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {}
-		for e=1, max_efficiency_level do
-			mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {}
+-- The groups which affect dig times
+local basegroups = {}
+for group, _ in pairs(mcl_autogroup.registered_digtime_groups) do
+	table.insert(basegroups, group)
+end
+
+-- Returns a table containing the unique "_mcl_hardness" for nodes belonging to
+-- each basegroup.
+local function get_hardness_values_for_groups()
+	local maps = {}
+	local values = {}
+	for _, g in pairs(basegroups) do
+		maps[g] = {}
+		values[g] = {}
+	end
+
+	for _, ndef in pairs(minetest.registered_nodes) do
+		for _, g in pairs(basegroups) do
+			if ndef.groups[g] ~= nil then
+				maps[g][ndef._mcl_hardness or 0] = true
+			end
 		end
 	end
-end
-for g=1, #minigroups do
-	mcl_autogroup.digtimes[minigroups[g].."_dig"] = {}
-	mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {}
-	for e=1, max_efficiency_level do
-		mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {}
-		mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {}
+
+	for g, map in pairs(maps) do
+		for k, _ in pairs(map) do
+			table.insert(values[g], k)
+		end
 	end
+
+	for _, g in pairs(basegroups) do
+		table.sort(values[g])
+	end
+	return values
 end
 
+-- Returns a table containing a table indexed by "_mcl_hardness_value" to get
+-- its index in the list of unique hardnesses for each basegroup.
+local function get_hardness_lookup_for_groups(hardness_values)
+	map = {}
+	for g, values in pairs(hardness_values) do
+		map[g] = {}
+		for k, v in pairs(values) do
+			map[g][v] = k
+		end
+	end
+	return map
+end
+
+-- Array of unique hardness values for each group which affects dig time.
+local hardness_values = get_hardness_values_for_groups()
+
+-- Map indexed by hardness values which return the index of that value in
+-- hardness_value.  Used for quick lookup.
+local hardness_lookup = get_hardness_lookup_for_groups(hardness_values)
+
+local function compute_creativetimes(group)
+	local creativetimes = {}
+
+	for index, hardness in pairs(hardness_values[group]) do
+		table.insert(creativetimes, 0)
+	end
+
+	return creativetimes
+end
+
+-- Get the list of digging times for using a specific tool on a specific group.
+--
+-- Parameters:
+-- group - the group which it is digging
+-- can_harvest - if the tool can harvest the block
+-- tool_multiplier - dig speed multiplier for tool (default 1)
+-- efficiency - efficiency level for the tool (default 0)
+local function get_digtimes(group, can_harvest, tool_multiplier, efficiency)
+	efficiency = efficiency or 0
+	tool_multiplier = tool_multiplier or 1
+	speed_multiplier = tool_multiplier
+	if efficiency > 0 then
+		speed_multiplier = speed_multiplier + efficiency * efficiency + 1
+	end
+
+	local digtimes = {}
+
+	for index, hardness in pairs(hardness_values[group]) do
+		local digtime = (hardness or 0) / speed_multiplier
+		if can_harvest then
+			digtime = digtime * 1.5
+		else
+			digtime = digtime * 5
+		end
+
+		if digtime <= 0.05 then
+			digtime = 0
+		else
+			digtime = math.ceil(digtime * 20) / 20
+		end
+		table.insert(digtimes, digtime)
+	end
+
+	return digtimes
+end
+
+-- Get one groupcap field for using a specific tool on a specific group.
+local function get_groupcap(group, can_harvest, multiplier, efficiency, uses)
+	return {
+		times = get_digtimes(group, can_harvest, multiplier, efficiency),
+		uses = uses,
+		maxlevel = 0,
+	}
+end
+
+-- Get the groupcaps for a tool on the specified digging groups.  groupcaps_def
+-- contains a table with keys being the digging group and values being the tools
+-- properties for that digging group.
+--
+-- The tool properties can have the following values:
+--
+--   tool_multiplier - the digging speed multiplier for this tool (default 1)
+--   efficiency - the efficiency level for this tool (default 0)
+--   level - the maximum level of the group the tool can harvest (default 1)
+--   uses - the number of uses the tool has for this group
+--
+-- A level of 0 means that the tool will be able to dig that group but will
+-- never be able to harvest the nodes of that group and will always get a
+-- digging time penalty.  This is useful for implementing the hand.
+--
+-- Example usage:
+--
+--   mcl_autogroup.get_groupcaps {
+--       pickaxey = { tool_multiplier = 4, level = 3, uses = 132 }
+--   }
+--
+-- This computes the groupcaps for a tool mining "pickaxey" blocks.  The tool
+-- has a digging speed multiplier of 4, can mine nodes of level >= 3 and has 132
+-- uses.
+function mcl_autogroup.get_groupcaps(groupcaps_def)
+	local groupcaps = {}
+
+	for g, capsdef in pairs(groupcaps_def) do
+		local mult = capsdef.tool_multiplier or 1
+		local eff = capsdef.efficiency or 0
+		local def = mcl_autogroup.registered_digtime_groups[g]
+		local level = capsdef.level or 1
+		local max_level = def.levels or 0
+
+		if max_level > 0 then
+			level = math.min(level, max_level)
+			groupcaps[g .. "_0_dig"] = get_groupcap(g, false, mult, eff)
+			groupcaps[g .. "_" .. level .. "_dig"] = get_groupcap(g, true, mult, eff)
+		else
+			groupcaps[g .. "_dig"] = get_groupcap(g, true, mult, eff)
+		end
+	end
+
+	return groupcaps
+end
+
+-- Checks if the given node would drop its useful drop if dug by a tool with the
+-- given tool capabilities. Returns true if it will yield its useful drop, false
+-- otherwise.
+function mcl_autogroup.can_harvest(nodename, tool_capabilities)
+	local ndef = minetest.registered_nodes[nodename]
+	local groupcaps = tool_capabilities.groupcaps
+
+	local handy = minetest.get_item_group(nodename, "handy")
+	local dig_immediate = minetest.get_item_group(nodename, "handy")
+	if handy > 0 or dig_immediate >= 2 then
+		return true
+	end
+
+	for g, _ in pairs(groupcaps) do
+		if ndef.groups[g] then
+			if not string.find(g, "_0_dig$") and string.find(g, "_dig$") then
+				return true
+			end
+		end
+	end
+	return false
+end
+
+-- This function automatically assigns the "solid" and "opaque" groups to all
+-- registered nodes and assigns groups to get the correct digging times for
+-- groups registered with "mcl_autogroup.register_digtime_group".
 local overwrite = function()
 	for nname, ndef in pairs(minetest.registered_nodes) do
-		local groups_changed = false
 		local newgroups = table.copy(ndef.groups)
 		if (nname ~= "ignore" and ndef.diggable) then
-			-- Automatically assign the “solid” group for solid nodes
+			-- Automatically assign the "solid" group for solid nodes
 			if (ndef.walkable == nil or ndef.walkable == true)
 					and (ndef.collision_box == nil or ndef.collision_box.type == "regular")
 					and (ndef.node_box == nil or ndef.node_box.type == "regular")
 					and (ndef.groups.not_solid == 0 or ndef.groups.not_solid == nil) then
 				newgroups.solid = 1
-				groups_changed = true
 			end
-			-- Automatically assign the “opaque” group for opaque nodes
+			-- Automatically assign the "opaque" group for opaque nodes
 			if (not (ndef.paramtype == "light" or ndef.sunlight_propagates)) and
 					(ndef.groups.not_opaque == 0 or ndef.groups.not_opaque == nil) then
 				newgroups.opaque = 1
-				groups_changed = true
 			end
 
-			local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating, efficiency)
-				local time, validity_factor
-				if actual_rating >= expected_rating then
-					-- Valid tool
-					validity_factor = 1.5
-				else
-					-- Wrong tool (higher digging time)
-					validity_factor = 5
-				end
-				local speed_multiplier = divisors[material]
-				if efficiency then
-					speed_multiplier = speed_multiplier + efficiency * efficiency + 1
-				end
-				time = (hardness * validity_factor) / speed_multiplier
-				if time <= 0.05 then
-					time = 0
-				else
-					time = math.ceil(time * 20) / 20
-				end
-				table.insert(mcl_autogroup.digtimes[diggroup], time)
-				if not efficiency then
-					table.insert(mcl_autogroup.creativetimes[diggroup], 0)
-				end
-				newgroups[diggroup] = #mcl_autogroup.digtimes[diggroup]
-				return newgroups
-			end
-
-			-- Hack in digging times
-			local hardness = ndef._mcl_hardness
-			if not hardness then
-				hardness = 0
-			end
-
-			-- Handle pickaxey, axey and shovely
-			for _, basegroup in pairs(basegroups) do
-				if (hardness ~= -1 and ndef.groups[basegroup]) then
-					for g=1,#materials do
-						local diggroup = basegroup.."_dig_"..materials[g]
-						newgroups = calculate_group(hardness, materials[g], diggroup, newgroups, g, ndef.groups[basegroup])
-						for e=1,max_efficiency_level do
-							newgroups = calculate_group(hardness, materials[g], diggroup .. "_efficiency_" .. e, newgroups, g, ndef.groups[basegroup], e)
+			for g, gdef in pairs(mcl_autogroup.registered_digtime_groups) do
+				local index = hardness_lookup[g][ndef._mcl_hardness]
+				if ndef.groups[g] then
+					if gdef.levels then
+						newgroups[g .. "_0_dig"] = index
+						for i = ndef.groups.pickaxey, gdef.levels do
+							newgroups[g .. "_" .. i .. "_dig"] = index
 						end
-						groups_changed = true
-					end
-				end
-			end
-			for m=1, #minigroups do
-				local minigroup = minigroups[m]
-				if hardness ~= -1 then
-					local diggroup = minigroup.."_dig"
-					-- actual rating
-					local ar = ndef.groups[minigroup]
-					if ar == nil then
-						ar = 0
-					end
-					if (minigroup == "handy")
-							or
-							(ndef.groups.shearsy_wool and minigroup == "shearsy_wool" and ndef.groups.wool)
-							or
-							(ndef.groups.swordy_cobweb and minigroup == "swordy_cobweb" and nname == "mcl_core:cobweb")
-							or
-							(ndef.groups[minigroup] and minigroup ~= "swordy_cobweb" and minigroup ~= "shearsy_wool") then
-						newgroups = calculate_group(hardness, minigroup, diggroup, newgroups, ar, 1)
-						for e=1,max_efficiency_level do
-							newgroups = calculate_group(hardness, minigroup, diggroup .. "_efficiency_" .. e, newgroups, ar, 1, e)
-						end
-						groups_changed = true
+					else
+						local index = hardness_lookup[g][ndef._mcl_hardness]
+						newgroups[g .. "_dig"] = index
 					end
 				end
 			end
 
-			if groups_changed then
-				minetest.override_item(nname, {
-					groups = newgroups
-				})
-			end
+			minetest.override_item(nname, {
+				groups = newgroups
+			})
 		end
 	end
 end
diff --git a/mods/CORE/mcl_autogroup/init.lua b/mods/CORE/mcl_autogroup/init.lua
new file mode 100644
index 000000000..ff1c90cd0
--- /dev/null
+++ b/mods/CORE/mcl_autogroup/init.lua
@@ -0,0 +1,15 @@
+--[[
+This mod implements the API to register digging groups for mcl_autogroups.  The
+rest of the mod is implemented and documented in the mod "_mcl_autogroup".
+
+The mcl_autogroups mod is split up into two mods, mcl_autogroups and
+_mcl_autogroups.  mcl_autogroups contains the API functions used to register
+custom digging groups.  _mcl_autogroups contains parts of the mod which need to
+be executed after loading all other mods.
+--]]
+mcl_autogroup = {}
+mcl_autogroup.registered_digtime_groups = {}
+
+function mcl_autogroup.register_digtime_group(group, def)
+	mcl_autogroup.registered_digtime_groups[group] = def or {}
+end
diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua
index e5863abbc..f0aa289f2 100644
--- a/mods/ENTITIES/mcl_item_entity/init.lua
+++ b/mods/ENTITIES/mcl_item_entity/init.lua
@@ -169,62 +169,6 @@ local minigroups = { "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
 local basegroups = { "pickaxey", "axey", "shovely" }
 local materials = { "wood", "gold", "stone", "iron", "diamond" }
 
--- Checks if the given node would drop its useful drop if dug by a tool
--- with the given tool capabilities. Returns true if it will yield its useful
--- drop, false otherwise.
-local check_can_drop = function(node_name, tool_capabilities)
-	local handy = minetest.get_item_group(node_name, "handy")
-	local dig_immediate = minetest.get_item_group(node_name, "dig_immediate")
-	if handy == 1 or dig_immediate == 2 or dig_immediate == 3 then
-		return true
-	else
-		local toolgroupcaps
-		if tool_capabilities then
-			toolgroupcaps = tool_capabilities.groupcaps
-		else
-			return false
-		end
-
-		-- Compare node groups with tool capabilities
-		for m=1, #minigroups do
-			local minigroup = minigroups[m]
-			local g = minetest.get_item_group(node_name, minigroup)
-			if g ~= 0 then
-				local plus = minigroup .. "_dig"
-				if toolgroupcaps[plus] then
-					return true
-				end
-				for e=1,5 do
-					local effplus = plus .. "_efficiency_" .. e
-					if toolgroupcaps[effplus] then
-						return true
-					end
-				end
-			end
-		end
-		for b=1, #basegroups do
-			local basegroup = basegroups[b]
-			local g = minetest.get_item_group(node_name, basegroup)
-			if g ~= 0 then
-				for m=g, #materials do
-					local plus = basegroup .. "_dig_"..materials[m]
-					if toolgroupcaps[plus] then
-						return true
-					end
-					for e=1,5 do
-						local effplus = plus .. "_efficiency_" .. e
-						if toolgroupcaps[effplus] then
-							return true
-						end
-					end
-				end
-			end
-		end
-
-		return false
-	end
-end
-
 -- Stupid workaround to get drops from a drop table:
 -- Create a temporary table in minetest.registered_nodes that contains the proper drops,
 -- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition
@@ -287,7 +231,7 @@ function minetest.handle_node_drops(pos, drops, digger)
 		tool = digger:get_wielded_item()
 		toolcaps = tool:get_tool_capabilities()
 
-		if not check_can_drop(dug_node.name, toolcaps) then
+		if not mcl_autogroup.can_harvest(dug_node.name, toolcaps) then
 			return
 		end
 	end
diff --git a/mods/ITEMS/mcl_core/depends.txt b/mods/ITEMS/mcl_core/depends.txt
index fb9861814..4e3912e1d 100644
--- a/mods/ITEMS/mcl_core/depends.txt
+++ b/mods/ITEMS/mcl_core/depends.txt
@@ -1,3 +1,4 @@
+mcl_autogroup
 mcl_init
 mcl_sounds
 mcl_particles
diff --git a/mods/ITEMS/mcl_core/init.lua b/mods/ITEMS/mcl_core/init.lua
index 520f158bd..91e82be6e 100644
--- a/mods/ITEMS/mcl_core/init.lua
+++ b/mods/ITEMS/mcl_core/init.lua
@@ -3,6 +3,17 @@ mcl_core = {}
 -- Repair percentage for toolrepair
 mcl_core.repair = 0.05
 
+mcl_autogroup.register_digtime_group("handy")
+mcl_autogroup.register_digtime_group("pickaxey", { levels = 5 })
+mcl_autogroup.register_digtime_group("axey")
+mcl_autogroup.register_digtime_group("shovely")
+mcl_autogroup.register_digtime_group("shearsy")
+mcl_autogroup.register_digtime_group("shearsy_wool")
+mcl_autogroup.register_digtime_group("shearsy_cobweb")
+mcl_autogroup.register_digtime_group("swordy")
+mcl_autogroup.register_digtime_group("swordy_cobweb")
+mcl_autogroup.register_digtime_group("creative_breakable")
+
 -- Load files
 local modpath = minetest.get_modpath("mcl_core")
 dofile(modpath.."/functions.lua")
diff --git a/mods/ITEMS/mcl_core/nodes_misc.lua b/mods/ITEMS/mcl_core/nodes_misc.lua
index 305682244..083aa0b85 100644
--- a/mods/ITEMS/mcl_core/nodes_misc.lua
+++ b/mods/ITEMS/mcl_core/nodes_misc.lua
@@ -108,7 +108,7 @@ minetest.register_node("mcl_core:cobweb", {
 	liquid_renewable = false,
 	liquid_range = 0,
 	walkable = false,
-	groups = {swordy_cobweb=1,shearsy=1, fake_liquid=1, disable_jump=1, deco_block=1, dig_by_piston=1, dig_by_water=1,destroy_by_lava_flow=1,},
+	groups = {swordy_cobweb=1, shearsy_cobweb=1, fake_liquid=1, disable_jump=1, deco_block=1, dig_by_piston=1, dig_by_water=1,destroy_by_lava_flow=1,},
 	drop = "mcl_mobitems:string",
 	_mcl_shears_drop = true,
 	sounds = mcl_sounds.node_sound_leaves_defaults(),
diff --git a/mods/ITEMS/mcl_tools/init.lua b/mods/ITEMS/mcl_tools/init.lua
index d40b8e01b..c8263ef73 100644
--- a/mods/ITEMS/mcl_tools/init.lua
+++ b/mods/ITEMS/mcl_tools/init.lua
@@ -28,18 +28,17 @@ dig_speed_class group:
 local groupcaps, hand_range, hand_groups
 if minetest.is_creative_enabled("") then
 	-- Instant breaking in creative mode
-	groupcaps = {
-		creative_breakable = {times={[1]=0}, uses=0},
+	groupcaps = mcl_autogroup.get_groupcaps {
+		creative_breakable = { tool_multiplier = 1000000, level = 0, uses = 0 },
+		handy = { tool_multiplier = 1000000, level = 0, uses = 0 },
+		pickaxey = { tool_multiplier = 1000000, level = 0, uses = 0 }
 	}
-	-- mcl_autogroup provides the creative digging times for all digging groups
-	for k,v in pairs(mcl_autogroup.creativetimes) do
-		groupcaps[k] = { times = v, uses = 0 }
-	end
 	hand_range = 10
 	hand_groups = { dig_speed_class = 7 }
 else
-	groupcaps = {
-		handy_dig = {times=mcl_autogroup.digtimes.handy_dig, uses=0},
+	groupcaps = mcl_autogroup.get_groupcaps {
+		handy = { tool_multiplier = 1, level = 0, uses = 0 },
+		pickaxey = { tool_multiplier = 1, level = 0, uses = 0 }
 	}
 	hand_range = 4
 	hand_groups = { dig_speed_class = 1 }
@@ -86,8 +85,8 @@ minetest.register_tool("mcl_tools:pick_wood", {
 		-- 1/1.2
 		full_punch_interval = 0.83333333,
 		max_drop_level=1,
-		groupcaps={
-			pickaxey_dig_wood = {times=mcl_autogroup.digtimes.pickaxey_dig_wood, uses=60, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			pickaxey = { tool_multiplier = 2, level = 1, uses = 60 }
 		},
 		damage_groups = {fleshy=2},
 		punch_attack_uses = 30,
@@ -106,8 +105,8 @@ minetest.register_tool("mcl_tools:pick_stone", {
 		-- 1/1.2
 		full_punch_interval = 0.83333333,
 		max_drop_level=3,
-		groupcaps={
-			pickaxey_dig_stone = {times=mcl_autogroup.digtimes.pickaxey_dig_stone, uses=132, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			pickaxey = { tool_multiplier = 4, level = 3, uses = 132 }
 		},
 		damage_groups = {fleshy=3},
 		punch_attack_uses = 66,
@@ -126,8 +125,8 @@ minetest.register_tool("mcl_tools:pick_iron", {
 		-- 1/1.2
 		full_punch_interval = 0.83333333,
 		max_drop_level=4,
-		groupcaps={
-			pickaxey_dig_iron = {times=mcl_autogroup.digtimes.pickaxey_dig_iron , uses=251, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			pickaxey = { tool_multiplier = 6, level = 4, uses = 251 }
 		},
 		damage_groups = {fleshy=4},
 		punch_attack_uses = 126,
@@ -146,8 +145,8 @@ minetest.register_tool("mcl_tools:pick_gold", {
 		-- 1/1.2
 		full_punch_interval = 0.83333333,
 		max_drop_level=2,
-		groupcaps={
-			pickaxey_dig_gold = {times=mcl_autogroup.digtimes.pickaxey_dig_gold , uses=33, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			pickaxey = { tool_multiplier = 12, level = 2, uses = 33 }
 		},
 		damage_groups = {fleshy=2},
 		punch_attack_uses = 17,
@@ -166,8 +165,8 @@ minetest.register_tool("mcl_tools:pick_diamond", {
 		-- 1/1.2
 		full_punch_interval = 0.83333333,
 		max_drop_level=5,
-		groupcaps={
-			pickaxey_dig_diamond = {times=mcl_autogroup.digtimes.pickaxey_dig_diamond, uses=1562, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			pickaxey = { tool_multiplier = 8, level = 5, uses = 1562 }
 		},
 		damage_groups = {fleshy=5},
 		punch_attack_uses = 781,
@@ -288,8 +287,8 @@ minetest.register_tool("mcl_tools:shovel_wood", {
 	tool_capabilities = {
 		full_punch_interval = 1,
 		max_drop_level=1,
-		groupcaps={
-			shovely_dig_wood = {times=mcl_autogroup.digtimes.shovely_dig_wood, uses=60, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			shovely = { tool_multiplier = 2, level = 1, uses = 60 }
 		},
 		damage_groups = {fleshy=2},
 		punch_attack_uses = 30,
@@ -309,8 +308,8 @@ minetest.register_tool("mcl_tools:shovel_stone", {
 	tool_capabilities = {
 		full_punch_interval = 1,
 		max_drop_level=3,
-		groupcaps={
-			shovely_dig_stone = {times=mcl_autogroup.digtimes.shovely_dig_stone, uses=132, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			shovely = { tool_multiplier = 4, level = 3, uses = 132 }
 		},
 		damage_groups = {fleshy=3},
 		punch_attack_uses = 66,
@@ -330,8 +329,8 @@ minetest.register_tool("mcl_tools:shovel_iron", {
 	tool_capabilities = {
 		full_punch_interval = 1,
 		max_drop_level=4,
-		groupcaps={
-			shovely_dig_iron = {times=mcl_autogroup.digtimes.shovely_dig_iron, uses=251, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			shovely = { tool_multiplier = 6, level = 4, uses = 251 }
 		},
 		damage_groups = {fleshy=4},
 		punch_attack_uses = 126,
@@ -351,8 +350,8 @@ minetest.register_tool("mcl_tools:shovel_gold", {
 	tool_capabilities = {
 		full_punch_interval = 1,
 		max_drop_level=2,
-		groupcaps={
-			shovely_dig_gold = {times=mcl_autogroup.digtimes.shovely_dig_gold, uses=33, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			shovely = { tool_multiplier = 12, level = 2, uses = 33 }
 		},
 		damage_groups = {fleshy=2},
 		punch_attack_uses = 17,
@@ -372,8 +371,8 @@ minetest.register_tool("mcl_tools:shovel_diamond", {
 	tool_capabilities = {
 		full_punch_interval = 1,
 		max_drop_level=5,
-		groupcaps={
-			shovely_dig_diamond = {times=mcl_autogroup.digtimes.shovely_dig_diamond, uses=1562, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			shovely = { tool_multiplier = 8, level = 5, uses = 1562 }
 		},
 		damage_groups = {fleshy=5},
 		punch_attack_uses = 781,
@@ -395,8 +394,8 @@ minetest.register_tool("mcl_tools:axe_wood", {
 	tool_capabilities = {
 		full_punch_interval = 1.25,
 		max_drop_level=1,
-		groupcaps={
-			axey_dig_wood = {times=mcl_autogroup.digtimes.axey_dig_wood, uses=60, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			axey = { tool_multiplier = 2, level = 1, uses = 60 }
 		},
 		damage_groups = {fleshy=7},
 		punch_attack_uses = 30,
@@ -414,8 +413,8 @@ minetest.register_tool("mcl_tools:axe_stone", {
 	tool_capabilities = {
 		full_punch_interval = 1.25,
 		max_drop_level=3,
-		groupcaps={
-			axey_dig_stone = {times=mcl_autogroup.digtimes.axey_dig_stone, uses=132, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			axey = { tool_multiplier = 4, level = 3, uses = 132 }
 		},
 		damage_groups = {fleshy=9},
 		punch_attack_uses = 66,
@@ -434,8 +433,8 @@ minetest.register_tool("mcl_tools:axe_iron", {
 		-- 1/0.9
 		full_punch_interval = 1.11111111,
 		max_drop_level=4,
-		groupcaps={
-			axey_dig_iron = {times=mcl_autogroup.digtimes.axey_dig_iron, uses=251, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			axey = { tool_multiplier = 6, level = 4, uses = 251 }
 		},
 		damage_groups = {fleshy=9},
 		punch_attack_uses = 126,
@@ -453,8 +452,8 @@ minetest.register_tool("mcl_tools:axe_gold", {
 	tool_capabilities = {
 		full_punch_interval = 1.0,
 		max_drop_level=2,
-		groupcaps={
-			axey_dig_gold= {times=mcl_autogroup.digtimes.axey_dig_gold, uses=33, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			axey = { tool_multiplier = 12, level = 2, uses = 33 }
 		},
 		damage_groups = {fleshy=7},
 		punch_attack_uses = 17,
@@ -472,8 +471,8 @@ minetest.register_tool("mcl_tools:axe_diamond", {
 	tool_capabilities = {
 		full_punch_interval = 1.0,
 		max_drop_level=5,
-		groupcaps={
-			axey_dig_diamond = {times=mcl_autogroup.digtimes.axey_dig_diamond, uses=1562, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			axey = { tool_multiplier = 8, level = 5, uses = 1562 }
 		},
 		damage_groups = {fleshy=9},
 		punch_attack_uses = 781,
@@ -494,9 +493,9 @@ minetest.register_tool("mcl_tools:sword_wood", {
 	tool_capabilities = {
 		full_punch_interval = 0.625,
 		max_drop_level=1,
-		groupcaps={
-			swordy_dig = {times=mcl_autogroup.digtimes.swordy_dig , uses=60, maxlevel=0},
-			swordy_cobweb_dig = {times=mcl_autogroup.digtimes.swordy_cobweb_dig , uses=60, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			swordy = { tool_multiplier = 2, level = 1, uses = 60 },
+			swordy_cobweb = { tool_multiplier = 2, level = 1, uses = 60 }
 		},
 		damage_groups = {fleshy=4},
 		punch_attack_uses = 60,
@@ -514,9 +513,9 @@ minetest.register_tool("mcl_tools:sword_stone", {
 	tool_capabilities = {
 		full_punch_interval = 0.625,
 		max_drop_level=3,
-		groupcaps={
-			swordy_dig = {times=mcl_autogroup.digtimes.swordy_dig , uses=132, maxlevel=0},
-			swordy_cobweb_dig = {times=mcl_autogroup.digtimes.swordy_cobweb_dig , uses=132, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			swordy = { tool_multiplier = 4, level = 3, uses = 132 },
+			swordy_cobweb = { tool_multiplier = 4, level = 3, uses = 132 }
 		},
 		damage_groups = {fleshy=5},
 		punch_attack_uses = 132,
@@ -534,9 +533,9 @@ minetest.register_tool("mcl_tools:sword_iron", {
 	tool_capabilities = {
 		full_punch_interval = 0.625,
 		max_drop_level=4,
-		groupcaps={
-			swordy_dig = {times=mcl_autogroup.digtimes.swordy_dig, uses=251, maxlevel=0},
-			swordy_cobweb_dig = {times=mcl_autogroup.digtimes.swordy_cobweb_dig , uses=251, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			swordy = { tool_multiplier = 6, level = 4, uses = 251 },
+			swordy_cobweb = { tool_multiplier = 6, level = 4, uses = 251 }
 		},
 		damage_groups = {fleshy=6},
 		punch_attack_uses = 251,
@@ -554,9 +553,9 @@ minetest.register_tool("mcl_tools:sword_gold", {
 	tool_capabilities = {
 		full_punch_interval = 0.625,
 		max_drop_level=2,
-		groupcaps={
-			swordy_dig = {times=mcl_autogroup.digtimes.swordy_dig, uses=33, maxlevel=0},
-			swordy_cobweb_dig = {times=mcl_autogroup.digtimes.swordy_cobweb_dig, uses=33, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			swordy = { tool_multiplier = 12, level = 2, uses = 33 },
+			swordy_cobweb = { tool_multiplier = 12, level = 2, uses = 33 }
 		},
 		damage_groups = {fleshy=4},
 		punch_attack_uses = 33,
@@ -574,9 +573,9 @@ minetest.register_tool("mcl_tools:sword_diamond", {
 	tool_capabilities = {
 		full_punch_interval = 0.625,
 		max_drop_level=5,
-		groupcaps={
-			swordy_dig = {times=mcl_autogroup.digtimes.swordy_dig, uses=1562, maxlevel=0},
-			swordy_cobweb_dig = {times=mcl_autogroup.digtimes.swordy_cobweb_dig, uses=1562, maxlevel=0},
+		groupcaps = mcl_autogroup.get_groupcaps {
+			swordy = { tool_multiplier = 8, level = 5, uses = 1562 },
+			swordy_cobweb = { tool_multiplier = 8, level = 5, uses = 1562 }
 		},
 		damage_groups = {fleshy=7},
 		punch_attack_uses = 1562,
@@ -598,10 +597,11 @@ minetest.register_tool("mcl_tools:shears", {
 	tool_capabilities = {
 	        full_punch_interval = 0.5,
 	        max_drop_level=1,
-	        groupcaps={
-			shearsy_dig = {times=mcl_autogroup.digtimes.shearsy_dig, uses=238, maxlevel=0},
-			shearsy_wool_dig = {times=mcl_autogroup.digtimes.shearsy_wool_dig, uses=238, maxlevel=0},
-		}
+		groupcaps = mcl_autogroup.get_groupcaps {
+			shearsy = { tool_multiplier = 1.5, level = 1, uses = 238 },
+			shearsy_wool = { tool_multiplier = 5, level = 1, uses = 238 },
+			shearsy_cobweb = { tool_multiplier = 15, level = 1, uses = 238 }
+		},
 	},
 	on_place = carve_pumpkin,
 	sound = { breaks = "default_tool_breaks" },