<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://forge.gemwire.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tslat</id>
	<title>Forge Community Wiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://forge.gemwire.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tslat"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/Tslat"/>
	<updated>2026-05-01T17:59:33Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2591</id>
		<title>Dynamic Loot Modification</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2591"/>
		<updated>2021-05-09T19:07:36Z</updated>

		<summary type="html">&lt;p&gt;Tslat: /* The global_loot_modifiers.json */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global Loot Modifiers are a data-driven method of handling modification of harvested drops without the need to overwrite dozens to hundreds of vanilla loot tables or to handle effects that would require interactions with another mod's loot tables without knowing what mods may be loaded. Global Loot Modifiers are also stacking, rather than last-load-wins as modifications to loot tables would be.&lt;br /&gt;
&lt;br /&gt;
== Registering a Global Loot Modifier ==&lt;br /&gt;
&lt;br /&gt;
You will need 3 things:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;global_loot_modifiers.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/forge/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will tell Forge about your modifiers and works similar to [[Tags|tags]].&lt;br /&gt;
# A serialized json representing your modifier at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/&amp;lt;modID&amp;gt;/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will contain all of the data about your modification and allows data packs to tweak your effect.&lt;br /&gt;
# A class that extends &amp;lt;code&amp;gt;LootModifier&amp;lt;/code&amp;gt;&lt;br /&gt;
#* The operational code that makes your modifier work and associated serializer.&lt;br /&gt;
&lt;br /&gt;
Finally, the serializer for your operational class is [[Registration|registered]] as any other &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==The global_loot_modifiers.json==&lt;br /&gt;
All you need to add here are the file names of your loot modifiers.&lt;br /&gt;
These are the names of the json files you have made in the loot_modifiers folder, in ResourceLocation format.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;replace&amp;quot;: false,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;global_loot_test:silk_touch_bamboo&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:smelting&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:wheat_harvest&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;replace&amp;lt;/code&amp;gt; causes the cache of modifiers to be cleared fully when this asset loads (mods are loaded in an order that may be specified by a data pack). For modders you will want to use &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; while data pack makers may want to specify their overrides with &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt; is an ''ordered list'' of the modifiers that will be loaded. Any modifier that is not listed will not be loaded and the ones listed are called in the order listed. This is primarily relevant to data pack makers for resolving conflicts between modifiers from separate mods.&lt;br /&gt;
&lt;br /&gt;
== The serialized json ==&lt;br /&gt;
&lt;br /&gt;
This file contains all of the potential variables related to your modifier, including the conditions that must be met prior to modifying any loot as well as any other parameters your modifier might have. Avoid hard-coded values where ever possible so that data pack makers can adjust balance if they wish to.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conditions&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;minecraft:match_tool&amp;quot;,&lt;br /&gt;
      &amp;quot;predicate&amp;quot;: {&lt;br /&gt;
        &amp;quot;item&amp;quot;: &amp;quot;minecraft:shears&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;block_state_property&amp;quot;,&lt;br /&gt;
      &amp;quot;block&amp;quot;:&amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedItem&amp;quot;: &amp;quot;minecraft:wheat_seeds&amp;quot;,&lt;br /&gt;
  &amp;quot;numSeeds&amp;quot;: 3,&lt;br /&gt;
  &amp;quot;replacement&amp;quot;: &amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the modification only happens if the player harvests wheat when using shears (specified by the two &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; which are automatically &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;ed together). The &amp;lt;code&amp;gt;seedsItem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; values are then used to count how many seeds were generated by the vanilla loot table, and if matched, are substituted for an additional &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; item instead. The operation code will be shown below.&lt;br /&gt;
&amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; is the only object needed by the system specification, everything else is the mod maker's data.&lt;br /&gt;
&lt;br /&gt;
== The LootModifier Subclass ==&lt;br /&gt;
&lt;br /&gt;
You will also need a static child class that extends &amp;lt;code&amp;gt;GlobalLootModifierSerializer&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is your LootModifier subclass in order to deserialize your json data file into operational code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private static class WheatSeedsConverterModifier extends LootModifier {&lt;br /&gt;
	private final int numSeedsToConvert;&lt;br /&gt;
	private final Item itemToCheck;&lt;br /&gt;
	private final Item itemReward;&lt;br /&gt;
	public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {&lt;br /&gt;
		super(conditionsIn);&lt;br /&gt;
		numSeedsToConvert = numSeeds;&lt;br /&gt;
		itemToCheck = itemCheck;&lt;br /&gt;
		itemReward = reward;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	@Nonnull&lt;br /&gt;
	@Override&lt;br /&gt;
	public List&amp;lt;ItemStack&amp;gt; doApply(List&amp;lt;ItemStack&amp;gt; generatedLoot, LootContext context) {&lt;br /&gt;
		/*&lt;br /&gt;
		* Additional conditions can be checked, though as much as possible should be parameterized via JSON data.&lt;br /&gt;
		* It is better to write a new ILootCondition implementation than to do things here.&lt;br /&gt;
		*/&lt;br /&gt;
		int numSeeds = 0;&lt;br /&gt;
		for(ItemStack stack : generatedLoot) {&lt;br /&gt;
			if(stack.getItem() == itemToCheck)&lt;br /&gt;
				numSeeds+=stack.getCount();&lt;br /&gt;
		}&lt;br /&gt;
		if(numSeeds &amp;gt;= numSeedsToConvert) {&lt;br /&gt;
			generatedLoot.removeIf(x -&amp;gt; x.getItem() == itemToCheck);&lt;br /&gt;
			generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));&lt;br /&gt;
			numSeeds = numSeeds%numSeedsToConvert;&lt;br /&gt;
			if(numSeeds &amp;gt; 0)&lt;br /&gt;
				generatedLoot.add(new ItemStack(itemToCheck, numSeeds));&lt;br /&gt;
		}&lt;br /&gt;
		return generatedLoot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	private static class Serializer extends GlobalLootModifierSerializer&amp;lt;WheatSeedsConverterModifier&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
		@Override&lt;br /&gt;
		public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {&lt;br /&gt;
			int numSeeds = JSONUtils.getInt(object, &amp;quot;numSeeds&amp;quot;);&lt;br /&gt;
			Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, &amp;quot;seedItem&amp;quot;))));&lt;br /&gt;
			Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, &amp;quot;replacement&amp;quot;)));&lt;br /&gt;
			return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The critical portion is the &amp;lt;code&amp;gt;doApply&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
