package info.u_team.u_team_core.util.registry;

import java.util.function.Supplier;

import info.u_team.u_team_core.api.registry.*;
import net.minecraft.block.Block;
import net.minecraft.item.*;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent.Register;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.*;

public class BlockDeferredRegister {
	
	public static BlockDeferredRegister create(String modid) {
		return new BlockDeferredRegister(modid);
	}
	
	private final String modid;
	
	private final DeferredRegister<Block> blocksWithItemBlockProvider;
	
	protected BlockDeferredRegister(String modid) {
		this.modid = modid;
		blocksWithItemBlockProvider = DeferredRegister.create(ForgeRegistries.BLOCKS, modid);
	}
	
	public <B extends Block & IUBlockRegistryType, I extends BlockItem> BlockRegistryObject<B, I> register(String name, Supplier<? extends B> supplier) {
		final RegistryObject<B> block = blocksWithItemBlockProvider.register(name, supplier);
		final RegistryObject<I> item = RegistryObject.of(new ResourceLocation(modid, name), ForgeRegistries.ITEMS);
		
		return new BlockRegistryObject<B, I>(block, item);
	}
	
	public void register(IEventBus bus) {
		blocksWithItemBlockProvider.register(bus);
		bus.addGenericListener(Item.class, this::addItems);
	}
	
	private void addItems(Register<Item> event) {
		final IForgeRegistry<Item> registry = event.getRegistry();
		blocksWithItemBlockProvider.getEntries() //
				.stream() //
				.map(RegistryObject::get) //
				.filter(block -> {
					if (block instanceof IBlockItemProvider) {
						return ((IBlockItemProvider) block).getBlockItem() != null;
					}
					return false;
				}) //
				.forEach(block -> registry.register(((IBlockItemProvider) block).getBlockItem().setRegistryName(block.getRegistryName())));
	}
	
}

@@ -41,16 +41,36 @@
 istry;%0A%0A
+import java.util.*;%0A
 import j
@@ -668,33 +668,33 @@
 %3E blocksWith
-Item
 Block
+Item
 Provider;%0A%09%0A
@@ -691,16 +691,117 @@
 ovider;%0A
+%09private final Map%3CRegistryObject%3C? extends Block%3E, RegistryObject%3C? extends Item%3E%3E blockToItemsMap;%0A
 %09%0A%09prote
@@ -873,33 +873,33 @@
 %09%09blocksWith
-Item
 Block
+Item
 Provider = D
@@ -949,24 +949,61 @@
 KS, modid);%0A
+%09%09blockToItemsMap = new HashMap%3C%3E();%0A
 %09%7D%0A%09%0A%09public
@@ -1186,33 +1186,33 @@
 = blocksWith
-Item
 Block
+Item
 Provider.reg
@@ -1347,16 +1347,55 @@
 MS);%0A%09%09%0A
+%09%09blockToItemsMap.put(block, item);%0A%09%09%0A
 %09%09return
@@ -1491,33 +1491,33 @@
 %09%09blocksWith
-Item
 Block
+Item
 Provider.reg
@@ -1579,32 +1579,64 @@
 addItems);%0A%09%7D%0A%09%0A
+%09@SuppressWarnings(%22unchecked%22)%0A
 %09private void ad
@@ -1731,129 +1731,110 @@
 ();%0A
+%09%09%0A
 %09%09block
-sWithItemBlockProvider.getEntries() //%0A%09%09%09%09.stream() //%0A%09%09%09%09.map(RegistryObject::get) //%0A%09%09%09%09.filter(block -%3E %7B%0A%09%09
+ToItemsMap.forEach((blockObject, itemObject) -%3E %7B%0A%09%09%09final Block block = blockObject.get();%0A
 %09%09%09i
@@ -1879,24 +1879,43 @@
 ) %7B%0A%09%09%09%09
-%09%09return
+final BlockItem blockItem =
  ((IBloc
@@ -1954,135 +1954,41 @@
 em()
- != null;%0A%09%09%09%09%09%7D%0A%09%09%09%09%09return false;%0A%09%09%09%09%7D) //%0A%09%09%09%09.forEach(block -%3E registry.register(((IBlockItemProvider) block).getB
+;%0A%09%09%09%09registry.register(b
 lockItem
 ().s
@@ -1983,18 +1983,16 @@
 lockItem
-()
 .setRegi
@@ -2004,33 +2004,105 @@
 ame(
-block.getRegistryName()))
+itemObject.getId()));%0A%09%09%09%09((RegistryObject%3CItem%3E) itemObject).updateReference(registry);%0A%09%09%09%7D%0A%09%09%7D
 );%0A%09

Update the reference of the item object now. Generics are so strange sometimes ...