diff --git a/src/generated/resources/.cache/132ced8588d83c256215f9004a517e67500de5e8 b/src/generated/resources/.cache/132ced8588d83c256215f9004a517e67500de5e8 new file mode 100644 index 0000000..60f2877 --- /dev/null +++ b/src/generated/resources/.cache/132ced8588d83c256215f9004a517e67500de5e8 @@ -0,0 +1,5 @@ +// 1.20.2 2023-12-27T14:38:20.1780825 Ender IO Data (examplemod com.example.examplemod.registry.EnderBlockRegistry@430b5c0e) +c1179f903b7e75f188bc87b191d646264a7c1c10 assets/examplemod/blockstates/example_block.json +d32c5ad4076b1e22be3420304265a566242e4fb7 assets/examplemod/lang/en_us.json +7c88b8231b94199736a42deb3c7c4afaf43ce8c6 assets/examplemod/models/block/example_block.json +dea7c460ab71faf20207d3584b00732bdd44ae43 data/examplemod/loot_tables/blocks/example_block.json diff --git a/src/generated/resources/.cache/ceeb1d80e7df35351cd63f885edb271da6a88fd0 b/src/generated/resources/.cache/ceeb1d80e7df35351cd63f885edb271da6a88fd0 new file mode 100644 index 0000000..138a957 --- /dev/null +++ b/src/generated/resources/.cache/ceeb1d80e7df35351cd63f885edb271da6a88fd0 @@ -0,0 +1,2 @@ +// 1.20.2 2023-12-27T14:38:20.1780825 Ender IO Data (examplemod com.example.examplemod.registry.EnderItemRegistry@155f437a) +608e98bf5926abfd9d441b916410bb804f31f633 assets/examplemod/models/item/example_block.json diff --git a/src/generated/resources/.cache/f974ae965ba85610fe3af49963ed1ddd4a94d07f b/src/generated/resources/.cache/f974ae965ba85610fe3af49963ed1ddd4a94d07f new file mode 100644 index 0000000..b232e81 --- /dev/null +++ b/src/generated/resources/.cache/f974ae965ba85610fe3af49963ed1ddd4a94d07f @@ -0,0 +1,2 @@ +// 1.20.2 2023-12-27T14:38:20.1660732 Ender IO Data (examplemod com.example.examplemod.registry.EnderItemRegistry@7b3ebc30) +af0d8df01e38c368aa227d28d9f4050fedcf032a assets/examplemod/models/item/example_item.json diff --git a/src/generated/resources/assets/examplemod/blockstates/example_block.json b/src/generated/resources/assets/examplemod/blockstates/example_block.json new file mode 100644 index 0000000..a94cb7b --- /dev/null +++ b/src/generated/resources/assets/examplemod/blockstates/example_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "examplemod:block/example_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/examplemod/lang/en_us.json b/src/generated/resources/assets/examplemod/lang/en_us.json new file mode 100644 index 0000000..0ea63ad --- /dev/null +++ b/src/generated/resources/assets/examplemod/lang/en_us.json @@ -0,0 +1,3 @@ +{ + "block.examplemod.example_block": "Example block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/examplemod/models/block/example_block.json b/src/generated/resources/assets/examplemod/models/block/example_block.json new file mode 100644 index 0000000..0626252 --- /dev/null +++ b/src/generated/resources/assets/examplemod/models/block/example_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "examplemod:block/example_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/examplemod/models/item/example_block.json b/src/generated/resources/assets/examplemod/models/item/example_block.json new file mode 100644 index 0000000..f882b09 --- /dev/null +++ b/src/generated/resources/assets/examplemod/models/item/example_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "examplemod:item/example_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/examplemod/models/item/example_item.json b/src/generated/resources/assets/examplemod/models/item/example_item.json new file mode 100644 index 0000000..94849ea --- /dev/null +++ b/src/generated/resources/assets/examplemod/models/item/example_item.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "examplemod:item/example_item" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/examplemod/loot_tables/blocks/example_block.json b/src/generated/resources/data/examplemod/loot_tables/blocks/example_block.json new file mode 100644 index 0000000..3b7bb80 --- /dev/null +++ b/src/generated/resources/data/examplemod/loot_tables/blocks/example_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "examplemod:example_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "examplemod:blocks/example_block" +} \ No newline at end of file diff --git a/src/main/java/com/example/examplemod/ExampleMod.java b/src/main/java/com/example/examplemod/ExampleMod.java index 4f50275..86c1b4e 100644 --- a/src/main/java/com/example/examplemod/ExampleMod.java +++ b/src/main/java/com/example/examplemod/ExampleMod.java @@ -1,9 +1,16 @@ package com.example.examplemod; +import com.example.examplemod.data.EnderBlockLootProvider; +import com.example.examplemod.data.EnderItemModelProvider; +import com.example.examplemod.registry.EnderBlockRegistry; +import com.example.examplemod.registry.EnderDeferredBlock; +import com.example.examplemod.registry.EnderItemRegistry; import com.mojang.logging.LogUtils; import net.minecraft.client.Minecraft; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.ItemTags; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.CreativeModeTab; @@ -21,6 +28,7 @@ import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.neoforge.client.model.generators.BlockStateProvider; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; import net.neoforged.neoforge.event.server.ServerStartingEvent; @@ -39,16 +47,23 @@ public class ExampleMod // Directly reference a slf4j logger private static final Logger LOGGER = LogUtils.getLogger(); // Create a Deferred Register to hold Blocks which will all be registered under the "examplemod" namespace - public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(MODID); + public static final EnderBlockRegistry BLOCKS = EnderBlockRegistry.createRegistry(MODID); // Create a Deferred Register to hold Items which will all be registered under the "examplemod" namespace - public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MODID); + public static final EnderItemRegistry ITEMS = EnderItemRegistry.createRegistry(MODID); // Create a Deferred Register to hold CreativeModeTabs which will all be registered under the "examplemod" namespace public static final DeferredRegister CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID); // Creates a new Block with the id "examplemod:example_block", combining the namespace and path - public static final DeferredBlock EXAMPLE_BLOCK = BLOCKS.registerSimpleBlock("example_block", BlockBehaviour.Properties.of().mapColor(MapColor.STONE)); - // Creates a new BlockItem with the id "examplemod:example_block", combining the namespace and path - public static final DeferredItem EXAMPLE_BLOCK_ITEM = ITEMS.registerSimpleBlockItem("example_block", EXAMPLE_BLOCK); + public static final EnderDeferredBlock EXAMPLE_BLOCK = BLOCKS + .registerBlock("example_block", BlockBehaviour.Properties.of().mapColor(MapColor.STONE)) + .addBlockTags(BlockTags.MUSHROOM_GROW_BLOCK) + .setBlockStateProvider(BlockStateProvider::simpleBlock) + .setLootTable(EnderBlockLootProvider::dropSelf) + .createBlockItem() + .addBlockItemTags(ItemTags.PLANKS) + .setModelProvider(EnderItemModelProvider::basicItem) + .setTab(CreativeModeTabs.BUILDING_BLOCKS) + .finishBlockItem(); // Creates a new food item with the id "examplemod:example_id", nutrition 1 and saturation 2 public static final DeferredItem EXAMPLE_ITEM = ITEMS.registerSimpleItem("example_item", new Item.Properties().food(new FoodProperties.Builder() @@ -102,8 +117,8 @@ private void commonSetup(final FMLCommonSetupEvent event) // Add the example block item to the building blocks tab private void addCreative(BuildCreativeModeTabContentsEvent event) { - if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) - event.accept(EXAMPLE_BLOCK_ITEM); + //if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) + //event.accept(EXAMPLE_BLOCK_ITEM); } // You can use SubscribeEvent and let the Event Bus discover methods to call diff --git a/src/main/java/com/example/examplemod/data/EnderBlockLootProvider.java b/src/main/java/com/example/examplemod/data/EnderBlockLootProvider.java new file mode 100644 index 0000000..ba91e71 --- /dev/null +++ b/src/main/java/com/example/examplemod/data/EnderBlockLootProvider.java @@ -0,0 +1,80 @@ +package com.example.examplemod.data; + +import com.example.examplemod.registry.EnderBlockRegistry; +import com.example.examplemod.registry.EnderDeferredBlock; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.loot.BlockLootSubProvider; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.flag.FeatureFlags; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; +import net.minecraft.world.level.storage.loot.LootTable; +import net.neoforged.neoforge.registries.DeferredHolder; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.function.BiConsumer; + +public class EnderBlockLootProvider extends BlockLootSubProvider { + + private final EnderBlockRegistry registry; + + public EnderBlockLootProvider(Set explosionResistant, EnderBlockRegistry registry) { + super(explosionResistant, FeatureFlags.REGISTRY.allFlags()); + this.registry = registry; + } + + @Override + protected void generate() { + for (DeferredHolder block : registry.getEntries()) { + BiConsumer lootTable = ((EnderDeferredBlock) block).getLootTable(); + if (lootTable != null) { + lootTable.accept(this, block.get()); + } + } + } + + //TODO why these 2 methods, can we join them? + @Override + public void generate(BiConsumer p_249322_) { + this.generate(); + Set set = new HashSet<>(); + + for(DeferredHolder block : registry.getEntries()) { + if (block.get().isEnabled(this.enabledFeatures)) { + ResourceLocation resourcelocation = block.get().getLootTable(); + if (resourcelocation != BuiltInLootTables.EMPTY && set.add(resourcelocation)) { + LootTable.Builder loottable$builder = this.map.remove(resourcelocation); + if (loottable$builder == null) { + throw new IllegalStateException( + String.format(Locale.ROOT, "Missing loottable '%s' for '%s'", resourcelocation, BuiltInRegistries.BLOCK.getKey(block.get())) + ); + } + + p_249322_.accept(resourcelocation, loottable$builder); + } + } + } + + if (!this.map.isEmpty()) { + throw new IllegalStateException("Created block loot tables for non-blocks: " + this.map.keySet()); + } + } + + @Override + public void dropSelf(Block block) { + super.dropSelf(block); + } + + public void createDoor(Block block) { + this.add(block, super::createDoorTable); + } + + @Override + public void add(Block p_250610_, LootTable.Builder p_249817_) { + super.add(p_250610_, p_249817_); + } +} diff --git a/src/main/java/com/example/examplemod/data/EnderBlockStateProvider.java b/src/main/java/com/example/examplemod/data/EnderBlockStateProvider.java new file mode 100644 index 0000000..34fb387 --- /dev/null +++ b/src/main/java/com/example/examplemod/data/EnderBlockStateProvider.java @@ -0,0 +1,30 @@ +package com.example.examplemod.data; + +import com.example.examplemod.registry.EnderBlockRegistry; +import com.example.examplemod.registry.EnderDeferredBlock; +import net.minecraft.data.PackOutput; +import net.minecraft.world.level.block.Block; +import net.neoforged.neoforge.client.model.generators.BlockStateProvider; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.registries.DeferredHolder; + +import java.util.function.BiConsumer; + +public class EnderBlockStateProvider extends BlockStateProvider { + private final EnderBlockRegistry registry; + + public EnderBlockStateProvider(PackOutput output, String modid, ExistingFileHelper exFileHelper, EnderBlockRegistry registry) { + super(output, modid, exFileHelper); + this.registry = registry; + } + + @Override + protected void registerStatesAndModels() { + for (DeferredHolder block : registry.getEntries()) { + BiConsumer blockstate = ((EnderDeferredBlock) block).getBlockStateProvider(); + if (blockstate != null) { + blockstate.accept(this, block.get()); + } + } + } +} diff --git a/src/main/java/com/example/examplemod/data/EnderDataProvider.java b/src/main/java/com/example/examplemod/data/EnderDataProvider.java new file mode 100644 index 0000000..1a25191 --- /dev/null +++ b/src/main/java/com/example/examplemod/data/EnderDataProvider.java @@ -0,0 +1,43 @@ +package com.example.examplemod.data; + +import com.example.examplemod.ExampleMod; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class EnderDataProvider implements DataProvider { + private final String modid; + private final List subProviders = new ArrayList<>(); + private final static EnderDataProvider INSTANCE = new EnderDataProvider(ExampleMod.MODID); + + public EnderDataProvider(String modid) { + this.modid = modid; + } + + public static EnderDataProvider getInstance() { + return INSTANCE; + } + + public void addSubProvider(boolean include, DataProvider provider) { + if (include) { + subProviders.add(provider); + } + } + + @Override + public CompletableFuture run(CachedOutput pOutput) { + List> list = new ArrayList<>(); + for (DataProvider provider : subProviders) { + list.add(provider.run(pOutput)); + } + return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new)); + } + + @Override + public String getName() { + return "Ender IO Data (" + modid + ")"; + } +} diff --git a/src/main/java/com/example/examplemod/data/EnderItemModelProvider.java b/src/main/java/com/example/examplemod/data/EnderItemModelProvider.java new file mode 100644 index 0000000..5b5556c --- /dev/null +++ b/src/main/java/com/example/examplemod/data/EnderItemModelProvider.java @@ -0,0 +1,59 @@ +package com.example.examplemod.data; + +import com.example.examplemod.registry.EnderDeferredItem; +import com.example.examplemod.registry.EnderItemRegistry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import net.neoforged.neoforge.client.model.generators.ItemModelBuilder; +import net.neoforged.neoforge.client.model.generators.ItemModelProvider; +import net.neoforged.neoforge.client.model.generators.ModelFile; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.registries.DeferredHolder; + +import java.util.Objects; +import java.util.function.BiConsumer; + +public class EnderItemModelProvider extends ItemModelProvider { + private final EnderItemRegistry registry; + + public EnderItemModelProvider(PackOutput output, String modid, ExistingFileHelper existingFileHelper, EnderItemRegistry itemRegistry) { + super(output, modid, existingFileHelper); + this.registry = itemRegistry; + } + + @Override + protected void registerModels() { + for (DeferredHolder item : registry.getEntries()) { + BiConsumer modelProvider = ((EnderDeferredItem) item).getModelProvider(); + if (modelProvider != null) { + modelProvider.accept(this, item.get()); + } + } + } + + public ItemModelBuilder basicBlock(Item item) { + return basicBlock(Objects.requireNonNull(BuiltInRegistries.ITEM.getKey(item))); + } + + public ItemModelBuilder basicBlock(ResourceLocation item) { + return getBuilder(item.toString()) + .parent(new ModelFile.UncheckedModelFile("item/generated")) + .texture("layer0", new ResourceLocation(item.getNamespace(), "block/" + item.getPath())); + } + + public ItemModelBuilder basicItem(Item item, ResourceLocation texture) { + return getBuilder(BuiltInRegistries.ITEM.getKey(item).toString()) + .parent(new ModelFile.UncheckedModelFile("item/generated")) + .texture("layer0", new ResourceLocation(texture.getNamespace(), "item/" + texture.getPath())); + } + + public ResourceLocation itemTexture(ItemLike item) { + return Objects.requireNonNull(BuiltInRegistries.ITEM.getKey(item.asItem())); + } + + +} + diff --git a/src/main/java/com/example/examplemod/data/EnderLangProvider.java b/src/main/java/com/example/examplemod/data/EnderLangProvider.java new file mode 100644 index 0000000..0967a3e --- /dev/null +++ b/src/main/java/com/example/examplemod/data/EnderLangProvider.java @@ -0,0 +1,44 @@ +package com.example.examplemod.data; + +import com.example.examplemod.registry.EnderBlockRegistry; +import com.example.examplemod.registry.EnderDeferredBlock; +import com.example.examplemod.registry.EnderDeferredItem; +import com.example.examplemod.registry.EnderItemRegistry; +import net.minecraft.data.PackOutput; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.neoforged.neoforge.common.data.LanguageProvider; +import net.neoforged.neoforge.registries.DeferredHolder; + +import javax.annotation.Nullable; + +public class EnderLangProvider extends LanguageProvider { + @Nullable + private EnderBlockRegistry blocks; + @Nullable + private EnderItemRegistry items; + + public EnderLangProvider(PackOutput output, String modid, String locale, EnderBlockRegistry registry) { + super(output, modid, locale); + this.blocks = registry; + } + + public EnderLangProvider(PackOutput output, String modid, String locale, EnderItemRegistry registry) { + super(output, modid, locale); + this.items = registry; + } + + @Override + protected void addTranslations() { + if (blocks != null) { + for (DeferredHolder block : blocks.getEntries()) { + this.add(block.get(), ((EnderDeferredBlock) block).getTranslation()); + } + } + if (items != null) { + for (DeferredHolder item : items.getEntries()) { + this.add(item.get(), ((EnderDeferredItem) item).getTranslation()); + } + } + } +} diff --git a/src/main/java/com/example/examplemod/events/ColorEvents.java b/src/main/java/com/example/examplemod/events/ColorEvents.java new file mode 100644 index 0000000..ec7ed10 --- /dev/null +++ b/src/main/java/com/example/examplemod/events/ColorEvents.java @@ -0,0 +1,51 @@ +package com.example.examplemod.events; + +import com.example.examplemod.registry.EnderBlockRegistry; +import com.example.examplemod.registry.EnderDeferredBlock; +import com.example.examplemod.registry.EnderDeferredItem; +import com.example.examplemod.registry.EnderItemRegistry; +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.neoforged.bus.api.Event; +import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; +import net.neoforged.neoforge.registries.DeferredHolder; + +import javax.annotation.Nullable; +import java.util.function.Supplier; + +public class ColorEvents { + + @Nullable + private final EnderBlockRegistry blocks; + @Nullable + private final EnderItemRegistry items; + + public ColorEvents(@Nullable EnderBlockRegistry blocks, @Nullable EnderItemRegistry items) { + this.blocks = blocks; + this.items = items; + } + + public void registerBlockColor(RegisterColorHandlersEvent.Block event) { + if (blocks == null) { + return; + } + for (DeferredHolder block : blocks.getEntries()) { + Supplier colorSupplier = ((EnderDeferredBlock) block).getColorSupplier(); + if (colorSupplier != null) + event.register(colorSupplier.get(), block.get()); + } + } + + public void registerItemColor(RegisterColorHandlersEvent.Item event) { + if (items == null) { + return; + } + for (DeferredHolder item : items.getEntries()) { + Supplier colorSupplier = ((EnderDeferredItem) item).getColorSupplier(); + if (colorSupplier != null) + event.register(colorSupplier.get(), item.get()); + } + } +} diff --git a/src/main/java/com/example/examplemod/mixin/DeferredRegisterAccessor.java b/src/main/java/com/example/examplemod/mixin/DeferredRegisterAccessor.java new file mode 100644 index 0000000..545552b --- /dev/null +++ b/src/main/java/com/example/examplemod/mixin/DeferredRegisterAccessor.java @@ -0,0 +1,18 @@ +package com.example.examplemod.mixin; + +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +@Mixin(DeferredRegister.class) +public interface DeferredRegisterAccessor { + + @Accessor + Map, Supplier> getEntries(); + +} diff --git a/src/main/java/com/example/examplemod/registry/EnderBlockEntityRegistry.java b/src/main/java/com/example/examplemod/registry/EnderBlockEntityRegistry.java new file mode 100644 index 0000000..ebf001a --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderBlockEntityRegistry.java @@ -0,0 +1,36 @@ +package com.example.examplemod.registry; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +public class EnderBlockEntityRegistry extends DeferredRegister> { + protected EnderBlockEntityRegistry(String namespace) { + super(BuiltInRegistries.BLOCK_ENTITY_TYPE.key(), namespace); + } + + public EnderDeferredBlockEntity registerBlockEntity(String name, BlockEntityType.BlockEntitySupplier sup, Block... blocks) { + DeferredHolder, BlockEntityType> holder = this.register(name, () -> BlockEntityType.Builder.of(sup, blocks).build(null)); + return EnderDeferredBlockEntity.createBlockEntity(holder); + } + + @SafeVarargs + public final EnderDeferredBlockEntity registerBlockEntity(String name, BlockEntityType.BlockEntitySupplier sup, + Supplier... blocks) { + List blockList = Arrays.stream(blocks).map(Supplier::get).toList(); + DeferredHolder, BlockEntityType> holder = this.register(name, () -> BlockEntityType.Builder.of(sup, blockList.toArray(new Block[] {})).build(null)); + return EnderDeferredBlockEntity.createBlockEntity(holder); + } + + public static EnderBlockEntityRegistry create(String modid) { + return new EnderBlockEntityRegistry(modid); + } + +} diff --git a/src/main/java/com/example/examplemod/registry/EnderBlockRegistry.java b/src/main/java/com/example/examplemod/registry/EnderBlockRegistry.java new file mode 100644 index 0000000..4129ed4 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderBlockRegistry.java @@ -0,0 +1,125 @@ +package com.example.examplemod.registry; + +import com.example.examplemod.data.*; +import com.example.examplemod.events.ColorEvents; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.Registry; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.PackOutput; +import net.minecraft.data.loot.LootTableProvider; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.data.event.GatherDataEvent; +import net.neoforged.neoforge.registries.DeferredBlock; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.function.Supplier; + +public class EnderBlockRegistry extends DeferredRegister.Blocks { + private final EnderItemRegistry ItemRegistry; + protected EnderBlockRegistry(String namespace) { + super(namespace); + ItemRegistry = new EnderItemRegistry(namespace); + } + + /** + * Adds a new block to the list of entries to be registered and returns a {@link DeferredHolder} that will be populated with the created block automatically. + * + * @param name The new block's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param func A factory for the new block. The factory should not cache the created block. + * @return A {@link DeferredHolder} that will track updates from the registry for this block. + */ + @SuppressWarnings("unchecked") + @Override + public EnderDeferredBlock register(String name, Function func) { + return ((EnderDeferredBlock) super.register(name, func)).setRegistry(ItemRegistry); + } + + /** + * Adds a new block to the list of entries to be registered and returns a {@link DeferredHolder} that will be populated with the created block automatically. + * + * @param name The new block's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param sup A factory for the new block. The factory should not cache the created block. + * @return A {@link DeferredHolder} that will track updates from the registry for this block. + */ + @Override + public EnderDeferredBlock register(String name, Supplier sup) { + return this.register(name, key -> sup.get()); + } + + /** + * Adds a new block to the list of entries to be registered and returns a {@link DeferredHolder} that will be populated with the created block automatically. + * + * @param name The new block's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param func A factory for the new block. The factory should not cache the created block. + * @param props The properties for the created block. + * @return A {@link DeferredHolder} that will track updates from the registry for this block. + * @see #registerBlock(String, BlockBehaviour.Properties) + */ + public EnderDeferredBlock registerBlock(String name, Function func, BlockBehaviour.Properties props) { + return this.register(name, () -> func.apply(props)); + } + + /** + * Adds a new block to the list of entries to be registered and returns a {@link DeferredHolder} that will be populated with the created block automatically. + * + * @param name The new block's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param props The properties for the created block. + * @return A {@link DeferredHolder} that will track updates from the registry for this block. + * @see #registerBlock(String, Function, BlockBehaviour.Properties) + */ + public EnderDeferredBlock registerBlock(String name, BlockBehaviour.Properties props) { + return this.registerBlock(name, Block::new, props); + } + + @Override + protected DeferredBlock createHolder(ResourceKey> registryKey, ResourceLocation key) { + return EnderDeferredBlock.createBlock(ResourceKey.create(registryKey, key)); + } + + public EnderItemRegistry getItemRegistry() { + return ItemRegistry; + } + + public static EnderBlockRegistry createRegistry(String modid) { + return new EnderBlockRegistry(modid); + } + + @Override + public void register(IEventBus bus) { + super.register(bus); + ItemRegistry.register(bus); + bus.addListener(EventPriority.LOWEST, this::onGatherData); + if (FMLEnvironment.dist.isClient()) { + bus.addListener(new ColorEvents(this, getItemRegistry())::registerBlockColor); + } + } + + private void onGatherData(GatherDataEvent event) { + DataGenerator generator = event.getGenerator(); + PackOutput packOutput = event.getGenerator().getPackOutput(); + CompletableFuture lookupProvider = event.getLookupProvider(); + ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); + + EnderDataProvider provider = EnderDataProvider.getInstance(); + + provider.addSubProvider(event.includeServer(), new EnderBlockStateProvider(packOutput, getNamespace(), existingFileHelper, this)); + provider.addSubProvider(event.includeServer(), new EnderLangProvider(packOutput,getNamespace(), "en_us", this )); + provider.addSubProvider(event.includeServer(), new LootTableProvider(packOutput, Collections.emptySet(), + List.of(new LootTableProvider.SubProviderEntry(() -> new EnderBlockLootProvider(Set.of(), this), LootContextParamSets.BLOCK)))); + generator.addProvider(true, provider); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredBlock.java b/src/main/java/com/example/examplemod/registry/EnderDeferredBlock.java new file mode 100644 index 0000000..e8b4c1b --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredBlock.java @@ -0,0 +1,107 @@ +package com.example.examplemod.registry; + +import com.example.examplemod.data.EnderBlockLootProvider; +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.level.block.Block; +import net.neoforged.neoforge.client.model.generators.BlockStateProvider; +import net.neoforged.neoforge.registries.DeferredBlock; +import net.neoforged.neoforge.registries.DeferredHolder; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Nullable; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class EnderDeferredBlock extends DeferredBlock implements ITranslatable{ + private String translation = StringUtils.capitalize(getId().getPath().replace('_', ' ')); + private Set> blockTags = Set.of(); + @Nullable + private BiConsumer lootTable = EnderBlockLootProvider::dropSelf; + @Nullable + private BiConsumer blockStateProvider = BlockStateProvider::simpleBlock; + @Nullable + private Supplier colorSupplier; + @Nullable + private EnderItemRegistry registry; + protected EnderDeferredBlock(ResourceKey key) { + super(key); + } + + public EnderDeferredBlock setTranslation(String translation) { + this.translation = translation; + return this; + } + + @Override + public String getTranslation() { + return translation; + } + + @SafeVarargs + public final EnderDeferredBlock addBlockTags(TagKey... tags) { + blockTags = Set.of(tags); + return this; + } + + public Set> getBlockTags() { + return blockTags; + } + + public EnderDeferredBlock setLootTable(BiConsumer lootTable) { + this.lootTable = lootTable; + return this; + } + + @Nullable + public BiConsumer getLootTable() { + return lootTable; + } + + public EnderDeferredBlock setBlockStateProvider(BiConsumer blockStateProvider) { + this.blockStateProvider = blockStateProvider; + return this; + } + + @Nullable + public BiConsumer getBlockStateProvider() { + return blockStateProvider; + } + + @Nullable + public Supplier getColorSupplier() { + return colorSupplier; + } + + public EnderDeferredBlock setColorSupplier(@Nullable Supplier colorSupplier) { + this.colorSupplier = colorSupplier; + return this; + } + + public EnderDeferredBlock setRegistry(@Nullable EnderItemRegistry registry) { + this.registry = registry; + return this; + } + + public EnderDeferredBlockItem createBlockItem() { + return registry.registerBlockItem(this); + } + + public EnderDeferredBlockItem createBlockItem(Function function) { + return registry.registerBlockItem(getId().getPath(), this, () -> function.apply(this.get())); + } + + public static EnderDeferredBlock createBlock(ResourceLocation key) { + return createBlock(ResourceKey.create(Registries.BLOCK, key)); + } + + public static EnderDeferredBlock createBlock(ResourceKey key) { + return new EnderDeferredBlock<>(key); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredBlockEntity.java b/src/main/java/com/example/examplemod/registry/EnderDeferredBlockEntity.java new file mode 100644 index 0000000..6154bd0 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredBlockEntity.java @@ -0,0 +1,37 @@ +package com.example.examplemod.registry; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.registries.DeferredHolder; + +import javax.annotation.Nullable; + +public class EnderDeferredBlockEntity extends DeferredHolder, BlockEntityType> { + + /** + * Creates a new DeferredHolder with a ResourceKey. + * + *