This method is only called if the &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; specified return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the modder is now able to make the modifications they desire. In this case we can see that the number of &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; meets or exceeds the &amp;lt;code&amp;gt;numSeedsToConvert&amp;lt;/code&amp;gt; before modifying the list by adding an &amp;lt;code&amp;gt;itemReward&amp;lt;/code&amp;gt; and removing any excess &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; stacks, matching the previously mentioned effects: When a wheat block is harvested with shears, if enough seeds are generated as loot, they are converted to additional wheat instead.&lt;br /&gt;
&lt;br /&gt;
Also take note of the &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; method in the serializer. The conditions are already deserialized for you and if you have no other data, simply &amp;lt;code&amp;gt;return new MyModifier(conditionsIn)&amp;lt;/code&amp;gt;. However, the full &amp;lt;code&amp;gt;JsonObject&amp;lt;/code&amp;gt; is available if needed.&lt;br /&gt;
&lt;br /&gt;
Additional [https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java examples] can be found on the Forge Git repository, including silk touch and smelting effects.&lt;/div&gt;</summary>
		<author><name>Tslat</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2590</id>
		<title>Dynamic Loot Modification</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2590"/>
		<updated>2021-05-09T19:07:23Z</updated>

		<summary type="html">&lt;p&gt;Tslat: /* The global_loot_modifiers.json */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global Loot Modifiers are a data-driven method of handling modification of harvested drops without the need to overwrite dozens to hundreds of vanilla loot tables or to handle effects that would require interactions with another mod's loot tables without knowing what mods may be loaded. Global Loot Modifiers are also stacking, rather than last-load-wins as modifications to loot tables would be.&lt;br /&gt;
