<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://modded.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Carter57</id>
	<title>Modded Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://modded.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Carter57"/>
	<link rel="alternate" type="text/html" href="https://modded.wiki/w/Special:Contributions/Carter57"/>
	<updated>2026-06-02T15:26:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://modded.wiki/index.php?title=Desertification:Scorpion&amp;diff=14099</id>
		<title>Desertification:Scorpion</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Desertification:Scorpion&amp;diff=14099"/>
		<updated>2026-06-02T03:10:10Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Fixed image&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox entity&lt;br /&gt;
 |title=Scorpion&lt;br /&gt;
 |image=Desertification-Scorpion.png&lt;br /&gt;
 |health={{hp|8}}&lt;br /&gt;
 |armor={{armor|2}}&lt;br /&gt;
 |behavior=Neutral&lt;br /&gt;
 |damage={{hp|2}} &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[https://minecraft.wiki/w/Wither_(effect) Wither] for 40 ({{hp|20|withered=1}}) or 65 ({{hp|32|withered=1}}) seconds&lt;br /&gt;
 |speed=0.4&lt;br /&gt;
 |knockbackresistance=0%&lt;br /&gt;
 |spawn=On {{BlockLink|Desertification:Desert Sand}}.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Scorpion&#039;&#039;&#039; is a small neutral mob spawned by {{BlockLink|Desertification:Desert Sand}}.&lt;br /&gt;
&lt;br /&gt;
== Behavior ==&lt;br /&gt;
=== Player Interaction ===&lt;br /&gt;
Scorpions will run away from the player. If the player steps on the Scorpion, they will take {{hp|2}} damage, and get 40 seconds of [https://minecraft.wiki/w/Wither_(effect) Wither], dealing {{hp|22|withered=1}} damage total.&lt;br /&gt;
=== Mob Interaction ===&lt;br /&gt;
Scorpions will run very fast away from infected mobs. If the mob attacks the Scorpion, they will take {{hp|2}} damage, and get [https://minecraft.wiki/w/Wither_(effect) Wither] for 65 seconds, dealing {{hp|34|withered=1}} damage total. When fighting infected mobs, the cooldown on stinging is reduced.&lt;br /&gt;
&lt;br /&gt;
== Drops ==&lt;br /&gt;
The Scorpion is guaranteed to drop one {{ItemLink|Desertification:Scorpion Tail}} when killed.&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Desertification:Scorpion&amp;diff=14098</id>
		<title>Desertification:Scorpion</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Desertification:Scorpion&amp;diff=14098"/>
		<updated>2026-06-02T03:04:27Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;{{Infobox entity  |title=Scorpion  |image=Desertification-Scorpion  |health={{hp|8}}  |armor={{armor|2}}  |behavior=Neutral  |damage={{hp|2}} &amp;lt;br&amp;gt; &amp;lt;hr&amp;gt; [https://minecraft.wiki/w/Wither_(effect) Wither] for 40 ({{hp|20|withered=1}}) or 65 ({{hp|32|withered=1}}) seconds  |speed=0.4  |knockbackresistance=0%  |spawn=On {{BlockLink|Desertification:Desert Sand}}. }}  The &amp;#039;&amp;#039;&amp;#039;Scorpion&amp;#039;&amp;#039;&amp;#039; is a small neutral mob spawned by {{BlockLink|Desertification:Desert Sand}}.  == Behavior ==...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox entity&lt;br /&gt;
 |title=Scorpion&lt;br /&gt;
 |image=Desertification-Scorpion&lt;br /&gt;
 |health={{hp|8}}&lt;br /&gt;
 |armor={{armor|2}}&lt;br /&gt;
 |behavior=Neutral&lt;br /&gt;
 |damage={{hp|2}} &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[https://minecraft.wiki/w/Wither_(effect) Wither] for 40 ({{hp|20|withered=1}}) or 65 ({{hp|32|withered=1}}) seconds&lt;br /&gt;
 |speed=0.4&lt;br /&gt;
 |knockbackresistance=0%&lt;br /&gt;
 |spawn=On {{BlockLink|Desertification:Desert Sand}}.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Scorpion&#039;&#039;&#039; is a small neutral mob spawned by {{BlockLink|Desertification:Desert Sand}}.&lt;br /&gt;
&lt;br /&gt;
== Behavior ==&lt;br /&gt;
=== Player Interaction ===&lt;br /&gt;
Scorpions will run away from the player. If the player steps on the Scorpion, they will take {{hp|2}} damage, and get 40 seconds of [https://minecraft.wiki/w/Wither_(effect) Wither], dealing {{hp|22|withered=1}} damage total.&lt;br /&gt;
=== Mob Interaction ===&lt;br /&gt;
Scorpions will run very fast away from infected mobs. If the mob attacks the Scorpion, they will take {{hp|2}} damage, and get [https://minecraft.wiki/w/Wither_(effect) Wither] for 65 seconds, dealing {{hp|34|withered=1}} damage total. When fighting infected mobs, the cooldown on stinging is reduced.&lt;br /&gt;
&lt;br /&gt;
== Drops ==&lt;br /&gt;
The Scorpion is guaranteed to drop one {{ItemLink|Desertification:Scorpion Tail}} when killed.&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Module:DropTable/doc&amp;diff=14097</id>
		<title>Module:DropTable/doc</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Module:DropTable/doc&amp;diff=14097"/>
		<updated>2026-06-02T02:51:20Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;This module unfortunately does not work.  &amp;quot;Lua error at line 825: attempt to call global &amp;#039;setBucketData&amp;#039; (a nil value).&amp;quot;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This module unfortunately does not work.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Lua error at line 825: attempt to call global &#039;setBucketData&#039; (a nil value).&amp;quot;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Module:DropTable&amp;diff=14096</id>
		<title>Module:DropTable</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Module:DropTable&amp;diff=14096"/>
		<updated>2026-06-02T02:49:19Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Undo revision 14095 by Carter57 (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local i18n = {&lt;br /&gt;
	imageSprite = {&lt;br /&gt;
		item = &#039;Invicon&#039;,&lt;br /&gt;
		mob = &#039;EntitySprite&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerThing = {&lt;br /&gt;
		item = &#039;Item&#039;,&lt;br /&gt;
		mob = &#039;Mob&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerWithoutLooting = &#039;Default&#039;,&lt;br /&gt;
	headerLooting1 = &#039;Looting I&#039;,&lt;br /&gt;
	headerLooting2 = &#039;Looting II&#039;,&lt;br /&gt;
	headerLooting3 = &#039;Looting III&#039;,&lt;br /&gt;
	headerOverview = &#039;Quantity / Chance / Average&#039;,&lt;br /&gt;
	headerDropAmount = &#039;Amount&#039;,&lt;br /&gt;
	headerDistribution = &#039;Probability&#039;,&lt;br /&gt;
	headerAverage = &#039;Average&#039;,&lt;br /&gt;
	headerTotal = {&lt;br /&gt;
		item = &#039;Killed&#039;,&lt;br /&gt;
		mob = &#039;Drops&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerExpectation = {&lt;br /&gt;
		item = &#039;Expected Drops&#039;,&lt;br /&gt;
		mob = &#039;Expected Number of Kills&#039;&lt;br /&gt;
	},&lt;br /&gt;
	tabOverviewDecimal = &#039;Decimal&#039;,&lt;br /&gt;
	tabOverviewFraction = &#039;Fraction&#039;,&lt;br /&gt;
	tabDistribution = &#039;Distribution&#039;,&lt;br /&gt;
	tabCalculator = &#039;Expectation&#039;,&lt;br /&gt;
	titlejava = &amp;quot;&#039;&#039;[[Java Edition]]&#039;&#039;:&amp;quot;,&lt;br /&gt;
	titlebedrock = &amp;quot;&#039;&#039;[[Bedrock Edition]]&#039;&#039;:&amp;quot;,&lt;br /&gt;
	notePlayerOrPet = &#039;Only when killed by a [[player]] or a tamed [[wolf]].&#039;,&lt;br /&gt;
	notePlayerOnly = &#039;Only when killed by a [[player]].&#039;,&lt;br /&gt;
	noteBurnOrFireAspect = &#039;Only when on fire or killed with a weapon enchanted with [[Fire Aspect]].&#039;,&lt;br /&gt;
	noteBurnOnly = &#039;Only when on fire.&#039;,&lt;br /&gt;
	noteNotBurnOrFireAspect = &amp;quot;Only when &#039;&#039;not&#039;&#039; on fire and &#039;&#039;not&#039;&#039; killed with a weapon enchanted with [[Fire Aspect]].&amp;quot;,&lt;br /&gt;
	noteNotBurnOnly = &amp;quot;Only when &#039;&#039;not&#039;&#039; on fire.&amp;quot;,&lt;br /&gt;
	refgroup = &#039;FN&#039;, -- [[MediaWiki:Cite link label group-FN]]&lt;br /&gt;
	style = &#039;DropTable/styles.css&#039;, -- [[Template:DropTable/styles.css]]&lt;br /&gt;
	bucket = &#039;droptable&#039;, -- [[Bucket:droptable]]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local Frac = {}&lt;br /&gt;
&lt;br /&gt;
-- Defined types:&lt;br /&gt;
-- * frac: { numerator = numerator, denominator = denominator }, used on Frac.*( ..., fraction, ... )&lt;br /&gt;
&lt;br /&gt;
local function GCD( x, y )	-- get Greatest Common Divisor (GCD)&lt;br /&gt;
	-- Test&lt;br /&gt;
	-- gcd( 0, 0 ) = undef&lt;br /&gt;
	if type( x ) ~= &#039;number&#039; or type( y ) ~= &#039;number&#039; or ( x == 0 and y == 0 ) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	x = math.abs( x )&lt;br /&gt;
	y = math.abs( y )&lt;br /&gt;
&lt;br /&gt;
	-- Improve precision&lt;br /&gt;
	local multiplier = 1&lt;br /&gt;
	while x % 1 ~= 0 or y % 1 ~= 0 do&lt;br /&gt;
		x = x * 10&lt;br /&gt;
		y = y * 10&lt;br /&gt;
		multiplier = multiplier * 10&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function euclidean( x, y )&lt;br /&gt;
		return y == 0 and x or euclidean( y, x % y )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return euclidean( x, y ) / multiplier&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function LCM( x, y )	-- get Least Common Multiple (LCM)&lt;br /&gt;
	-- Test&lt;br /&gt;
	local GCD = GCD( x, y )&lt;br /&gt;
	if not GCD then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return x * y / GCD&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Start of Frac: Fraction Library&lt;br /&gt;
local fracMetatable = {&lt;br /&gt;
	__index    = Frac,&lt;br /&gt;
	__add      = function ( fraction1, fraction2 ) return Frac.add( fraction1, fraction2 )      end,&lt;br /&gt;
	__sub      = function ( fraction1, fraction2 ) return Frac.sub( fraction1, fraction2 )      end,&lt;br /&gt;
	__mul      = function ( fraction1, fraction2 ) return Frac.mul( fraction1, fraction2 )      end,&lt;br /&gt;
	__div      = function ( fraction1, fraction2 ) return Frac.div( fraction1, fraction2 )      end,&lt;br /&gt;
	__pow      = function ( fraction, n )          return Frac.pow( fraction, n )               end,&lt;br /&gt;
	__unm      = function ( fraction )             return Frac.neg( fraction )                  end,&lt;br /&gt;
	__eq       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) == 0 end,&lt;br /&gt;
	__lt       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) &amp;lt; 0  end,&lt;br /&gt;
	__le       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) &amp;lt;= 0 end,&lt;br /&gt;
	__tostring = function ( fraction )             return Frac.display( fraction )              end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Tests&lt;br /&gt;
function Frac.isFrac( fraction )	-- Check if it is a valid fraction&lt;br /&gt;
	return not ( type( fraction ) ~= &#039;table&#039; or not fraction.numerator or not fraction.denominator or fraction.denominator &amp;lt;= 0 or fraction.numerator % 1 ~= 0 or fraction.denominator % 1 ~= 0 )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Create a fraction directly&lt;br /&gt;
function Frac.new( numerator, denominator )&lt;br /&gt;
	if type( numerator ) ~= &#039;number&#039; or denominator and ( type( denominator ) ~= &#039;number&#039; or denominator == 0 ) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local fraction = denominator and ( denominator &amp;lt; 0 and { numerator = - numerator, denominator = - denominator } or { numerator = numerator, denominator = denominator } ) or Frac.fromDec( numerator )&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	setmetatable( fraction, fracMetatable )&lt;br /&gt;
	return fraction&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.fromDec( decimal )	-- Convert decimal to fraction&lt;br /&gt;
	if type( decimal ) ~= &#039;number&#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local numerator = decimal&lt;br /&gt;
	local denominator = 1&lt;br /&gt;
	while #tostring(numerator % 1) ~= 1 do&lt;br /&gt;
		numerator = numerator * 10&lt;br /&gt;
		denominator = denominator * 10&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.reduce( Frac.new( math.floor(numerator + 0.5), denominator ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.toDec( fraction )	-- Convert fraction to decimal&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return fraction.numerator / fraction.denominator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Basic calculations&lt;br /&gt;
function Frac.neg( fraction )	-- Take the negative fraction&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( - fraction.numerator, fraction.denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.inv( fraction )	-- Take the inversed fraction&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if fraction.numerator == 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ( fraction.numerator &amp;lt; 0 ) and Frac.new( - fraction.denominator, - fraction.numerator ) or Frac.new( fraction.denominator, fraction.numerator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.mul( fraction1, fraction2 )	-- Fractions multiplication&lt;br /&gt;
	fraction1 = Frac.isFrac( fraction1 ) and fraction1 or Frac.new( fraction1 )&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	if Frac.isFrac( fraction1 ) == false or Frac.isFrac( fraction2 ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( fraction1.numerator * fraction2.numerator, fraction1.denominator * fraction2.denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.div( fraction1, fraction2 )	-- Fractions division&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	return Frac.mul( fraction1, Frac.inv( fraction2 ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.pow( fraction, n )	-- Fractions exponentiation&lt;br /&gt;
	if Frac.isFrac( fraction ) == false or n % 1 ~= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ( n &amp;lt; 0 ) and Frac.new( fraction.denominator ^ ( - n ), fraction.numerator ^ ( -n ) ) or Frac.new( fraction.numerator ^ n, fraction.denominator ^ n )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Advanced calculation&lt;br /&gt;
function Frac.expand( fraction, newDenominator )	-- Fractions expansion&lt;br /&gt;
	if Frac.isFrac( fraction ) == false or type( newDenominator ) ~= &#039;number&#039; or ( type( newDenominator ) == &#039;number&#039; and newDenominator % 1 ~= 0 ) or newDenominator &amp;lt;= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local newNumerator = fraction.numerator * newDenominator / fraction.denominator&lt;br /&gt;
	if newNumerator % 1 ~= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( newNumerator, newDenominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.reduce( fraction )	-- Fractions reduction (to simplest)&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.expand( fraction, fraction.denominator / GCD( fraction.denominator, fraction.numerator ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.common( fractionList )	-- Get fractions with the common denominator&lt;br /&gt;
	if type( fractionList ) ~= &#039;table&#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local candidates = {}&lt;br /&gt;
	local denominators = {}&lt;br /&gt;
	for _, fraction in pairs( fractionList ) do&lt;br /&gt;
		if Frac.isFrac( fraction ) == false then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( candidates, fraction )&lt;br /&gt;
			table.insert( denominators, fraction.denominator )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if #candidates == 1 then&lt;br /&gt;
		return candidates&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local lcm = 1&lt;br /&gt;
	for _, denominator in pairs( denominators ) do&lt;br /&gt;
		lcm = LCM( denominator, lcm )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local results = {}&lt;br /&gt;
	for _, fraction in pairs( candidates ) do&lt;br /&gt;
		table.insert( results, Frac.expand( fraction, lcm ) )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return results&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Basic calculations, with dependencies&lt;br /&gt;
function Frac.add( fraction1, fraction2 )	-- Fractions addition&lt;br /&gt;
	fraction1 = Frac.isFrac( fraction1 ) and fraction1 or Frac.new( fraction1 )&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	if Frac.isFrac( fraction1 ) == false or Frac.isFrac( fraction2 ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local fractions = Frac.common{ fraction1, fraction2 }&lt;br /&gt;
	return Frac.new( fractions[ 1 ].numerator + fractions[ 2 ].numerator, fractions[ 1 ].denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.sub( fraction1, fraction2 )	-- Fractions subtraction&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	return Frac.add( fraction1, Frac.neg( fraction2 ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.cmp( fraction1, fraction2 )	-- Compare fractions&lt;br /&gt;
	return Frac.sub( fraction1, fraction2 ).numerator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Formattings to human readable&lt;br /&gt;
function Frac.display( fraction, isReduced, isMixed )	-- Convert fractions to human-readable style&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return &#039;&#039; &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if fraction.numerator == 0 then&lt;br /&gt;
		return &#039;0&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local prefix = &#039;&#039;&lt;br /&gt;
	if fraction.numerator &amp;lt; 0 then&lt;br /&gt;
		prefix = prefix .. &#039;-&#039;&lt;br /&gt;
		fraction = Frac.neg( fraction )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if isReduced then&lt;br /&gt;
		fraction = Frac.reduce( fraction )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local numerator = fraction.numerator&lt;br /&gt;
	local denominator = fraction.denominator&lt;br /&gt;
	if denominator == 1 then&lt;br /&gt;
		return prefix .. tostring( numerator )&lt;br /&gt;
	end&lt;br /&gt;
	if numerator == denominator then&lt;br /&gt;
		return prefix .. &#039;1&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if isMixed and numerator &amp;gt; denominator then&lt;br /&gt;
		prefix = prefix .. math.floor( numerator / denominator )&lt;br /&gt;
		numerator = numerator % denominator&lt;br /&gt;
		if numerator == 0 then&lt;br /&gt;
			return prefix&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return string.format( &#039;%s&amp;lt;sup&amp;gt;%s&amp;lt;/sup&amp;gt;&amp;amp;frasl;&amp;lt;sub&amp;gt;%s&amp;lt;/sub&amp;gt;&#039;, prefix, numerator, denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local Distr = {}&lt;br /&gt;
Distr.mt = {}&lt;br /&gt;
function Distr.mt.__index( t, k )&lt;br /&gt;
	if type( k ) == &#039;number&#039; then return Frac.new( 0 ) end&lt;br /&gt;
	return Distr[ k ]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.mt.__newindex( t, k, v )&lt;br /&gt;
	v = Frac.isFrac( v ) and v or Frac.new( v )&lt;br /&gt;
	if type( k ) ~= &#039;number&#039; or v == nil then error() end&lt;br /&gt;
	if v == Frac.new( 0 ) then return end&lt;br /&gt;
	return rawset( t, k, v )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.new( t )&lt;br /&gt;
	t = t or {}&lt;br /&gt;
	local distribution = {}&lt;br /&gt;
	setmetatable( distribution, Distr.mt )&lt;br /&gt;
	for k, v in pairs( t ) do&lt;br /&gt;
		distribution[ k ] = v&lt;br /&gt;
	end&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.shift( distribution, s )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		newDistribution[ i + s ] = v&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.limitRange( distribution, min, max )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		if max and i &amp;gt;= max then&lt;br /&gt;
			newDistribution[ max ] = newDistribution[ max ] + v&lt;br /&gt;
		elseif min and i &amp;lt;= min then&lt;br /&gt;
			newDistribution[ min ] = newDistribution[ min ] + v&lt;br /&gt;
		else&lt;br /&gt;
			newDistribution[ i ] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.add( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = distribution1:new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution[ i ] = newDistribution[ i ] + v&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.multiply( distribution, x )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		newDistribution[ i ] = v * x&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Distr.expectation( distribution )&lt;br /&gt;
	local expectation = Frac.new( 0 )&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		expectation = expectation + v * i&lt;br /&gt;
	end&lt;br /&gt;
	return expectation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Distr.times( distribution, n )&lt;br /&gt;
	local newDistribution = Distr.new({[0] = 1})&lt;br /&gt;
	for i = 1, n do&lt;br /&gt;
		newDistribution = newDistribution:addIncrease( distribution )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.addIncrease( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution = newDistribution:add( distribution1:shift( i ):multiply( v ) )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.rolls( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution = newDistribution:add( distribution1:times( i ):multiply( v ) )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.getUniform( min, max )&lt;br /&gt;
	local value = Frac.new( 1, max - min + 1 )&lt;br /&gt;
	local distribution = Distr.new()&lt;br /&gt;
	for i = min, max do&lt;br /&gt;
		distribution[ i ] = value&lt;br /&gt;
	end&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.getLootingIncrease( level, min, max )&lt;br /&gt;
	min = min or 0&lt;br /&gt;
	max = max or min + 1&lt;br /&gt;
	min = min * level&lt;br /&gt;
	max = max * level&lt;br /&gt;
	if max - min &amp;lt; 2 then&lt;br /&gt;
		return Distr.getUniform( min, max )&lt;br /&gt;
	end&lt;br /&gt;
	local distribution = Distr.new()&lt;br /&gt;
	local value = Frac.new( 1, max - min )&lt;br /&gt;
	for i = min, max do&lt;br /&gt;
		distribution[ i ] = value&lt;br /&gt;
	end&lt;br /&gt;
	distribution[ min ] = value / 2&lt;br /&gt;
	distribution[ max ] = value / 2&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.addLootingIncrease( distribution1, distribution2, edition )&lt;br /&gt;
	local base = distribution1:limitRange(0, nil)&lt;br /&gt;
	local backup = base[ 0 ]&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		base[ 0 ] = 0 -- MCPE-35307: Looting doesn&#039;t work when the mob drops nothing&lt;br /&gt;
	end&lt;br /&gt;
	local newDistribution = base:addIncrease(distribution2)&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		newDistribution[ 0 ] = newDistribution[ 0 ] + backup&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function calculateDistributions( args, edition )&lt;br /&gt;
	local function parseRange(str)&lt;br /&gt;
		local n = tonumber(str)&lt;br /&gt;
		if n then return {min = n, max = n} end&lt;br /&gt;
		local min, max = str:match(&#039;^%s*(%-?%d+)%s*%-%s*(%-?%d+)%s*$&#039;)&lt;br /&gt;
		min = tonumber(min)&lt;br /&gt;
		max = tonumber(max)&lt;br /&gt;
		if min and max and min &amp;lt;= max then return {min = min, max = max} end&lt;br /&gt;
		error(string.format(&amp;quot;&#039;%s&#039; isn&#039;t a range!&amp;quot;, str))&lt;br /&gt;
	end&lt;br /&gt;
	local function parseProbability(str)&lt;br /&gt;
		local n = Frac.fromDec(tonumber(str)) or Frac.div(tonumber(str:match(&#039;(.*)%%%s*$&#039;)), 100)&lt;br /&gt;
		if n then return n end&lt;br /&gt;
		local numerator, denominator = str:match(&#039;^%s*(%-?%d+)%s*/%s*(%-?%d+)%s*$&#039;)&lt;br /&gt;
		numerator = tonumber(numerator)&lt;br /&gt;
		denominator = tonumber(denominator)&lt;br /&gt;
		local frac = Frac.new(numerator, denominator)&lt;br /&gt;
		if frac then return frac end&lt;br /&gt;
		error(string.format(&amp;quot;&#039;%s&#039; isn&#039;t a probability!&amp;quot;, str))&lt;br /&gt;
	end&lt;br /&gt;
	local quantity = parseRange(args.quantity or 1)&lt;br /&gt;
	local lootingquantity = parseRange(args.lootingquantity or 0)&lt;br /&gt;
	local dropchance = parseProbability(args.dropchance or 1)&lt;br /&gt;
	local lootingchance = parseProbability(args.lootingchance or 0)&lt;br /&gt;
	local multiplychance = parseProbability(args.multiplychance or 1)&lt;br /&gt;
	local rolls = parseRange(args.rolls or 1)&lt;br /&gt;
	local limit = tonumber(args.limit)&lt;br /&gt;
&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		limit = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local independent = {}&lt;br /&gt;
	for _, sub in ipairs(args.independent or {}) do&lt;br /&gt;
		table.insert(independent, calculateDistributions(sub, edition))&lt;br /&gt;
	end&lt;br /&gt;
	local mutuallyexclusive = {}&lt;br /&gt;
	for _, sub in ipairs(args.mutuallyexclusive or {}) do&lt;br /&gt;
		table.insert(mutuallyexclusive, calculateDistributions(sub, edition))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local distributions = {}&lt;br /&gt;
	for level = 0, 3 do&lt;br /&gt;
		local lootingIncrease = Distr.getLootingIncrease(level, lootingquantity.min, lootingquantity.max)&lt;br /&gt;
		local chance = (dropchance + lootingchance * level) * multiplychance&lt;br /&gt;
		local distribution = Distr.getUniform(quantity.min, quantity.max)&lt;br /&gt;
			:addLootingIncrease(lootingIncrease, edition)&lt;br /&gt;
			:rolls(Distr.new{[0] = 1 - chance, [1] = chance})&lt;br /&gt;
			:limitRange(0, limit)&lt;br /&gt;
			:rolls(Distr.getUniform(rolls.min, rolls.max))&lt;br /&gt;
		for _, sub in ipairs(independent) do&lt;br /&gt;
			distribution = distribution:addIncrease(sub[level])&lt;br /&gt;
		end&lt;br /&gt;
		for _, sub in ipairs(mutuallyexclusive) do&lt;br /&gt;
			local nodropchance1 = distribution[0]&lt;br /&gt;
			local nodropchance2 = sub[level][0]&lt;br /&gt;
			distribution = distribution:add(sub[level])&lt;br /&gt;
			distribution[0] = nodropchance1 + nodropchance2 - Frac.new(1)&lt;br /&gt;
		end&lt;br /&gt;
		distributions[level] = distribution&lt;br /&gt;
	end&lt;br /&gt;
	return distributions&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getImageAndLink(args, mode)&lt;br /&gt;
	local link = args.link or args.name&lt;br /&gt;
	local image = require([[Module:SpriteFile]]).sprite{&lt;br /&gt;
		args.image or args.name,&lt;br /&gt;
		name = args.spritetype or i18n.imageSprite[mode],&lt;br /&gt;
		link = link,&lt;br /&gt;
		size = 32,&lt;br /&gt;
		align = &#039;middle&#039;,&lt;br /&gt;
		keepcase = mode == &#039;item&#039;&lt;br /&gt;
	}&lt;br /&gt;
	local displayname = args.displayname or args.name&lt;br /&gt;
	local linktext = string.format(&#039;[[%s|%s]]&#039;, link, displayname)&lt;br /&gt;
	return image, linktext&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getDropData(args, edition)&lt;br /&gt;
	local data = {}&lt;br /&gt;
	for level, distribution in pairs(calculateDistributions(args, edition)) do&lt;br /&gt;
		local quantity = {}&lt;br /&gt;
		for k, v in pairs(distribution) do&lt;br /&gt;
			if v ~= Frac.new(0) then table.insert(quantity, k) end&lt;br /&gt;
		end&lt;br /&gt;
		table.sort(quantity)&lt;br /&gt;
		local min = quantity[1]&lt;br /&gt;
		local max = quantity[#quantity]&lt;br /&gt;
		local from = min&lt;br /&gt;
		local to&lt;br /&gt;
		local quantitytext = &#039;&#039;&lt;br /&gt;
		local function range()&lt;br /&gt;
			quantitytext = quantitytext .. (from == min and &#039;&#039; or &#039; / &#039;)&lt;br /&gt;
				.. (from == to and to or (from .. &#039;&amp;amp;ndash;&#039; .. to))&lt;br /&gt;
		end&lt;br /&gt;
		for _, num in ipairs(quantity) do&lt;br /&gt;
			if to and to ~= num - 1 then&lt;br /&gt;
				range()&lt;br /&gt;
				from = num&lt;br /&gt;
			end&lt;br /&gt;
			to = num&lt;br /&gt;
		end&lt;br /&gt;
		range()&lt;br /&gt;
		data[level] = {&lt;br /&gt;
			distribution = distribution,&lt;br /&gt;
			average = distribution:expectation():reduce(),&lt;br /&gt;
			dropchance = (1 - distribution[0]):reduce(),&lt;br /&gt;
			min = min,&lt;br /&gt;
			max = max,&lt;br /&gt;
			quantitytext = quantitytext&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function linesToDatas(lines, notes, edition)&lt;br /&gt;
	local datas = {}&lt;br /&gt;
	for _, line in ipairs(lines) do&lt;br /&gt;
		local args = mw.text.jsonDecode(line)&lt;br /&gt;
		local data = { name = args.name }&lt;br /&gt;
		data.image, data.linktext = getImageAndLink(args, &#039;item&#039;)&lt;br /&gt;
		if edition ~= &#039;bedrock&#039; and args.edition ~= &#039;bedrock&#039; then&lt;br /&gt;
			data.java = getDropData(args, &#039;java&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if edition ~= &#039;java&#039; and args.edition ~= &#039;java&#039; then&lt;br /&gt;
			data.bedrock = getDropData(args, &#039;bedrock&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local notenames = args.notes and mw.text.split(args.notes, &#039;,&#039;) or {}&lt;br /&gt;
		data.notes = {}&lt;br /&gt;
		for _, name in ipairs(notenames) do&lt;br /&gt;
			table.insert(data.notes, notes[name])&lt;br /&gt;
		end&lt;br /&gt;
		table.insert(datas, data)&lt;br /&gt;
	end&lt;br /&gt;
	return datas&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createOverviewTable(format, datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;12&#039;):wikitext(i18n.headerOverview):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local info = data[edition][level]&lt;br /&gt;
				row:tag(&#039;td&#039;):css(&#039;text-wrap-mode&#039;, &#039;nowrap&#039;):wikitext(info.quantitytext):done()&lt;br /&gt;
				if format == &#039;decimal&#039; then&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(string.format(&#039;%.2f%%&#039;, Frac.toDec(info.dropchance) * 100)):done()&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(string.format(&#039;%.2f&#039;, Frac.toDec(info.average))):done()&lt;br /&gt;
				else&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(Frac.display(info.dropchance)):done()&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(Frac.display(info.average)):done()&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createDistributionsTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerDropAmount):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;4&#039;):wikitext(i18n.headerDistribution):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local min = math.huge&lt;br /&gt;
			local max = -math.huge&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				min = math.min(min, data[edition][level].min)&lt;br /&gt;
				max = math.max(max, data[edition][level].max)&lt;br /&gt;
			end&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):attr(&#039;rowspan&#039;, max - min + 2):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):attr(&#039;rowspan&#039;, max - min + 2):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for drops = min, max do&lt;br /&gt;
				row:tag(&#039;td&#039;):wikitext(tostring(drops)):done()&lt;br /&gt;
				for level = 0, 3 do&lt;br /&gt;
					local probability = data[edition][level].distribution[drops] or Frac.new(0)&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(&lt;br /&gt;
						probability == Frac.new(0) and &#039;0&#039; or&lt;br /&gt;
						string.format(&#039;%s (%.2f%%)&#039;, Frac.display(probability, true), Frac.toDec(probability) * 100)&lt;br /&gt;
					):done()&lt;br /&gt;
				end&lt;br /&gt;
				wikitable:node(row)&lt;br /&gt;
				row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
			end&lt;br /&gt;
			row:tag(&#039;th&#039;):wikitext(i18n.headerAverage):done()&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local average = data[edition][level].average&lt;br /&gt;
				row:tag(&#039;th&#039;):wikitext(string.format(&#039;%s (%.2f)&#039;, Frac.display(average), Frac.toDec(average))):done()&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createCalculatorTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;):addClass(&#039;calculator-container&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;2&#039;)&lt;br /&gt;
				:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;Simplecalc label&#039;, args = {&lt;br /&gt;
					label = i18n.headerTotal[mode],&lt;br /&gt;
					[&#039;for&#039;] = &#039;count&#039;&lt;br /&gt;
				}})&lt;br /&gt;
				:done()&lt;br /&gt;
			:tag(&#039;td&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;4&#039;)&lt;br /&gt;
				:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;simplecalc&#039;, args = {&lt;br /&gt;
					type = &#039;number&#039;,&lt;br /&gt;
					id = &#039;count&#039;,&lt;br /&gt;
					min = 0,&lt;br /&gt;
					step = 1,&lt;br /&gt;
					default = 1&lt;br /&gt;
				}})&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;4&#039;):wikitext(i18n.headerExpectation[mode]):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local average = data[edition][level].average&lt;br /&gt;
				if mode == &#039;mob&#039; then&lt;br /&gt;
					average = Frac.inv(average)&lt;br /&gt;
				end&lt;br /&gt;
				row:tag(&#039;td&#039;)&lt;br /&gt;
					:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;simplecalc&#039;, args = {&lt;br /&gt;
						type = &#039;plain&#039;,&lt;br /&gt;
						formula = string.format(&#039;count*(%s/%s)&#039;, average.numerator, average.denominator),&lt;br /&gt;
						decimals = 2,&lt;br /&gt;
						default = string.format(&#039;%.2f&#039;, Frac.toDec(average))&lt;br /&gt;
					}})&lt;br /&gt;
					:done()&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createTabs (datas, mode, edition)&lt;br /&gt;
	local f = mw.getCurrentFrame()&lt;br /&gt;
	local noteTexts = {}&lt;br /&gt;
	for i, data in pairs(datas) do&lt;br /&gt;
		local noteText = &#039;&#039;&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			for _, note in ipairs(data.notes) do&lt;br /&gt;
				local ref = note.name and note or note[edition]&lt;br /&gt;
				if ref then&lt;br /&gt;
					noteText = noteText .. f:extensionTag{&lt;br /&gt;
						name = &#039;ref&#039;,&lt;br /&gt;
						content = ref.content,&lt;br /&gt;
						args = { name = ref.name, group = i18n.refgroup }&lt;br /&gt;
					}&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		noteTexts[i] = noteText&lt;br /&gt;
	end&lt;br /&gt;
	local tabber = f:extensionTag(&#039;tabber&#039;, string.format(&lt;br /&gt;
		&#039;%s=%s|-|%s=%s|-|%s=%s|-|%s=%s&#039;,&lt;br /&gt;
		i18n.tabOverviewDecimal,&lt;br /&gt;
		createOverviewTable(&#039;decimal&#039;, datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabOverviewFraction,&lt;br /&gt;
		createOverviewTable(&#039;fraction&#039;, datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabDistribution,&lt;br /&gt;
		createDistributionsTable(datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabCalculator,&lt;br /&gt;
		createCalculatorTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	)) &lt;br /&gt;
	return require(&#039;Module:TSLoader&#039;).call(i18n.style)&lt;br /&gt;
		.. tostring(mw.html.create(&#039;div&#039;):addClass(&#039;droptable-tabber&#039;):wikitext(tabber))&lt;br /&gt;
		.. tostring(mw.html.create(&#039;div&#039;):addClass(&#039;droptable-references&#039;):wikitext(f:extensionTag{&lt;br /&gt;
			name = &#039;references&#039;,&lt;br /&gt;
			args = { group = i18n.refgroup }&lt;br /&gt;
		}))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function setBucketData(datas, args)&lt;br /&gt;
	args.name = args.name or mw.title.getCurrentTitle().text&lt;br /&gt;
	local image, link = getImageAndLink(args, &#039;mob&#039;)&lt;br /&gt;
	for _, data in ipairs(datas) do&lt;br /&gt;
		local jsonData = mw.text.jsonEncode({&lt;br /&gt;
			name = args.name,&lt;br /&gt;
			image = image,&lt;br /&gt;
			linktext = link,&lt;br /&gt;
			java = data.java,&lt;br /&gt;
			bedrock = data.bedrock,&lt;br /&gt;
			notes = data.notes&lt;br /&gt;
		}, mw.text.JSON_PRESERVE_KEYS)&lt;br /&gt;
&lt;br /&gt;
		local bucketObject = {&lt;br /&gt;
			item = data.name,&lt;br /&gt;
			json = jsonData&lt;br /&gt;
		}&lt;br /&gt;
		bucket(i18n.bucket).put(bucketObject)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getBucketData(args)&lt;br /&gt;
	local name = args.name or args[1] or mw.title.getCurrentTitle().text&lt;br /&gt;
	local data = bucket(i18n.bucket)&lt;br /&gt;
		.select(&#039;json&#039;)&lt;br /&gt;
		.where(&#039;item&#039;, name)&lt;br /&gt;
		.run()&lt;br /&gt;
	local jsons = {}&lt;br /&gt;
	for _, object in ipairs(data) do&lt;br /&gt;
		local jsondata = object[&#039;json&#039;]&lt;br /&gt;
		table.insert(jsons, mw.text.jsonDecode(jsondata, mw.text.JSON_PRESERVE_KEYS))&lt;br /&gt;
	end&lt;br /&gt;
	return jsons&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseNotes(defines)&lt;br /&gt;
	local notes = {&lt;br /&gt;
		burn_only = { name = &#039;burn_only&#039;, content = i18n.noteBurnOnly },&lt;br /&gt;
		burn_or_fire_aspect = { name = &#039;burn_or_fire_aspect&#039;, content = i18n.noteBurnOrFireAspect },&lt;br /&gt;
		not_burn_only = { name = &#039;not_burn_only&#039;, content = i18n.noteNotBurnOnly },&lt;br /&gt;
		not_burn_or_fire_aspect = { name = &#039;not_burn_or_fire_aspect&#039;, content = i18n.noteNotBurnOrFireAspect },&lt;br /&gt;
		player_only = { name = &#039;player_only&#039;, content = i18n.notePlayerOnly },&lt;br /&gt;
		player_or_pet = { name = &#039;player_or_pet&#039;, content = i18n.notePlayerOrPet }&lt;br /&gt;
	}&lt;br /&gt;
	notes.player = { java = notes.player_or_pet, bedrock = notes.player_only }&lt;br /&gt;
	notes.burn = { java = notes.burn_or_fire_aspect, bedrock = notes.burn_only }&lt;br /&gt;
	notes.not_burn = { java = notes.not_burn_or_fire_aspect, bedrock = notes.not_burn_only }&lt;br /&gt;
&lt;br /&gt;
	for _, str in ipairs(defines and mw.text.split(defines, &#039;\n&#039;) or {}) do&lt;br /&gt;
		local key, text = str:match(&#039;^%s*([^=]-)%s*=%s*(.-)%s*$&#039;)&lt;br /&gt;
		if key and text then&lt;br /&gt;
			local name, edition = key:match(&#039;^(.-)%.(.*)$&#039;)&lt;br /&gt;
			if edition then&lt;br /&gt;
				notes[name] = notes[name] or {}&lt;br /&gt;
				local redirect = text:match(&#039;^&amp;gt;%s*(.-)$&#039;)&lt;br /&gt;
				if redirect and notes[redirect].name then&lt;br /&gt;
					notes[name][edition] = notes[redirect]&lt;br /&gt;
				else&lt;br /&gt;
					notes[name][edition] = { name = name, content = text }&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				notes[key] = { name = key, content = text }&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return notes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.line( frame )&lt;br /&gt;
	local args = require( &#039;Module:ProcessArgs&#039; ).norm( frame:getParent().args )&lt;br /&gt;
	for _, name in pairs({&#039;independent&#039;, &#039;mutuallyexclusive&#039;}) do&lt;br /&gt;
		if args[name] then&lt;br /&gt;
			args[name] = mw.text.jsonDecode(&#039;[&#039; .. args[name] .. &#039;]&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.text.jsonEncode(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main( frame )&lt;br /&gt;
	return p._main( frame:getParent().args )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main( args )&lt;br /&gt;
	local notes = parseNotes(args.notes)&lt;br /&gt;
	local edition = args.edition and mw.text.trim(args.edition)&lt;br /&gt;
	local datas = linesToDatas(args, notes, edition)&lt;br /&gt;
	if not args.nosource and mw.title.getCurrentTitle().isContentPage then&lt;br /&gt;
		setBucketData(datas, args)&lt;br /&gt;
	end&lt;br /&gt;
	if edition then&lt;br /&gt;
		return createTabs(datas, &#039;item&#039;, edition)&lt;br /&gt;
	end&lt;br /&gt;
	return i18n.titlejava .. createTabs(datas, &#039;item&#039;, &#039;java&#039;)&lt;br /&gt;
		.. i18n.titlebedrock .. createTabs(datas, &#039;item&#039;, &#039;bedrock&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.source( frame )&lt;br /&gt;
	return p._source( frame:getParent().args )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._source( args )&lt;br /&gt;
	local datas = getBucketData( args )&lt;br /&gt;
	local edition = args.edition and mw.text.trim(args.edition)&lt;br /&gt;
	if edition then&lt;br /&gt;
		return createTabs(datas, &#039;mob&#039;, edition)&lt;br /&gt;
	end&lt;br /&gt;
	return i18n.titlejava .. createTabs(datas, &#039;mob&#039;, &#039;java&#039;)&lt;br /&gt;
		.. i18n.titlebedrock .. createTabs(datas, &#039;mob&#039;, &#039;bedrock&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Module:DropTable&amp;diff=14095</id>
		<title>Module:DropTable</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Module:DropTable&amp;diff=14095"/>
		<updated>2026-06-02T02:48:13Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Attempted fix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local i18n = {&lt;br /&gt;
	imageSprite = {&lt;br /&gt;
		item = &#039;Invicon&#039;,&lt;br /&gt;
		mob = &#039;EntitySprite&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerThing = {&lt;br /&gt;
		item = &#039;Item&#039;,&lt;br /&gt;
		mob = &#039;Mob&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerWithoutLooting = &#039;Default&#039;,&lt;br /&gt;
	headerLooting1 = &#039;Looting I&#039;,&lt;br /&gt;
	headerLooting2 = &#039;Looting II&#039;,&lt;br /&gt;
	headerLooting3 = &#039;Looting III&#039;,&lt;br /&gt;
	headerOverview = &#039;Quantity / Chance / Average&#039;,&lt;br /&gt;
	headerDropAmount = &#039;Amount&#039;,&lt;br /&gt;
	headerDistribution = &#039;Probability&#039;,&lt;br /&gt;
	headerAverage = &#039;Average&#039;,&lt;br /&gt;
	headerTotal = {&lt;br /&gt;
		item = &#039;Killed&#039;,&lt;br /&gt;
		mob = &#039;Drops&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerExpectation = {&lt;br /&gt;
		item = &#039;Expected Drops&#039;,&lt;br /&gt;
		mob = &#039;Expected Number of Kills&#039;&lt;br /&gt;
	},&lt;br /&gt;
	tabOverviewDecimal = &#039;Decimal&#039;,&lt;br /&gt;
	tabOverviewFraction = &#039;Fraction&#039;,&lt;br /&gt;
	tabDistribution = &#039;Distribution&#039;,&lt;br /&gt;
	tabCalculator = &#039;Expectation&#039;,&lt;br /&gt;
	titlejava = &amp;quot;&#039;&#039;[[Java Edition]]&#039;&#039;:&amp;quot;,&lt;br /&gt;
	titlebedrock = &amp;quot;&#039;&#039;[[Bedrock Edition]]&#039;&#039;:&amp;quot;,&lt;br /&gt;
	notePlayerOrPet = &#039;Only when killed by a [[player]] or a tamed [[wolf]].&#039;,&lt;br /&gt;
	notePlayerOnly = &#039;Only when killed by a [[player]].&#039;,&lt;br /&gt;
	noteBurnOrFireAspect = &#039;Only when on fire or killed with a weapon enchanted with [[Fire Aspect]].&#039;,&lt;br /&gt;
	noteBurnOnly = &#039;Only when on fire.&#039;,&lt;br /&gt;
	noteNotBurnOrFireAspect = &amp;quot;Only when &#039;&#039;not&#039;&#039; on fire and &#039;&#039;not&#039;&#039; killed with a weapon enchanted with [[Fire Aspect]].&amp;quot;,&lt;br /&gt;
	noteNotBurnOnly = &amp;quot;Only when &#039;&#039;not&#039;&#039; on fire.&amp;quot;,&lt;br /&gt;
	refgroup = &#039;FN&#039;, -- [[MediaWiki:Cite link label group-FN]]&lt;br /&gt;
	style = &#039;DropTable/styles.css&#039;, -- [[Template:DropTable/styles.css]]&lt;br /&gt;
	bucket = &#039;droptable&#039;, -- [[Bucket:droptable]]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local Frac = {}&lt;br /&gt;
&lt;br /&gt;
-- Defined types:&lt;br /&gt;
-- * frac: { numerator = numerator, denominator = denominator }, used on Frac.*( ..., fraction, ... )&lt;br /&gt;
&lt;br /&gt;
local function GCD( x, y )	-- get Greatest Common Divisor (GCD)&lt;br /&gt;
	-- Test&lt;br /&gt;
	-- gcd( 0, 0 ) = undef&lt;br /&gt;
	if type( x ) ~= &#039;number&#039; or type( y ) ~= &#039;number&#039; or ( x == 0 and y == 0 ) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	x = math.abs( x )&lt;br /&gt;
	y = math.abs( y )&lt;br /&gt;
&lt;br /&gt;
	-- Improve precision&lt;br /&gt;
	local multiplier = 1&lt;br /&gt;
	while x % 1 ~= 0 or y % 1 ~= 0 do&lt;br /&gt;
		x = x * 10&lt;br /&gt;
		y = y * 10&lt;br /&gt;
		multiplier = multiplier * 10&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function euclidean( x, y )&lt;br /&gt;
		return y == 0 and x or euclidean( y, x % y )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return euclidean( x, y ) / multiplier&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function LCM( x, y )	-- get Least Common Multiple (LCM)&lt;br /&gt;
	-- Test&lt;br /&gt;
	local GCD = GCD( x, y )&lt;br /&gt;
	if not GCD then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return x * y / GCD&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Start of Frac: Fraction Library&lt;br /&gt;
local fracMetatable = {&lt;br /&gt;
	__index    = Frac,&lt;br /&gt;
	__add      = function ( fraction1, fraction2 ) return Frac.add( fraction1, fraction2 )      end,&lt;br /&gt;
	__sub      = function ( fraction1, fraction2 ) return Frac.sub( fraction1, fraction2 )      end,&lt;br /&gt;
	__mul      = function ( fraction1, fraction2 ) return Frac.mul( fraction1, fraction2 )      end,&lt;br /&gt;
	__div      = function ( fraction1, fraction2 ) return Frac.div( fraction1, fraction2 )      end,&lt;br /&gt;
	__pow      = function ( fraction, n )          return Frac.pow( fraction, n )               end,&lt;br /&gt;
	__unm      = function ( fraction )             return Frac.neg( fraction )                  end,&lt;br /&gt;
	__eq       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) == 0 end,&lt;br /&gt;
	__lt       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) &amp;lt; 0  end,&lt;br /&gt;
	__le       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) &amp;lt;= 0 end,&lt;br /&gt;
	__tostring = function ( fraction )             return Frac.display( fraction )              end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Tests&lt;br /&gt;
function Frac.isFrac( fraction )	-- Check if it is a valid fraction&lt;br /&gt;
	return not ( type( fraction ) ~= &#039;table&#039; or not fraction.numerator or not fraction.denominator or fraction.denominator &amp;lt;= 0 or fraction.numerator % 1 ~= 0 or fraction.denominator % 1 ~= 0 )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Create a fraction directly&lt;br /&gt;
function Frac.new( numerator, denominator )&lt;br /&gt;
	if type( numerator ) ~= &#039;number&#039; or denominator and ( type( denominator ) ~= &#039;number&#039; or denominator == 0 ) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local fraction = denominator and ( denominator &amp;lt; 0 and { numerator = - numerator, denominator = - denominator } or { numerator = numerator, denominator = denominator } ) or Frac.fromDec( numerator )&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	setmetatable( fraction, fracMetatable )&lt;br /&gt;
	return fraction&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.fromDec( decimal )	-- Convert decimal to fraction&lt;br /&gt;
	if type( decimal ) ~= &#039;number&#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local numerator = decimal&lt;br /&gt;
	local denominator = 1&lt;br /&gt;
	while #tostring(numerator % 1) ~= 1 do&lt;br /&gt;
		numerator = numerator * 10&lt;br /&gt;
		denominator = denominator * 10&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.reduce( Frac.new( math.floor(numerator + 0.5), denominator ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.toDec( fraction )	-- Convert fraction to decimal&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return fraction.numerator / fraction.denominator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Basic calculations&lt;br /&gt;
function Frac.neg( fraction )	-- Take the negative fraction&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( - fraction.numerator, fraction.denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.inv( fraction )	-- Take the inversed fraction&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if fraction.numerator == 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ( fraction.numerator &amp;lt; 0 ) and Frac.new( - fraction.denominator, - fraction.numerator ) or Frac.new( fraction.denominator, fraction.numerator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.mul( fraction1, fraction2 )	-- Fractions multiplication&lt;br /&gt;
	fraction1 = Frac.isFrac( fraction1 ) and fraction1 or Frac.new( fraction1 )&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	if Frac.isFrac( fraction1 ) == false or Frac.isFrac( fraction2 ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( fraction1.numerator * fraction2.numerator, fraction1.denominator * fraction2.denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.div( fraction1, fraction2 )	-- Fractions division&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	return Frac.mul( fraction1, Frac.inv( fraction2 ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.pow( fraction, n )	-- Fractions exponentiation&lt;br /&gt;
	if Frac.isFrac( fraction ) == false or n % 1 ~= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ( n &amp;lt; 0 ) and Frac.new( fraction.denominator ^ ( - n ), fraction.numerator ^ ( -n ) ) or Frac.new( fraction.numerator ^ n, fraction.denominator ^ n )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Advanced calculation&lt;br /&gt;
function Frac.expand( fraction, newDenominator )	-- Fractions expansion&lt;br /&gt;
	if Frac.isFrac( fraction ) == false or type( newDenominator ) ~= &#039;number&#039; or ( type( newDenominator ) == &#039;number&#039; and newDenominator % 1 ~= 0 ) or newDenominator &amp;lt;= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local newNumerator = fraction.numerator * newDenominator / fraction.denominator&lt;br /&gt;
	if newNumerator % 1 ~= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( newNumerator, newDenominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.reduce( fraction )	-- Fractions reduction (to simplest)&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.expand( fraction, fraction.denominator / GCD( fraction.denominator, fraction.numerator ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.common( fractionList )	-- Get fractions with the common denominator&lt;br /&gt;
	if type( fractionList ) ~= &#039;table&#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local candidates = {}&lt;br /&gt;
	local denominators = {}&lt;br /&gt;
	for _, fraction in pairs( fractionList ) do&lt;br /&gt;
		if Frac.isFrac( fraction ) == false then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( candidates, fraction )&lt;br /&gt;
			table.insert( denominators, fraction.denominator )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if #candidates == 1 then&lt;br /&gt;
		return candidates&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local lcm = 1&lt;br /&gt;
	for _, denominator in pairs( denominators ) do&lt;br /&gt;
		lcm = LCM( denominator, lcm )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local results = {}&lt;br /&gt;
	for _, fraction in pairs( candidates ) do&lt;br /&gt;
		table.insert( results, Frac.expand( fraction, lcm ) )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return results&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Basic calculations, with dependencies&lt;br /&gt;
function Frac.add( fraction1, fraction2 )	-- Fractions addition&lt;br /&gt;
	fraction1 = Frac.isFrac( fraction1 ) and fraction1 or Frac.new( fraction1 )&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	if Frac.isFrac( fraction1 ) == false or Frac.isFrac( fraction2 ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local fractions = Frac.common{ fraction1, fraction2 }&lt;br /&gt;
	return Frac.new( fractions[ 1 ].numerator + fractions[ 2 ].numerator, fractions[ 1 ].denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.sub( fraction1, fraction2 )	-- Fractions subtraction&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	return Frac.add( fraction1, Frac.neg( fraction2 ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.cmp( fraction1, fraction2 )	-- Compare fractions&lt;br /&gt;
	return Frac.sub( fraction1, fraction2 ).numerator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Formattings to human readable&lt;br /&gt;
function Frac.display( fraction, isReduced, isMixed )	-- Convert fractions to human-readable style&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return &#039;&#039; &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if fraction.numerator == 0 then&lt;br /&gt;
		return &#039;0&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local prefix = &#039;&#039;&lt;br /&gt;
	if fraction.numerator &amp;lt; 0 then&lt;br /&gt;
		prefix = prefix .. &#039;-&#039;&lt;br /&gt;
		fraction = Frac.neg( fraction )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if isReduced then&lt;br /&gt;
		fraction = Frac.reduce( fraction )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local numerator = fraction.numerator&lt;br /&gt;
	local denominator = fraction.denominator&lt;br /&gt;
	if denominator == 1 then&lt;br /&gt;
		return prefix .. tostring( numerator )&lt;br /&gt;
	end&lt;br /&gt;
	if numerator == denominator then&lt;br /&gt;
		return prefix .. &#039;1&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if isMixed and numerator &amp;gt; denominator then&lt;br /&gt;
		prefix = prefix .. math.floor( numerator / denominator )&lt;br /&gt;
		numerator = numerator % denominator&lt;br /&gt;
		if numerator == 0 then&lt;br /&gt;
			return prefix&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return string.format( &#039;%s&amp;lt;sup&amp;gt;%s&amp;lt;/sup&amp;gt;&amp;amp;frasl;&amp;lt;sub&amp;gt;%s&amp;lt;/sub&amp;gt;&#039;, prefix, numerator, denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local Distr = {}&lt;br /&gt;
Distr.mt = {}&lt;br /&gt;
function Distr.mt.__index( t, k )&lt;br /&gt;
	if type( k ) == &#039;number&#039; then return Frac.new( 0 ) end&lt;br /&gt;
	return Distr[ k ]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.mt.__newindex( t, k, v )&lt;br /&gt;
	v = Frac.isFrac( v ) and v or Frac.new( v )&lt;br /&gt;
	if type( k ) ~= &#039;number&#039; or v == nil then error() end&lt;br /&gt;
	if v == Frac.new( 0 ) then return end&lt;br /&gt;
	return rawset( t, k, v )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.new( t )&lt;br /&gt;
	t = t or {}&lt;br /&gt;
	local distribution = {}&lt;br /&gt;
	setmetatable( distribution, Distr.mt )&lt;br /&gt;
	for k, v in pairs( t ) do&lt;br /&gt;
		distribution[ k ] = v&lt;br /&gt;
	end&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.shift( distribution, s )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		newDistribution[ i + s ] = v&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.limitRange( distribution, min, max )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		if max and i &amp;gt;= max then&lt;br /&gt;
			newDistribution[ max ] = newDistribution[ max ] + v&lt;br /&gt;
		elseif min and i &amp;lt;= min then&lt;br /&gt;
			newDistribution[ min ] = newDistribution[ min ] + v&lt;br /&gt;
		else&lt;br /&gt;
			newDistribution[ i ] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.add( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = distribution1:new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution[ i ] = newDistribution[ i ] + v&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.multiply( distribution, x )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		newDistribution[ i ] = v * x&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Distr.expectation( distribution )&lt;br /&gt;
	local expectation = Frac.new( 0 )&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		expectation = expectation + v * i&lt;br /&gt;
	end&lt;br /&gt;
	return expectation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Distr.times( distribution, n )&lt;br /&gt;
	local newDistribution = Distr.new({[0] = 1})&lt;br /&gt;
	for i = 1, n do&lt;br /&gt;
		newDistribution = newDistribution:addIncrease( distribution )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.addIncrease( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution = newDistribution:add( distribution1:shift( i ):multiply( v ) )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.rolls( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution = newDistribution:add( distribution1:times( i ):multiply( v ) )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.getUniform( min, max )&lt;br /&gt;
	local value = Frac.new( 1, max - min + 1 )&lt;br /&gt;
	local distribution = Distr.new()&lt;br /&gt;
	for i = min, max do&lt;br /&gt;
		distribution[ i ] = value&lt;br /&gt;
	end&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.getLootingIncrease( level, min, max )&lt;br /&gt;
	min = min or 0&lt;br /&gt;
	max = max or min + 1&lt;br /&gt;
	min = min * level&lt;br /&gt;
	max = max * level&lt;br /&gt;
	if max - min &amp;lt; 2 then&lt;br /&gt;
		return Distr.getUniform( min, max )&lt;br /&gt;
	end&lt;br /&gt;
	local distribution = Distr.new()&lt;br /&gt;
	local value = Frac.new( 1, max - min )&lt;br /&gt;
	for i = min, max do&lt;br /&gt;
		distribution[ i ] = value&lt;br /&gt;
	end&lt;br /&gt;
	distribution[ min ] = value / 2&lt;br /&gt;
	distribution[ max ] = value / 2&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.addLootingIncrease( distribution1, distribution2, edition )&lt;br /&gt;
	local base = distribution1:limitRange(0, nil)&lt;br /&gt;
	local backup = base[ 0 ]&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		base[ 0 ] = 0 -- MCPE-35307: Looting doesn&#039;t work when the mob drops nothing&lt;br /&gt;
	end&lt;br /&gt;
	local newDistribution = base:addIncrease(distribution2)&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		newDistribution[ 0 ] = newDistribution[ 0 ] + backup&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function calculateDistributions( args, edition )&lt;br /&gt;
	local function parseRange(str)&lt;br /&gt;
		local n = tonumber(str)&lt;br /&gt;
		if n then return {min = n, max = n} end&lt;br /&gt;
		local min, max = str:match(&#039;^%s*(%-?%d+)%s*%-%s*(%-?%d+)%s*$&#039;)&lt;br /&gt;
		min = tonumber(min)&lt;br /&gt;
		max = tonumber(max)&lt;br /&gt;
		if min and max and min &amp;lt;= max then return {min = min, max = max} end&lt;br /&gt;
		error(string.format(&amp;quot;&#039;%s&#039; isn&#039;t a range!&amp;quot;, str))&lt;br /&gt;
	end&lt;br /&gt;
	local function parseProbability(str)&lt;br /&gt;
		local n = Frac.fromDec(tonumber(str)) or Frac.div(tonumber(str:match(&#039;(.*)%%%s*$&#039;)), 100)&lt;br /&gt;
		if n then return n end&lt;br /&gt;
		local numerator, denominator = str:match(&#039;^%s*(%-?%d+)%s*/%s*(%-?%d+)%s*$&#039;)&lt;br /&gt;
		numerator = tonumber(numerator)&lt;br /&gt;
		denominator = tonumber(denominator)&lt;br /&gt;
		local frac = Frac.new(numerator, denominator)&lt;br /&gt;
		if frac then return frac end&lt;br /&gt;
		error(string.format(&amp;quot;&#039;%s&#039; isn&#039;t a probability!&amp;quot;, str))&lt;br /&gt;
	end&lt;br /&gt;
	local quantity = parseRange(args.quantity or 1)&lt;br /&gt;
	local lootingquantity = parseRange(args.lootingquantity or 0)&lt;br /&gt;
	local dropchance = parseProbability(args.dropchance or 1)&lt;br /&gt;
	local lootingchance = parseProbability(args.lootingchance or 0)&lt;br /&gt;
	local multiplychance = parseProbability(args.multiplychance or 1)&lt;br /&gt;
	local rolls = parseRange(args.rolls or 1)&lt;br /&gt;
	local limit = tonumber(args.limit)&lt;br /&gt;
&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		limit = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local independent = {}&lt;br /&gt;
	for _, sub in ipairs(args.independent or {}) do&lt;br /&gt;
		table.insert(independent, calculateDistributions(sub, edition))&lt;br /&gt;
	end&lt;br /&gt;
	local mutuallyexclusive = {}&lt;br /&gt;
	for _, sub in ipairs(args.mutuallyexclusive or {}) do&lt;br /&gt;
		table.insert(mutuallyexclusive, calculateDistributions(sub, edition))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local distributions = {}&lt;br /&gt;
	for level = 0, 3 do&lt;br /&gt;
		local lootingIncrease = Distr.getLootingIncrease(level, lootingquantity.min, lootingquantity.max)&lt;br /&gt;
		local chance = (dropchance + lootingchance * level) * multiplychance&lt;br /&gt;
		local distribution = Distr.getUniform(quantity.min, quantity.max)&lt;br /&gt;
			:addLootingIncrease(lootingIncrease, edition)&lt;br /&gt;
			:rolls(Distr.new{[0] = 1 - chance, [1] = chance})&lt;br /&gt;
			:limitRange(0, limit)&lt;br /&gt;
			:rolls(Distr.getUniform(rolls.min, rolls.max))&lt;br /&gt;
		for _, sub in ipairs(independent) do&lt;br /&gt;
			distribution = distribution:addIncrease(sub[level])&lt;br /&gt;
		end&lt;br /&gt;
		for _, sub in ipairs(mutuallyexclusive) do&lt;br /&gt;
			local nodropchance1 = distribution[0]&lt;br /&gt;
			local nodropchance2 = sub[level][0]&lt;br /&gt;
			distribution = distribution:add(sub[level])&lt;br /&gt;
			distribution[0] = nodropchance1 + nodropchance2 - Frac.new(1)&lt;br /&gt;
		end&lt;br /&gt;
		distributions[level] = distribution&lt;br /&gt;
	end&lt;br /&gt;
	return distributions&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getImageAndLink(args, mode)&lt;br /&gt;
	local link = args.link or args.name&lt;br /&gt;
	local image = require([[Module:SpriteFile]]).sprite{&lt;br /&gt;
		args.image or args.name,&lt;br /&gt;
		name = args.spritetype or i18n.imageSprite[mode],&lt;br /&gt;
		link = link,&lt;br /&gt;
		size = 32,&lt;br /&gt;
		align = &#039;middle&#039;,&lt;br /&gt;
		keepcase = mode == &#039;item&#039;&lt;br /&gt;
	}&lt;br /&gt;
	local displayname = args.displayname or args.name&lt;br /&gt;
	local linktext = string.format(&#039;[[%s|%s]]&#039;, link, displayname)&lt;br /&gt;
	return image, linktext&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getDropData(args, edition)&lt;br /&gt;
	local data = {}&lt;br /&gt;
	for level, distribution in pairs(calculateDistributions(args, edition)) do&lt;br /&gt;
		local quantity = {}&lt;br /&gt;
		for k, v in pairs(distribution) do&lt;br /&gt;
			if v ~= Frac.new(0) then table.insert(quantity, k) end&lt;br /&gt;
		end&lt;br /&gt;
		table.sort(quantity)&lt;br /&gt;
		local min = quantity[1]&lt;br /&gt;
		local max = quantity[#quantity]&lt;br /&gt;
		local from = min&lt;br /&gt;
		local to&lt;br /&gt;
		local quantitytext = &#039;&#039;&lt;br /&gt;
		local function range()&lt;br /&gt;
			quantitytext = quantitytext .. (from == min and &#039;&#039; or &#039; / &#039;)&lt;br /&gt;
				.. (from == to and to or (from .. &#039;&amp;amp;ndash;&#039; .. to))&lt;br /&gt;
		end&lt;br /&gt;
		for _, num in ipairs(quantity) do&lt;br /&gt;
			if to and to ~= num - 1 then&lt;br /&gt;
				range()&lt;br /&gt;
				from = num&lt;br /&gt;
			end&lt;br /&gt;
			to = num&lt;br /&gt;
		end&lt;br /&gt;
		range()&lt;br /&gt;
		data[level] = {&lt;br /&gt;
			distribution = distribution,&lt;br /&gt;
			average = distribution:expectation():reduce(),&lt;br /&gt;
			dropchance = (1 - distribution[0]):reduce(),&lt;br /&gt;
			min = min,&lt;br /&gt;
			max = max,&lt;br /&gt;
			quantitytext = quantitytext&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function linesToDatas(lines, notes, edition)&lt;br /&gt;
	local datas = {}&lt;br /&gt;
	for _, line in ipairs(lines) do&lt;br /&gt;
		local args = mw.text.jsonDecode(line)&lt;br /&gt;
		local data = { name = args.name }&lt;br /&gt;
		data.image, data.linktext = getImageAndLink(args, &#039;item&#039;)&lt;br /&gt;
		if edition ~= &#039;bedrock&#039; and args.edition ~= &#039;bedrock&#039; then&lt;br /&gt;
			data.java = getDropData(args, &#039;java&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if edition ~= &#039;java&#039; and args.edition ~= &#039;java&#039; then&lt;br /&gt;
			data.bedrock = getDropData(args, &#039;bedrock&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local notenames = args.notes and mw.text.split(args.notes, &#039;,&#039;) or {}&lt;br /&gt;
		data.notes = {}&lt;br /&gt;
		for _, name in ipairs(notenames) do&lt;br /&gt;
			table.insert(data.notes, notes[name])&lt;br /&gt;
		end&lt;br /&gt;
		table.insert(datas, data)&lt;br /&gt;
	end&lt;br /&gt;
	return datas&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createOverviewTable(format, datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;12&#039;):wikitext(i18n.headerOverview):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local info = data[edition][level]&lt;br /&gt;
				row:tag(&#039;td&#039;):css(&#039;text-wrap-mode&#039;, &#039;nowrap&#039;):wikitext(info.quantitytext):done()&lt;br /&gt;
				if format == &#039;decimal&#039; then&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(string.format(&#039;%.2f%%&#039;, Frac.toDec(info.dropchance) * 100)):done()&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(string.format(&#039;%.2f&#039;, Frac.toDec(info.average))):done()&lt;br /&gt;
				else&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(Frac.display(info.dropchance)):done()&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(Frac.display(info.average)):done()&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createDistributionsTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerDropAmount):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;4&#039;):wikitext(i18n.headerDistribution):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local min = math.huge&lt;br /&gt;
			local max = -math.huge&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				min = math.min(min, data[edition][level].min)&lt;br /&gt;
				max = math.max(max, data[edition][level].max)&lt;br /&gt;
			end&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):attr(&#039;rowspan&#039;, max - min + 2):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):attr(&#039;rowspan&#039;, max - min + 2):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for drops = min, max do&lt;br /&gt;
				row:tag(&#039;td&#039;):wikitext(tostring(drops)):done()&lt;br /&gt;
				for level = 0, 3 do&lt;br /&gt;
					local probability = data[edition][level].distribution[drops] or Frac.new(0)&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(&lt;br /&gt;
						probability == Frac.new(0) and &#039;0&#039; or&lt;br /&gt;
						string.format(&#039;%s (%.2f%%)&#039;, Frac.display(probability, true), Frac.toDec(probability) * 100)&lt;br /&gt;
					):done()&lt;br /&gt;
				end&lt;br /&gt;
				wikitable:node(row)&lt;br /&gt;
				row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
			end&lt;br /&gt;
			row:tag(&#039;th&#039;):wikitext(i18n.headerAverage):done()&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local average = data[edition][level].average&lt;br /&gt;
				row:tag(&#039;th&#039;):wikitext(string.format(&#039;%s (%.2f)&#039;, Frac.display(average), Frac.toDec(average))):done()&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createCalculatorTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;):addClass(&#039;calculator-container&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;2&#039;)&lt;br /&gt;
				:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;Simplecalc label&#039;, args = {&lt;br /&gt;
					label = i18n.headerTotal[mode],&lt;br /&gt;
					[&#039;for&#039;] = &#039;count&#039;&lt;br /&gt;
				}})&lt;br /&gt;
				:done()&lt;br /&gt;
			:tag(&#039;td&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;4&#039;)&lt;br /&gt;
				:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;simplecalc&#039;, args = {&lt;br /&gt;
					type = &#039;number&#039;,&lt;br /&gt;
					id = &#039;count&#039;,&lt;br /&gt;
					min = 0,&lt;br /&gt;
					step = 1,&lt;br /&gt;
					default = 1&lt;br /&gt;
				}})&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;4&#039;):wikitext(i18n.headerExpectation[mode]):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local average = data[edition][level].average&lt;br /&gt;
				if mode == &#039;mob&#039; then&lt;br /&gt;
					average = Frac.inv(average)&lt;br /&gt;
				end&lt;br /&gt;
				row:tag(&#039;td&#039;)&lt;br /&gt;
					:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;simplecalc&#039;, args = {&lt;br /&gt;
						type = &#039;plain&#039;,&lt;br /&gt;
						formula = string.format(&#039;count*(%s/%s)&#039;, average.numerator, average.denominator),&lt;br /&gt;
						decimals = 2,&lt;br /&gt;
						default = string.format(&#039;%.2f&#039;, Frac.toDec(average))&lt;br /&gt;
					}})&lt;br /&gt;
					:done()&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createTabs (datas, mode, edition)&lt;br /&gt;
	local f = mw.getCurrentFrame()&lt;br /&gt;
	local noteTexts = {}&lt;br /&gt;
	for i, data in pairs(datas) do&lt;br /&gt;
		local noteText = &#039;&#039;&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			for _, note in ipairs(data.notes) do&lt;br /&gt;
				local ref = note.name and note or note[edition]&lt;br /&gt;
				if ref then&lt;br /&gt;
					noteText = noteText .. f:extensionTag{&lt;br /&gt;
						name = &#039;ref&#039;,&lt;br /&gt;
						content = ref.content,&lt;br /&gt;
						args = { name = ref.name, group = i18n.refgroup }&lt;br /&gt;
					}&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		noteTexts[i] = noteText&lt;br /&gt;
	end&lt;br /&gt;
	local tabber = f:extensionTag(&#039;tabber&#039;, string.format(&lt;br /&gt;
		&#039;%s=%s|-|%s=%s|-|%s=%s|-|%s=%s&#039;,&lt;br /&gt;
		i18n.tabOverviewDecimal,&lt;br /&gt;
		createOverviewTable(&#039;decimal&#039;, datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabOverviewFraction,&lt;br /&gt;
		createOverviewTable(&#039;fraction&#039;, datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabDistribution,&lt;br /&gt;
		createDistributionsTable(datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabCalculator,&lt;br /&gt;
		createCalculatorTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	)) &lt;br /&gt;
	return require(&#039;Module:TSLoader&#039;).call(i18n.style)&lt;br /&gt;
		.. tostring(mw.html.create(&#039;div&#039;):addClass(&#039;droptable-tabber&#039;):wikitext(tabber))&lt;br /&gt;
		.. tostring(mw.html.create(&#039;div&#039;):addClass(&#039;droptable-references&#039;):wikitext(f:extensionTag{&lt;br /&gt;
			name = &#039;references&#039;,&lt;br /&gt;
			args = { group = i18n.refgroup }&lt;br /&gt;
		}))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getBucketData(args)&lt;br /&gt;
	local name = args.name or args[1] or mw.title.getCurrentTitle().text&lt;br /&gt;
	local data = bucket(i18n.bucket)&lt;br /&gt;
		.select(&#039;json&#039;)&lt;br /&gt;
		.where(&#039;item&#039;, name)&lt;br /&gt;
		.run()&lt;br /&gt;
	local jsons = {}&lt;br /&gt;
	for _, object in ipairs(data) do&lt;br /&gt;
		local jsondata = object[&#039;json&#039;]&lt;br /&gt;
		table.insert(jsons, mw.text.jsonDecode(jsondata, mw.text.JSON_PRESERVE_KEYS))&lt;br /&gt;
	end&lt;br /&gt;
	return jsons&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseNotes(defines)&lt;br /&gt;
	local notes = {&lt;br /&gt;
		burn_only = { name = &#039;burn_only&#039;, content = i18n.noteBurnOnly },&lt;br /&gt;
		burn_or_fire_aspect = { name = &#039;burn_or_fire_aspect&#039;, content = i18n.noteBurnOrFireAspect },&lt;br /&gt;
		not_burn_only = { name = &#039;not_burn_only&#039;, content = i18n.noteNotBurnOnly },&lt;br /&gt;
		not_burn_or_fire_aspect = { name = &#039;not_burn_or_fire_aspect&#039;, content = i18n.noteNotBurnOrFireAspect },&lt;br /&gt;
		player_only = { name = &#039;player_only&#039;, content = i18n.notePlayerOnly },&lt;br /&gt;
		player_or_pet = { name = &#039;player_or_pet&#039;, content = i18n.notePlayerOrPet }&lt;br /&gt;
	}&lt;br /&gt;
	notes.player = { java = notes.player_or_pet, bedrock = notes.player_only }&lt;br /&gt;
	notes.burn = { java = notes.burn_or_fire_aspect, bedrock = notes.burn_only }&lt;br /&gt;
	notes.not_burn = { java = notes.not_burn_or_fire_aspect, bedrock = notes.not_burn_only }&lt;br /&gt;
&lt;br /&gt;
	for _, str in ipairs(defines and mw.text.split(defines, &#039;\n&#039;) or {}) do&lt;br /&gt;
		local key, text = str:match(&#039;^%s*([^=]-)%s*=%s*(.-)%s*$&#039;)&lt;br /&gt;
		if key and text then&lt;br /&gt;
			local name, edition = key:match(&#039;^(.-)%.(.*)$&#039;)&lt;br /&gt;
			if edition then&lt;br /&gt;
				notes[name] = notes[name] or {}&lt;br /&gt;
				local redirect = text:match(&#039;^&amp;gt;%s*(.-)$&#039;)&lt;br /&gt;
				if redirect and notes[redirect].name then&lt;br /&gt;
					notes[name][edition] = notes[redirect]&lt;br /&gt;
				else&lt;br /&gt;
					notes[name][edition] = { name = name, content = text }&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				notes[key] = { name = key, content = text }&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return notes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.line( frame )&lt;br /&gt;
	local args = require( &#039;Module:ProcessArgs&#039; ).norm( frame:getParent().args )&lt;br /&gt;
	for _, name in pairs({&#039;independent&#039;, &#039;mutuallyexclusive&#039;}) do&lt;br /&gt;
		if args[name] then&lt;br /&gt;
			args[name] = mw.text.jsonDecode(&#039;[&#039; .. args[name] .. &#039;]&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.text.jsonEncode(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main( frame )&lt;br /&gt;
	return p._main( frame:getParent().args )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main( args )&lt;br /&gt;
	local notes = parseNotes(args.notes)&lt;br /&gt;
	local edition = args.edition and mw.text.trim(args.edition)&lt;br /&gt;
	local datas = linesToDatas(args, notes, edition)&lt;br /&gt;
	if not args.nosource and mw.title.getCurrentTitle().isContentPage then&lt;br /&gt;
		setBucketData(datas, args)&lt;br /&gt;
	end&lt;br /&gt;
	if edition then&lt;br /&gt;
		return createTabs(datas, &#039;item&#039;, edition)&lt;br /&gt;
	end&lt;br /&gt;
	return i18n.titlejava .. createTabs(datas, &#039;item&#039;, &#039;java&#039;)&lt;br /&gt;
		.. i18n.titlebedrock .. createTabs(datas, &#039;item&#039;, &#039;bedrock&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.source( frame )&lt;br /&gt;
	return p._source( frame:getParent().args )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._source( args )&lt;br /&gt;
	local datas = getBucketData( args )&lt;br /&gt;
	local edition = args.edition and mw.text.trim(args.edition)&lt;br /&gt;
	if edition then&lt;br /&gt;
		return createTabs(datas, &#039;mob&#039;, edition)&lt;br /&gt;
	end&lt;br /&gt;
	return i18n.titlejava .. createTabs(datas, &#039;mob&#039;, &#039;java&#039;)&lt;br /&gt;
		.. i18n.titlebedrock .. createTabs(datas, &#039;mob&#039;, &#039;bedrock&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:DropLine&amp;diff=14094</id>
		<title>Template:DropLine</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:DropLine&amp;diff=14094"/>
		<updated>2026-06-02T02:45:56Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;{{#invoke:DropTable|line}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}} &amp;lt;!-- Put categories/interwikis on the documentation page --&amp;gt;&amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:DropTable|line}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&lt;br /&gt;
&amp;lt;!-- Put categories/interwikis on the documentation page --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Module:DropTable&amp;diff=14093</id>
		<title>Module:DropTable</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Module:DropTable&amp;diff=14093"/>
		<updated>2026-06-02T02:45:11Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;local i18n = { 	imageSprite = { 		item = &amp;#039;Invicon&amp;#039;, 		mob = &amp;#039;EntitySprite&amp;#039; 	}, 	headerThing = { 		item = &amp;#039;Item&amp;#039;, 		mob = &amp;#039;Mob&amp;#039; 	}, 	headerWithoutLooting = &amp;#039;Default&amp;#039;, 	headerLooting1 = &amp;#039;Looting I&amp;#039;, 	headerLooting2 = &amp;#039;Looting II&amp;#039;, 	headerLooting3 = &amp;#039;Looting III&amp;#039;, 	headerOverview = &amp;#039;Quantity / Chance / Average&amp;#039;, 	headerDropAmount = &amp;#039;Amount&amp;#039;, 	headerDistribution = &amp;#039;Probability&amp;#039;, 	headerAverage = &amp;#039;Average&amp;#039;, 	headerTotal = { 		item = &amp;#039;Killed&amp;#039;, 		mob = &amp;#039;Drops&amp;#039; 	}, 	headerExpect...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local i18n = {&lt;br /&gt;
	imageSprite = {&lt;br /&gt;
		item = &#039;Invicon&#039;,&lt;br /&gt;
		mob = &#039;EntitySprite&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerThing = {&lt;br /&gt;
		item = &#039;Item&#039;,&lt;br /&gt;
		mob = &#039;Mob&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerWithoutLooting = &#039;Default&#039;,&lt;br /&gt;
	headerLooting1 = &#039;Looting I&#039;,&lt;br /&gt;
	headerLooting2 = &#039;Looting II&#039;,&lt;br /&gt;
	headerLooting3 = &#039;Looting III&#039;,&lt;br /&gt;
	headerOverview = &#039;Quantity / Chance / Average&#039;,&lt;br /&gt;
	headerDropAmount = &#039;Amount&#039;,&lt;br /&gt;
	headerDistribution = &#039;Probability&#039;,&lt;br /&gt;
	headerAverage = &#039;Average&#039;,&lt;br /&gt;
	headerTotal = {&lt;br /&gt;
		item = &#039;Killed&#039;,&lt;br /&gt;
		mob = &#039;Drops&#039;&lt;br /&gt;
	},&lt;br /&gt;
	headerExpectation = {&lt;br /&gt;
		item = &#039;Expected Drops&#039;,&lt;br /&gt;
		mob = &#039;Expected Number of Kills&#039;&lt;br /&gt;
	},&lt;br /&gt;
	tabOverviewDecimal = &#039;Decimal&#039;,&lt;br /&gt;
	tabOverviewFraction = &#039;Fraction&#039;,&lt;br /&gt;
	tabDistribution = &#039;Distribution&#039;,&lt;br /&gt;
	tabCalculator = &#039;Expectation&#039;,&lt;br /&gt;
	titlejava = &amp;quot;&#039;&#039;[[Java Edition]]&#039;&#039;:&amp;quot;,&lt;br /&gt;
	titlebedrock = &amp;quot;&#039;&#039;[[Bedrock Edition]]&#039;&#039;:&amp;quot;,&lt;br /&gt;
	notePlayerOrPet = &#039;Only when killed by a [[player]] or a tamed [[wolf]].&#039;,&lt;br /&gt;
	notePlayerOnly = &#039;Only when killed by a [[player]].&#039;,&lt;br /&gt;
	noteBurnOrFireAspect = &#039;Only when on fire or killed with a weapon enchanted with [[Fire Aspect]].&#039;,&lt;br /&gt;
	noteBurnOnly = &#039;Only when on fire.&#039;,&lt;br /&gt;
	noteNotBurnOrFireAspect = &amp;quot;Only when &#039;&#039;not&#039;&#039; on fire and &#039;&#039;not&#039;&#039; killed with a weapon enchanted with [[Fire Aspect]].&amp;quot;,&lt;br /&gt;
	noteNotBurnOnly = &amp;quot;Only when &#039;&#039;not&#039;&#039; on fire.&amp;quot;,&lt;br /&gt;
	refgroup = &#039;FN&#039;, -- [[MediaWiki:Cite link label group-FN]]&lt;br /&gt;
	style = &#039;DropTable/styles.css&#039;, -- [[Template:DropTable/styles.css]]&lt;br /&gt;
	bucket = &#039;droptable&#039;, -- [[Bucket:droptable]]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local Frac = {}&lt;br /&gt;
&lt;br /&gt;
-- Defined types:&lt;br /&gt;
-- * frac: { numerator = numerator, denominator = denominator }, used on Frac.*( ..., fraction, ... )&lt;br /&gt;
&lt;br /&gt;
local function GCD( x, y )	-- get Greatest Common Divisor (GCD)&lt;br /&gt;
	-- Test&lt;br /&gt;
	-- gcd( 0, 0 ) = undef&lt;br /&gt;
	if type( x ) ~= &#039;number&#039; or type( y ) ~= &#039;number&#039; or ( x == 0 and y == 0 ) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	x = math.abs( x )&lt;br /&gt;
	y = math.abs( y )&lt;br /&gt;
&lt;br /&gt;
	-- Improve precision&lt;br /&gt;
	local multiplier = 1&lt;br /&gt;
	while x % 1 ~= 0 or y % 1 ~= 0 do&lt;br /&gt;
		x = x * 10&lt;br /&gt;
		y = y * 10&lt;br /&gt;
		multiplier = multiplier * 10&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function euclidean( x, y )&lt;br /&gt;
		return y == 0 and x or euclidean( y, x % y )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return euclidean( x, y ) / multiplier&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function LCM( x, y )	-- get Least Common Multiple (LCM)&lt;br /&gt;
	-- Test&lt;br /&gt;
	local GCD = GCD( x, y )&lt;br /&gt;
	if not GCD then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return x * y / GCD&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Start of Frac: Fraction Library&lt;br /&gt;
local fracMetatable = {&lt;br /&gt;
	__index    = Frac,&lt;br /&gt;
	__add      = function ( fraction1, fraction2 ) return Frac.add( fraction1, fraction2 )      end,&lt;br /&gt;
	__sub      = function ( fraction1, fraction2 ) return Frac.sub( fraction1, fraction2 )      end,&lt;br /&gt;
	__mul      = function ( fraction1, fraction2 ) return Frac.mul( fraction1, fraction2 )      end,&lt;br /&gt;
	__div      = function ( fraction1, fraction2 ) return Frac.div( fraction1, fraction2 )      end,&lt;br /&gt;
	__pow      = function ( fraction, n )          return Frac.pow( fraction, n )               end,&lt;br /&gt;
	__unm      = function ( fraction )             return Frac.neg( fraction )                  end,&lt;br /&gt;
	__eq       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) == 0 end,&lt;br /&gt;
	__lt       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) &amp;lt; 0  end,&lt;br /&gt;
	__le       = function ( fraction1, fraction2 ) return Frac.cmp( fraction1, fraction2 ) &amp;lt;= 0 end,&lt;br /&gt;
	__tostring = function ( fraction )             return Frac.display( fraction )              end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Tests&lt;br /&gt;
function Frac.isFrac( fraction )	-- Check if it is a valid fraction&lt;br /&gt;
	return not ( type( fraction ) ~= &#039;table&#039; or not fraction.numerator or not fraction.denominator or fraction.denominator &amp;lt;= 0 or fraction.numerator % 1 ~= 0 or fraction.denominator % 1 ~= 0 )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Create a fraction directly&lt;br /&gt;
function Frac.new( numerator, denominator )&lt;br /&gt;
	if type( numerator ) ~= &#039;number&#039; or denominator and ( type( denominator ) ~= &#039;number&#039; or denominator == 0 ) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local fraction = denominator and ( denominator &amp;lt; 0 and { numerator = - numerator, denominator = - denominator } or { numerator = numerator, denominator = denominator } ) or Frac.fromDec( numerator )&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	setmetatable( fraction, fracMetatable )&lt;br /&gt;
	return fraction&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.fromDec( decimal )	-- Convert decimal to fraction&lt;br /&gt;
	if type( decimal ) ~= &#039;number&#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local numerator = decimal&lt;br /&gt;
	local denominator = 1&lt;br /&gt;
	while #tostring(numerator % 1) ~= 1 do&lt;br /&gt;
		numerator = numerator * 10&lt;br /&gt;
		denominator = denominator * 10&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.reduce( Frac.new( math.floor(numerator + 0.5), denominator ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.toDec( fraction )	-- Convert fraction to decimal&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return fraction.numerator / fraction.denominator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Basic calculations&lt;br /&gt;
function Frac.neg( fraction )	-- Take the negative fraction&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( - fraction.numerator, fraction.denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.inv( fraction )	-- Take the inversed fraction&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if fraction.numerator == 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ( fraction.numerator &amp;lt; 0 ) and Frac.new( - fraction.denominator, - fraction.numerator ) or Frac.new( fraction.denominator, fraction.numerator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.mul( fraction1, fraction2 )	-- Fractions multiplication&lt;br /&gt;
	fraction1 = Frac.isFrac( fraction1 ) and fraction1 or Frac.new( fraction1 )&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	if Frac.isFrac( fraction1 ) == false or Frac.isFrac( fraction2 ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( fraction1.numerator * fraction2.numerator, fraction1.denominator * fraction2.denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.div( fraction1, fraction2 )	-- Fractions division&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	return Frac.mul( fraction1, Frac.inv( fraction2 ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.pow( fraction, n )	-- Fractions exponentiation&lt;br /&gt;
	if Frac.isFrac( fraction ) == false or n % 1 ~= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ( n &amp;lt; 0 ) and Frac.new( fraction.denominator ^ ( - n ), fraction.numerator ^ ( -n ) ) or Frac.new( fraction.numerator ^ n, fraction.denominator ^ n )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Advanced calculation&lt;br /&gt;
function Frac.expand( fraction, newDenominator )	-- Fractions expansion&lt;br /&gt;
	if Frac.isFrac( fraction ) == false or type( newDenominator ) ~= &#039;number&#039; or ( type( newDenominator ) == &#039;number&#039; and newDenominator % 1 ~= 0 ) or newDenominator &amp;lt;= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local newNumerator = fraction.numerator * newDenominator / fraction.denominator&lt;br /&gt;
	if newNumerator % 1 ~= 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.new( newNumerator, newDenominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.reduce( fraction )	-- Fractions reduction (to simplest)&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return Frac.expand( fraction, fraction.denominator / GCD( fraction.denominator, fraction.numerator ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.common( fractionList )	-- Get fractions with the common denominator&lt;br /&gt;
	if type( fractionList ) ~= &#039;table&#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local candidates = {}&lt;br /&gt;
	local denominators = {}&lt;br /&gt;
	for _, fraction in pairs( fractionList ) do&lt;br /&gt;
		if Frac.isFrac( fraction ) == false then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( candidates, fraction )&lt;br /&gt;
			table.insert( denominators, fraction.denominator )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if #candidates == 1 then&lt;br /&gt;
		return candidates&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local lcm = 1&lt;br /&gt;
	for _, denominator in pairs( denominators ) do&lt;br /&gt;
		lcm = LCM( denominator, lcm )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local results = {}&lt;br /&gt;
	for _, fraction in pairs( candidates ) do&lt;br /&gt;
		table.insert( results, Frac.expand( fraction, lcm ) )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return results&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Basic calculations, with dependencies&lt;br /&gt;
function Frac.add( fraction1, fraction2 )	-- Fractions addition&lt;br /&gt;
	fraction1 = Frac.isFrac( fraction1 ) and fraction1 or Frac.new( fraction1 )&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	if Frac.isFrac( fraction1 ) == false or Frac.isFrac( fraction2 ) == false then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local fractions = Frac.common{ fraction1, fraction2 }&lt;br /&gt;
	return Frac.new( fractions[ 1 ].numerator + fractions[ 2 ].numerator, fractions[ 1 ].denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.sub( fraction1, fraction2 )	-- Fractions subtraction&lt;br /&gt;
	fraction2 = Frac.isFrac( fraction2 ) and fraction2 or Frac.new( fraction2 )&lt;br /&gt;
	return Frac.add( fraction1, Frac.neg( fraction2 ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Frac.cmp( fraction1, fraction2 )	-- Compare fractions&lt;br /&gt;
	return Frac.sub( fraction1, fraction2 ).numerator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Formattings to human readable&lt;br /&gt;
function Frac.display( fraction, isReduced, isMixed )	-- Convert fractions to human-readable style&lt;br /&gt;
	if Frac.isFrac( fraction ) == false then&lt;br /&gt;
		return &#039;&#039; &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if fraction.numerator == 0 then&lt;br /&gt;
		return &#039;0&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local prefix = &#039;&#039;&lt;br /&gt;
	if fraction.numerator &amp;lt; 0 then&lt;br /&gt;
		prefix = prefix .. &#039;-&#039;&lt;br /&gt;
		fraction = Frac.neg( fraction )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if isReduced then&lt;br /&gt;
		fraction = Frac.reduce( fraction )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local numerator = fraction.numerator&lt;br /&gt;
	local denominator = fraction.denominator&lt;br /&gt;
	if denominator == 1 then&lt;br /&gt;
		return prefix .. tostring( numerator )&lt;br /&gt;
	end&lt;br /&gt;
	if numerator == denominator then&lt;br /&gt;
		return prefix .. &#039;1&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if isMixed and numerator &amp;gt; denominator then&lt;br /&gt;
		prefix = prefix .. math.floor( numerator / denominator )&lt;br /&gt;
		numerator = numerator % denominator&lt;br /&gt;
		if numerator == 0 then&lt;br /&gt;
			return prefix&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return string.format( &#039;%s&amp;lt;sup&amp;gt;%s&amp;lt;/sup&amp;gt;&amp;amp;frasl;&amp;lt;sub&amp;gt;%s&amp;lt;/sub&amp;gt;&#039;, prefix, numerator, denominator )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local Distr = {}&lt;br /&gt;
Distr.mt = {}&lt;br /&gt;
function Distr.mt.__index( t, k )&lt;br /&gt;
	if type( k ) == &#039;number&#039; then return Frac.new( 0 ) end&lt;br /&gt;
	return Distr[ k ]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.mt.__newindex( t, k, v )&lt;br /&gt;
	v = Frac.isFrac( v ) and v or Frac.new( v )&lt;br /&gt;
	if type( k ) ~= &#039;number&#039; or v == nil then error() end&lt;br /&gt;
	if v == Frac.new( 0 ) then return end&lt;br /&gt;
	return rawset( t, k, v )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.new( t )&lt;br /&gt;
	t = t or {}&lt;br /&gt;
	local distribution = {}&lt;br /&gt;
	setmetatable( distribution, Distr.mt )&lt;br /&gt;
	for k, v in pairs( t ) do&lt;br /&gt;
		distribution[ k ] = v&lt;br /&gt;
	end&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.shift( distribution, s )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		newDistribution[ i + s ] = v&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.limitRange( distribution, min, max )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		if max and i &amp;gt;= max then&lt;br /&gt;
			newDistribution[ max ] = newDistribution[ max ] + v&lt;br /&gt;
		elseif min and i &amp;lt;= min then&lt;br /&gt;
			newDistribution[ min ] = newDistribution[ min ] + v&lt;br /&gt;
		else&lt;br /&gt;
			newDistribution[ i ] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.add( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = distribution1:new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution[ i ] = newDistribution[ i ] + v&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.multiply( distribution, x )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		newDistribution[ i ] = v * x&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Distr.expectation( distribution )&lt;br /&gt;
	local expectation = Frac.new( 0 )&lt;br /&gt;
	for i, v in pairs( distribution ) do&lt;br /&gt;
		expectation = expectation + v * i&lt;br /&gt;
	end&lt;br /&gt;
	return expectation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Distr.times( distribution, n )&lt;br /&gt;
	local newDistribution = Distr.new({[0] = 1})&lt;br /&gt;
	for i = 1, n do&lt;br /&gt;
		newDistribution = newDistribution:addIncrease( distribution )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.addIncrease( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution = newDistribution:add( distribution1:shift( i ):multiply( v ) )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.rolls( distribution1, distribution2 )&lt;br /&gt;
	local newDistribution = Distr.new()&lt;br /&gt;
	for i, v in pairs( distribution2 ) do&lt;br /&gt;
		newDistribution = newDistribution:add( distribution1:times( i ):multiply( v ) )&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.getUniform( min, max )&lt;br /&gt;
	local value = Frac.new( 1, max - min + 1 )&lt;br /&gt;
	local distribution = Distr.new()&lt;br /&gt;
	for i = min, max do&lt;br /&gt;
		distribution[ i ] = value&lt;br /&gt;
	end&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.getLootingIncrease( level, min, max )&lt;br /&gt;
	min = min or 0&lt;br /&gt;
	max = max or min + 1&lt;br /&gt;
	min = min * level&lt;br /&gt;
	max = max * level&lt;br /&gt;
	if max - min &amp;lt; 2 then&lt;br /&gt;
		return Distr.getUniform( min, max )&lt;br /&gt;
	end&lt;br /&gt;
	local distribution = Distr.new()&lt;br /&gt;
	local value = Frac.new( 1, max - min )&lt;br /&gt;
	for i = min, max do&lt;br /&gt;
		distribution[ i ] = value&lt;br /&gt;
	end&lt;br /&gt;
	distribution[ min ] = value / 2&lt;br /&gt;
	distribution[ max ] = value / 2&lt;br /&gt;
	return distribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Distr.addLootingIncrease( distribution1, distribution2, edition )&lt;br /&gt;
	local base = distribution1:limitRange(0, nil)&lt;br /&gt;
	local backup = base[ 0 ]&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		base[ 0 ] = 0 -- MCPE-35307: Looting doesn&#039;t work when the mob drops nothing&lt;br /&gt;
	end&lt;br /&gt;
	local newDistribution = base:addIncrease(distribution2)&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		newDistribution[ 0 ] = newDistribution[ 0 ] + backup&lt;br /&gt;
	end&lt;br /&gt;
	return newDistribution&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function calculateDistributions( args, edition )&lt;br /&gt;
	local function parseRange(str)&lt;br /&gt;
		local n = tonumber(str)&lt;br /&gt;
		if n then return {min = n, max = n} end&lt;br /&gt;
		local min, max = str:match(&#039;^%s*(%-?%d+)%s*%-%s*(%-?%d+)%s*$&#039;)&lt;br /&gt;
		min = tonumber(min)&lt;br /&gt;
		max = tonumber(max)&lt;br /&gt;
		if min and max and min &amp;lt;= max then return {min = min, max = max} end&lt;br /&gt;
		error(string.format(&amp;quot;&#039;%s&#039; isn&#039;t a range!&amp;quot;, str))&lt;br /&gt;
	end&lt;br /&gt;
	local function parseProbability(str)&lt;br /&gt;
		local n = Frac.fromDec(tonumber(str)) or Frac.div(tonumber(str:match(&#039;(.*)%%%s*$&#039;)), 100)&lt;br /&gt;
		if n then return n end&lt;br /&gt;
		local numerator, denominator = str:match(&#039;^%s*(%-?%d+)%s*/%s*(%-?%d+)%s*$&#039;)&lt;br /&gt;
		numerator = tonumber(numerator)&lt;br /&gt;
		denominator = tonumber(denominator)&lt;br /&gt;
		local frac = Frac.new(numerator, denominator)&lt;br /&gt;
		if frac then return frac end&lt;br /&gt;
		error(string.format(&amp;quot;&#039;%s&#039; isn&#039;t a probability!&amp;quot;, str))&lt;br /&gt;
	end&lt;br /&gt;
	local quantity = parseRange(args.quantity or 1)&lt;br /&gt;
	local lootingquantity = parseRange(args.lootingquantity or 0)&lt;br /&gt;
	local dropchance = parseProbability(args.dropchance or 1)&lt;br /&gt;
	local lootingchance = parseProbability(args.lootingchance or 0)&lt;br /&gt;
	local multiplychance = parseProbability(args.multiplychance or 1)&lt;br /&gt;
	local rolls = parseRange(args.rolls or 1)&lt;br /&gt;
	local limit = tonumber(args.limit)&lt;br /&gt;
&lt;br /&gt;
	if edition == &#039;bedrock&#039; then&lt;br /&gt;
		limit = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local independent = {}&lt;br /&gt;
	for _, sub in ipairs(args.independent or {}) do&lt;br /&gt;
		table.insert(independent, calculateDistributions(sub, edition))&lt;br /&gt;
	end&lt;br /&gt;
	local mutuallyexclusive = {}&lt;br /&gt;
	for _, sub in ipairs(args.mutuallyexclusive or {}) do&lt;br /&gt;
		table.insert(mutuallyexclusive, calculateDistributions(sub, edition))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local distributions = {}&lt;br /&gt;
	for level = 0, 3 do&lt;br /&gt;
		local lootingIncrease = Distr.getLootingIncrease(level, lootingquantity.min, lootingquantity.max)&lt;br /&gt;
		local chance = (dropchance + lootingchance * level) * multiplychance&lt;br /&gt;
		local distribution = Distr.getUniform(quantity.min, quantity.max)&lt;br /&gt;
			:addLootingIncrease(lootingIncrease, edition)&lt;br /&gt;
			:rolls(Distr.new{[0] = 1 - chance, [1] = chance})&lt;br /&gt;
			:limitRange(0, limit)&lt;br /&gt;
			:rolls(Distr.getUniform(rolls.min, rolls.max))&lt;br /&gt;
		for _, sub in ipairs(independent) do&lt;br /&gt;
			distribution = distribution:addIncrease(sub[level])&lt;br /&gt;
		end&lt;br /&gt;
		for _, sub in ipairs(mutuallyexclusive) do&lt;br /&gt;
			local nodropchance1 = distribution[0]&lt;br /&gt;
			local nodropchance2 = sub[level][0]&lt;br /&gt;
			distribution = distribution:add(sub[level])&lt;br /&gt;
			distribution[0] = nodropchance1 + nodropchance2 - Frac.new(1)&lt;br /&gt;
		end&lt;br /&gt;
		distributions[level] = distribution&lt;br /&gt;
	end&lt;br /&gt;
	return distributions&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getImageAndLink(args, mode)&lt;br /&gt;
	local link = args.link or args.name&lt;br /&gt;
	local image = require([[Module:SpriteFile]]).sprite{&lt;br /&gt;
		args.image or args.name,&lt;br /&gt;
		name = args.spritetype or i18n.imageSprite[mode],&lt;br /&gt;
		link = link,&lt;br /&gt;
		size = 32,&lt;br /&gt;
		align = &#039;middle&#039;,&lt;br /&gt;
		keepcase = mode == &#039;item&#039;&lt;br /&gt;
	}&lt;br /&gt;
	local displayname = args.displayname or args.name&lt;br /&gt;
	local linktext = string.format(&#039;[[%s|%s]]&#039;, link, displayname)&lt;br /&gt;
	return image, linktext&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getDropData(args, edition)&lt;br /&gt;
	local data = {}&lt;br /&gt;
	for level, distribution in pairs(calculateDistributions(args, edition)) do&lt;br /&gt;
		local quantity = {}&lt;br /&gt;
		for k, v in pairs(distribution) do&lt;br /&gt;
			if v ~= Frac.new(0) then table.insert(quantity, k) end&lt;br /&gt;
		end&lt;br /&gt;
		table.sort(quantity)&lt;br /&gt;
		local min = quantity[1]&lt;br /&gt;
		local max = quantity[#quantity]&lt;br /&gt;
		local from = min&lt;br /&gt;
		local to&lt;br /&gt;
		local quantitytext = &#039;&#039;&lt;br /&gt;
		local function range()&lt;br /&gt;
			quantitytext = quantitytext .. (from == min and &#039;&#039; or &#039; / &#039;)&lt;br /&gt;
				.. (from == to and to or (from .. &#039;&amp;amp;ndash;&#039; .. to))&lt;br /&gt;
		end&lt;br /&gt;
		for _, num in ipairs(quantity) do&lt;br /&gt;
			if to and to ~= num - 1 then&lt;br /&gt;
				range()&lt;br /&gt;
				from = num&lt;br /&gt;
			end&lt;br /&gt;
			to = num&lt;br /&gt;
		end&lt;br /&gt;
		range()&lt;br /&gt;
		data[level] = {&lt;br /&gt;
			distribution = distribution,&lt;br /&gt;
			average = distribution:expectation():reduce(),&lt;br /&gt;
			dropchance = (1 - distribution[0]):reduce(),&lt;br /&gt;
			min = min,&lt;br /&gt;
			max = max,&lt;br /&gt;
			quantitytext = quantitytext&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function linesToDatas(lines, notes, edition)&lt;br /&gt;
	local datas = {}&lt;br /&gt;
	for _, line in ipairs(lines) do&lt;br /&gt;
		local args = mw.text.jsonDecode(line)&lt;br /&gt;
		local data = { name = args.name }&lt;br /&gt;
		data.image, data.linktext = getImageAndLink(args, &#039;item&#039;)&lt;br /&gt;
		if edition ~= &#039;bedrock&#039; and args.edition ~= &#039;bedrock&#039; then&lt;br /&gt;
			data.java = getDropData(args, &#039;java&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if edition ~= &#039;java&#039; and args.edition ~= &#039;java&#039; then&lt;br /&gt;
			data.bedrock = getDropData(args, &#039;bedrock&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local notenames = args.notes and mw.text.split(args.notes, &#039;,&#039;) or {}&lt;br /&gt;
		data.notes = {}&lt;br /&gt;
		for _, name in ipairs(notenames) do&lt;br /&gt;
			table.insert(data.notes, notes[name])&lt;br /&gt;
		end&lt;br /&gt;
		table.insert(datas, data)&lt;br /&gt;
	end&lt;br /&gt;
	return datas&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createOverviewTable(format, datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;12&#039;):wikitext(i18n.headerOverview):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;3&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local info = data[edition][level]&lt;br /&gt;
				row:tag(&#039;td&#039;):css(&#039;text-wrap-mode&#039;, &#039;nowrap&#039;):wikitext(info.quantitytext):done()&lt;br /&gt;
				if format == &#039;decimal&#039; then&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(string.format(&#039;%.2f%%&#039;, Frac.toDec(info.dropchance) * 100)):done()&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(string.format(&#039;%.2f&#039;, Frac.toDec(info.average))):done()&lt;br /&gt;
				else&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(Frac.display(info.dropchance)):done()&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(Frac.display(info.average)):done()&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createDistributionsTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerDropAmount):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;4&#039;):wikitext(i18n.headerDistribution):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local min = math.huge&lt;br /&gt;
			local max = -math.huge&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				min = math.min(min, data[edition][level].min)&lt;br /&gt;
				max = math.max(max, data[edition][level].max)&lt;br /&gt;
			end&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):attr(&#039;rowspan&#039;, max - min + 2):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):attr(&#039;rowspan&#039;, max - min + 2):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for drops = min, max do&lt;br /&gt;
				row:tag(&#039;td&#039;):wikitext(tostring(drops)):done()&lt;br /&gt;
				for level = 0, 3 do&lt;br /&gt;
					local probability = data[edition][level].distribution[drops] or Frac.new(0)&lt;br /&gt;
					row:tag(&#039;td&#039;):wikitext(&lt;br /&gt;
						probability == Frac.new(0) and &#039;0&#039; or&lt;br /&gt;
						string.format(&#039;%s (%.2f%%)&#039;, Frac.display(probability, true), Frac.toDec(probability) * 100)&lt;br /&gt;
					):done()&lt;br /&gt;
				end&lt;br /&gt;
				wikitable:node(row)&lt;br /&gt;
				row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
			end&lt;br /&gt;
			row:tag(&#039;th&#039;):wikitext(i18n.headerAverage):done()&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local average = data[edition][level].average&lt;br /&gt;
				row:tag(&#039;th&#039;):wikitext(string.format(&#039;%s (%.2f)&#039;, Frac.display(average), Frac.toDec(average))):done()&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createCalculatorTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	local wikitable = mw.html.create(&#039;table&#039;):addClass(&#039;wikitable&#039;):addClass(&#039;calculator-container&#039;)&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;2&#039;)&lt;br /&gt;
				:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;Simplecalc label&#039;, args = {&lt;br /&gt;
					label = i18n.headerTotal[mode],&lt;br /&gt;
					[&#039;for&#039;] = &#039;count&#039;&lt;br /&gt;
				}})&lt;br /&gt;
				:done()&lt;br /&gt;
			:tag(&#039;td&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;4&#039;)&lt;br /&gt;
				:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;simplecalc&#039;, args = {&lt;br /&gt;
					type = &#039;number&#039;,&lt;br /&gt;
					id = &#039;count&#039;,&lt;br /&gt;
					min = 0,&lt;br /&gt;
					step = 1,&lt;br /&gt;
					default = 1&lt;br /&gt;
				}})&lt;br /&gt;
				:done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):attr(&#039;rowspan&#039;, &#039;2&#039;):wikitext(i18n.headerThing[mode]):done()&lt;br /&gt;
			:tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;4&#039;):wikitext(i18n.headerExpectation[mode]):done()&lt;br /&gt;
			:done()&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerWithoutLooting):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting1):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting2):done()&lt;br /&gt;
			:tag(&#039;th&#039;):wikitext(i18n.headerLooting3):done()&lt;br /&gt;
			:done()&lt;br /&gt;
&lt;br /&gt;
	for i, data in ipairs(datas) do&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			local row = mw.html.create(&#039;tr&#039;)&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.image):done()&lt;br /&gt;
				:tag(&#039;td&#039;):wikitext(data.linktext .. noteTexts[i]):done()&lt;br /&gt;
&lt;br /&gt;
			for level = 0, 3 do&lt;br /&gt;
				local average = data[edition][level].average&lt;br /&gt;
				if mode == &#039;mob&#039; then&lt;br /&gt;
					average = Frac.inv(average)&lt;br /&gt;
				end&lt;br /&gt;
				row:tag(&#039;td&#039;)&lt;br /&gt;
					:wikitext(mw.getCurrentFrame():expandTemplate{ title = &#039;simplecalc&#039;, args = {&lt;br /&gt;
						type = &#039;plain&#039;,&lt;br /&gt;
						formula = string.format(&#039;count*(%s/%s)&#039;, average.numerator, average.denominator),&lt;br /&gt;
						decimals = 2,&lt;br /&gt;
						default = string.format(&#039;%.2f&#039;, Frac.toDec(average))&lt;br /&gt;
					}})&lt;br /&gt;
					:done()&lt;br /&gt;
			end&lt;br /&gt;
			wikitable:node(row)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(wikitable)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function createTabs (datas, mode, edition)&lt;br /&gt;
	local f = mw.getCurrentFrame()&lt;br /&gt;
	local noteTexts = {}&lt;br /&gt;
	for i, data in pairs(datas) do&lt;br /&gt;
		local noteText = &#039;&#039;&lt;br /&gt;
		if data[edition] then&lt;br /&gt;
			for _, note in ipairs(data.notes) do&lt;br /&gt;
				local ref = note.name and note or note[edition]&lt;br /&gt;
				if ref then&lt;br /&gt;
					noteText = noteText .. f:extensionTag{&lt;br /&gt;
						name = &#039;ref&#039;,&lt;br /&gt;
						content = ref.content,&lt;br /&gt;
						args = { name = ref.name, group = i18n.refgroup }&lt;br /&gt;
					}&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		noteTexts[i] = noteText&lt;br /&gt;
	end&lt;br /&gt;
	local tabber = f:extensionTag(&#039;tabber&#039;, string.format(&lt;br /&gt;
		&#039;%s=%s|-|%s=%s|-|%s=%s|-|%s=%s&#039;,&lt;br /&gt;
		i18n.tabOverviewDecimal,&lt;br /&gt;
		createOverviewTable(&#039;decimal&#039;, datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabOverviewFraction,&lt;br /&gt;
		createOverviewTable(&#039;fraction&#039;, datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabDistribution,&lt;br /&gt;
		createDistributionsTable(datas, noteTexts, mode, edition),&lt;br /&gt;
		i18n.tabCalculator,&lt;br /&gt;
		createCalculatorTable(datas, noteTexts, mode, edition)&lt;br /&gt;
	)) &lt;br /&gt;
	return require(&#039;Module:TSLoader&#039;).call(i18n.style)&lt;br /&gt;
		.. tostring(mw.html.create(&#039;div&#039;):addClass(&#039;droptable-tabber&#039;):wikitext(tabber))&lt;br /&gt;
		.. tostring(mw.html.create(&#039;div&#039;):addClass(&#039;droptable-references&#039;):wikitext(f:extensionTag{&lt;br /&gt;
			name = &#039;references&#039;,&lt;br /&gt;
			args = { group = i18n.refgroup }&lt;br /&gt;
		}))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function setBucketData(datas, args)&lt;br /&gt;
	args.name = args.name or mw.title.getCurrentTitle().text&lt;br /&gt;
	local image, link = getImageAndLink(args, &#039;mob&#039;)&lt;br /&gt;
	for _, data in ipairs(datas) do&lt;br /&gt;
		local jsonData = mw.text.jsonEncode({&lt;br /&gt;
			name = args.name,&lt;br /&gt;
			image = image,&lt;br /&gt;
			linktext = link,&lt;br /&gt;
			java = data.java,&lt;br /&gt;
			bedrock = data.bedrock,&lt;br /&gt;
			notes = data.notes&lt;br /&gt;
		}, mw.text.JSON_PRESERVE_KEYS)&lt;br /&gt;
&lt;br /&gt;
		local bucketObject = {&lt;br /&gt;
			item = data.name,&lt;br /&gt;
			json = jsonData&lt;br /&gt;
		}&lt;br /&gt;
		bucket(i18n.bucket).put(bucketObject)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getBucketData(args)&lt;br /&gt;
	local name = args.name or args[1] or mw.title.getCurrentTitle().text&lt;br /&gt;
	local data = bucket(i18n.bucket)&lt;br /&gt;
		.select(&#039;json&#039;)&lt;br /&gt;
		.where(&#039;item&#039;, name)&lt;br /&gt;
		.run()&lt;br /&gt;
	local jsons = {}&lt;br /&gt;
	for _, object in ipairs(data) do&lt;br /&gt;
		local jsondata = object[&#039;json&#039;]&lt;br /&gt;
		table.insert(jsons, mw.text.jsonDecode(jsondata, mw.text.JSON_PRESERVE_KEYS))&lt;br /&gt;
	end&lt;br /&gt;
	return jsons&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseNotes(defines)&lt;br /&gt;
	local notes = {&lt;br /&gt;
		burn_only = { name = &#039;burn_only&#039;, content = i18n.noteBurnOnly },&lt;br /&gt;
		burn_or_fire_aspect = { name = &#039;burn_or_fire_aspect&#039;, content = i18n.noteBurnOrFireAspect },&lt;br /&gt;
		not_burn_only = { name = &#039;not_burn_only&#039;, content = i18n.noteNotBurnOnly },&lt;br /&gt;
		not_burn_or_fire_aspect = { name = &#039;not_burn_or_fire_aspect&#039;, content = i18n.noteNotBurnOrFireAspect },&lt;br /&gt;
		player_only = { name = &#039;player_only&#039;, content = i18n.notePlayerOnly },&lt;br /&gt;
		player_or_pet = { name = &#039;player_or_pet&#039;, content = i18n.notePlayerOrPet }&lt;br /&gt;
	}&lt;br /&gt;
	notes.player = { java = notes.player_or_pet, bedrock = notes.player_only }&lt;br /&gt;
	notes.burn = { java = notes.burn_or_fire_aspect, bedrock = notes.burn_only }&lt;br /&gt;
	notes.not_burn = { java = notes.not_burn_or_fire_aspect, bedrock = notes.not_burn_only }&lt;br /&gt;
&lt;br /&gt;
	for _, str in ipairs(defines and mw.text.split(defines, &#039;\n&#039;) or {}) do&lt;br /&gt;
		local key, text = str:match(&#039;^%s*([^=]-)%s*=%s*(.-)%s*$&#039;)&lt;br /&gt;
		if key and text then&lt;br /&gt;
			local name, edition = key:match(&#039;^(.-)%.(.*)$&#039;)&lt;br /&gt;
			if edition then&lt;br /&gt;
				notes[name] = notes[name] or {}&lt;br /&gt;
				local redirect = text:match(&#039;^&amp;gt;%s*(.-)$&#039;)&lt;br /&gt;
				if redirect and notes[redirect].name then&lt;br /&gt;
					notes[name][edition] = notes[redirect]&lt;br /&gt;
				else&lt;br /&gt;
					notes[name][edition] = { name = name, content = text }&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				notes[key] = { name = key, content = text }&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return notes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.line( frame )&lt;br /&gt;
	local args = require( &#039;Module:ProcessArgs&#039; ).norm( frame:getParent().args )&lt;br /&gt;
	for _, name in pairs({&#039;independent&#039;, &#039;mutuallyexclusive&#039;}) do&lt;br /&gt;
		if args[name] then&lt;br /&gt;
			args[name] = mw.text.jsonDecode(&#039;[&#039; .. args[name] .. &#039;]&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.text.jsonEncode(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main( frame )&lt;br /&gt;
	return p._main( frame:getParent().args )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main( args )&lt;br /&gt;
	local notes = parseNotes(args.notes)&lt;br /&gt;
	local edition = args.edition and mw.text.trim(args.edition)&lt;br /&gt;
	local datas = linesToDatas(args, notes, edition)&lt;br /&gt;
	if not args.nosource and mw.title.getCurrentTitle().isContentPage then&lt;br /&gt;
		setBucketData(datas, args)&lt;br /&gt;
	end&lt;br /&gt;
	if edition then&lt;br /&gt;
		return createTabs(datas, &#039;item&#039;, edition)&lt;br /&gt;
	end&lt;br /&gt;
	return i18n.titlejava .. createTabs(datas, &#039;item&#039;, &#039;java&#039;)&lt;br /&gt;
		.. i18n.titlebedrock .. createTabs(datas, &#039;item&#039;, &#039;bedrock&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.source( frame )&lt;br /&gt;
	return p._source( frame:getParent().args )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._source( args )&lt;br /&gt;
	local datas = getBucketData( args )&lt;br /&gt;
	local edition = args.edition and mw.text.trim(args.edition)&lt;br /&gt;
	if edition then&lt;br /&gt;
		return createTabs(datas, &#039;mob&#039;, edition)&lt;br /&gt;
	end&lt;br /&gt;
	return i18n.titlejava .. createTabs(datas, &#039;mob&#039;, &#039;java&#039;)&lt;br /&gt;
		.. i18n.titlebedrock .. createTabs(datas, &#039;mob&#039;, &#039;bedrock&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:DropTable&amp;diff=14092</id>
		<title>Template:DropTable</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:DropTable&amp;diff=14092"/>
		<updated>2026-06-02T02:44:40Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;{{#invoke:DropTable|main}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}} &amp;lt;!-- Put categories/interwikis on the documentation page --&amp;gt;&amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:DropTable|main}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&lt;br /&gt;
&amp;lt;!-- Put categories/interwikis on the documentation page --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=File:Desertification-Scorpion.png&amp;diff=14091</id>
		<title>File:Desertification-Scorpion.png</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=File:Desertification-Scorpion.png&amp;diff=14091"/>
		<updated>2026-06-02T02:32:18Z</updated>

		<summary type="html">&lt;p&gt;Carter57: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Crafting&amp;diff=14090</id>
		<title>Crafting</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Crafting&amp;diff=14090"/>
		<updated>2026-06-02T02:14:57Z</updated>

		<summary type="html">&lt;p&gt;Carter57: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#redirect [https://minecraft.wiki/w/Crafting]&lt;br /&gt;
&lt;br /&gt;
[[Category:Redirect Pages]]&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Crafting&amp;diff=14089</id>
		<title>Crafting</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Crafting&amp;diff=14089"/>
		<updated>2026-06-02T02:14:27Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Fixed redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#redirect [https://minecraft.wiki/w/Crafting]&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:Armorbar/doc&amp;diff=14088</id>
		<title>Template:Armorbar/doc</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:Armorbar/doc&amp;diff=14088"/>
		<updated>2026-06-02T02:12:36Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;{{Documentation header}} {{lua|Iconbar}} This template creates an armor bar.  {| class=&amp;quot;wikitable&amp;quot; ! Parameter ! Function ! Default value |- | {{p|1}} || Integer armor value between 0 and 32. Empty armor = 0, half armor = 1, full armor = 2, etc. || 0 |- | {{p|2}} || Width of each icon in pixels. || 18 |- | {{p|link}} || Page linked when clicking on an icon. || &amp;#039;&amp;#039;None&amp;#039;&amp;#039; |- | {{p|total}} || Total amount of armor points to be shown. || 0 |}  {| class=&amp;quot;wikitable&amp;quot; ! Code ! Re...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Documentation header}}&lt;br /&gt;
{{lua|Iconbar}}&lt;br /&gt;
This template creates an armor bar.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter&lt;br /&gt;
! Function&lt;br /&gt;
! Default value&lt;br /&gt;
|-&lt;br /&gt;
| {{p|1}} || Integer armor value between 0 and 32. Empty armor = 0, half armor = 1, full armor = 2, etc. || 0&lt;br /&gt;
|-&lt;br /&gt;
| {{p|2}} || Width of each icon in pixels. || 18&lt;br /&gt;
|-&lt;br /&gt;
| {{p|link}} || Page linked when clicking on an icon. || &#039;&#039;None&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| {{p|total}} || Total amount of armor points to be shown. || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Code&lt;br /&gt;
! Result&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar}} || {{armorbar}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|0|9px}} || {{armorbar|0|9px}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|1}} || {{armorbar|1}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|2}} || {{armorbar|2}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|5}} || {{armorbar|5}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|5|3=total=20}} || {{armorbar|5|total=20}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|20}} || {{armorbar|20}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|10|9px}} || {{armorbar|10|9px}}&lt;br /&gt;
|-&lt;br /&gt;
| {{t|armorbar|6|45px}} || {{armorbar|6|45px}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
{{Iconbar see also}}&lt;br /&gt;
&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;!-- Template categories/interwiki here --&amp;gt;&lt;br /&gt;
[[Category:Image templates]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- Documentation categories/interwiki here --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:Armorbar&amp;diff=14087</id>
		<title>Template:Armorbar</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:Armorbar&amp;diff=14087"/>
		<updated>2026-06-02T02:12:07Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;{{#invoke: iconbar | bar | full  = Armor (icon).png | size  = {{{2|18}}} | value = {{{1}}} | title  = {{#expr:{{{1|0}}}}} armor point{{#ifeq: {{{1}}} | 2 || s }} | min = {{{total|}}} | link = {{{link|}}} | alt = &amp;amp;#128737; }}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; {{documentation}} &amp;lt;!-- Put categories/interwiki on the documentation page --&amp;gt; &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke: iconbar | bar&lt;br /&gt;
| full  = Armor (icon).png&lt;br /&gt;
| size  = {{{2|18}}}&lt;br /&gt;
| value = {{{1}}}&lt;br /&gt;
| title  = {{#expr:{{{1|0}}}}} armor point{{#ifeq: {{{1}}} | 2 || s }}&lt;br /&gt;
| min = {{{total|}}}&lt;br /&gt;
| link = {{{link|}}}&lt;br /&gt;
| alt = &amp;amp;#128737;&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Put categories/interwiki on the documentation page --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:Armor/doc&amp;diff=14086</id>
		<title>Template:Armor/doc</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:Armor/doc&amp;diff=14086"/>
		<updated>2026-06-02T02:11:29Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;{{Documentation header}}  This template displays armor points and visualizes these with the help of {{tl|Armorbar}}.  For a more compact display, all armor point values above 10 (5 armor points) are replaced by {{Armorbar|2|9px}} × [armor / 2]. {| class=&amp;quot;wikitable&amp;quot; ! Code ! Result |- | &amp;lt;nowiki&amp;gt;{{Armor|0}}&amp;lt;/nowiki&amp;gt; || {{Armor|0}} |- | &amp;lt;nowiki&amp;gt;{{Armor|4}}&amp;lt;/nowiki&amp;gt; || {{Armor|4}} |- | &amp;lt;nowiki&amp;gt;{{Armor|16}}&amp;lt;/nowiki&amp;gt; || {{Armor|16}} |- | &amp;lt;nowiki&amp;gt;{{Armor|20}}&amp;lt;/nowiki&amp;gt; || {{Arm...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Documentation header}}&lt;br /&gt;
&lt;br /&gt;
This template displays armor points and visualizes these with the help of {{tl|Armorbar}}.&lt;br /&gt;
&lt;br /&gt;
For a more compact display, all armor point values above 10 (5 armor points) are replaced by {{Armorbar|2|9px}} × [armor / 2].&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Code&lt;br /&gt;
! Result&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{Armor|0}}&amp;lt;/nowiki&amp;gt; || {{Armor|0}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{Armor|4}}&amp;lt;/nowiki&amp;gt; || {{Armor|4}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{Armor|16}}&amp;lt;/nowiki&amp;gt; || {{Armor|16}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{Armor|20}}&amp;lt;/nowiki&amp;gt; || {{Armor|20}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{Armor|41}}&amp;lt;/nowiki&amp;gt; || {{Armor|41}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:Armor&amp;diff=14085</id>
		<title>Template:Armor</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:Armor&amp;diff=14085"/>
		<updated>2026-06-02T02:11:03Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;{{{1}}}&amp;amp;nbsp;({{armorbar|{{ #ifexpr: {{{1}}} &amp;gt; 10 | 2 | {{{1}}} }}|9px}}{{ #ifexpr: {{{1}}} &amp;gt; 10 | &amp;amp;nbsp;× {{ #expr: {{{1}}} / 2 }} }})&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}}&amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{{1}}}&amp;amp;nbsp;({{armorbar|{{ #ifexpr: {{{1}}} &amp;gt; 10 | 2 | {{{1}}} }}|9px}}{{ #ifexpr: {{{1}}} &amp;gt; 10 | &amp;amp;nbsp;× {{ #expr: {{{1}}} / 2 }} }})&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Crafting&amp;diff=14084</id>
		<title>Crafting</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Crafting&amp;diff=14084"/>
		<updated>2026-06-02T02:03:12Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Redirected page to Https://minecraft.wiki/w/Crafting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#redirect [[https://minecraft.wiki/w/Crafting]]&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Desertification&amp;diff=14083</id>
		<title>Desertification</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Desertification&amp;diff=14083"/>
		<updated>2026-06-02T01:46:50Z</updated>

		<summary type="html">&lt;p&gt;Carter57: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox mod|title=Desertification|image=Desertification_Logo.webp|author=nergizer81|latest_release=0.42.1 (2026-5-20)|initial_release=0.9.1 (2024-8-4)|modloader=&lt;br /&gt;
{{Fabric}}, {{Forge}}, {{NeoForge}}|minecraft_version=Active: 1.21.1, 1.20.1&lt;br /&gt;
&lt;br /&gt;
Available: 1.20.4|modrinth=https://modrinth.com/mod/desertification|curseforge=https://www.curseforge.com/minecraft/mc-mods/desertification}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Desertification&#039;&#039;&#039; is a mod for Fabric, Forge, NeoForge, and Quilt that adds an expanding desert.&lt;br /&gt;
&lt;br /&gt;
== Content ==&lt;br /&gt;
=== Blocks ===&lt;br /&gt;
* {{BlockLink|Weathered Sandstone}}&lt;br /&gt;
** Can be crafted into {{BlockLink|Weathered Sandstone Stairs}},&lt;br /&gt;
** {{BlockLink|Weathered Sandstone Slab}},&lt;br /&gt;
** and {{BlockLink|Weathered Sandstone Wall}}&lt;br /&gt;
* {{BlockLink|Weathered Sandstone Bricks}}&lt;br /&gt;
** Can be crafted into [[File:Desertification Weathered Sandstone Bricks Stairs|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Stairs|Weathered Sandstone Bricks Stairs]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Bricks Slab|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Slab|Weathered Sandstone Bricks Slab]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Bricks Wall|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Wall|Weathered Sandstone Bricks Wall]],&lt;br /&gt;
** and [[File:Desertification Weathered Sandstone Pillar|frameless|32x32px]] [[Desertification:Weathered Sandstone Pillar|Weathered Sandstone Pillar]]&lt;br /&gt;
*** Which can be crafted into [[File:Desertification Polished Weathered Sandstone|frameless|32x32px]] [[Desertification:Polished Weathered Sandstone|Polished Weathered Sandstone]]&lt;br /&gt;
* {{BlockLink|Desert Sand}}&lt;br /&gt;
WIP&lt;br /&gt;
=== Items ===&lt;br /&gt;
WIP&lt;br /&gt;
=== Mobs ===&lt;br /&gt;
* {{EntityLink|Desertification:Scorpion}}&lt;br /&gt;
* {{EntityLink|Desertification:Nameless Construct}}&lt;br /&gt;
* {{EntityLink|Desertification:Glass Skeleton}}&lt;br /&gt;
* {{EntityLink|Desertification:Rolling Cactus}}&lt;br /&gt;
* {{EntityLink|Desertification:Sentient Rift}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Cow Husk}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Pig Husk}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Chicken Husk}}&lt;br /&gt;
&lt;br /&gt;
{{Navboxes/Desertification}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Mods]]&lt;br /&gt;
[[Category:Desertification]]&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:BlockLink/doc&amp;diff=14082</id>
		<title>Template:BlockLink/doc</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:BlockLink/doc&amp;diff=14082"/>
		<updated>2026-06-02T01:42:07Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Removed deprecated documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{documentation header}}&lt;br /&gt;
{{lua|SpriteFile}}&lt;br /&gt;
This templates creates a page link with an associated sprite image on the left side using the format from [[Template:BlockSprite]].&lt;br /&gt;
&lt;br /&gt;
{{Sprite/LinkParameters}}&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Code&lt;br /&gt;
! Result&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{BlockLink|Cobblestone}}&amp;lt;/nowiki&amp;gt; || {{BlockLink|Cobblestone}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{BlockLink|Glass}}&amp;lt;/nowiki&amp;gt; || {{BlockLink|Glass}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{BlockLink|Lava}}&amp;lt;/nowiki&amp;gt; || {{BlockLink|Lava}}&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;{{BlockLink|id=redstone-dust-cross-on|Redstone}}&amp;lt;/nowiki&amp;gt; || {{BlockLink|id=redstone-dust-cross-on|Redstone}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- template categories/interwikis here --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- doc categories/interwikis here --&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Template:BlockSprite&amp;diff=14081</id>
		<title>Template:BlockSprite</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Template:BlockSprite&amp;diff=14081"/>
		<updated>2026-06-02T01:40:03Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;{{#invoke: SpriteFile | sprite | name = BlockSprite }}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; {{documentation}} &amp;lt;!-- Put categories/interwiki on the documentation page --&amp;gt; &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke: SpriteFile | sprite&lt;br /&gt;
| name = BlockSprite&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Put categories/interwiki on the documentation page --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Desertification&amp;diff=14080</id>
		<title>Desertification</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Desertification&amp;diff=14080"/>
		<updated>2026-06-01T06:39:08Z</updated>

		<summary type="html">&lt;p&gt;Carter57: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox mod|title=Desertification|image=Desertification_Logo.webp|author=nergizer81|latest_release=0.42.1 (2026-5-20)|initial_release=0.9.1 (2024-8-4)|modloader=&lt;br /&gt;
{{Fabric}}, {{Forge}}, {{NeoForge}}|minecraft_version=Active: 1.21.1, 1.20.1&lt;br /&gt;
&lt;br /&gt;
Available: 1.20.4|modrinth=https://modrinth.com/mod/desertification|curseforge=https://www.curseforge.com/minecraft/mc-mods/desertification}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Desertification&#039;&#039;&#039; is a mod for Fabric, Forge, NeoForge, and Quilt that adds an expanding desert.&lt;br /&gt;
&lt;br /&gt;
== Content ==&lt;br /&gt;
=== Blocks ===&lt;br /&gt;
* [[File:Desertification Weathered Sandstone.png|frameless|32x32px]] [[Desertification:Weathered Sandstone|Weathered Sandstone]]&lt;br /&gt;
** Can be crafted into [[File:Desertification Weathered Sandstone Stairs|frameless|32x32px]] [[Desertification:Weathered Sandstone Stairs|Weathered Sandstone Stairs]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Slab|frameless|32x32px]] [[Desertification:Weathered Sandstone Slab|Weathered Sandstone Slab]],&lt;br /&gt;
** and [[File:Desertification Weathered Sandstone Wall|frameless|32x32px]] [[Desertification:Weathered Sandstone Wall|Weathered Sandstone Wall]]&lt;br /&gt;
* [[File:Desertification Weathered Sandstone Bricks|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks|Weathered Sandstone Bricks]]&lt;br /&gt;
** Can be crafted into [[File:Desertification Weathered Sandstone Bricks Stairs|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Stairs|Weathered Sandstone Bricks Stairs]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Bricks Slab|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Slab|Weathered Sandstone Bricks Slab]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Bricks Wall|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Wall|Weathered Sandstone Bricks Wall]],&lt;br /&gt;
** and [[File:Desertification Weathered Sandstone Pillar|frameless|32x32px]] [[Desertification:Weathered Sandstone Pillar|Weathered Sandstone Pillar]]&lt;br /&gt;
*** Which can be crafted into [[File:Desertification Polished Weathered Sandstone|frameless|32x32px]] [[Desertification:Polished Weathered Sandstone|Polished Weathered Sandstone]]&lt;br /&gt;
* [[File:Desertification Desert Sand|frameless|32x32px]] [[Desertification:Desert Sand|Desert Sand]]&lt;br /&gt;
WIP&lt;br /&gt;
=== Items ===&lt;br /&gt;
WIP&lt;br /&gt;
=== Mobs ===&lt;br /&gt;
* {{EntityLink|Desertification:Scorpion}}&lt;br /&gt;
* {{EntityLink|Desertification:Nameless Construct}}&lt;br /&gt;
* {{EntityLink|Desertification:Glass Skeleton}}&lt;br /&gt;
* {{EntityLink|Desertification:Rolling Cactus}}&lt;br /&gt;
* {{EntityLink|Desertification:Sentient Rift}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Cow Husk}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Pig Husk}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Chicken Husk}}&lt;br /&gt;
&lt;br /&gt;
{{Navboxes/Desertification}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Mods]]&lt;br /&gt;
[[Category:Desertification]]&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=File:Desertification_Desert_Sand.png&amp;diff=14079</id>
		<title>File:Desertification Desert Sand.png</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=File:Desertification_Desert_Sand.png&amp;diff=14079"/>
		<updated>2026-06-01T06:11:10Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Carter57 uploaded a new version of File:Desertification Desert Sand.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=File:Desertification_Desert_Sand.png&amp;diff=14078</id>
		<title>File:Desertification Desert Sand.png</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=File:Desertification_Desert_Sand.png&amp;diff=14078"/>
		<updated>2026-06-01T06:10:02Z</updated>

		<summary type="html">&lt;p&gt;Carter57: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=Desertification&amp;diff=14077</id>
		<title>Desertification</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=Desertification&amp;diff=14077"/>
		<updated>2026-06-01T04:24:59Z</updated>

		<summary type="html">&lt;p&gt;Carter57: Created page with &amp;quot;{{Infobox mod|title=Desertification|image=Desertification_Logo.webp|author=nergizer81|latest_release=0.42.1 (2026-5-20)|initial_release=0.9.1 (2024-8-4)|modloader= {{Fabric}}, {{Forge}}, {{NeoForge}}|minecraft_version=Active: 1.21.1, 1.20.1  Available: 1.20.4|modrinth=https://modrinth.com/mod/desertification|curseforge=https://www.curseforge.com/minecraft/mc-mods/desertification}}  &amp;#039;&amp;#039;&amp;#039;Desertification&amp;#039;&amp;#039;&amp;#039; is a mod for Fabric, Forge, NeoForge, and Quilt that adds an expandi...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox mod|title=Desertification|image=Desertification_Logo.webp|author=nergizer81|latest_release=0.42.1 (2026-5-20)|initial_release=0.9.1 (2024-8-4)|modloader=&lt;br /&gt;
{{Fabric}}, {{Forge}}, {{NeoForge}}|minecraft_version=Active: 1.21.1, 1.20.1&lt;br /&gt;
&lt;br /&gt;
Available: 1.20.4|modrinth=https://modrinth.com/mod/desertification|curseforge=https://www.curseforge.com/minecraft/mc-mods/desertification}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Desertification&#039;&#039;&#039; is a mod for Fabric, Forge, NeoForge, and Quilt that adds an expanding desert.&lt;br /&gt;
&lt;br /&gt;
== Content ==&lt;br /&gt;
=== Blocks ===&lt;br /&gt;
* [[File:Desertification Weathered Sandstone.png|frameless|32x32px]] [[Desertification:Weathered Sandstone|Weathered Sandstone]]&lt;br /&gt;
** Can be crafted into [[File:Desertification Weathered Sandstone Stairs|frameless|32x32px]] [[Desertification:Weathered Sandstone Stairs|Weathered Sandstone Stairs]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Slab|frameless|32x32px]] [[Desertification:Weathered Sandstone Slab|Weathered Sandstone Slab]],&lt;br /&gt;
** and [[File:Desertification Weathered Sandstone Wall|frameless|32x32px]] [[Desertification:Weathered Sandstone Wall|Weathered Sandstone Wall]]&lt;br /&gt;
* [[File:Desertification Weathered Sandstone Bricks|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks|Weathered Sandstone Bricks]]&lt;br /&gt;
** Can be crafted into [[File:Desertification Weathered Sandstone Bricks Stairs|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Stairs|Weathered Sandstone Bricks Stairs]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Bricks Slab|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Slab|Weathered Sandstone Bricks Slab]],&lt;br /&gt;
** [[File:Desertification Weathered Sandstone Bricks Wall|frameless|32x32px]] [[Desertification:Weathered Sandstone Bricks Wall|Weathered Sandstone Bricks Wall]],&lt;br /&gt;
** and [[File:Desertification Weathered Sandstone Pillar|frameless|32x32px]] [[Desertification:Weathered Sandstone Pillar|Weathered Sandstone Pillar]]&lt;br /&gt;
*** Which can be crafted into [[File:Desertification Polished Weathered Sandstone|frameless|32x32px]] [[Desertification:Polished Weathered Sandstone|Polished Weathered Sandstone]]&lt;br /&gt;
WIP&lt;br /&gt;
=== Items ===&lt;br /&gt;
WIP&lt;br /&gt;
=== Mobs ===&lt;br /&gt;
* {{EntityLink|Desertification:Scorpion}}&lt;br /&gt;
* {{EntityLink|Desertification:Nameless Construct}}&lt;br /&gt;
* {{EntityLink|Desertification:Glass Skeleton}}&lt;br /&gt;
* {{EntityLink|Desertification:Rolling Cactus}}&lt;br /&gt;
* {{EntityLink|Desertification:Sentient Rift}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Cow Husk}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Pig Husk}}&lt;br /&gt;
* {{EntityLink|Desertification:Vengeful Chicken Husk}}&lt;br /&gt;
&lt;br /&gt;
{{Navboxes/Desertification}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Mods]]&lt;br /&gt;
[[Category:Desertification]]&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
	<entry>
		<id>https://modded.wiki/index.php?title=File:Desertification_Logo.webp&amp;diff=14076</id>
		<title>File:Desertification Logo.webp</title>
		<link rel="alternate" type="text/html" href="https://modded.wiki/index.php?title=File:Desertification_Logo.webp&amp;diff=14076"/>
		<updated>2026-06-01T03:41:42Z</updated>

		<summary type="html">&lt;p&gt;Carter57: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carter57</name></author>
	</entry>
</feed>