Attempts to bind immediately if possible. + * + * @param key The resource key of the target object. + * @see #create(ResourceKey, ResourceLocation) + * @see #create(ResourceLocation, ResourceLocation) + * @see #create(ResourceKey) + */ + protected EnderDeferredBlockEntity(ResourceKey> key) { + super(key); + } + + public static EnderDeferredBlockEntity createBlockEntity(DeferredHolder, BlockEntityType> holder) { + return new EnderDeferredBlockEntity<>(holder.getKey()); + } + + @Nullable + public T create(BlockPos pos, BlockState state) { + return this.get().create(pos, state); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredBlockItem.java b/src/main/java/com/example/examplemod/registry/EnderDeferredBlockItem.java new file mode 100644 index 0000000..64c65d8 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredBlockItem.java @@ -0,0 +1,63 @@ +package com.example.examplemod.registry; + +import com.example.examplemod.data.EnderItemModelProvider; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; + +import java.util.Set; +import java.util.function.BiConsumer; + +public class EnderDeferredBlockItem extends EnderDeferredItem{ + private EnderDeferredBlock block; + protected EnderDeferredBlockItem(ResourceKey key) { + super(key); + } + + public EnderDeferredBlockItem(ResourceKey itemResourceKey, EnderDeferredBlock block) { + this(itemResourceKey); + this.block = block; + this.translation = ""; + } + + public static EnderDeferredBlockItem createBlockItem(ResourceKey itemResourceKey, EnderDeferredBlock block) { + return new EnderDeferredBlockItem<>(itemResourceKey, block); + } + + public EnderDeferredBlock finishBlockItem() { + return block; + } + + @Override + public EnderDeferredBlockItem setTab(ResourceKey tab) { + super.setTab(tab); + return this; + } + + @Override + public EnderDeferredBlockItem setTab(ResourceKey tab, CreativeModeTab.TabVisibility visibility) { + super.setTab(tab, visibility); + return this; + } + + @SafeVarargs + public final EnderDeferredBlockItem addBlockItemTags(TagKey... tags) { + this.ItemTags = Set.of(tags); + return this; + } + + @Override + public EnderDeferredBlockItem setTranslation(String translation) { + this.translation = translation; + return this; + } + + @Override + public EnderDeferredBlockItem setModelProvider(BiConsumer modelProvider) { + this.modelProvider = modelProvider; + return this; + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredFluid.java b/src/main/java/com/example/examplemod/registry/EnderDeferredFluid.java new file mode 100644 index 0000000..0f2d24b --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredFluid.java @@ -0,0 +1,115 @@ +package com.example.examplemod.registry; + +import com.example.examplemod.data.EnderItemModelProvider; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LiquidBlock; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.fluids.BaseFlowingFluid; +import net.neoforged.neoforge.fluids.FluidType; +import net.neoforged.neoforge.registries.DeferredBlock; +import net.neoforged.neoforge.registries.DeferredItem; +import net.neoforged.neoforge.registries.DeferredRegister; + +import javax.annotation.Nullable; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class EnderDeferredFluid extends EnderDeferredObject{ + private Set> FluidTags = Set.of(); + protected Set> ItemTags = Set.of(); + protected ResourceKey tab; + @Nullable + protected BiConsumer modelProvider = EnderItemModelProvider::basicItem; + private EnderDeferredObject flowingFluid; + private EnderDeferredObject sourceFluid; + private DeferredBlock block; + private DeferredItem bucket; + private final BaseFlowingFluid.Properties properties = new BaseFlowingFluid.Properties(this, sourceFluid, flowingFluid).block(block).bucket(bucket); + private EnderRegistry fluid; + private DeferredRegister.Blocks BLOCKS; + private DeferredRegister.Items ITEMS; + + protected EnderDeferredFluid(ResourceKey key) { + super(key); + } + + public EnderDeferredFluid createFluids(Consumer consumer, Supplier bucket, Supplier block) { + this.block = BLOCKS.register(getId().getPath(), block); + this.bucket = ITEMS.register(getId().getPath(), bucket); + consumer.accept(properties); + this.flowingFluid = fluid.register("fluid_" + getId().getPath() + "_flowing", () -> new BaseFlowingFluid.Flowing(properties)); + this.sourceFluid = fluid.register("fluid_" + getId().getPath() + "_still", () -> new BaseFlowingFluid.Source(properties)); + return this; + } + + public EnderDeferredFluid createFluids(Consumer consumer) { + return this.createFluids(consumer, () -> new BucketItem(this.sourceFluid, new Item.Properties().stacksTo(1)), + () -> new LiquidBlock(this.flowingFluid, BlockBehaviour.Properties.copy(Blocks.WATER))); + } + + public BaseFlowingFluid.Source getSource() { + return sourceFluid.get(); + } + + public BaseFlowingFluid.Flowing getFlowing() { + return flowingFluid.get(); + } + + public void setRegistries(EnderRegistry fluid, DeferredRegister.Blocks blocks, DeferredRegister.Items items) { + this.fluid = fluid; + this.BLOCKS = blocks; + this.ITEMS = items; + } + + @SafeVarargs + public final EnderDeferredFluid addItemTags(TagKey... tags) { + ItemTags = Set.of(tags); + return this; + } + + public Set> getItemTags() { + return ItemTags; + } + + @SafeVarargs + public final EnderDeferredFluid addFluidTags(TagKey... tags) { + this.FluidTags = Set.of(tags); + return this; + } + + public Set> getFluidTags() { + return FluidTags; + } + + public EnderDeferredFluid setTab(ResourceKey tab) { + this.tab = tab; + return this; + } + + public ResourceKey getTab() { + return tab; + } + + public EnderDeferredFluid setModelProvider(BiConsumer modelProvider) { + this.modelProvider = modelProvider; + return this; + } + + public BiConsumer getModelProvider() { + return modelProvider; + } + + @Override + public EnderDeferredFluid setTranslation(String translation) { + super.setTranslation(translation); + return this; + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredItem.java b/src/main/java/com/example/examplemod/registry/EnderDeferredItem.java new file mode 100644 index 0000000..5c11db3 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredItem.java @@ -0,0 +1,110 @@ +package com.example.examplemod.registry; + +import com.example.examplemod.data.EnderItemModelProvider; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.models.ModelProvider; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTabs; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.neoforged.neoforge.client.model.generators.ItemModelProvider; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredItem; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class EnderDeferredItem extends DeferredItem implements ITranslatable{ + protected String translation = StringUtils.capitalize(getId().getPath().replace('_', ' ')); + protected Set> ItemTags = new HashSet<>(); + protected Map, Consumer> tab = new HashMap<>(); + @Nullable + protected BiConsumer modelProvider = EnderItemModelProvider::basicItem; + protected Supplier colorSupplier; + + protected EnderDeferredItem(ResourceKey key) { + super(key); + } + + public EnderDeferredItem setTranslation(String translation) { + this.translation = translation; + return this; + } + + public String getTranslation() { + return translation; + } + + @SafeVarargs + public final EnderDeferredItem addItemTags(TagKey... tags) { + ItemTags.addAll(Set.of(tags)); + return this; + } + + public Set> getItemTags() { + return ItemTags; + } + + public EnderDeferredItem setTab(ResourceKey tab) { + this.tab.put(tab, output -> output.accept(new ItemStack(this.get()))); + return this; + } + + public EnderDeferredItem setTab(ResourceKey tab, CreativeModeTab.TabVisibility visibility) { + this.tab.put(tab, output -> output.accept(new ItemStack(this.get()), visibility)); + return this; + } + + public EnderDeferredItem setTab(ResourceKey tab, Consumer output) { + this.tab.put(tab, output); + return this; + } + + public Map, Consumer> getTab() { + return tab; + } + + public EnderDeferredItem setModelProvider(BiConsumer modelProvider) { + this.modelProvider = modelProvider; + return this; + } + + public BiConsumer getModelProvider() { + return modelProvider; + } + + public Supplier getColorSupplier() { + return colorSupplier; + } + + public EnderDeferredItem setColorSupplier(Supplier colorSupplier) { + this.colorSupplier = colorSupplier; + return this; + } + + public static EnderDeferredItem createItem(ResourceLocation key) { + return createItem(ResourceKey.create(Registries.ITEM, key)); + } + + /** + * Creates a new {@link DeferredHolder} targeting the specified {@link Item}. + * + * @param The type of the target {@link Item}. + * @param key The resource key of the target {@link Item}. + */ + public static EnderDeferredItem createItem(ResourceKey key) { + return new EnderDeferredItem<>(key); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredMenu.java b/src/main/java/com/example/examplemod/registry/EnderDeferredMenu.java new file mode 100644 index 0000000..0f6189a --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredMenu.java @@ -0,0 +1,38 @@ +package com.example.examplemod.registry; + +import net.minecraft.client.gui.screens.MenuScreens; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.neoforged.neoforge.registries.DeferredHolder; + +import java.util.function.Supplier; + +public class EnderDeferredMenu extends EnderDeferredObject, MenuType> { + + private Supplier>> screenConstructor; + + protected EnderDeferredMenu(ResourceKey> key) { + super(key); + } + + public EnderDeferredMenu setScreenConstructor(Supplier>> screenConstructor) { + this.screenConstructor = screenConstructor; + return this; + } + + public Supplier>> getScreenConstructor() { + return screenConstructor; + } + + @Override + public EnderDeferredMenu setTranslation(String translation) { + this.translation = translation; + return this; + } + + public static EnderDeferredMenu createMenu(EnderDeferredObject, MenuType> holder) { + return new EnderDeferredMenu<>(holder.getKey()); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderDeferredObject.java b/src/main/java/com/example/examplemod/registry/EnderDeferredObject.java new file mode 100644 index 0000000..a31cd26 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderDeferredObject.java @@ -0,0 +1,23 @@ +package com.example.examplemod.registry; + +import net.minecraft.resources.ResourceKey; +import net.neoforged.neoforge.registries.DeferredHolder; +import org.apache.commons.lang3.StringUtils; + +public class EnderDeferredObject extends DeferredHolder implements ITranslatable { + protected String translation = StringUtils.capitalize(getId().getPath().replace('_', ' ')); + + protected EnderDeferredObject(ResourceKey key) { + super(key); + } + + @Override + public String getTranslation() { + return translation; + } + + public EnderDeferredObject setTranslation(String translation) { + this.translation = translation; + return this; + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderFluidRegister.java b/src/main/java/com/example/examplemod/registry/EnderFluidRegister.java new file mode 100644 index 0000000..355a112 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderFluidRegister.java @@ -0,0 +1,63 @@ +package com.example.examplemod.registry; + +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.fluids.FluidType; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class EnderFluidRegister extends EnderRegistry{ + private final EnderRegistry FLUID; + private final DeferredRegister.Blocks BLOCKS; + private final DeferredRegister.Items ITEMS; + + + protected EnderFluidRegister(String namespace) { + super(NeoForgeRegistries.FLUID_TYPES.key(), namespace); + FLUID = EnderRegistry.createRegistry(BuiltInRegistries.FLUID, namespace); + BLOCKS = DeferredRegister.Blocks.createBlocks(namespace); + ITEMS = DeferredRegister.Items.createItems(namespace); + + } + + public static EnderFluidRegister create(String modid) { + return new EnderFluidRegister(modid); + } + + @Override + public EnderDeferredFluid register(String name, Function func) { + return (EnderDeferredFluid) super.register(name, func); + } + + @Override + public EnderDeferredFluid register(String name, Supplier sup) { + return this.register(name, key -> sup.get()); + } + + public EnderDeferredFluid registerFluid(String name, FluidType.Properties type) { + EnderDeferredFluid fluid = this.register(name, () -> new FluidType(type)); + fluid.setRegistries(FLUID, BLOCKS, ITEMS); + return fluid; + } + + @Override + public void register(IEventBus bus) { + super.register(bus); + FLUID.register(bus); + BLOCKS.register(bus); + ITEMS.register(bus); + } + + @Override + protected DeferredHolder createHolder(ResourceKey> registryKey, ResourceLocation key) { + return EnderDeferredFluid.create(ResourceKey.create(registryKey, key)); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderItemRegistry.java b/src/main/java/com/example/examplemod/registry/EnderItemRegistry.java new file mode 100644 index 0000000..03887d8 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderItemRegistry.java @@ -0,0 +1,214 @@ +package com.example.examplemod.registry; + +import com.example.examplemod.data.*; +import com.example.examplemod.events.ColorEvents; +import com.example.examplemod.mixin.DeferredRegisterAccessor; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.Registry; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.PackOutput; +import net.minecraft.data.loot.LootTableProvider; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTabs; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.data.event.GatherDataEvent; +import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; +import net.neoforged.neoforge.registries.DeferredBlock; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredItem; +import net.neoforged.neoforge.registries.DeferredRegister; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class EnderItemRegistry extends DeferredRegister.Items { + protected EnderItemRegistry(String namespace) { + super(namespace); + } + + /** + * Adds a new item to the list of entries to be registered and returns a {@link DeferredItem} that will be populated with the created item automatically. + * + * @param name The new item's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param func A factory for the new item. The factory should not cache the created item. + * @return A {@link DeferredItem} that will track updates from the registry for this item. + * @see #register(String, Supplier) + */ + @SuppressWarnings("unchecked") + @Override + public EnderDeferredItem register(String name, Function func) { + return (EnderDeferredItem) super.register(name, func); + } + + /** + * Adds a new item to the list of entries to be registered and returns a {@link DeferredItem} that will be populated with the created item automatically. + * + * @param name The new item's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param sup A factory for the new item. The factory should not cache the created item. + * @return A {@link DeferredItem} that will track updates from the registry for this item. + * @see #register(String, Function) + */ + @Override + public EnderDeferredItem register(String name, Supplier sup) { + return this.register(name, key -> sup.get()); + } + + private EnderDeferredBlockItem registerBlockItem(String name, Function func, EnderDeferredBlock block) { + //if (seenRegisterEvent) + //throw new IllegalStateException("Cannot register new entries to DeferredRegister after RegisterEvent has been fired."); + Objects.requireNonNull(name); + Objects.requireNonNull(func); + final ResourceLocation key = new ResourceLocation(getNamespace(), name); + + EnderDeferredBlockItem ret = createBlockItemHolder(getRegistryKey(), key, block); + + if (((DeferredRegisterAccessor)this).getEntries().putIfAbsent(ret, () -> func.apply(key)) != null) { + throw new IllegalArgumentException("Duplicate registration " + name); + } + + return ret; + } + + public EnderDeferredBlockItem registerBlockItem(String name, EnderDeferredBlock block, Supplier sup) { + return this.registerBlockItem(name, key -> sup.get(), block); + } + + + public EnderDeferredBlockItem registerBlockItem(String name, EnderDeferredBlock block, Item.Properties properties) { + return this.registerBlockItem(name, key -> new BlockItem(block.get(), properties), block); + } + + public EnderDeferredBlockItem registerBlockItem(String name, EnderDeferredBlock block) { + return this.registerBlockItem(name, block, new Item.Properties()); + } + + public EnderDeferredBlockItem registerBlockItem(EnderDeferredBlock block, Item.Properties properties) { + return this.registerBlockItem(block.unwrapKey().orElseThrow().location().getPath(), block, properties); + } + + public EnderDeferredBlockItem registerBlockItem(EnderDeferredBlock block) { + return this.registerBlockItem(block, new Item.Properties()); + } + + /** + * Adds a new item to the list of entries to be registered and returns a {@link DeferredItem} that will be populated with the created item automatically. + * + * @param name The new item's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param func A factory for the new item. The factory should not cache the created item. + * @param props The properties for the created item. + * @return A {@link DeferredItem} that will track updates from the registry for this item. + * @see #registerItem(String, Function) + * @see #registerItem(String, Item.Properties) + * @see #registerItem(String) + */ + public EnderDeferredItem registerItem(String name, Function func, Item.Properties props) { + return this.register(name, () -> func.apply(props)); + } + + /** + * Adds a new item to the list of entries to be registered and returns a {@link DeferredItem} that will be populated with the created item automatically. + * This method uses the default {@link Item.Properties}. + * + * @param name The new item's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param func A factory for the new item. The factory should not cache the created item. + * @return A {@link DeferredItem} that will track updates from the registry for this item. + * @see #registerItem(String, Function, Item.Properties) + * @see #registerItem(String, Item.Properties) + * @see #registerItem(String) + */ + public EnderDeferredItem registerItem(String name, Function func) { + return this.registerItem(name, func, new Item.Properties()); + } + + /** + * Adds a new {@link Item} with the given {@link Item.Properties properties} to the list of entries to be registered and + * returns a {@link DeferredItem} that will be populated with the created item automatically. + * + * @param name The new item's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @param props A factory for the new item. The factory should not cache the created item. + * @return A {@link DeferredItem} that will track updates from the registry for this item. + * @see #registerItem(String, Function, Item.Properties) + * @see #registerItem(String, Function) + * @see #registerItem(String) + */ + public EnderDeferredItem registerItem(String name, Item.Properties props) { + return this.registerItem(name, Item::new, props); + } + + /** + * Adds a new {@link Item} with the default {@link Item.Properties properties} to the list of entries to be registered and + * returns a {@link DeferredItem} that will be populated with the created item automatically. + * + * @param name The new item's name. It will automatically have the {@linkplain #getNamespace() namespace} prefixed. + * @return A {@link DeferredItem} that will track updates from the registry for this item. + * @see #registerItem(String, Function, Item.Properties) + * @see #registerItem(String, Function) + * @see #registerItem(String, Item.Properties) + */ + public EnderDeferredItem registerItem(String name) { + return this.registerItem(name, Item::new, new Item.Properties()); + } + + @Override + protected EnderDeferredItem createHolder(ResourceKey> registryKey, ResourceLocation key) { + return EnderDeferredItem.createItem(ResourceKey.create(registryKey, key)); + } + + protected EnderDeferredBlockItem createBlockItemHolder(ResourceKey> registryKey, ResourceLocation key, EnderDeferredBlock block) { + return EnderDeferredBlockItem.createBlockItem(ResourceKey.create(registryKey, key), block); + } + + public static EnderItemRegistry createRegistry(String modid) { + return new EnderItemRegistry(modid); + } + + @Override + public void register(IEventBus bus) { + super.register(bus); + bus.addListener(EventPriority.LOWEST, this::onGatherData); + bus.addListener(this::addCreative); + if (FMLEnvironment.dist.isClient()) { + bus.addListener(new ColorEvents(null, this)::registerBlockColor); + } + + } + + private void onGatherData(GatherDataEvent event) { + DataGenerator generator = event.getGenerator(); + PackOutput packOutput = event.getGenerator().getPackOutput(); + CompletableFuture lookupProvider = event.getLookupProvider(); + ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); + + EnderDataProvider provider = new EnderDataProvider(getNamespace() + " " + this); + + provider.addSubProvider(event.includeServer(), new EnderItemModelProvider(packOutput, getNamespace(), existingFileHelper, this)); + provider.addSubProvider(event.includeServer(), new EnderLangProvider(packOutput,getNamespace(), "en_us", this)); + generator.addProvider(true, provider); + } + + private void addCreative(BuildCreativeModeTabContentsEvent event) { + for (DeferredHolder item : this.getEntries()) { + Consumer outputConsumer = ((EnderDeferredItem) item).getTab().get(event.getTabKey()); + if (outputConsumer != null) { + outputConsumer.accept(event); + } + } + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderMenuRegistry.java b/src/main/java/com/example/examplemod/registry/EnderMenuRegistry.java new file mode 100644 index 0000000..0ffae46 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderMenuRegistry.java @@ -0,0 +1,30 @@ +package com.example.examplemod.registry; + +import net.minecraft.client.gui.screens.MenuScreens; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.flag.FeatureFlagRegistry; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.neoforged.neoforge.common.extensions.IMenuTypeExtension; +import net.neoforged.neoforge.network.IContainerFactory; + +import java.util.function.Supplier; + +public class EnderMenuRegistry extends EnderRegistry>{ + + protected EnderMenuRegistry(String namespace) { + super(BuiltInRegistries.MENU.key(), namespace); + } + + public static EnderMenuRegistry create(String modid) { + return new EnderMenuRegistry(modid); + } + + public EnderDeferredMenu registerMenu(String name, IContainerFactory factory, Supplier>> screenConstructor) { + EnderDeferredObject, MenuType> holder = this.register(name, () -> IMenuTypeExtension.create(factory)); + return EnderDeferredMenu.createMenu(holder).setScreenConstructor(screenConstructor); + } +} diff --git a/src/main/java/com/example/examplemod/registry/EnderRegistry.java b/src/main/java/com/example/examplemod/registry/EnderRegistry.java new file mode 100644 index 0000000..91a4f36 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/EnderRegistry.java @@ -0,0 +1,35 @@ +package com.example.examplemod.registry; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class EnderRegistry extends DeferredRegister { + protected EnderRegistry(ResourceKey> registryKey, String namespace) { + super(registryKey, namespace); + } + + @Override + public EnderDeferredObject register(String name, Supplier sup) { + return this.register(name, key -> sup.get()); + } + + @Override + public EnderDeferredObject register(String name, Function func) { + return (EnderDeferredObject) super.register(name, func); + } + + public static EnderRegistry createRegistry(Registry registry, String namespace) { + return new EnderRegistry<>(registry.key(), namespace); + } + + @Override + protected DeferredHolder createHolder(ResourceKey> registryKey, ResourceLocation key) { + return EnderDeferredObject.create(ResourceKey.create(registryKey, key)); + } +} diff --git a/src/main/java/com/example/examplemod/registry/ITranslatable.java b/src/main/java/com/example/examplemod/registry/ITranslatable.java new file mode 100644 index 0000000..3f9ba21 --- /dev/null +++ b/src/main/java/com/example/examplemod/registry/ITranslatable.java @@ -0,0 +1,5 @@ +package com.example.examplemod.registry; + +public interface ITranslatable { + String getTranslation(); +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index b0ad9f8..e3b222e 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -68,3 +68,6 @@ description='''${mod_description}''' # stop your mod loading on the server for example. #[features.${mod_id}] #openGLVersion="[3.2,)" + +[[mixins]] +config = "mixins.examplemod.json" diff --git a/src/main/resources/assets/examplemod/textures/block/example_block.png b/src/main/resources/assets/examplemod/textures/block/example_block.png new file mode 100644 index 0000000..14c277c Binary files /dev/null and b/src/main/resources/assets/examplemod/textures/block/example_block.png differ diff --git a/src/main/resources/assets/examplemod/textures/item/example_block.png b/src/main/resources/assets/examplemod/textures/item/example_block.png new file mode 100644 index 0000000..516005e Binary files /dev/null and b/src/main/resources/assets/examplemod/textures/item/example_block.png differ diff --git a/src/main/resources/assets/examplemod/textures/item/example_item.png b/src/main/resources/assets/examplemod/textures/item/example_item.png new file mode 100644 index 0000000..14c277c Binary files /dev/null and b/src/main/resources/assets/examplemod/textures/item/example_item.png differ diff --git a/src/main/resources/mixins.examplemod.json b/src/main/resources/mixins.examplemod.json new file mode 100644 index 0000000..416136f --- /dev/null +++ b/src/main/resources/mixins.examplemod.json @@ -0,0 +1,9 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.example.examplemod.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "DeferredRegisterAccessor" + ] +} \ No newline at end of file diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 59c5240..1d1b48d 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -3,6 +3,6 @@ "description": { "text": "${mod_id} resources" }, - "pack_format": ${pack_format_number} + "pack_format": 18 } }