package com.gtnewhorizons.postea.api;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.annotation.Nonnull;
import net.minecraft.block.Block;
import net.minecraftforge.oredict.OreDictionary;
import com.gtnewhorizons.postea.utility.BlockConversionInfo;
import com.gtnewhorizons.postea.utility.IDRegistry;
import com.gtnewhorizons.postea.utility.MissingMappingHandler;
import com.gtnewhorizons.postea.utility.SimpleTransformationRegistry;
import com.gtnewhorizons.postea.utility.TransformerRegistry;
/**
* Public API used to register block transformers via postea's handler system.
*
* Block transformers are executed after Tile Entity transformers, when chunks being loading into the world.
*/
public abstract class BlockReplacementManager {
// region custom transformer registration
/**
* Adds a custom transformer for a given id.
*
* @apiNote When the transformer function passed to this function returns a null, value Postea will assume that
* the transformer has failed to identify and run the handler on any other handler function registered
* to the given ID.
*
* If you need to perform a simple transformations consider using the following methods instead:
*
{@code
* import net.minecraft.block.Block;
* import net.minecraft.block.material.Material;
* import net.minecraft.nbt.NBTTagCompound;
* import net.minecraft.world.World;
* import net.minecraft.world.chunk.Chunk;
*
* import com.gtnewhorizons.postea.api.BlockAccessCompat;
* import com.gtnewhorizons.postea.api.BlockReplacementManager;
* import com.gtnewhorizons.postea.api.TileEntityReplacementManager;
* import com.gtnewhorizons.postea.utility.BlockInfo;
* import com.gtnewhorizons.postea.utility.PosteaUtilities;
*
* import cpw.mods.fml.common.Mod;
* import cpw.mods.fml.common.event.FMLPostInitializationEvent;
* import cpw.mods.fml.common.event.FMLPreInitializationEvent;
* import cpw.mods.fml.common.registry.GameRegistry;
*
* @Mod(
* modid = "mymod",
* version = "1.0.0",
* name = "Example Mod",
* acceptedMinecraftVersions = "[1.7.10]",
* dependencies = " after:otherMod;")
* @SuppressWarnings("unused")
* public class ExampleMod {
*
* private static int targetBlock1 = -1;
* private static int targetBlock2 = -1;
* private static int targetBlock3 = -1;
*
* private static class MyBlocks {
* public static Block block1;
* public static Block block2;
* public static Block block3;
* public static Block block4;
* public static Block block5;
* public static Block block6;
* }
*
* private static class TestBlock extends Block {
* public TestBlock(String id) {
* super(Material.ground);
* GameRegistry.registerBlock(this, id);
* }
* }
*
* @Mod.EventHandler
* @SuppressWarnings("unused")
* public static void preInit(FMLPreInitializationEvent event) {
* MyBlocks.block1 = new TestBlock("block1");
* MyBlocks.block2 = new TestBlock("block2");
* MyBlocks.block3 = new TestBlock("block3");
* MyBlocks.block4 = new TestBlock("block4");
* MyBlocks.block5 = new TestBlock("block5");
* MyBlocks.block6 = new TestBlock("block6");
* }
*
* @Mod.EventHandler
* @SuppressWarnings("unused")
* public static void postLoad(FMLPostInitializationEvent event) {
* BlockReplacementManager.registerIDResolver("otherMod:block1", i -> targetBlock1 = i);
* BlockReplacementManager.registerIDResolver("otherMod:block2", i -> targetBlock2 = i);
* BlockReplacementManager.registerIDResolver("otherMod:block3", i -> targetBlock3 = i);
* TileEntityReplacementManager.tileEntityTransformer("otherModTE", ExampleMod::transform);
* // If you were to have all of these in one mod,
* // the general recommendation would be to merge the handlers,
* // but let's pretend that these are set up by other mods
* // for the sake of example.
* TileEntityReplacementManager.tileEntityTransformer("otherModTE", ExampleMod::transformOther);
* BlockReplacementManager.addBlockReplacement("otherMod:block1", 0, MyBlocks.block1, 0);
* }
*
* public static BlockInfo transform(NBTTagCompound tag, World world, Chunk chunk) {
* int oldBlock = BlockAccessCompat.getBlockIDAtTE(tag, chunk);
* int x = tag.getInteger("x") & 0xF;
* int y = tag.getInteger("y");
* int z = tag.getInteger("z") & 0xF;
* int meta = chunk.getBlockMetadata(x, y, z);
* Block newBlock;
* String targetType;
* if (oldBlock == targetBlock1) {
* // block transformer executes after TE transformers
* // so we sill need to check for meta 0
* if (meta == 0) return null;
* newBlock = MyBlocks.block2;
* targetType = "stone";
* } else if (oldBlock == targetBlock2) {
* // another mod would be handling the transformation for 0
* if (meta != 1 && meta != 2) return null;
* newBlock = meta == 1 ? MyBlocks.block3 : MyBlocks.block4;
* targetType = "iron";
* } else {
* // Return null to tell postea that you can't handle via this transformer.
* // Maybe another transformer can handle it.
* return null;
* }
* return new BlockInfo(newBlock, 0, originalNBT -> {
* NBTTagCompound newNBT = PosteaUtilities.cleanseNBT("myTE", originalNBT);
* newNBT.setString("type", targetType);
* newNBT.setInteger("level", meta);
* newNBT.setInteger("fuelLevel", originalNBT.getInteger("storage") * 20);
* return newNBT;
* });
* }
*
* public static BlockInfo transformOther(NBTTagCompound tag, World world, Chunk chunk) {
* int oldBlock = BlockAccessCompat.getBlockIDAtTE(tag, chunk);
* int x = tag.getInteger("x") & 0xF;
* int y = tag.getInteger("y");
* int z = tag.getInteger("z") & 0xF;
* int meta = chunk.getBlockMetadata(x, y, z);
* if (oldBlock == targetBlock2) {
* if (meta != 3) return null;
* // that doesn't need to be a TE anymore.
* return new BlockInfo(MyBlocks.block5, 0, null);
* } else if (oldBlock == targetBlock3) {
* // transfer the TE correctly
* return new BlockInfo(MyBlocks.block6, meta, originalNBT -> {
* NBTTagCompound newNBT = PosteaUtilities.cleanseNBT("myOtherTE", originalNBT);
* newNBT.setInteger("remaining", originalNBT.getInteger("storage"));
* return newNBT;
* });
* }
* // can't handle this
* return null;
* }
* }
* }
*
*
* @param originalId The namespaced ID of a block you wish to identify in one of your transformers.
* @param resolver The callback executed to provide the numeric ID of the given namespaced ID.
*/
// spotless:on
@SuppressWarnings("unused")
public static void registerIDResolver(String originalId, Consumer