&lt;br /&gt;
== Registering a Global Loot Modifier ==&lt;br /&gt;
&lt;br /&gt;
You will need 3 things:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;global_loot_modifiers.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/forge/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will tell Forge about your modifiers and works similar to [[Tags|tags]].&lt;br /&gt;
# A serialized json representing your modifier at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/&amp;lt;modID&amp;gt;/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will contain all of the data about your modification and allows data packs to tweak your effect.&lt;br /&gt;
# A class that extends &amp;lt;code&amp;gt;LootModifier&amp;lt;/code&amp;gt;&lt;br /&gt;
#* The operational code that makes your modifier work and associated serializer.&lt;br /&gt;
&lt;br /&gt;
Finally, the serializer for your operational class is [[Registration|registered]] as any other &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==The global_loot_modifiers.json==&lt;br /&gt;
All you need to add here are the file names of your loot modifiers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These are the names of the json files you have made in the loot_modifiers folder, in ResourceLocation format.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;replace&amp;quot;: false,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;global_loot_test:silk_touch_bamboo&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:smelting&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:wheat_harvest&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;replace&amp;lt;/code&amp;gt; causes the cache of modifiers to be cleared fully when this asset loads (mods are loaded in an order that may be specified by a data pack). For modders you will want to use &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; while data pack makers may want to specify their overrides with &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt; is an ''ordered list'' of the modifiers that will be loaded. Any modifier that is not listed will not be loaded and the ones listed are called in the order listed. This is primarily relevant to data pack makers for resolving conflicts between modifiers from separate mods.&lt;br /&gt;
&lt;br /&gt;
== The serialized json ==&lt;br /&gt;
&lt;br /&gt;
This file contains all of the potential variables related to your modifier, including the conditions that must be met prior to modifying any loot as well as any other parameters your modifier might have. Avoid hard-coded values where ever possible so that data pack makers can adjust balance if they wish to.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conditions&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;minecraft:match_tool&amp;quot;,&lt;br /&gt;
      &amp;quot;predicate&amp;quot;: {&lt;br /&gt;
        &amp;quot;item&amp;quot;: &amp;quot;minecraft:shears&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;block_state_property&amp;quot;,&lt;br /&gt;
      &amp;quot;block&amp;quot;:&amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedItem&amp;quot;: &amp;quot;minecraft:wheat_seeds&amp;quot;,&lt;br /&gt;
  &amp;quot;numSeeds&amp;quot;: 3,&lt;br /&gt;
  &amp;quot;replacement&amp;quot;: &amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the modification only happens if the player harvests wheat when using shears (specified by the two &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; which are automatically &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;ed together). The &amp;lt;code&amp;gt;seedsItem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; values are then used to count how many seeds were generated by the vanilla loot table, and if matched, are substituted for an additional &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; item instead. The operation code will be shown below.&lt;br /&gt;
&amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; is the only object needed by the system specification, everything else is the mod maker's data.&lt;br /&gt;
&lt;br /&gt;
== The LootModifier Subclass ==&lt;br /&gt;
&lt;br /&gt;
You will also need a static child class that extends &amp;lt;code&amp;gt;GlobalLootModifierSerializer&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is your LootModifier subclass in order to deserialize your json data file into operational code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private static class WheatSeedsConverterModifier extends LootModifier {&lt;br /&gt;
	private final int numSeedsToConvert;&lt;br /&gt;
	private final Item itemToCheck;&lt;br /&gt;
	private final Item itemReward;&lt;br /&gt;
	public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {&lt;br /&gt;
		super(conditionsIn);&lt;br /&gt;
		numSeedsToConvert = numSeeds;&lt;br /&gt;
		itemToCheck = itemCheck;&lt;br /&gt;
		itemReward = reward;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	@Nonnull&lt;br /&gt;
	@Override&lt;br /&gt;
	public List&amp;lt;ItemStack&amp;gt; doApply(List&amp;lt;ItemStack&amp;gt; generatedLoot, LootContext context) {&lt;br /&gt;
		/*&lt;br /&gt;
		* Additional conditions can be checked, though as much as possible should be parameterized via JSON data.&lt;br /&gt;
		* It is better to write a new ILootCondition implementation than to do things here.&lt;br /&gt;
		*/&lt;br /&gt;
		int numSeeds = 0;&lt;br /&gt;
		for(ItemStack stack : generatedLoot) {&lt;br /&gt;
			if(stack.getItem() == itemToCheck)&lt;br /&gt;
				numSeeds+=stack.getCount();&lt;br /&gt;
		}&lt;br /&gt;
		if(numSeeds &amp;gt;= numSeedsToConvert) {&lt;br /&gt;
			generatedLoot.removeIf(x -&amp;gt; x.getItem() == itemToCheck);&lt;br /&gt;
			generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));&lt;br /&gt;
			numSeeds = numSeeds%numSeedsToConvert;&lt;br /&gt;
			if(numSeeds &amp;gt; 0)&lt;br /&gt;
				generatedLoot.add(new ItemStack(itemToCheck, numSeeds));&lt;br /&gt;
		}&lt;br /&gt;
		return generatedLoot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	private static class Serializer extends GlobalLootModifierSerializer&amp;lt;WheatSeedsConverterModifier&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
		@Override&lt;br /&gt;
		public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {&lt;br /&gt;
			int numSeeds = JSONUtils.getInt(object, &amp;quot;numSeeds&amp;quot;);&lt;br /&gt;
			Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, &amp;quot;seedItem&amp;quot;))));&lt;br /&gt;
			Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, &amp;quot;replacement&amp;quot;)));&lt;br /&gt;
			return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The critical portion is the &amp;lt;code&amp;gt;doApply&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
