package nova.microblock; import nova.core.block.Block; import nova.core.block.BlockFactory; import nova.core.block.BlockManager; import nova.core.component.Category; import nova.core.component.misc.Collider; import nova.core.component.misc.FactoryProvider; import nova.core.component.renderer.DynamicRenderer; import nova.core.component.renderer.StaticRenderer; import nova.core.component.transform.BlockTransform; import nova.core.event.BlockEvent; import nova.core.event.bus.EventBus; import nova.core.event.bus.EventListener; import nova.core.event.bus.GlobalEvents; import nova.core.game.ClientManager; import nova.core.item.ItemManager; import nova.core.loader.Loadable; import nova.core.loader.Mod; import nova.core.network.NetworkManager; import nova.internal.core.tick.UpdateTicker; import nova.microblock.common.BlockContainer; import nova.microblock.common.ItemBlockContainer; import nova.microblock.injection.ComponentInjection; import nova.microblock.injection.ComponentInjectionModule; import nova.microblock.injection.component.ContainerCollider; import nova.microblock.injection.component.ContainerDynamicRenderer; import nova.microblock.injection.component.ContainerStaticRenderer; import nova.microblock.injection.prefab.CopyInjector; import nova.microblock.injection.prefab.ForwardInjector; import nova.microblock.micro.Microblock; import nova.microblock.multi.Multiblock; import org.slf4j.Logger; import java.util.HashMap; import java.util.Map; /** * Make sure your mod loads AFTER this mod, if your mod uses microblocks or multiblock. * @author Calclavia */ @Mod(id = NovaMicroblock.MOD_ID, name = "NOVA Microblock", version = NovaMicroblock.VERSION, novaVersion = "0.1.0", modules = { ComponentInjectionModule.class }, priority = 1) public class NovaMicroblock implements Loadable { public static final String MOD_ID = "nova-microblock"; public static final String VERSION = "0.0.1"; public static NovaMicroblock instance; public final ComponentInjection componentInjection; public final ClientManager client; public final NetworkManager network; public final UpdateTicker.SynchronizedTicker ticker; public final ItemManager items; public final BlockManager blocks; public final Logger logger; public final GlobalEvents events; public final Map<String, MicroblockInjectFactory> containedIDToFactory = new HashMap<>(); public final Map<BlockFactory, MicroblockInjectFactory> containedFactoryToFactory = new HashMap<>(); public NovaMicroblock(ComponentInjection componentInjection, ClientManager client, NetworkManager network, UpdateTicker.SynchronizedTicker ticker, ItemManager items, BlockManager blocks, GlobalEvents events, Logger logger) { this.componentInjection = componentInjection; this.client = client; this.network = network; this.ticker = ticker; this.items = items; this.blocks = blocks; this.logger = logger; this.events = events; instance = this; } @Override public void preInit() { NovaMicroblock.instance.network.register(new MicroblockPacket()); componentInjection.register("collider", () -> new ForwardInjector<>(Collider.class, ContainerCollider::new)); componentInjection.register("dynamicRenderer", () -> new ForwardInjector<>(DynamicRenderer.class, ContainerDynamicRenderer::new)); componentInjection.register("staticRenderer", () -> new ForwardInjector<>(StaticRenderer.class, ContainerStaticRenderer::new)); componentInjection.register("blockTransform", () -> new CopyInjector<>(BlockTransform.class)); componentInjection.register("factoryProvider", () -> new CopyInjector<>(FactoryProvider.class)); componentInjection.register("category", () -> new CopyInjector<>(Category.class)); //Replace block registration by sneakily providing our own way to put container blocks instead of the actual block. events.on(BlockEvent.Register.class).withPriority(EventBus.PRIORITY_HIGH).bind(this::blockRegisterEvent); } //TODO: building extra instances is not good private void blockRegisterEvent(BlockEvent.Register evt) { BlockFactory blockFactory = evt.blockFactory; Block dummy = blockFactory.build(); if (dummy.components.has(Microblock.class) || dummy.components.has(Multiblock.class)) { //Sneaky block factory replacement MicroblockInjectFactory microblockInjectFactory = new MicroblockInjectFactory(evt.blockFactory); containedIDToFactory.put(evt.blockFactory.getID(), microblockInjectFactory); containedFactoryToFactory.put(evt.blockFactory, microblockInjectFactory); evt.blockFactory = microblockInjectFactory; evt.cancel(); } } public static class MicroblockInjectFactory extends BlockFactory { public final BlockFactory containedFactory; public MicroblockInjectFactory(BlockFactory containedFactory) { super("blockContainer-" + containedFactory.getID(), BlockContainer::new, evt -> { NovaMicroblock.instance.items.register("blockContainer-" + containedFactory.getID(), () -> new ItemBlockContainer(evt.blockFactory)); } ); this.containedFactory = containedFactory; //Check the contained factory's dummy, and injectToContainer components. BlockContainer dummy = (BlockContainer) build(); //TODO: Changes in MB injection might not work NovaMicroblock.instance.componentInjection.injectToContainer(containedFactory.build(), dummy); } @Override protected void postCreate(EventListener<BlockEvent.Register> postCreate) { super.postCreate(evt -> NovaMicroblock.instance.items.register(getID(), () -> new ItemBlockContainer(evt.blockFactory))); } } }