From 41d725878ea363117aa445479fb512ee29e69bb6 Mon Sep 17 00:00:00 2001 From: TropheusJ Date: Wed, 12 Feb 2025 08:08:19 -0500 Subject: [PATCH] AttachedRegistry refactors, and several adjacent ones --- .../java/com/simibubi/create/AllBlocks.java | 6 +- .../create/AllInteractionBehaviours.java | 79 ++-------- .../create/AllMovementBehaviours.java | 61 ++------ src/main/java/com/simibubi/create/Create.java | 7 +- ...java => MountedStorageTypeRegistries.java} | 21 +-- .../fluid/MountedFluidStorageType.java | 4 +- .../MountedFluidStorageTypeBuilder.java | 9 +- .../storage/item/MountedItemStorageType.java | 4 +- .../MountedItemStorageTypeBuilder.java | 9 +- .../train/TrainConductorHandler.java | 37 ++--- .../ContraptionTransformableRegistry.java | 49 ------ .../MovedBlockTransformerRegistries.java | 28 ++++ .../create/api/lookup/BlockLookup.java | 66 -------- .../create/api/registry/AttachedRegistry.java | 92 +++++++++++ .../schematic/nbt/SafeNbtWriterRegistry.java | 27 ++++ .../nbt/SchematicSafeNBTRegistry.java | 37 ----- .../SchematicRequirementRegistries.java | 45 ++++++ .../SchematicRequirementsRegistry.java | 115 -------------- .../ContraptionMovementSetting.java | 43 ++---- .../contraptions/MountedStorageManager.java | 10 +- .../contraptions/StructureTransform.java | 17 +- .../content/fluids/tank/BoilerHeaters.java | 70 ++------- .../displayLink/AllDisplayBehaviours.java | 60 +++---- .../requirement/ItemRequirement.java | 27 ++-- .../content/trains/track/AllPortalTracks.java | 50 +++--- .../foundation/data/CreateRegistrate.java | 12 +- .../foundation/item/TooltipModifier.java | 9 +- .../foundation/utility/AttachedRegistry.java | 146 ------------------ .../foundation/utility/BlockHelper.java | 14 +- .../MountedStorageTypeRegistryImpl.java | 44 ++++-- .../ContraptionTransformableRegistryImpl.java | 33 ---- .../create/impl/lookup/BlockLookupImpl.java | 103 ------------ .../impl/registry/AttachedRegistryImpl.java | 103 ++++++++++++ .../create/impl/registry/TagProviderImpl.java | 41 +++++ .../nbt/SchematicSafeNBTRegistryImpl.java | 23 --- .../SchematicRequirementsRegistryImpl.java | 59 ------- 36 files changed, 568 insertions(+), 992 deletions(-) rename src/main/java/com/simibubi/create/api/contraption/storage/{MountedStorageTypeRegistry.java => MountedStorageTypeRegistries.java} (78%) delete mode 100644 src/main/java/com/simibubi/create/api/contraption/transformable/ContraptionTransformableRegistry.java create mode 100644 src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java delete mode 100644 src/main/java/com/simibubi/create/api/lookup/BlockLookup.java create mode 100644 src/main/java/com/simibubi/create/api/registry/AttachedRegistry.java create mode 100644 src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java delete mode 100644 src/main/java/com/simibubi/create/api/schematic/nbt/SchematicSafeNBTRegistry.java create mode 100644 src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java delete mode 100644 src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementsRegistry.java delete mode 100644 src/main/java/com/simibubi/create/foundation/utility/AttachedRegistry.java delete mode 100644 src/main/java/com/simibubi/create/impl/contraption/transformable/ContraptionTransformableRegistryImpl.java delete mode 100644 src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java create mode 100644 src/main/java/com/simibubi/create/impl/registry/AttachedRegistryImpl.java create mode 100644 src/main/java/com/simibubi/create/impl/registry/TagProviderImpl.java delete mode 100644 src/main/java/com/simibubi/create/impl/schematic/nbt/SchematicSafeNBTRegistryImpl.java delete mode 100644 src/main/java/com/simibubi/create/impl/schematic/requirement/SchematicRequirementsRegistryImpl.java diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 1a7373f0ca..7713a1e97a 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -3,8 +3,8 @@ package com.simibubi.create; import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour; import static com.simibubi.create.AllMovementBehaviours.movementBehaviour; import static com.simibubi.create.Create.REGISTRATE; -import static com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry.mountedFluidStorage; -import static com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry.mountedItemStorage; +import static com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries.mountedFluidStorage; +import static com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries.mountedItemStorage; import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviour; import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock; import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll; @@ -768,7 +768,7 @@ public class AllBlocks { .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour())) - .onRegister(block -> TrainConductorHandler.registerBlazeBurner()) + .onRegister(TrainConductorHandler::registerBlazeBurner) .item(BlazeBurnerBlockItem::withBlaze) .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) .build() diff --git a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java index 85eefbb530..a5ef6b7ff0 100644 --- a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java +++ b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java @@ -1,94 +1,39 @@ package com.simibubi.create; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.annotations.Nullable; +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.content.contraptions.behaviour.DoorMovingInteraction; -import com.simibubi.create.content.contraptions.behaviour.FenceGateMovingInteraction; import com.simibubi.create.content.contraptions.behaviour.LeverMovingInteraction; import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.behaviour.TrapdoorMovingInteraction; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.tterrag.registrate.util.nullness.NonNullConsumer; -import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; public class AllInteractionBehaviours { - private static final AttachedRegistry BLOCK_BEHAVIOURS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final List GLOBAL_BEHAVIOURS = new ArrayList<>(); - - public static void registerBehaviour(ResourceLocation block, MovingInteractionBehaviour provider) { - BLOCK_BEHAVIOURS.register(block, provider); - } - - public static void registerBehaviour(Block block, MovingInteractionBehaviour provider) { - BLOCK_BEHAVIOURS.register(block, provider); - } - - public static void registerBehaviourProvider(BehaviourProvider provider) { - GLOBAL_BEHAVIOURS.add(provider); - } + public static final AttachedRegistry REGISTRY = AttachedRegistry.create(); @Nullable public static MovingInteractionBehaviour getBehaviour(BlockState state) { - MovingInteractionBehaviour behaviour = BLOCK_BEHAVIOURS.get(state.getBlock()); - if (behaviour != null) { - return behaviour; - } - - for (BehaviourProvider provider : GLOBAL_BEHAVIOURS) { - behaviour = provider.getBehaviour(state); - if (behaviour != null) { - return behaviour; - } - } - - return null; + return REGISTRY.get(state.getBlock()); } - public static NonNullConsumer interactionBehaviour( - MovingInteractionBehaviour behaviour) { - return b -> registerBehaviour(b, behaviour); + /** + * Creates a consumer that will register a behavior to a block. Useful for Registrate. + */ + public static NonNullConsumer interactionBehaviour(MovingInteractionBehaviour behaviour) { + return b -> REGISTRY.register(b, behaviour); } static void registerDefaults() { - registerBehaviour(Blocks.LEVER, new LeverMovingInteraction()); + REGISTRY.register(Blocks.LEVER, new LeverMovingInteraction()); - DoorMovingInteraction doorBehaviour = new DoorMovingInteraction(); - registerBehaviourProvider(state -> { - if (state.is(BlockTags.WOODEN_DOORS)) { - return doorBehaviour; - } - return null; - }); - - TrapdoorMovingInteraction trapdoorBehaviour = new TrapdoorMovingInteraction(); - registerBehaviourProvider(state -> { - if (state.is(BlockTags.WOODEN_TRAPDOORS)) { - return trapdoorBehaviour; - } - return null; - }); - - FenceGateMovingInteraction fenceGateBehavior = new FenceGateMovingInteraction(); - registerBehaviourProvider(state -> { - if (state.is(BlockTags.FENCE_GATES)) { - return fenceGateBehavior; - } - return null; - }); - - } - - public interface BehaviourProvider { - @Nullable - MovingInteractionBehaviour getBehaviour(BlockState state); + REGISTRY.registerProvider(AttachedRegistry.Provider.forBlockTag(BlockTags.WOODEN_DOORS, new DoorMovingInteraction())); + REGISTRY.registerProvider(AttachedRegistry.Provider.forBlockTag(BlockTags.WOODEN_TRAPDOORS, new TrapdoorMovingInteraction())); + REGISTRY.registerProvider(AttachedRegistry.Provider.forBlockTag(BlockTags.FENCE_GATES, new TrapdoorMovingInteraction())); } } diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index 6dde486402..2be5bc5933 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -1,74 +1,41 @@ package com.simibubi.create; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.content.contraptions.behaviour.BellMovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.CampfireMovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.dispenser.DispenserMovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.dispenser.DropperMovementBehaviour; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.tterrag.registrate.util.nullness.NonNullConsumer; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; public class AllMovementBehaviours { - private static final AttachedRegistry BLOCK_BEHAVIOURS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final List GLOBAL_BEHAVIOURS = new ArrayList<>(); - - public static void registerBehaviour(ResourceLocation block, MovementBehaviour behaviour) { - BLOCK_BEHAVIOURS.register(block, behaviour); - } - - public static void registerBehaviour(Block block, MovementBehaviour behaviour) { - BLOCK_BEHAVIOURS.register(block, behaviour); - } - - public static void registerBehaviourProvider(BehaviourProvider provider) { - GLOBAL_BEHAVIOURS.add(provider); - } + public static final AttachedRegistry REGISTRY = AttachedRegistry.create(); @Nullable public static MovementBehaviour getBehaviour(BlockState state) { - MovementBehaviour behaviour = BLOCK_BEHAVIOURS.get(state.getBlock()); - if (behaviour != null) { - return behaviour; - } - - for (BehaviourProvider provider : GLOBAL_BEHAVIOURS) { - behaviour = provider.getBehaviour(state); - if (behaviour != null) { - return behaviour; - } - } - - return null; + return REGISTRY.get(state.getBlock()); } - public static NonNullConsumer movementBehaviour( - MovementBehaviour behaviour) { - return b -> registerBehaviour(b, behaviour); + /** + * Creates a consumer that will register a behavior to a block. Useful for Registrate. + */ + public static NonNullConsumer movementBehaviour(MovementBehaviour behaviour) { + return b -> REGISTRY.register(b, behaviour); } static void registerDefaults() { - registerBehaviour(Blocks.BELL, new BellMovementBehaviour()); - registerBehaviour(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); - registerBehaviour(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour()); + REGISTRY.register(Blocks.BELL, new BellMovementBehaviour()); + REGISTRY.register(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); + REGISTRY.register(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour()); DispenserMovementBehaviour.gatherMovedDispenseItemBehaviours(); - registerBehaviour(Blocks.DISPENSER, new DispenserMovementBehaviour()); - registerBehaviour(Blocks.DROPPER, new DropperMovementBehaviour()); - } - - public interface BehaviourProvider { - @Nullable - MovementBehaviour getBehaviour(BlockState state); + REGISTRY.register(Blocks.DISPENSER, new DispenserMovementBehaviour()); + REGISTRY.register(Blocks.DROPPER, new DropperMovementBehaviour()); } } diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 41540fc060..4477ab56af 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -33,7 +33,6 @@ import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.KineticStats; import com.simibubi.create.foundation.item.TooltipModifier; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.simibubi.create.foundation.utility.CreateNBTProcessors; import com.simibubi.create.infrastructure.command.ServerLagger; import com.simibubi.create.infrastructure.config.AllConfigs; @@ -48,6 +47,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.level.Level; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.MinecraftForge; @@ -140,8 +140,6 @@ public class Create { // FIXME: some of these registrations are not thread-safe AllMovementBehaviours.registerDefaults(); AllInteractionBehaviours.registerDefaults(); - AllPortalTracks.registerDefaults(); - AllDisplayBehaviours.registerDefaults(); ContraptionMovementSetting.registerDefaults(); BogeySizes.init(); AllBogeyStyles.init(); @@ -173,9 +171,10 @@ public class Create { // These registrations use Create's registered objects directly so they must run after registration has finished. BuiltinPotatoProjectileTypes.register(); BoilerHeaters.registerDefaults(); + AllPortalTracks.registerDefaults(); + AllDisplayBehaviours.registerDefaults(); // -- - AttachedRegistry.unwrapAll(); AllAdvancements.register(); AllTriggers.register(); }); diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistry.java b/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistries.java similarity index 78% rename from src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistry.java rename to src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistries.java index 845637970c..b78dcb0168 100644 --- a/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistry.java +++ b/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistries.java @@ -3,7 +3,7 @@ package com.simibubi.create.api.contraption.storage; import com.simibubi.create.Create; import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; -import com.simibubi.create.api.lookup.BlockLookup; +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.impl.contraption.storage.MountedStorageTypeRegistryImpl; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.util.entry.RegistryEntry; @@ -12,9 +12,10 @@ import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.Block; + import net.minecraftforge.registries.IForgeRegistry; -public class MountedStorageTypeRegistry { +public class MountedStorageTypeRegistries { public static final ResourceKey>> ITEMS = ResourceKey.createRegistryKey( Create.asResource("mounted_item_storage_type") ); @@ -22,16 +23,8 @@ public class MountedStorageTypeRegistry { Create.asResource("mounted_fluid_storage_type") ); - /** - * Lookup used for finding the item storage type associated with a block. - * @see BlockLookup - */ - public static final BlockLookup> ITEM_LOOKUP = MountedStorageTypeRegistryImpl.ITEM_LOOKUP; - /** - * Lookup used for finding the fluid storage type associated with a block. - * @see BlockLookup - */ - public static final BlockLookup> FLUID_LOOKUP = MountedStorageTypeRegistryImpl.FLUID_LOOKUP; + public static final AttachedRegistry> ITEM_STORAGES = MountedStorageTypeRegistryImpl.ITEM_STORAGES; + public static final AttachedRegistry> FLUID_STORAGES = MountedStorageTypeRegistryImpl.FLUID_STORAGES; /** * @throws NullPointerException if called before registry registration @@ -52,7 +45,7 @@ public class MountedStorageTypeRegistry { * that will register the given MountedItemStorageType to a block when ready. */ public static NonNullUnaryOperator> mountedItemStorage(RegistryEntry> type) { - return builder -> builder.onRegisterAfter(ITEMS, block -> ITEM_LOOKUP.register(block, type.get())); + return builder -> builder.onRegisterAfter(ITEMS, block -> ITEM_STORAGES.register(block, type.get())); } /** @@ -60,6 +53,6 @@ public class MountedStorageTypeRegistry { * that will register the given MountedFluidStorageType to a block when ready. */ public static NonNullUnaryOperator> mountedFluidStorage(RegistryEntry> type) { - return builder -> builder.onRegisterAfter(ITEMS, block -> FLUID_LOOKUP.register(block, type.get())); + return builder -> builder.onRegisterAfter(ITEMS, block -> FLUID_STORAGES.register(block, type.get())); } } diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java index 75dc708195..977a44ef92 100644 --- a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java @@ -3,7 +3,7 @@ package com.simibubi.create.api.contraption.storage.fluid; import org.jetbrains.annotations.Nullable; import com.mojang.serialization.Codec; -import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries; import net.minecraft.core.BlockPos; import net.minecraft.util.ExtraCodecs; @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState; public abstract class MountedFluidStorageType { public static final Codec> CODEC = ExtraCodecs.lazyInitializedCodec( - () -> MountedStorageTypeRegistry.getFluidsRegistry().getCodec() + () -> MountedStorageTypeRegistries.getFluidsRegistry().getCodec() ); public final Codec codec; diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java index cf1ae43e8b..645ea1a694 100644 --- a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java @@ -1,7 +1,8 @@ package com.simibubi.create.api.contraption.storage.fluid.registrate; -import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries; import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.registry.AttachedRegistry; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.AbstractBuilder; import com.tterrag.registrate.builders.BuilderCallback; @@ -14,17 +15,17 @@ public class MountedFluidStorageTypeBuilder private final T type; public MountedFluidStorageTypeBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, T type) { - super(owner, parent, name, callback, MountedStorageTypeRegistry.FLUIDS); + super(owner, parent, name, callback, MountedStorageTypeRegistries.FLUIDS); this.type = type; } public MountedFluidStorageTypeBuilder registerTo(Block block) { - MountedStorageTypeRegistry.FLUID_LOOKUP.register(block, this.type); + MountedStorageTypeRegistries.FLUID_STORAGES.register(block, this.type); return this; } public MountedFluidStorageTypeBuilder registerTo(TagKey tag) { - MountedStorageTypeRegistry.FLUID_LOOKUP.registerTag(tag, this.type); + MountedStorageTypeRegistries.FLUID_STORAGES.registerProvider(AttachedRegistry.Provider.forBlockTag(tag, this.type)); return this; } diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java index 0376f0d776..99b85cfc95 100644 --- a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java @@ -3,7 +3,7 @@ package com.simibubi.create.api.contraption.storage.item; import org.jetbrains.annotations.Nullable; import com.mojang.serialization.Codec; -import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries; import net.minecraft.core.BlockPos; import net.minecraft.util.ExtraCodecs; @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState; public abstract class MountedItemStorageType { public static final Codec> CODEC = ExtraCodecs.lazyInitializedCodec( - () -> MountedStorageTypeRegistry.getItemsRegistry().getCodec() + () -> MountedStorageTypeRegistries.getItemsRegistry().getCodec() ); public final Codec codec; diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java index 0739a772c0..3b94069568 100644 --- a/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java @@ -1,7 +1,8 @@ package com.simibubi.create.api.contraption.storage.item.registrate; -import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries; import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.registry.AttachedRegistry; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.AbstractBuilder; import com.tterrag.registrate.builders.BuilderCallback; @@ -14,17 +15,17 @@ public class MountedItemStorageTypeBuilder, private final T type; public MountedItemStorageTypeBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, T type) { - super(owner, parent, name, callback, MountedStorageTypeRegistry.ITEMS); + super(owner, parent, name, callback, MountedStorageTypeRegistries.ITEMS); this.type = type; } public MountedItemStorageTypeBuilder registerTo(Block block) { - MountedStorageTypeRegistry.ITEM_LOOKUP.register(block, this.type); + MountedStorageTypeRegistries.ITEM_STORAGES.register(block, this.type); return this; } public MountedItemStorageTypeBuilder registerTo(TagKey tag) { - MountedStorageTypeRegistry.ITEM_LOOKUP.registerTag(tag, this.type); + MountedStorageTypeRegistries.ITEM_STORAGES.registerProvider(AttachedRegistry.Provider.forBlockTag(tag, this.type)); return this; } diff --git a/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java b/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java index 05cd1e09e3..ea84d580f3 100644 --- a/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java +++ b/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java @@ -1,52 +1,49 @@ package com.simibubi.create.api.contraption.train; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllInteractionBehaviours; -import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; - -import com.simibubi.create.content.processing.burner.BlockBasedTrainConductorInteractionBehaviour; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockState; - - -import org.jetbrains.annotations.ApiStatus; - import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; +import org.jetbrains.annotations.ApiStatus; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllInteractionBehaviours; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.processing.burner.BlockBasedTrainConductorInteractionBehaviour; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + /** * All required methods to make your block a train conductor similar to the blaze burner */ +@FunctionalInterface public interface TrainConductorHandler { - @ApiStatus.Internal List CONDUCTOR_HANDLERS = new ArrayList<>(); - - boolean isValidConductor(BlockState state); private static void registerHandler(TrainConductorHandler handler) { CONDUCTOR_HANDLERS.add(handler); } - static void registerConductor(ResourceLocation blockRl, Predicate isValidConductor, UpdateScheduleCallback updateScheduleCallback) { - AllInteractionBehaviours.registerBehaviour(blockRl, new BlockBasedTrainConductorInteractionBehaviour(isValidConductor, updateScheduleCallback)); + static void registerConductor(Block block, Predicate isValidConductor, UpdateScheduleCallback updateScheduleCallback) { + BlockBasedTrainConductorInteractionBehaviour behavior = new BlockBasedTrainConductorInteractionBehaviour(isValidConductor, updateScheduleCallback); + AllInteractionBehaviours.REGISTRY.register(block, behavior); registerHandler(isValidConductor::test); } @ApiStatus.Internal - static void registerBlazeBurner() { - registerConductor(AllBlocks.BLAZE_BURNER.getId(), blockState -> AllBlocks.BLAZE_BURNER.has(blockState) + static void registerBlazeBurner(Block block) { + registerConductor(block, blockState -> AllBlocks.BLAZE_BURNER.has(blockState) && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.NONE, UpdateScheduleCallback.EMPTY); } + @FunctionalInterface interface UpdateScheduleCallback { - UpdateScheduleCallback EMPTY = (hasSchedule, blockState, blockStateSetter) -> {}; void update(boolean hasSchedule, BlockState currentBlockState, Consumer blockStateSetter); diff --git a/src/main/java/com/simibubi/create/api/contraption/transformable/ContraptionTransformableRegistry.java b/src/main/java/com/simibubi/create/api/contraption/transformable/ContraptionTransformableRegistry.java deleted file mode 100644 index 15456daa18..0000000000 --- a/src/main/java/com/simibubi/create/api/contraption/transformable/ContraptionTransformableRegistry.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.api.contraption.transformable; - -import com.simibubi.create.content.contraptions.StructureTransform; -import com.simibubi.create.impl.contraption.transformable.ContraptionTransformableRegistryImpl; - -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.minecraft.world.level.block.state.BlockState; - -/** - * Registry for registering new contraption transformations - * to properly place blocks when disassembled after being part of a contraption - */ -public class ContraptionTransformableRegistry { - /** - * Register a new transform for a provided block - * - * @param block The block you want to register a new {@link TransformableBlock} for - * @param transformableBlock The transform that should be applied whenever this block is being placed from - * contraption disassembly - */ - public static void registerForBlock(Block block, TransformableBlock transformableBlock) { - ContraptionTransformableRegistryImpl.registerForBlock(block, transformableBlock); - } - - /** - * Register a new transform for a provided block entity type - * - * @param blockEntityType The blockEntityType you want to register a new {@link TransformableBlockEntity} for - * @param transformableBlockEntity The transform that should be applied whenever this block entity type is - * being placed from contraption disassembly - */ - public static void registerForBlockEntity(BlockEntityType blockEntityType, TransformableBlockEntity transformableBlockEntity) { - ContraptionTransformableRegistryImpl.registerForBlockEntity(blockEntityType, transformableBlockEntity); - } - - // --- Interfaces that provide the context that would be accessible if you implemented the ITransformable* interfaces --- - - @FunctionalInterface - public interface TransformableBlock { - BlockState transform(Block block, BlockState state, StructureTransform transform); - } - - @FunctionalInterface - public interface TransformableBlockEntity { - void transform(BlockEntity blockEntity, StructureTransform transform); - } -} diff --git a/src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java b/src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java new file mode 100644 index 0000000000..f46534238c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java @@ -0,0 +1,28 @@ +package com.simibubi.create.api.contraption.transformable; + +import com.simibubi.create.api.registry.AttachedRegistry; +import com.simibubi.create.content.contraptions.StructureTransform; + +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.minecraft.world.level.block.state.BlockState; + +/** + * Registry for custom transformations to apply to blocks after they've been moved by a contraption. + * These interfaces are alternatives to the {@link ITransformableBlock} and {@link ITransformableBlockEntity} interfaces. + */ +public class MovedBlockTransformerRegistries { + public static final AttachedRegistry BLOCK_TRANSFORMERS = AttachedRegistry.create(); + public static final AttachedRegistry, BlockEntityTransformer> BLOCK_ENTITY_TRANSFORMERS = AttachedRegistry.create(); + + @FunctionalInterface + public interface BlockTransformer { + BlockState transform(Block block, BlockState state, StructureTransform transform); + } + + @FunctionalInterface + public interface BlockEntityTransformer { + void transform(BlockEntity be, StructureTransform transform); + } +} diff --git a/src/main/java/com/simibubi/create/api/lookup/BlockLookup.java b/src/main/java/com/simibubi/create/api/lookup/BlockLookup.java deleted file mode 100644 index ce0936b0e6..0000000000 --- a/src/main/java/com/simibubi/create/api/lookup/BlockLookup.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.api.lookup; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.impl.lookup.BlockLookupImpl; - -import net.minecraft.tags.TagKey; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -/** - * Lookup for objects provided by blocks. Values can either be registered directly - * or found lazily through providers. Providers are only queried once per block. - * If they return a value, that value is cached. If they don't, that block is recorded - * as not having a corresponding value. - *

- * Provided values are reset on resource reloads and will be re-queried and re-cached the - * next time a block is queried. - *

- * All providers are expected to be registered synchronously during game init. - * Adding new ones late is not supported. - */ -@ApiStatus.NonExtendable -public interface BlockLookup { - @Nullable - T find(Block block); - - /** - * Shortcut to avoid calling getBlock() on a BlockState. - */ - @Nullable - T find(BlockState state); - - /** - * Register a value to one block. - */ - void register(Block block, T value); - - /** - * Register a value to all entries of a tag. - */ - void registerTag(TagKey tag, T value); - - /** - * Register a new provider that will be queried. - * Providers are queried in reverse-registration order. - */ - void registerProvider(Provider provider); - - static BlockLookup create() { - return new BlockLookupImpl<>(); - } - - static BlockLookup create(Provider initialProvider) { - BlockLookup lookup = new BlockLookupImpl<>(); - lookup.registerProvider(initialProvider); - return lookup; - } - - @FunctionalInterface - interface Provider { - @Nullable - T get(Block block); - } -} diff --git a/src/main/java/com/simibubi/create/api/registry/AttachedRegistry.java b/src/main/java/com/simibubi/create/api/registry/AttachedRegistry.java new file mode 100644 index 0000000000..0f44dd135a --- /dev/null +++ b/src/main/java/com/simibubi/create/api/registry/AttachedRegistry.java @@ -0,0 +1,92 @@ +package com.simibubi.create.api.registry; + +import java.util.function.Function; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.impl.registry.AttachedRegistryImpl; +import com.simibubi.create.impl.registry.TagProviderImpl; + +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; + +/** + * A mapping of registered objects to something else. + * This class is thread-safe, and may be safely used during parallel mod init. + */ +public interface AttachedRegistry { + /** + * Register an association between a key and a value. + * @throws IllegalArgumentException if the object already has an associated value + */ + void register(K object, V value); + + /** + * Add a new provider to this registry. For information on providers, see {@link Provider}. + * @throws IllegalArgumentException if the provider has already been registered to this registry + */ + void registerProvider(Provider provider); + + /** + * Invalidate the cached values provided by the given provider, so they get re-computed on the next query. + * @throws IllegalArgumentException if the provider is not registered to this registry + */ + void invalidateProvider(Provider provider); + + /** + * Query the value associated with the given object. May be null if no association is present. + */ + @Nullable + V get(K object); + + static AttachedRegistry create() { + return new AttachedRegistryImpl<>(); + } + + /** + * A provider can provide values to the registry in a lazy fashion. When a key does not have an + * associated value, all providers will be queried in reverse-registration order. + *

+ * The values returned by providers are cached so that repeated queries always return the same value. + * To invalidate the cache of a provider, call {@link AttachedRegistry#invalidateProvider(Provider)}. + */ + @FunctionalInterface + interface Provider { + @Nullable + V get(K object); + + /** + * Called by the AttachedRegistry this provider is registered to after it's registered. + * This is useful for behavior that should only happen if a provider is actually registered, + * such as registering event listeners. + */ + default void onRegister(AttachedRegistry registry) { + } + + /** + * Create a provider that will return the same value for all entries in a tag. + * The Provider will invalidate itself when tags are reloaded. + */ + static Provider forTag(TagKey tag, Function> holderGetter, V value) { + return new TagProviderImpl<>(tag, holderGetter, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is Block. + */ + @SuppressWarnings("deprecation") + static Provider forBlockTag(TagKey tag, V value) { + return new TagProviderImpl<>(tag, Block::builtInRegistryHolder, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is Item. + */ + @SuppressWarnings("deprecation") + static Provider forItemTag(TagKey tag, V value) { + return new TagProviderImpl<>(tag, Item::builtInRegistryHolder, value); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java b/src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java new file mode 100644 index 0000000000..bc6e778f9f --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java @@ -0,0 +1,27 @@ +package com.simibubi.create.api.schematic.nbt; + +import com.simibubi.create.api.registry.AttachedRegistry; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +/** + * Registry for safe NBT writers, used for filtering unsafe BlockEntity data out of schematics. + *

+ * This is used to exclude specific tags that would result in exploits, ex. signs that execute commands when clicked. + *

+ * This is provided as an alternative to {@link IPartialSafeNBT}. + */ +public class SafeNbtWriterRegistry { + public static final AttachedRegistry, SafeNbtWriter> REGISTRY = AttachedRegistry.create(); + + @FunctionalInterface + public interface SafeNbtWriter { + /** + * Write filtered, safe NBT to the given tag. This is always called on the logical server. + * @param tag the NBT tag to write to + */ + void writeSafe(BlockEntity be, CompoundTag tag); + } +} diff --git a/src/main/java/com/simibubi/create/api/schematic/nbt/SchematicSafeNBTRegistry.java b/src/main/java/com/simibubi/create/api/schematic/nbt/SchematicSafeNBTRegistry.java deleted file mode 100644 index 846f96a4ab..0000000000 --- a/src/main/java/com/simibubi/create/api/schematic/nbt/SchematicSafeNBTRegistry.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.simibubi.create.api.schematic.nbt; - -import com.simibubi.create.impl.schematic.nbt.SchematicSafeNBTRegistryImpl; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; - -/** - * Registry for modifying the data of BlockEntities when being placed with the schematic system. - *
- * Mostly used to exclude specific tags that would result in exploits from being written. - */ -public class SchematicSafeNBTRegistry { - /** - * Register a new partial safe nbt provider for a specific blockEntityType - * - * @param blockEntityType The block entity type you would like to register this for - * @param safeNBT The custom PartialSafeNBT provider you would like to register for this blockEntityType, - * your {@link ContextProvidingPartialSafeNBT#writeSafe(BlockEntity, CompoundTag)} method will be - * called on the passed {@link ContextProvidingPartialSafeNBT} - * when the block entities data is being prepared for placement. - */ - public static void register(BlockEntityType blockEntityType, ContextProvidingPartialSafeNBT safeNBT) { - SchematicSafeNBTRegistryImpl.register(blockEntityType, safeNBT); - } - - // --- Interface that provides the context that would be available if you were to implement IPartialSafeNBT instead --- - - @FunctionalInterface - public interface ContextProvidingPartialSafeNBT { - /** - * This will always be called from the logical server - */ - void writeSafe(BlockEntity blockEntity, CompoundTag tag); - } -} diff --git a/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java b/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java new file mode 100644 index 0000000000..4c4a12a01d --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java @@ -0,0 +1,45 @@ +package com.simibubi.create.api.schematic.requirement; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.AttachedRegistry; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +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.minecraft.world.level.block.state.BlockState; + +/** + * Registries for custom schematic requirements for blocks, block entities, and entities. These requirements determine + * the items that are needed for placement into the world through schematics. + *

+ * This is provided as an alternative to the following interfaces: + *

    + *
  • {@link ISpecialBlockItemRequirement}
  • + *
  • {@link ISpecialBlockEntityItemRequirement}
  • + *
  • {@link ISpecialEntityItemRequirement}
  • + *
+ */ +public class SchematicRequirementRegistries { + public static final AttachedRegistry BLOCKS = AttachedRegistry.create(); + public static final AttachedRegistry, BlockEntityRequirement> BLOCK_ENTITIES = AttachedRegistry.create(); + public static final AttachedRegistry, EntityRequirement> ENTITIES = AttachedRegistry.create(); + + @FunctionalInterface + public interface BlockRequirement { + ItemRequirement getRequiredItems(Block block, BlockState state, @Nullable BlockEntity blockEntity); + } + + @FunctionalInterface + public interface BlockEntityRequirement { + ItemRequirement getRequiredItems(BlockEntity blockEntity, BlockState state); + } + + @FunctionalInterface + public interface EntityRequirement { + ItemRequirement getRequiredItems(Entity entity); + } +} diff --git a/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementsRegistry.java b/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementsRegistry.java deleted file mode 100644 index 3df156e6bd..0000000000 --- a/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementsRegistry.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.simibubi.create.api.schematic.requirement; - -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.content.schematics.requirement.ItemRequirement; -import com.simibubi.create.impl.schematic.requirement.SchematicRequirementsRegistryImpl; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -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.minecraft.world.level.block.state.BlockState; - -/** - * Registry for schematic requirements for blocks, block entities, and entities. - */ -public class SchematicRequirementsRegistry { - /** - * Register a new special requirement for a specified block - * - * @param block The block you want to register a {@link BlockRequirement} for - * @param requirement The requirement you would like to add to this block, - * the {@link BlockRequirement#getRequiredItems(Block, BlockState, BlockEntity)} - * method will be called on the {@link BlockRequirement} you have provided, - * and you will be able to insert requirements based off the context that is given - */ - public static void registerForBlock(Block block, BlockRequirement requirement) { - SchematicRequirementsRegistryImpl.registerForBlock(block, requirement); - } - - /** - * Register a new special requirement for a specified block - * - * @param block The id of the block you want to register a {@link BlockRequirement} for - * @param requirement The requirement you would like to add to this block, - * the {@link BlockRequirement#getRequiredItems(Block, BlockState, BlockEntity)} - * method will be called on the {@link BlockRequirement} you have provided, - * and you will be able to insert requirements based off the context that is given - */ - public static void registerForBlock(ResourceLocation block, BlockRequirement requirement) { - SchematicRequirementsRegistryImpl.registerForBlock(block, requirement); - } - - /** - * Register a new special requirement for a specified block entity type - * - * @param blockEntityType The blockEntityType you want to register a {@link BlockEntityRequirement} for - * @param requirement The requirement you would like to add to this block entity type, - * the {@link BlockEntityRequirement#getRequiredItems(BlockEntity, BlockState)} - * method will be called on the {@link BlockEntityRequirement} you have provided, - * and you will be able to insert requirements based off the context that is given - */ - public static void registerForBlockEntity(BlockEntityType blockEntityType, BlockEntityRequirement requirement) { - SchematicRequirementsRegistryImpl.registerForBlockEntity(blockEntityType, requirement); - } - - /** - * Register a new special requirement for a specified block entity type - * - * @param blockEntityType The id of the blockEntityType you want to register a {@link BlockEntityRequirement} for - * @param requirement The requirement you would like to add to this block entity type, - * the {@link BlockEntityRequirement#getRequiredItems(BlockEntity, BlockState)} - * method will be called on the {@link BlockEntityRequirement} you have provided, - * and you will be able to insert requirements based off the context that is given - */ - public static void registerForBlockEntity(ResourceLocation blockEntityType, BlockEntityRequirement requirement) { - SchematicRequirementsRegistryImpl.registerForBlockEntity(blockEntityType, requirement); - } - - /** - * Register a new special requirement for a specified entity type - * - * @param entityType The entityType you want to register a {@link EntityRequirement} for - * @param requirement The requirement you would like to add to this entity type, - * the {@link EntityRequirement#getRequiredItems(Entity)} - * method will be called on the {@link EntityRequirement} you have provided, - * and you will be able to insert requirements based off the context that is given - */ - public static void registerForEntity(EntityType entityType, EntityRequirement requirement) { - SchematicRequirementsRegistryImpl.registerForEntity(entityType, requirement); - } - - /** - * Register a new special requirement for a specified entity type - * - * @param entityType The id of the entityType you want to register a {@link EntityRequirement} for - * @param requirement The requirement you would like to add to this entity type, - * the {@link EntityRequirement#getRequiredItems(Entity)} - * method will be called on the {@link EntityRequirement} you have provided, - * and you will be able to insert requirements based off the context that is given - */ - public static void registerForEntity(ResourceLocation entityType, EntityRequirement requirement) { - SchematicRequirementsRegistryImpl.registerForEntity(entityType, requirement); - } - - // --- Interfaces that provide the context that would be accessible if you implemented the ISpecial* interfaces --- - - @FunctionalInterface - public interface BlockRequirement { - ItemRequirement getRequiredItems(Block block, BlockState state, @Nullable BlockEntity blockEntity); - } - - @FunctionalInterface - public interface BlockEntityRequirement { - ItemRequirement getRequiredItems(BlockEntity blockEntity, BlockState state); - } - - @FunctionalInterface - public interface EntityRequirement { - ItemRequirement getRequiredItems(Entity entity); - } -} - diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java index a8296696b4..7e4878269a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java @@ -1,39 +1,30 @@ package com.simibubi.create.content.contraptions; -import com.simibubi.create.foundation.utility.AttachedRegistry; +import java.util.Collection; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.infrastructure.config.AllConfigs; -import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraftforge.common.extensions.IForgeBlock; -import net.minecraftforge.registries.ForgeRegistries; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.function.Supplier; +import net.minecraftforge.common.extensions.IForgeBlock; public enum ContraptionMovementSetting { MOVABLE, NO_PICKUP, UNMOVABLE; - private static final AttachedRegistry> SETTING_SUPPLIERS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - - public static void register(ResourceLocation block, Supplier settingSupplier) { - SETTING_SUPPLIERS.register(block, settingSupplier); - } - - public static void register(Block block, Supplier settingSupplier) { - SETTING_SUPPLIERS.register(block, settingSupplier); - } + public static final AttachedRegistry> REGISTRY = AttachedRegistry.create(); @Nullable public static ContraptionMovementSetting get(Block block) { if (block instanceof IMovementSettingProvider provider) return provider.getContraptionMovementSetting(); - Supplier supplier = SETTING_SUPPLIERS.get(block); - if (supplier == null) - return null; - return supplier.get(); + Supplier supplier = REGISTRY.get(block); + return supplier == null ? null : supplier.get(); } public static boolean allAre(Collection blocks, ContraptionMovementSetting are) { @@ -45,12 +36,12 @@ public enum ContraptionMovementSetting { } public static void registerDefaults() { - register(Blocks.SPAWNER, () -> AllConfigs.server().kinetics.spawnerMovement.get()); - register(Blocks.BUDDING_AMETHYST, () -> AllConfigs.server().kinetics.amethystMovement.get()); - register(Blocks.OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); - register(Blocks.CRYING_OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); - register(Blocks.RESPAWN_ANCHOR, () -> AllConfigs.server().kinetics.obsidianMovement.get()); - register(Blocks.REINFORCED_DEEPSLATE, () -> AllConfigs.server().kinetics.reinforcedDeepslateMovement.get()); + REGISTRY.register(Blocks.SPAWNER, () -> AllConfigs.server().kinetics.spawnerMovement.get()); + REGISTRY.register(Blocks.BUDDING_AMETHYST, () -> AllConfigs.server().kinetics.amethystMovement.get()); + REGISTRY.register(Blocks.OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + REGISTRY.register(Blocks.CRYING_OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + REGISTRY.register(Blocks.RESPAWN_ANCHOR, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + REGISTRY.register(Blocks.REINFORCED_DEEPSLATE, () -> AllConfigs.server().kinetics.reinforcedDeepslateMovement.get()); } public interface IMovementSettingProvider extends IForgeBlock { diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java index 8ff513095b..7d2886cf22 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java @@ -17,7 +17,7 @@ import com.google.common.collect.Sets.SetView; import com.mojang.datafixers.util.Pair; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries; import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; @@ -144,7 +144,7 @@ public class MountedStorageManager { } public void addBlock(Level level, BlockState state, BlockPos globalPos, BlockPos localPos, @Nullable BlockEntity be) { - MountedItemStorageType itemType = MountedStorageTypeRegistry.ITEM_LOOKUP.find(state); + MountedItemStorageType itemType = MountedStorageTypeRegistries.ITEM_STORAGES.get(state.getBlock()); if (itemType != null) { MountedItemStorage storage = itemType.mount(level, state, globalPos, be); if (storage != null) { @@ -152,7 +152,7 @@ public class MountedStorageManager { } } - MountedFluidStorageType fluidType = MountedStorageTypeRegistry.FLUID_LOOKUP.find(state); + MountedFluidStorageType fluidType = MountedStorageTypeRegistries.FLUID_STORAGES.get(state.getBlock()); if (fluidType != null) { MountedFluidStorage storage = fluidType.mount(level, state, globalPos, be); if (storage != null) { @@ -167,7 +167,7 @@ public class MountedStorageManager { MountedItemStorage itemStorage = this.getAllItemStorages().get(localPos); if (itemStorage != null) { - MountedItemStorageType expectedType = MountedStorageTypeRegistry.ITEM_LOOKUP.find(state); + MountedItemStorageType expectedType = MountedStorageTypeRegistries.ITEM_STORAGES.get(state.getBlock()); if (itemStorage.type == expectedType) { itemStorage.unmount(level, state, globalPos, be); } @@ -175,7 +175,7 @@ public class MountedStorageManager { MountedFluidStorage fluidStorage = this.getFluids().storages.get(localPos); if (fluidStorage != null) { - MountedFluidStorageType expectedType = MountedStorageTypeRegistry.FLUID_LOOKUP.find(state); + MountedFluidStorageType expectedType = MountedStorageTypeRegistries.FLUID_STORAGES.get(state.getBlock()); if (fluidStorage.type == expectedType) { fluidStorage.unmount(level, state, globalPos, be); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java b/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java index f4b0bf3422..37e2684413 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java +++ b/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java @@ -4,10 +4,11 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; -import com.simibubi.create.api.contraption.transformable.ContraptionTransformableRegistry; import com.simibubi.create.api.contraption.transformable.ITransformableBlock; import com.simibubi.create.api.contraption.transformable.ITransformableBlockEntity; -import com.simibubi.create.impl.contraption.transformable.ContraptionTransformableRegistryImpl; +import com.simibubi.create.api.contraption.transformable.MovedBlockTransformerRegistries; +import com.simibubi.create.api.contraption.transformable.MovedBlockTransformerRegistries.BlockEntityTransformer; +import com.simibubi.create.api.contraption.transformable.MovedBlockTransformerRegistries.BlockTransformer; import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; @@ -133,9 +134,9 @@ public class StructureTransform { } public void apply(BlockEntity be) { - ContraptionTransformableRegistry.TransformableBlockEntity transformableBlockEntity = ContraptionTransformableRegistryImpl.get(be.getType()); - if (transformableBlockEntity != null) { - transformableBlockEntity.transform(be, this); + BlockEntityTransformer transformer = MovedBlockTransformerRegistries.BLOCK_ENTITY_TRANSFORMERS.get(be.getType()); + if (transformer != null) { + transformer.transform(be, this); } else if (be instanceof ITransformableBlockEntity itbe) { itbe.transform(this); } @@ -148,9 +149,9 @@ public class StructureTransform { */ public BlockState apply(BlockState state) { Block block = state.getBlock(); - ContraptionTransformableRegistry.TransformableBlock transformableBlock = ContraptionTransformableRegistryImpl.get(block); - if (transformableBlock != null) { - return transformableBlock.transform(block, state, this); + BlockTransformer transformer = MovedBlockTransformerRegistries.BLOCK_TRANSFORMERS.get(block); + if (transformer != null) { + return transformer.transform(block, state, this); } else if (block instanceof ITransformableBlock transformable) { return transformable.transform(state, this); } diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java index daec9ccaa9..077094e64f 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java @@ -1,66 +1,39 @@ package com.simibubi.create.content.fluids.tank; -import java.util.ArrayList; -import java.util.List; - -import org.jetbrains.annotations.Nullable; - import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.simibubi.create.foundation.utility.BlockHelper; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; public class BoilerHeaters { - private static final AttachedRegistry BLOCK_HEATERS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final List GLOBAL_HEATERS = new ArrayList<>(); + public static final int PASSIVE_HEAT = 0; + public static final int NO_HEAT = -1; - public static void registerHeater(ResourceLocation block, Heater heater) { - BLOCK_HEATERS.register(block, heater); - } + public static final AttachedRegistry REGISTRY = AttachedRegistry.create(); - public static void registerHeater(Block block, Heater heater) { - BLOCK_HEATERS.register(block, heater); - } - - public static void registerHeaterProvider(HeaterProvider provider) { - GLOBAL_HEATERS.add(provider); - } + public static final Heater PASSIVE_HEATER = (level, pos, state) -> BlockHelper.isNotUnheated(state) ? PASSIVE_HEAT : NO_HEAT; /** - * A return value of {@code -1} represents no heat. - * A return value of {@code 0} represents passive heat. - * All other positive values are used as the amount of active heat. + * Gets the heat at the given location. If a heater is present, queries it for heat. If not, returns {@link #NO_HEAT}. + * @see Heater#getActiveHeat(Level, BlockPos, BlockState) */ public static float getActiveHeat(Level level, BlockPos pos, BlockState state) { - Heater heater = BLOCK_HEATERS.get(state.getBlock()); - if (heater != null) { - return heater.getActiveHeat(level, pos, state); - } - - for (HeaterProvider provider : GLOBAL_HEATERS) { - heater = provider.getHeater(level, pos, state); - if (heater != null) { - return heater.getActiveHeat(level, pos, state); - } - } - - return -1; + Heater heater = REGISTRY.get(state.getBlock()); + return heater != null ? heater.getActiveHeat(level, pos, state) : NO_HEAT; } public static void registerDefaults() { - registerHeater(AllBlocks.BLAZE_BURNER.get(), (level, pos, state) -> { + REGISTRY.register(AllBlocks.BLAZE_BURNER.get(), (level, pos, state) -> { HeatLevel value = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); if (value == HeatLevel.NONE) { - return -1; + return NO_HEAT; } if (value == HeatLevel.SEETHING) { return 2; @@ -68,28 +41,19 @@ public class BoilerHeaters { if (value.isAtLeast(HeatLevel.FADING)) { return 1; } - return 0; + return PASSIVE_HEAT; }); - registerHeaterProvider((level, pos, state) -> { - if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) && BlockHelper.isNotUnheated(state)) { - return (level1, pos1, state1) -> 0; - } - return null; - }); + REGISTRY.registerProvider(AttachedRegistry.Provider.forBlockTag(AllBlockTags.PASSIVE_BOILER_HEATERS.tag, PASSIVE_HEATER)); } + @FunctionalInterface public interface Heater { /** - * A return value of {@code -1} represents no heat. - * A return value of {@code 0} represents passive heat. - * All other positive values are used as the amount of active heat. + * @return the amount of heat to provide. + * @see #NO_HEAT + * @see #PASSIVE_HEAT */ float getActiveHeat(Level level, BlockPos pos, BlockState state); } - - public interface HeaterProvider { - @Nullable - Heater getHeater(Level level, BlockPos pos, BlockState state); - } } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java index 24a0a0d194..ae936100f4 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java @@ -9,6 +9,7 @@ import java.util.Map; import javax.annotation.Nullable; import com.simibubi.create.Create; +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.compat.Mods; import com.simibubi.create.content.redstone.displayLink.source.ComputerDisplaySource; import com.simibubi.create.content.redstone.displayLink.source.DeathCounterDisplaySource; @@ -19,7 +20,6 @@ import com.simibubi.create.content.redstone.displayLink.source.ScoreboardDisplay import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; import com.simibubi.create.content.redstone.displayLink.target.LecternDisplayTarget; import com.simibubi.create.content.redstone.displayLink.target.SignDisplayTarget; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.tterrag.registrate.util.nullness.NonNullConsumer; import net.createmod.catnip.platform.CatnipServices; @@ -32,16 +32,17 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.registries.ForgeRegistries; public class AllDisplayBehaviours { public static final Map GATHERER_BEHAVIOURS = new HashMap<>(); - private static final AttachedRegistry> SOURCES_BY_BLOCK = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final AttachedRegistry, List> SOURCES_BY_BLOCK_ENTITY = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); + private static final AttachedRegistry> SOURCES_BY_BLOCK = AttachedRegistry.create(); + private static final AttachedRegistry, List> SOURCES_BY_BLOCK_ENTITY = AttachedRegistry.create(); - private static final AttachedRegistry TARGETS_BY_BLOCK = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final AttachedRegistry, DisplayTarget> TARGETS_BY_BLOCK_ENTITY = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); + private static final AttachedRegistry TARGETS_BY_BLOCK = AttachedRegistry.create(); + private static final AttachedRegistry, DisplayTarget> TARGETS_BY_BLOCK_ENTITY = AttachedRegistry.create(); public static DisplayBehaviour register(ResourceLocation id, DisplayBehaviour behaviour) { behaviour.id = id; @@ -49,34 +50,6 @@ public class AllDisplayBehaviours { return behaviour; } - public static void assignBlock(DisplayBehaviour behaviour, ResourceLocation block) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK.register(block, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK.register(block, target); - } - } - - public static void assignBlockEntity(DisplayBehaviour behaviour, ResourceLocation beType) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK_ENTITY.get(beType); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK_ENTITY.register(beType, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK_ENTITY.register(beType, target); - } - } - public static void assignBlock(DisplayBehaviour behaviour, Block block) { if (behaviour instanceof DisplaySource source) { List sources = SOURCES_BY_BLOCK.get(block); @@ -105,6 +78,15 @@ public class AllDisplayBehaviours { } } + public static void tryAssignBlockEntity(DisplayBehaviour behaviour, ResourceLocation id) { + if (ForgeRegistries.BLOCK_ENTITY_TYPES.containsKey(id)) { + BlockEntityType type = ForgeRegistries.BLOCK_ENTITY_TYPES.getValue(id); + assignBlockEntity(behaviour, type); + } else { + Create.LOGGER.warn("Block entity for display behavior wasn't found: {}. Outdated compat?", id); + } + } + public static NonNullConsumer assignDataBehaviour(DisplayBehaviour behaviour, String... suffix) { return b -> { @@ -113,7 +95,7 @@ public class AllDisplayBehaviours { if (suffix.length > 0) idSuffix += "_" + suffix[0]; assignBlock(register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), - behaviour), registryName); + behaviour), b); }; } @@ -127,7 +109,7 @@ public class AllDisplayBehaviours { assignBlockEntity( register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), behaviour), - registryName); + b); }; } @@ -237,10 +219,10 @@ public class AllDisplayBehaviours { Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource()); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("wired_modem_full")); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_normal")); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_advanced")); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_command")); + tryAssignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("wired_modem_full")); + tryAssignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_normal")); + tryAssignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_advanced")); + tryAssignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_command")); }); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java index 1e90c3a54c..4ba76575da 100644 --- a/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java +++ b/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java @@ -6,15 +6,15 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jetbrains.annotations.Nullable; + import com.simibubi.create.api.schematic.requirement.ISpecialBlockEntityItemRequirement; import com.simibubi.create.api.schematic.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.api.schematic.requirement.ISpecialEntityItemRequirement; -import com.simibubi.create.api.schematic.requirement.SchematicRequirementsRegistry; +import com.simibubi.create.api.schematic.requirement.SchematicRequirementRegistries; import com.simibubi.create.compat.framedblocks.FramedBlocksInSchematics; import com.simibubi.create.foundation.data.recipe.Mods; -import com.simibubi.create.impl.schematic.requirement.SchematicRequirementsRegistryImpl; - import net.createmod.catnip.nbt.NBTProcessors; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.ArmorStand; @@ -35,9 +35,8 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.SlabType; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.Nullable; +import net.minecraftforge.registries.ForgeRegistries; public class ItemRequirement { public static final ItemRequirement NONE = new ItemRequirement(Collections.emptyList()); @@ -71,9 +70,9 @@ public class ItemRequirement { Block block = state.getBlock(); ItemRequirement requirement; - SchematicRequirementsRegistry.BlockRequirement blockItemRequirement = SchematicRequirementsRegistryImpl.getRequirementForBlock(block); - if (blockItemRequirement != null) { - requirement = blockItemRequirement.getRequiredItems(block, state, be); + SchematicRequirementRegistries.BlockRequirement blockRequirement = SchematicRequirementRegistries.BLOCKS.get(block); + if (blockRequirement != null) { + requirement = blockRequirement.getRequiredItems(block, state, be); } else if (block instanceof ISpecialBlockItemRequirement specialBlock) { requirement = specialBlock.getRequiredItems(state, be); } else { @@ -81,9 +80,9 @@ public class ItemRequirement { } if (be != null) { - SchematicRequirementsRegistry.BlockEntityRequirement blockEntityItemRequirement = SchematicRequirementsRegistryImpl.getRequirementForBlockEntityType(be.getType()); - if (blockEntityItemRequirement != null) { - requirement = requirement.union(blockEntityItemRequirement.getRequiredItems(be, state)); + SchematicRequirementRegistries.BlockEntityRequirement beRequirement = SchematicRequirementRegistries.BLOCK_ENTITIES.get(be.getType()); + if (beRequirement != null) { + requirement = requirement.union(beRequirement.getRequiredItems(be, state)); } else if (be instanceof ISpecialBlockEntityItemRequirement specialBE) { requirement = requirement.union(specialBE.getRequiredItems(state)); } else if (com.simibubi.create.compat.Mods.FRAMEDBLOCKS.contains(block)) { @@ -134,9 +133,9 @@ public class ItemRequirement { } public static ItemRequirement of(Entity entity) { - SchematicRequirementsRegistry.EntityRequirement entityItemRequirement = SchematicRequirementsRegistryImpl.getRequirementForEntityType(entity.getType()); - if (entityItemRequirement != null) { - return entityItemRequirement.getRequiredItems(entity); + SchematicRequirementRegistries.EntityRequirement requirement = SchematicRequirementRegistries.ENTITIES.get(entity.getType()); + if (requirement != null) { + return requirement.getRequiredItems(entity); } else if (entity instanceof ISpecialEntityItemRequirement specialEntity) { return specialEntity.getRequiredItems(); } diff --git a/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java b/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java index 4e67b42468..e34465a66c 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java +++ b/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java @@ -5,13 +5,13 @@ import java.util.function.Function; import java.util.function.UnaryOperator; import com.simibubi.create.Create; +import com.simibubi.create.api.registry.AttachedRegistry; import com.simibubi.create.compat.Mods; import com.simibubi.create.compat.betterend.BetterEndPortalCompat; import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; -import com.simibubi.create.foundation.utility.AttachedRegistry; -import net.createmod.catnip.math.BlockFace; import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.BlockFace; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.registries.Registries; @@ -26,6 +26,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.phys.AABB; + import net.minecraftforge.common.util.ITeleporter; import net.minecraftforge.registries.ForgeRegistries; @@ -48,27 +49,22 @@ public class AllPortalTracks { /** * Registry mapping portal blocks to their respective {@link PortalTrackProvider}s. */ - private static final AttachedRegistry PORTAL_BEHAVIOURS = - new AttachedRegistry<>(ForgeRegistries.BLOCKS); + public static final AttachedRegistry REGISTRY = AttachedRegistry.create(); /** - * Registers a portal track integration for a given block identified by its {@link ResourceLocation}. + * Registers a portal track integration for a given block identified by its {@link ResourceLocation}, if it exists. + * If it does not, a warning will be logged. * - * @param block The resource location of the portal block. + * @param id The resource location of the portal block. * @param provider The portal track provider for the block. */ - public static void registerIntegration(ResourceLocation block, PortalTrackProvider provider) { - PORTAL_BEHAVIOURS.register(block, provider); - } - - /** - * Registers a portal track integration for a given {@link Block}. - * - * @param block The portal block. - * @param provider The portal track provider for the block. - */ - public static void registerIntegration(Block block, PortalTrackProvider provider) { - PORTAL_BEHAVIOURS.register(block, provider); + public static void tryRegisterIntegration(ResourceLocation id, PortalTrackProvider provider) { + if (ForgeRegistries.BLOCKS.containsKey(id)) { + Block block = ForgeRegistries.BLOCKS.getValue(id); + REGISTRY.register(block, provider); + } else { + Create.LOGGER.warn("Portal for integration wasn't found: {}. Compat outdated?", id); + } } /** @@ -78,7 +74,7 @@ public class AllPortalTracks { * @return {@code true} if the block state represents a supported portal; {@code false} otherwise. */ public static boolean isSupportedPortal(BlockState state) { - return PORTAL_BEHAVIOURS.get(state.getBlock()) != null; + return REGISTRY.get(state.getBlock()) != null; } /** @@ -92,7 +88,7 @@ public class AllPortalTracks { public static Pair getOtherSide(ServerLevel level, BlockFace inboundTrack) { BlockPos portalPos = inboundTrack.getConnectedPos(); BlockState portalState = level.getBlockState(portalPos); - PortalTrackProvider provider = PORTAL_BEHAVIOURS.get(portalState.getBlock()); + PortalTrackProvider provider = REGISTRY.get(portalState.getBlock()); return provider == null ? null : provider.apply(Pair.of(level, inboundTrack)); } @@ -103,11 +99,15 @@ public class AllPortalTracks { * This includes the Nether and the Aether (if loaded). */ public static void registerDefaults() { - registerIntegration(Blocks.NETHER_PORTAL, AllPortalTracks::nether); - if (Mods.AETHER.isLoaded()) - registerIntegration(Mods.AETHER.rl("aether_portal"), AllPortalTracks::aether); - if (Mods.BETTEREND.isLoaded()) - registerIntegration(Mods.BETTEREND.rl("end_portal_block"), AllPortalTracks::betterend); + REGISTRY.register(Blocks.NETHER_PORTAL, AllPortalTracks::nether); + + if (Mods.AETHER.isLoaded()) { + tryRegisterIntegration(Mods.AETHER.rl("aether_portal"), AllPortalTracks::aether); + } + + if (Mods.BETTEREND.isLoaded()) { + tryRegisterIntegration(Mods.BETTEREND.rl("end_portal_block"), AllPortalTracks::betterend); + } } /** diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java index 74ea306475..64d38c9931 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -47,6 +47,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; @@ -106,10 +107,13 @@ public class CreateRegistrate extends AbstractRegistrate { Builder builder, NonNullSupplier creator, NonNullFunction, ? extends RegistryEntry> entryFactory) { RegistryEntry entry = super.accept(name, type, builder, creator, entryFactory); - if (type.equals(Registries.ITEM)) { - if (currentTooltipModifierFactory != null) { - TooltipModifier.REGISTRY.registerDeferred(entry.getId(), currentTooltipModifierFactory); - } + if (type.equals(Registries.ITEM) && currentTooltipModifierFactory != null) { + // grab the factory here for the lambda, it can change between now and registration + Function factory = currentTooltipModifierFactory; + this.addRegisterCallback(name, Registries.ITEM, item -> { + TooltipModifier modifier = factory.apply(item); + TooltipModifier.REGISTRY.register(item, modifier); + }); } if (currentTab != null) { TAB_LOOKUP.put(entry, currentTab); diff --git a/src/main/java/com/simibubi/create/foundation/item/TooltipModifier.java b/src/main/java/com/simibubi/create/foundation/item/TooltipModifier.java index cfd82414a8..9cccf8a794 100644 --- a/src/main/java/com/simibubi/create/foundation/item/TooltipModifier.java +++ b/src/main/java/com/simibubi/create/foundation/item/TooltipModifier.java @@ -2,14 +2,15 @@ package com.simibubi.create.foundation.item; import org.jetbrains.annotations.Nullable; -import com.simibubi.create.foundation.utility.AttachedRegistry; +import com.simibubi.create.api.registry.AttachedRegistry; import net.minecraft.world.item.Item; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; + +@FunctionalInterface public interface TooltipModifier { - AttachedRegistry REGISTRY = new AttachedRegistry<>(ForgeRegistries.ITEMS); + AttachedRegistry REGISTRY = AttachedRegistry.create(); TooltipModifier EMPTY = new TooltipModifier() { @Override diff --git a/src/main/java/com/simibubi/create/foundation/utility/AttachedRegistry.java b/src/main/java/com/simibubi/create/foundation/utility/AttachedRegistry.java deleted file mode 100644 index f44e167aea..0000000000 --- a/src/main/java/com/simibubi/create/foundation/utility/AttachedRegistry.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.simibubi.create.foundation.utility; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.Create; - -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.registries.IForgeRegistry; - -public class AttachedRegistry { - private static final List> ALL = new ArrayList<>(); - - protected final IForgeRegistry objectRegistry; - protected final Map idMap = new HashMap<>(); - protected final Map objectMap = new IdentityHashMap<>(); - protected final Map> deferredRegistrations = new HashMap<>(); - protected boolean unwrapped = false; - - public AttachedRegistry(IForgeRegistry objectRegistry) { - this.objectRegistry = objectRegistry; - ALL.add(this); - } - - public void register(ResourceLocation id, V value) { - if (!unwrapped) { - idMap.put(id, value); - } else { - K object = objectRegistry.getValue(id); - if (object != null) { - objectMap.put(object, value); - } else { - Create.LOGGER.warn("Could not get object for id '" + id + "' in AttachedRegistry after unwrapping!"); - } - } - } - - public void register(K object, V value) { - if (unwrapped) { - objectMap.put(object, value); - } else { - ResourceLocation id = objectRegistry.getKey(object); - if (id != null) { - idMap.put(id, value); - } else { - Create.LOGGER.warn("Could not get id of object '" + object + "' in AttachedRegistry before unwrapping!"); - } - } - } - - public void registerDeferred(ResourceLocation id, Function func) { - if (!unwrapped) { - deferredRegistrations.put(id, func); - } else { - K object = objectRegistry.getValue(id); - if (object != null) { - objectMap.put(object, func.apply(object)); - } else { - Create.LOGGER.warn("Could not get object for id '" + id + "' in AttachedRegistry after unwrapping!"); - } - } - } - - public void registerDeferred(K object, Function func) { - if (unwrapped) { - objectMap.put(object, func.apply(object)); - } else { - ResourceLocation id = objectRegistry.getKey(object); - if (id != null) { - deferredRegistrations.put(id, func); - } else { - Create.LOGGER.warn("Could not get id of object '" + object + "' in AttachedRegistry before unwrapping!"); - } - } - } - - @Nullable - public V get(ResourceLocation id) { - if (!unwrapped) { - return idMap.get(id); - } else { - K object = objectRegistry.getValue(id); - if (object != null) { - return objectMap.get(object); - } else { - Create.LOGGER.warn("Could not get object for id '" + id + "' in AttachedRegistry after unwrapping!"); - return null; - } - } - } - - @Nullable - public V get(K object) { - if (unwrapped) { - return objectMap.get(object); - } else { - ResourceLocation id = objectRegistry.getKey(object); - if (id != null) { - return idMap.get(id); - } else { - Create.LOGGER.warn("Could not get id of object '" + object + "' in AttachedRegistry before unwrapping!"); - return null; - } - } - } - - public boolean isUnwrapped() { - return unwrapped; - } - - protected void unwrap() { - deferredRegistrations.forEach((id, func) -> { - K object = objectRegistry.getValue(id); - if (object != null) { - objectMap.put(object, func.apply(object)); - } else { - Create.LOGGER.warn("Could not get object for id '" + id + "' in AttachedRegistry during unwrapping!"); - } - }); - - idMap.forEach((id, value) -> { - K object = objectRegistry.getValue(id); - if (object != null) { - objectMap.put(object, value); - } else { - Create.LOGGER.warn("Could not get object for id '" + id + "' in AttachedRegistry during unwrapping!"); - } - }); - - deferredRegistrations.clear(); - idMap.clear(); - unwrapped = true; - } - - public static void unwrapAll() { - for (AttachedRegistry registry : ALL) { - registry.unwrap(); - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java index 0a576c6571..91acda588d 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -8,7 +8,8 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.api.schematic.nbt.IPartialSafeNBT; -import com.simibubi.create.api.schematic.nbt.SchematicSafeNBTRegistry; +import com.simibubi.create.api.schematic.nbt.SafeNbtWriterRegistry; +import com.simibubi.create.api.schematic.nbt.SafeNbtWriterRegistry.SafeNbtWriter; import com.simibubi.create.compat.Mods; import com.simibubi.create.compat.framedblocks.FramedBlocksInSchematics; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; @@ -16,7 +17,6 @@ import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.foundation.blockEntity.IMergeableBE; import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; -import com.simibubi.create.impl.schematic.nbt.SchematicSafeNBTRegistryImpl; import net.createmod.catnip.nbt.NBTProcessors; import net.minecraft.core.BlockPos; @@ -57,6 +57,7 @@ import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.material.FluidState; + import net.minecraftforge.common.IPlantable; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.level.BlockEvent; @@ -279,18 +280,19 @@ public class BlockHelper { if (blockEntity == null) return null; - SchematicSafeNBTRegistry.ContextProvidingPartialSafeNBT safeNBT = SchematicSafeNBTRegistryImpl.getPartialSafeNBT(blockEntity.getType()); + SafeNbtWriter writer = SafeNbtWriterRegistry.REGISTRY.get(blockEntity.getType()); if (AllBlockTags.SAFE_NBT.matches(blockState)) { data = blockEntity.saveWithFullMetadata(); - } else if (safeNBT != null) { + } else if (writer != null) { data = new CompoundTag(); - safeNBT.writeSafe(blockEntity, data); + writer.writeSafe(blockEntity, data); } else if (blockEntity instanceof IPartialSafeNBT safeNbtBE) { data = new CompoundTag(); safeNbtBE.writeSafe(data); } else if (Mods.FRAMEDBLOCKS.contains(blockState.getBlock())) { data = FramedBlocksInSchematics.prepareBlockEntityData(blockState, blockEntity); -} + } + return NBTProcessors.process(blockState, blockEntity, data, true); } diff --git a/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java b/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java index 66fa681d46..5ec14e6094 100644 --- a/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java +++ b/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java @@ -3,15 +3,20 @@ package com.simibubi.create.impl.contraption.storage; import java.util.Objects; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllMountedStorageTypes; import com.simibubi.create.AllTags; -import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistries; import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; -import com.simibubi.create.api.lookup.BlockLookup; +import com.simibubi.create.api.registry.AttachedRegistry; +import net.minecraft.Util; import net.minecraft.world.level.block.Block; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.TagsUpdatedEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.registries.IForgeRegistry; @@ -21,8 +26,12 @@ import net.minecraftforge.registries.RegistryBuilder; @ApiStatus.Internal @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public class MountedStorageTypeRegistryImpl { - public static final BlockLookup> ITEM_LOOKUP = BlockLookup.create(MountedStorageTypeRegistryImpl::itemFallback); - public static final BlockLookup> FLUID_LOOKUP = BlockLookup.create(); + public static final AttachedRegistry> ITEM_STORAGES = Util.make(() -> { + AttachedRegistry> registry = AttachedRegistry.create(); + registry.registerProvider(ItemFallbackProvider.INSTANCE); + return registry; + }); + public static final AttachedRegistry> FLUID_STORAGES = AttachedRegistry.create(); private static IForgeRegistry> itemsRegistry; private static IForgeRegistry> fluidsRegistry; @@ -39,19 +48,34 @@ public class MountedStorageTypeRegistryImpl { public static void registerRegistries(NewRegistryEvent event) { event.create( new RegistryBuilder>() - .setName(MountedStorageTypeRegistry.ITEMS.location()), + .setName(MountedStorageTypeRegistries.ITEMS.location()), registry -> itemsRegistry = registry ); event.create( new RegistryBuilder>() - .setName(MountedStorageTypeRegistry.FLUIDS.location()), + .setName(MountedStorageTypeRegistries.FLUIDS.location()), registry -> fluidsRegistry = registry ); } - private static MountedItemStorageType itemFallback(Block block) { - return AllTags.AllBlockTags.FALLBACK_MOUNTED_STORAGE_BLACKLIST.matches(block) - ? null - : AllMountedStorageTypes.FALLBACK.get(); + private enum ItemFallbackProvider implements AttachedRegistry.Provider> { + INSTANCE; + + @Override + @Nullable + public MountedItemStorageType get(Block block) { + return AllTags.AllBlockTags.FALLBACK_MOUNTED_STORAGE_BLACKLIST.matches(block) + ? null + : AllMountedStorageTypes.FALLBACK.get(); + } + + @Override + public void onRegister(AttachedRegistry> registry) { + MinecraftForge.EVENT_BUS.addListener((TagsUpdatedEvent event) -> { + if (event.shouldUpdateStaticData()) { + registry.invalidateProvider(this); + } + }); + } } } diff --git a/src/main/java/com/simibubi/create/impl/contraption/transformable/ContraptionTransformableRegistryImpl.java b/src/main/java/com/simibubi/create/impl/contraption/transformable/ContraptionTransformableRegistryImpl.java deleted file mode 100644 index f8878919d2..0000000000 --- a/src/main/java/com/simibubi/create/impl/contraption/transformable/ContraptionTransformableRegistryImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.simibubi.create.impl.contraption.transformable; - -import org.jetbrains.annotations.ApiStatus; - -import com.simibubi.create.api.contraption.transformable.ContraptionTransformableRegistry.TransformableBlock; -import com.simibubi.create.api.contraption.transformable.ContraptionTransformableRegistry.TransformableBlockEntity; -import com.simibubi.create.foundation.utility.AttachedRegistry; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraftforge.registries.ForgeRegistries; - -@ApiStatus.Internal -public class ContraptionTransformableRegistryImpl { - private static final AttachedRegistry TRANSFORMABLE_BLOCKS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final AttachedRegistry, TransformableBlockEntity> TRANSFORMABLE_BLOCK_ENTITIES = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - - public static void registerForBlock(Block block, TransformableBlock transformableBlock) { - TRANSFORMABLE_BLOCKS.register(block, transformableBlock); - } - - public static void registerForBlockEntity(BlockEntityType blockEntityType, TransformableBlockEntity transformableBlockEntity) { - TRANSFORMABLE_BLOCK_ENTITIES.register(blockEntityType, transformableBlockEntity); - } - - public static TransformableBlock get(Block block) { - return TRANSFORMABLE_BLOCKS.get(block); - } - - public static TransformableBlockEntity get(BlockEntityType blockEntityType) { - return TRANSFORMABLE_BLOCK_ENTITIES.get(blockEntityType); - } -} diff --git a/src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java b/src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java deleted file mode 100644 index a5406d9a9a..0000000000 --- a/src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.simibubi.create.impl.lookup; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.simibubi.create.api.lookup.BlockLookup; - -import net.minecraftforge.event.TagsUpdatedEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import net.minecraft.tags.TagKey; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -@ApiStatus.Internal -@Mod.EventBusSubscriber -public class BlockLookupImpl implements BlockLookup { - private static final List> allLookups = new ArrayList<>(); - - private final Map map; - private final Map providedValues; - private final Set providedNull; - private final List> providers; - - public BlockLookupImpl() { - this.map = new IdentityHashMap<>(); - this.providedValues = new IdentityHashMap<>(); - this.providedNull = new HashSet<>(); - this.providers = new ArrayList<>(); - allLookups.add(this); - } - - @Nullable - @Override - public T find(BlockState state) { - return this.find(state.getBlock()); - } - - @Nullable - @Override - public T find(Block block) { - T registered = this.map.get(block); - if (registered != null) - return registered; - - if (this.providedNull.contains(block)) - return null; - - return this.providedValues.computeIfAbsent(block, $ -> { - for (Provider provider : this.providers) { - T value = provider.get(block); - if (value != null) { - return value; - } - } - - this.providedNull.add(block); - return null; - }); - } - - @Override - public void register(Block block, T value) { - this.map.put(block, value); - } - - @Override - public void registerTag(TagKey tag, T value) { - this.registerProvider(new TagProvider<>(tag, value)); - } - - @Override - public void registerProvider(Provider provider) { - this.providers.add(0, provider); - } - - @SubscribeEvent - public static void onTagsReloaded(TagsUpdatedEvent event) { - if (event.getUpdateCause() == TagsUpdatedEvent.UpdateCause.SERVER_DATA_LOAD) { - for (BlockLookupImpl lookup : allLookups) { - lookup.providedValues.clear(); - lookup.providedNull.clear(); - } - } - } - - private record TagProvider(TagKey tag, T value) implements Provider { - @Override - @Nullable - @SuppressWarnings("deprecation") - public T get(Block block) { - return block.builtInRegistryHolder().is(this.tag) ? this.value : null; - } - } -} diff --git a/src/main/java/com/simibubi/create/impl/registry/AttachedRegistryImpl.java b/src/main/java/com/simibubi/create/impl/registry/AttachedRegistryImpl.java new file mode 100644 index 0000000000..7e23f950a8 --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/registry/AttachedRegistryImpl.java @@ -0,0 +1,103 @@ +package com.simibubi.create.impl.registry; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.AttachedRegistry; + +// methods are synchronized since registrations can happen during parallel mod loading +public class AttachedRegistryImpl implements AttachedRegistry { + private static final Object nullMarker = new Object(); + + // all of these have identity semantics + private final Map registrations = new IdentityHashMap<>(); + private final List> providers = new ArrayList<>(); + private final Map, Set> providedKeys = new IdentityHashMap<>(); + private final Map providedValues = new IdentityHashMap<>(); + + @Override + public synchronized void register(K object, V value) { + Objects.requireNonNull(object, "object"); + Objects.requireNonNull(value, "value"); + + V existing = this.registrations.get(object); + if (existing != null) { + String message = String.format("Tried to register duplicate values for object %s: old=%s, new=%s", object, existing, value); + throw new IllegalArgumentException(message); + } + + this.registrations.put(object, value); + } + + @Override + public synchronized void registerProvider(Provider provider) { + Objects.requireNonNull(provider); + if (this.providers.contains(provider)) { + throw new IllegalArgumentException("Tried to register provider twice: " + provider); + } + + // add to start of list so it's queried first + this.providers.add(0, provider); + provider.onRegister(this); + } + + @Override + public synchronized void invalidateProvider(Provider provider) { + Objects.requireNonNull(provider); + if (!this.providers.contains(provider)) { + throw new IllegalArgumentException("Cannot invalidate non-registered provider: " + provider); + } + + // discard all the values the provider has provided + Set keys = providedKeys.remove(provider); + if (keys != null) { + keys.forEach(providedValues::remove); + } + + // when a provider is invalidated, we need to clear all cached values that evaluated to null, so they can be re-queried + this.providedValues.values().removeIf(value -> value == nullMarker); + } + + @Override + @Nullable + public synchronized V get(K object) { + if (this.registrations.containsKey(object)) { + return this.registrations.get(object); + } else if (this.providedValues.containsKey(object)) { + V provided = this.providedValues.get(object); + return provided == nullMarker ? null : provided; + } + + // no value known, check providers + // descendingSet: go in reverse-registration order + for (Provider provider : this.providers) { + V value = provider.get(object); + if (value != null) { + this.providedValues.put(object, value); + // track which provider provided the value for invalidation + this.providedKeys.computeIfAbsent(provider, $ -> identityHashSet()).add(object); + return value; + } + } + + // no provider returned non-null + this.providedValues.put(object, nullMarker()); + return null; + } + + @SuppressWarnings("unchecked") + private static T nullMarker() { + return (T) nullMarker; + } + + private static Set identityHashSet() { + return Collections.newSetFromMap(new IdentityHashMap<>()); + } +} diff --git a/src/main/java/com/simibubi/create/impl/registry/TagProviderImpl.java b/src/main/java/com/simibubi/create/impl/registry/TagProviderImpl.java new file mode 100644 index 0000000000..876490fc32 --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/registry/TagProviderImpl.java @@ -0,0 +1,41 @@ +package com.simibubi.create.impl.registry; + +import java.util.function.Function; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.AttachedRegistry; + +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.TagsUpdatedEvent; + +public class TagProviderImpl implements AttachedRegistry.Provider { + private final TagKey tag; + private final Function> holderGetter; + private final V value; + + public TagProviderImpl(TagKey tag, Function> holderGetter, V value) { + this.tag = tag; + this.holderGetter = holderGetter; + this.value = value; + } + + @Override + @Nullable + public V get(K object) { + Holder holder = this.holderGetter.apply(object); + return holder.is(this.tag) ? this.value : null; + } + + @Override + public void onRegister(AttachedRegistry registry) { + MinecraftForge.EVENT_BUS.addListener((TagsUpdatedEvent event) -> { + if (event.shouldUpdateStaticData()) { + registry.invalidateProvider(this); + } + }); + } +} diff --git a/src/main/java/com/simibubi/create/impl/schematic/nbt/SchematicSafeNBTRegistryImpl.java b/src/main/java/com/simibubi/create/impl/schematic/nbt/SchematicSafeNBTRegistryImpl.java deleted file mode 100644 index d650d77bb1..0000000000 --- a/src/main/java/com/simibubi/create/impl/schematic/nbt/SchematicSafeNBTRegistryImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.simibubi.create.impl.schematic.nbt; - -import org.jetbrains.annotations.ApiStatus; - -import com.simibubi.create.api.schematic.nbt.SchematicSafeNBTRegistry; -import com.simibubi.create.foundation.utility.AttachedRegistry; - -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraftforge.registries.ForgeRegistries; - -@ApiStatus.Internal -public class SchematicSafeNBTRegistryImpl { - private static final AttachedRegistry, SchematicSafeNBTRegistry.ContextProvidingPartialSafeNBT> BLOCK_ENTITY_PARTIAL_SAFE_NBT = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - - public static void register(BlockEntityType blockEntityType, SchematicSafeNBTRegistry.ContextProvidingPartialSafeNBT safeNBT) { - BLOCK_ENTITY_PARTIAL_SAFE_NBT.register(blockEntityType, safeNBT); - } - - public static SchematicSafeNBTRegistry.ContextProvidingPartialSafeNBT getPartialSafeNBT(BlockEntityType blockEntityType) { - return BLOCK_ENTITY_PARTIAL_SAFE_NBT.get(blockEntityType); - } -} diff --git a/src/main/java/com/simibubi/create/impl/schematic/requirement/SchematicRequirementsRegistryImpl.java b/src/main/java/com/simibubi/create/impl/schematic/requirement/SchematicRequirementsRegistryImpl.java deleted file mode 100644 index c5044f254b..0000000000 --- a/src/main/java/com/simibubi/create/impl/schematic/requirement/SchematicRequirementsRegistryImpl.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.impl.schematic.requirement; - -import org.jetbrains.annotations.ApiStatus; - -import com.simibubi.create.api.schematic.requirement.SchematicRequirementsRegistry; -import com.simibubi.create.foundation.utility.AttachedRegistry; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -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.minecraftforge.registries.ForgeRegistries; - -@ApiStatus.Internal -public class SchematicRequirementsRegistryImpl { - private static final AttachedRegistry BLOCK_REQUIREMENTS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final AttachedRegistry, SchematicRequirementsRegistry.BlockEntityRequirement> BLOCK_ENTITY_REQUIREMENTS = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - private static final AttachedRegistry, SchematicRequirementsRegistry.EntityRequirement> ENTITY_REQUIREMENTS = new AttachedRegistry<>(ForgeRegistries.ENTITY_TYPES); - - public static void registerForBlock(Block block, SchematicRequirementsRegistry.BlockRequirement requirement) { - BLOCK_REQUIREMENTS.register(block, requirement); - } - - public static void registerForBlock(ResourceLocation block, SchematicRequirementsRegistry.BlockRequirement requirement) { - BLOCK_REQUIREMENTS.register(block, requirement); - } - - public static void registerForBlockEntity(BlockEntityType blockEntityType, SchematicRequirementsRegistry.BlockEntityRequirement requirement) { - BLOCK_ENTITY_REQUIREMENTS.register(blockEntityType, requirement); - } - - public static void registerForBlockEntity(ResourceLocation blockEntityType, SchematicRequirementsRegistry.BlockEntityRequirement requirement) { - BLOCK_ENTITY_REQUIREMENTS.register(blockEntityType, requirement); - } - - public static void registerForEntity(EntityType entityType, SchematicRequirementsRegistry.EntityRequirement requirement) { - ENTITY_REQUIREMENTS.register(entityType, requirement); - } - - // --- - - public static void registerForEntity(ResourceLocation entityType, SchematicRequirementsRegistry.EntityRequirement requirement) { - ENTITY_REQUIREMENTS.register(entityType, requirement); - } - - public static SchematicRequirementsRegistry.BlockRequirement getRequirementForBlock(Block block) { - return BLOCK_REQUIREMENTS.get(block); - } - - public static SchematicRequirementsRegistry.BlockEntityRequirement getRequirementForBlockEntityType(BlockEntityType blockEntityType) { - return BLOCK_ENTITY_REQUIREMENTS.get(blockEntityType); - } - - public static SchematicRequirementsRegistry.EntityRequirement getRequirementForEntityType(EntityType entityType) { - return ENTITY_REQUIREMENTS.get(entityType); - } -}