This method is only called if the &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; specified return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the modder is now able to make the modifications they desire. In this case we can see that the number of &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; meets or exceeds the &amp;lt;code&amp;gt;numSeedsToConvert&amp;lt;/code&amp;gt; before modifying the list by adding an &amp;lt;code&amp;gt;itemReward&amp;lt;/code&amp;gt; and removing any excess &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; stacks, matching the previously mentioned effects: When a wheat block is harvested with shears, if enough seeds are generated as loot, they are converted to additional wheat instead.&lt;br /&gt;
&lt;br /&gt;
Also take note of the &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; method in the serializer. The conditions are already deserialized for you and if you have no other data, simply &amp;lt;code&amp;gt;return new MyModifier(conditionsIn)&amp;lt;/code&amp;gt;. However, the full &amp;lt;code&amp;gt;JsonObject&amp;lt;/code&amp;gt; is available if needed.&lt;br /&gt;
&lt;br /&gt;
Additional [https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java examples] can be found on the Forge Git repository, including silk touch and smelting effects.&lt;/div&gt;</summary>
		<author><name>Tslat</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=DynamicOps&amp;diff=2393</id>
		<title>DynamicOps</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=DynamicOps&amp;diff=2393"/>
		<updated>2021-01-19T08:21:23Z</updated>

		<summary type="html">&lt;p&gt;Tslat: /* Format Conversion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &amp;lt;code&amp;gt;DynamicOps&amp;lt;/code&amp;gt; class is part of mojang's DataFixerUpper serialization library; DynamicOps are used alongside [[codecs]] to convert java objects to a serialized format and back. While Codecs describe how a java object is to be serialized, DynamicOps describe the format the object is to be serialized to.&lt;br /&gt;
&lt;br /&gt;
The DataFixerUpper library includes several DynamicOps for serializing to json; vanilla minecraft also includes a DynamicOps for serializing to minecraft's [[Using_NBT|NBT]] format.&lt;br /&gt;
&lt;br /&gt;
= Builtin DynamicOps =&lt;br /&gt;
&lt;br /&gt;
== JsonOps ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;JsonOps&amp;lt;/code&amp;gt; DynamicOps are used to serialize and deserialize json data. These are instances of &amp;lt;code&amp;gt;DynamicOps&amp;lt;JsonElement&amp;gt;&amp;lt;/code&amp;gt;, meaning that they are used to convert java objects to and from &amp;lt;code&amp;gt;JsonElement&amp;lt;/code&amp;gt; instances. These can used in conjunction with codecs to serialize/deserialize objects from assets and datapacks.&lt;br /&gt;
&lt;br /&gt;
There are two public instances of JsonOps: &amp;lt;code&amp;gt;JsonOps.INSTANCE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;JsonOps.COMPRESSED&amp;lt;/code&amp;gt;. Compressed data is represented as a single string to read/write. However, this is never used within vanilla itself.&lt;br /&gt;
&lt;br /&gt;
== NBTDynamicOps ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NBTDynamicOps.INSTANCE&amp;lt;/code&amp;gt; is an instance of &amp;lt;code&amp;gt;DynamicOps&amp;lt;INBT&amp;gt;&amp;lt;/code&amp;gt;, meaning it is used to convert java objects to and from &amp;lt;code&amp;gt;INBT&amp;lt;/code&amp;gt; instances. This can be used for serializing data into packets to send across networks, as well as serializing persistant data for entities and similar objects.&lt;br /&gt;
&lt;br /&gt;
There is only one public instance of NBTDynamicOps: &amp;lt;code&amp;gt;NBTDynamicOps.INSTANCE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Using DynamicOps =&lt;br /&gt;
&lt;br /&gt;
== Serializing and Deserializing ==&lt;br /&gt;
&lt;br /&gt;
By combining a &amp;lt;code&amp;gt;Codec&amp;lt;SomeJavaType&amp;gt;&amp;lt;/code&amp;gt; with a &amp;lt;code&amp;gt;DynamicOps&amp;lt;SomeSerializedFormat&amp;gt;&amp;lt;/code&amp;gt;, the proper java object can be converted to the serialized form and back. See [[codecs]] for details on this subject.&lt;br /&gt;
&lt;br /&gt;
== Format Conversion ==&lt;br /&gt;
&lt;br /&gt;
By using the &amp;lt;code&amp;gt;DynamicOps#convertTo&amp;lt;/code&amp;gt; instance method with a second DynamicOps instance, data can be converted between two different serialized formats, such as JsonElement to INBT and back.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
// converting INBT to JsonElement&lt;br /&gt;
JsonElement someJsonElement = NBTDynamicOps.INSTANCE.convertTo(JsonOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// converting JsonElement to INBT&lt;br /&gt;
INBT someNBT = JsonOps.INSTANCE.convertTo(NBTDynamicOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on the implementation of the DynamicOps used, this may throw an exception or return an empty object if the two formats are incompatible.&lt;br /&gt;
&lt;br /&gt;
In particular, it is '''not''' safe to convert lists of numbers to NBT in this manner, due to the NBT format's strong typing and the way the NBTDynamicOps attempts to create lists of numbers.&lt;br /&gt;
&lt;br /&gt;
= External Links =&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/DynamicOps.html DynamicOps unofficial javadocs]&lt;/div&gt;</summary>
		<author><name>Tslat</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2366</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2366"/>
		<updated>2021-01-10T22:41:41Z</updated>

		<summary type="html">&lt;p&gt;Tslat: Add final access modifier AT section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Access Transformers are Forge's native way of allowing you to access (read and write) functions that have a lower-than-ideal visibility, and/or removing finality.&lt;br /&gt;
&lt;br /&gt;
== Visibility ==&lt;br /&gt;
&lt;br /&gt;
Here's a quick rundown of the visibility options offered by Java 8:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visible to all classes inside and outside its package&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; visible only to classes inside the package and subclasses&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; visible only to classes inside the package&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; visible only to inside the class&lt;br /&gt;
&lt;br /&gt;
Additionally, there are final variants of each of these, each represented by the phrase &amp;quot;-f&amp;quot; on the end of the access specifier.&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
As Forge is loading, it scans the jar file for the META-INF/accesstransformers.cfg file. if it's found, it is parsed according to the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;NewAccessSpecifier MemberSignature # comment&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A random example to understand the syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public net.minecraft.util.palette.IResizeCallback # makes IResizeCallback public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a valid entry is found on a line, Forge will look into the bytecode of the file where that member is defined, and change its access to whatever you desire it to be.&lt;br /&gt;
&lt;br /&gt;
This startup modification means accessing is O(1) for all accesses after this initial change, which makes it a great option for performance if you're looking at something a lot&lt;br /&gt;
&lt;br /&gt;
=== Removing Finality ===&lt;br /&gt;
Access transformers can also be used to remove the '''final''' keyword on code elements. To do this, append &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; to the access specifier.&lt;br /&gt;
&lt;br /&gt;
An example of this in place:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public-f net.minecraft.util.palette.IResizeCallback # makes IResizeCallback public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You can also use this to ''add'' a final keyword via &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt;. This is never recommended however, and should be avoided at all costs unless absolutely necessary.&lt;br /&gt;
&lt;br /&gt;
== Using Access Transformers in your mod ==&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|You should avoid using ATs if a private variable / function you're looking at has a getter or a setter. Variables are usually private for a reason.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1: Uncomment the access transformer line in your build.gradle&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|600px|frameless]]&lt;br /&gt;
&lt;br /&gt;
Step 2: Create a new file called &amp;quot;accesstransformer.cfg&amp;quot; in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;src/main/resources/META-INF/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Step 3: Refresh the Gradle project. This can be done natively in IDEA and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== When not to use Access Transformers ==&lt;br /&gt;
* Unnecessary access transformations (e.g. using ATs to make something &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; when it's already &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Tslat</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2365</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2365"/>
		<updated>2021-01-10T22:31:17Z</updated>

		<summary type="html">&lt;p&gt;Tslat: /* How It Works */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Access Transformers are Forge's native way of allowing you to access (read &amp;lt;code&amp;gt;and &amp;lt;/code&amp;gt;write) functions that have a lower-than-ideal visibility, and/or removing finality.&lt;br /&gt;
&lt;br /&gt;
== Visibility ==&lt;br /&gt;
&lt;br /&gt;
Here's a quick rundown of the visibility options offered by Java 8:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visible to all classes inside and outside its package&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; visible only to classes inside the package and subclasses&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; visible only to classes inside the package&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; visible only to inside the class&lt;br /&gt;
&lt;br /&gt;
Additionally, there are final variants of each of these, each represented by the phrase &amp;quot;-f&amp;quot; on the end of the access specifier.&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
As Forge is loading, it scans the jar file for the META-INF/accesstransformers.cfg file. if it's found, it is parsed according to the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;NewAccessSpecifier MemberSignature # comment&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A random example to understand the syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public net.minecraft.util.palette.IResizeCallback # makes IResizeCallback public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a valid entry is found on a line, Forge will look into the bytecode of the file where that member is defined, and change its access to whatever you desire it to be.&lt;br /&gt;
&lt;br /&gt;
This startup modification means accessing is O(1) for all accesses after this initial change, which makes it a great option for performance if you're looking at something a lot.&lt;br /&gt;
&lt;br /&gt;
== Using Access Transformers in your mod ==&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|You should avoid using ATs if a private variable / function you're looking at has a getter or a setter. Variables are usually private for a reason.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1: Uncomment the access transformer line in your build.gradle&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|600px|frameless]]&lt;br /&gt;
&lt;br /&gt;
Step 2: Create a new file called &amp;quot;accesstransformer.cfg&amp;quot; in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;src/main/resources/META-INF/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Step 3: Refresh the Gradle project. This can be done natively in IDEA and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== When not to use Access Transformers ==&lt;br /&gt;
* Unnecessary access transformations (e.g. using ATs to make something &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; when it's already &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Tslat</name></author>
	</entry>
</feed>