From 30baef1740a2f9d90a92fea14a2c75910e26dfb1 Mon Sep 17 00:00:00 2001 From: TropheusJ <60247969+TropheusJ@users.noreply.github.com> Date: Fri, 21 Feb 2025 11:05:15 -0500 Subject: [PATCH 1/3] use tags for mounted item storage attributes (#16) --- .../f5350c6189acfbe5425c2432489f46008c69099a | 3 ++ .../fuel_blacklist.json | 5 ++ .../mounted_item_storage_type/internal.json | 5 ++ .../java/com/simibubi/create/AllTags.java | 28 +++++++++++ .../storage/item/MountedItemStorage.java | 23 --------- .../storage/item/MountedItemStorageType.java | 8 ++++ .../api/registry/CreateBuiltInRegistries.java | 2 +- .../registry/registrate/SimpleBuilder.java | 23 ++++----- .../contraptions/MountedStorageManager.java | 22 +++++---- .../dispenser/DropperMovementBehaviour.java | 4 +- .../storage/DispenserMountedStorage.java | 6 +-- .../vault/ItemVaultMountedStorage.java | 5 -- .../foundation/data/CreateRegistrate.java | 8 ++-- .../infrastructure/data/CreateDatagen.java | 1 + ...ateMountedItemStorageTypeTagsProvider.java | 47 +++++++++++++++++++ 15 files changed, 129 insertions(+), 61 deletions(-) create mode 100644 src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a create mode 100644 src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json create mode 100644 src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json create mode 100644 src/main/java/com/simibubi/create/infrastructure/data/CreateMountedItemStorageTypeTagsProvider.java diff --git a/src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a b/src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a new file mode 100644 index 0000000000..a185aa953b --- /dev/null +++ b/src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a @@ -0,0 +1,3 @@ +// 1.20.1 2025-02-20T19:36:44.18737762 Create's Mounted Item Storage Type Tags +c65f95f356db09e468847e5799a2cdd8e1417cac data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json +fdadceec842a4cd12dd95f7e271645a52829ec6e data/create/tags/create/mounted_item_storage_type/internal.json diff --git a/src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json new file mode 100644 index 0000000000..99eb273fe1 --- /dev/null +++ b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:vault" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json new file mode 100644 index 0000000000..f91fe16551 --- /dev/null +++ b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:dispenser" + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index fe346733e5..48bc7c6cf6 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -9,6 +9,8 @@ import static com.simibubi.create.AllTags.NameSpace.TIC; import java.util.Collections; import com.simibubi.create.api.contraption.ContraptionType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; import com.simibubi.create.api.registry.CreateRegistries; import net.createmod.catnip.lang.Lang; @@ -423,6 +425,31 @@ public class AllTags { } } + public enum AllMountedItemStorageTypeTags { + INTERNAL, + FUEL_BLACKLIST; + + public final TagKey> tag; + public final boolean alwaysDatagen; + + AllMountedItemStorageTypeTags() { + ResourceLocation tagId = Create.asResource(Lang.asId(this.name())); + this.tag = TagKey.create(CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, tagId); + this.alwaysDatagen = true; + } + + public boolean matches(MountedItemStorage storage) { + return this.matches(storage.type); + } + + public boolean matches(MountedItemStorageType type) { + return type.is(this.tag); + } + + private static void init() { + } + } + public static void init() { AllBlockTags.init(); AllItemTags.init(); @@ -430,5 +457,6 @@ public class AllTags { AllEntityTags.init(); AllRecipeSerializerTags.init(); AllContraptionTypeTags.init(); + AllMountedItemStorageTypeTags.init(); } } diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java index 8390b8a6f0..4b7ba3fe74 100644 --- a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java @@ -8,11 +8,8 @@ import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; import com.mojang.serialization.Codec; -import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.api.contraption.storage.item.menu.MountedStorageMenus; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.MountedStorageManager; -import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.core.BlockPos; @@ -49,26 +46,6 @@ public abstract class MountedItemStorage implements IItemHandlerModifiable { */ public abstract void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); - /** - * Internal mounted storages are not exposed to the larger contraption inventory. - * They are only for internal use, such as access from a {@link MovementBehaviour}. - * Internal storages are still accessible through {@link MovementContext#getItemStorage()} - * as well as {@link MountedStorageManager#getAllItemStorages()}. - * A storage being internal implies that it does not provide fuel either. - * This is only called once on assembly. - */ - public boolean isInternal() { - return false; - } - - /** - * Contraptions may search storage for fuel, such as for powering furnace minecarts - * and trains. Return false if this storage should - */ - public boolean providesFuel() { - return true; - } - /** * Handle a player clicking on this mounted storage. This is always called on the server. * The default implementation will try to open a generic GUI for standard inventories. 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 db7e36ba7b..9386173fc7 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 @@ -13,6 +13,8 @@ import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; @@ -27,9 +29,15 @@ public abstract class MountedItemStorageType { }); public final Codec codec; + public final Holder> holder; protected MountedItemStorageType(Codec codec) { this.codec = codec; + this.holder = CreateBuiltInRegistries.MOUNTED_ITEM_STORAGE_TYPE.createIntrusiveHolder(this); + } + + public final boolean is(TagKey> tag) { + return this.holder.is(tag); } @Nullable diff --git a/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java b/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java index 14107ebffd..7e5182cb85 100644 --- a/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java +++ b/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java @@ -33,7 +33,7 @@ public class CreateBuiltInRegistries { public static final Registry ITEM_ATTRIBUTE_TYPE = simple(CreateRegistries.ITEM_ATTRIBUTE_TYPE); public static final Registry DISPLAY_SOURCE = simple(CreateRegistries.DISPLAY_SOURCE); public static final Registry DISPLAY_TARGET = simple(CreateRegistries.DISPLAY_TARGET); - public static final Registry> MOUNTED_ITEM_STORAGE_TYPE = simple(CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE); + public static final Registry> MOUNTED_ITEM_STORAGE_TYPE = withIntrusiveHolders(CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE); public static final Registry> MOUNTED_FLUID_STORAGE_TYPE = simple(CreateRegistries.MOUNTED_FLUID_STORAGE_TYPE); public static final Registry CONTRAPTION_TYPE = withIntrusiveHolders(CreateRegistries.CONTRAPTION_TYPE); diff --git a/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java b/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java index 215d985648..81e6e9fbc2 100644 --- a/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java +++ b/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java @@ -2,6 +2,7 @@ package com.simibubi.create.api.registry.registrate; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; @@ -22,21 +23,21 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.material.Fluid; public class SimpleBuilder extends AbstractBuilder> { - private final T value; + private final Supplier value; private SimpleRegistryAccess byBlock; private SimpleRegistryAccess, R> byBlockEntity; private SimpleRegistryAccess, R> byEntity; private SimpleRegistryAccess byFluid; - public SimpleBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, ResourceKey> registryKey, T value) { + public SimpleBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, ResourceKey> registryKey, Supplier value) { super(owner, parent, name, callback, registryKey); this.value = value; } @Override protected T createEntry() { - return this.value; + return this.value.get(); } // for setup @@ -91,49 +92,49 @@ public class SimpleBuilder extends AbstractBuilder associate(Block block) { assertPresent(this.byBlock, "Block"); - this.byBlock.adder.accept(block, this.value); + this.onRegister(value -> this.byBlock.adder.accept(block, value)); return this; } public SimpleBuilder associateBlockTag(TagKey tag) { assertPresent(this.byBlock, "Block"); - this.byBlock.tagAdder.accept(tag, this.value); + this.onRegister(value -> this.byBlock.tagAdder.accept(tag, value)); return this; } public SimpleBuilder associate(BlockEntityType type) { assertPresent(this.byBlockEntity, "BlockEntityType"); - this.byBlockEntity.adder.accept(type, this.value); + this.onRegister(value -> this.byBlockEntity.adder.accept(type, value)); return this; } public SimpleBuilder associateBeTag(TagKey> tag) { assertPresent(this.byBlockEntity, "BlockEntityType"); - this.byBlockEntity.tagAdder.accept(tag, this.value); + this.onRegister(value -> this.byBlockEntity.tagAdder.accept(tag, value)); return this; } public SimpleBuilder associate(EntityType type) { assertPresent(this.byEntity, "EntityType"); - this.byEntity.adder.accept(type, this.value); + this.onRegister(value -> this.byEntity.adder.accept(type, value)); return this; } public SimpleBuilder associateEntityTag(TagKey> tag) { assertPresent(this.byEntity, "EntityType"); - this.byEntity.tagAdder.accept(tag, this.value); + this.onRegister(value -> this.byEntity.tagAdder.accept(tag, value)); return this; } public SimpleBuilder associate(Fluid fluid) { assertPresent(this.byFluid, "Fluid"); - this.byFluid.adder.accept(fluid, this.value); + this.onRegister(value -> this.byFluid.adder.accept(fluid, value)); return this; } public SimpleBuilder associateFluidTag(TagKey tag) { assertPresent(this.byFluid, "Fluid"); - this.byFluid.tagAdder.accept(tag, this.value); + this.onRegister(value -> this.byFluid.tagAdder.accept(tag, value)); return this; } 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 e3f51871c1..1ce9554475 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java @@ -16,6 +16,7 @@ import com.google.common.collect.Sets; import com.google.common.collect.Sets.SetView; import com.mojang.datafixers.util.Pair; import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags.AllMountedItemStorageTypeTags; import com.simibubi.create.Create; import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; @@ -96,16 +97,12 @@ public class MountedStorageManager { this.allItemStorages = ImmutableMap.copyOf(this.itemsBuilder); - this.items = new MountedItemStorageWrapper(subMap( - this.allItemStorages, storage -> !storage.isInternal() - )); + this.items = new MountedItemStorageWrapper(subMap(this.allItemStorages, this::isExposed)); this.allItems = this.items; this.itemsBuilder = null; - ImmutableMap fuelMap = subMap( - this.allItemStorages, storage -> !storage.isInternal() && storage.providesFuel() - ); + ImmutableMap fuelMap = subMap(this.allItemStorages, this::canUseForFuel); this.fuelItems = fuelMap.isEmpty() ? null : new MountedItemStorageWrapper(fuelMap); ImmutableMap fluids = ImmutableMap.copyOf(this.fluidsBuilder); @@ -118,6 +115,14 @@ public class MountedStorageManager { this.syncedFluidsBuilder = null; } + private boolean isExposed(MountedItemStorage storage) { + return !AllMountedItemStorageTypeTags.INTERNAL.matches(storage); + } + + private boolean canUseForFuel(MountedItemStorage storage) { + return this.isExposed(storage) && !AllMountedItemStorageTypeTags.FUEL_BLACKLIST.matches(storage); + } + private boolean isInitialized() { return this.itemsBuilder == null; } @@ -363,10 +368,7 @@ public class MountedStorageManager { } /** - * Gets a map of all MountedItemStorages in the contraption, irrelevant of them - * being internal or providing fuel. - * @see MountedItemStorage#isInternal() - * @see MountedItemStorage#providesFuel() + * Gets a map of all MountedItemStorages in the contraption, irrelevant of them being internal or providing fuel. */ public ImmutableMap getAllItemStorages() { this.assertInitialized(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java index cfb5b9fc56..581ed17556 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java @@ -59,8 +59,8 @@ public class DropperMovementBehaviour implements MovementBehaviour { if (stack.getCount() == 1 && stack.getMaxStackSize() != 1) { stack = tryTopOff(stack, contraptionInventory); - if (stack == null) { - continue; + if (stack != null) { + storage.setStackInSlot(i, stack); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java index b20c5cd906..e085b22c47 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java @@ -16,6 +16,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; @@ -30,11 +31,6 @@ public class DispenserMountedStorage extends SimpleMountedStorage { this(AllMountedStorageTypes.DISPENSER.get(), handler); } - @Override - public boolean isInternal() { - return true; - } - @Override @Nullable protected MenuProvider createMenuProvider(Component name, IItemHandlerModifiable handler, diff --git a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java index 244c533f79..035f80b337 100644 --- a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java @@ -45,11 +45,6 @@ public class ItemVaultMountedStorage extends WrapperMountedItemStorage { public > SimpleBuilder, T, CreateRegistrate> mountedItemStorage(String name, Supplier supplier) { return this.entry(name, callback -> new SimpleBuilder<>( - this, this, name, callback, CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, supplier.get() + this, this, name, callback, CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, supplier ).byBlock(MountedItemStorageType.REGISTRY)); } public > SimpleBuilder, T, CreateRegistrate> mountedFluidStorage(String name, Supplier supplier) { return this.entry(name, callback -> new SimpleBuilder<>( - this, this, name, callback, CreateRegistries.MOUNTED_FLUID_STORAGE_TYPE, supplier.get() + this, this, name, callback, CreateRegistries.MOUNTED_FLUID_STORAGE_TYPE, supplier ).byBlock(MountedFluidStorageType.REGISTRY)); } public SimpleBuilder displaySource(String name, Supplier supplier) { return this.entry(name, callback -> new SimpleBuilder<>( - this, this, name, callback, CreateRegistries.DISPLAY_SOURCE, supplier.get() + this, this, name, callback, CreateRegistries.DISPLAY_SOURCE, supplier ).byBlock(DisplaySource.BY_BLOCK).byBlockEntity(DisplaySource.BY_BLOCK_ENTITY)); } public SimpleBuilder displayTarget(String name, Supplier supplier) { return this.entry(name, callback -> new SimpleBuilder<>( - this, this, name, callback, CreateRegistries.DISPLAY_TARGET, supplier.get() + this, this, name, callback, CreateRegistries.DISPLAY_TARGET, supplier ).byBlock(DisplayTarget.BY_BLOCK).byBlockEntity(DisplayTarget.BY_BLOCK_ENTITY)); } diff --git a/src/main/java/com/simibubi/create/infrastructure/data/CreateDatagen.java b/src/main/java/com/simibubi/create/infrastructure/data/CreateDatagen.java index f40866cfe8..85f901f519 100644 --- a/src/main/java/com/simibubi/create/infrastructure/data/CreateDatagen.java +++ b/src/main/java/com/simibubi/create/infrastructure/data/CreateDatagen.java @@ -44,6 +44,7 @@ public class CreateDatagen { generator.addProvider(event.includeServer(), new CreateRecipeSerializerTagsProvider(output, lookupProvider, existingFileHelper)); generator.addProvider(event.includeServer(), new CreateContraptionTypeTagsProvider(output, lookupProvider, existingFileHelper)); + generator.addProvider(event.includeServer(), new CreateMountedItemStorageTypeTagsProvider(output, lookupProvider, existingFileHelper)); generator.addProvider(event.includeServer(), new DamageTypeTagGen(output, lookupProvider, existingFileHelper)); generator.addProvider(event.includeServer(), new AllAdvancements(output)); generator.addProvider(event.includeServer(), new StandardRecipeGen(output)); diff --git a/src/main/java/com/simibubi/create/infrastructure/data/CreateMountedItemStorageTypeTagsProvider.java b/src/main/java/com/simibubi/create/infrastructure/data/CreateMountedItemStorageTypeTagsProvider.java new file mode 100644 index 0000000000..3e314f0a48 --- /dev/null +++ b/src/main/java/com/simibubi/create/infrastructure/data/CreateMountedItemStorageTypeTagsProvider.java @@ -0,0 +1,47 @@ +package com.simibubi.create.infrastructure.data; + +import java.util.concurrent.CompletableFuture; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.AllTags.AllMountedItemStorageTypeTags; +import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.registry.CreateRegistries; + +import net.minecraft.core.HolderLookup.Provider; +import net.minecraft.data.PackOutput; +import net.minecraft.data.tags.TagsProvider; +import net.minecraft.tags.TagEntry; + +import net.minecraftforge.common.data.ExistingFileHelper; + +public class CreateMountedItemStorageTypeTagsProvider extends TagsProvider> { + public CreateMountedItemStorageTypeTagsProvider(PackOutput output, CompletableFuture lookupProvider, @Nullable ExistingFileHelper existingFileHelper) { + super(output, CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, lookupProvider, Create.ID, existingFileHelper); + } + + @Override + protected void addTags(Provider pProvider) { + tag(AllMountedItemStorageTypeTags.INTERNAL.tag).add( + TagEntry.element(AllMountedStorageTypes.DISPENSER.getId()) + ); + tag(AllMountedItemStorageTypeTags.FUEL_BLACKLIST.tag).add( + TagEntry.element(AllMountedStorageTypes.VAULT.getId()) + ); + + // VALIDATE + + for (AllMountedItemStorageTypeTags tag : AllMountedItemStorageTypeTags.values()) { + if (tag.alwaysDatagen) { + getOrCreateRawBuilder(tag.tag); + } + } + } + + @Override + public String getName() { + return "Create's Mounted Item Storage Type Tags"; + } +} From a2ab54e18a8a801d10caeed849a84df776e06cd1 Mon Sep 17 00:00:00 2001 From: TropheusJ <60247969+TropheusJ@users.noreply.github.com> Date: Fri, 21 Feb 2025 11:07:07 -0500 Subject: [PATCH 2/3] Refactor Mounted Dispense Behaviours (#17) --- .../2d64935085b86659cb7857bad9701dbf9bab6e4c | 3 +- .../dispense_behavior_wrap_blacklist.json | 3 + .../AllMountedDispenseItemBehaviors.java | 190 ++++++++++++++++++ .../create/AllMovementBehaviours.java | 2 - .../java/com/simibubi/create/AllTags.java | 1 + src/main/java/com/simibubi/create/Create.java | 1 + .../DefaultMountedDispenseBehavior.java | 88 ++++++++ .../dispenser/MountedDispenseBehavior.java | 79 ++++++++ .../MountedProjectileDispenseBehavior.java | 76 +++++++ .../OptionalMountedDispenseBehavior.java | 43 ++++ .../dispenser/DispenseItemLocation.java | 25 --- .../dispenser/DispenserMovementBehaviour.java | 101 +--------- .../dispenser/DropperMovementBehaviour.java | 8 +- .../IMovedDispenseItemBehaviour.java | 190 ------------------ .../MovedDefaultDispenseItemBehaviour.java | 119 ----------- .../MovedOptionalDispenseBehaviour.java | 13 -- .../MovedProjectileDispenserBehaviour.java | 68 ------- .../behaviour/dispenser/SimplePos.java | 30 --- .../dispenser/DispenserBehaviorConverter.java | 104 ++++++++++ 19 files changed, 597 insertions(+), 547 deletions(-) create mode 100644 src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json create mode 100644 src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java create mode 100644 src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java create mode 100644 src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java create mode 100644 src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java create mode 100644 src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java create mode 100644 src/main/java/com/simibubi/create/impl/contraption/dispenser/DispenserBehaviorConverter.java diff --git a/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c b/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c index a2d55dcaaa..51d7811da1 100644 --- a/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c +++ b/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c @@ -1,4 +1,4 @@ -// 1.20.1 2025-02-20T18:50:30.47170729 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] +// 1.20.1 2025-02-21T09:54:58.646012686 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] 60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json @@ -4728,6 +4728,7 @@ f43cac8216e2a9347e48cf93a43de95dd810ca20 data/create/tags/items/contraption_cont d371dfd35e49a7bef19f59c03e7f4ae20992f03d data/create/tags/items/create_ingots.json 910d0f5ccbc4c84b224eca1f1588b1695f41447b data/create/tags/items/crushed_raw_materials.json 0fa526e7e742573b603ad26b09526cf724efa1dc data/create/tags/items/deployable_drink.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/dispense_behavior_wrap_blacklist.json ebd7b09daf2f64c0c04d821696b0e145683d8693 data/create/tags/items/dyed_table_cloths.json d2bb65d893d71d2d9871f81f430c233a93adb4bb data/create/tags/items/invalid_for_track_paving.json 1cebeb92bd514b75d54ac6d5708047801f0501c5 data/create/tags/items/modded_stripped_logs.json diff --git a/src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json b/src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json new file mode 100644 index 0000000000..f72d209df7 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java b/src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java new file mode 100644 index 0000000000..167b2db402 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java @@ -0,0 +1,190 @@ +package com.simibubi.create; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedProjectileDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.OptionalMountedDispenseBehavior; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.entity.projectile.FireworkRocketEntity; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.BeehiveBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BucketPickup; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.level.block.entity.BeehiveBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class AllMountedDispenseItemBehaviors { + private static final MountedDispenseBehavior SPAWN_EGG = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + if (!(stack.getItem() instanceof SpawnEggItem egg)) + return super.execute(stack, context, pos, facing); + + if (context.world instanceof ServerLevel serverLevel) { + EntityType type = egg.getType(stack.getTag()); + BlockPos offset = BlockPos.containing(facing.x + .7, facing.y + .7, facing.z + .7); + Entity entity = type.spawn(serverLevel, stack, null, pos.offset(offset), MobSpawnType.DISPENSER, facing.y < .5, false); + if (entity != null) { + entity.setDeltaMovement(context.motion.scale(2)); + } + } + + stack.shrink(1); + return stack; + } + }; + private static final MountedDispenseBehavior TNT = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + PrimedTnt tnt = new PrimedTnt(context.world, x, y, z, null); + tnt.push(context.motion.x, context.motion.y, context.motion.z); + context.world.addFreshEntity(tnt); + context.world.playSound(null, tnt.getX(), tnt.getY(), tnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1, 1); + stack.shrink(1); + return stack; + } + }; + private static final MountedDispenseBehavior FIREWORK = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + FireworkRocketEntity firework = new FireworkRocketEntity(context.world, stack, x, y, z, true); + firework.shoot(facing.x, facing.y, facing.z, 0.5F, 1.0F); + context.world.addFreshEntity(firework); + stack.shrink(1); + return stack; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_FIREWORK_SHOOT, pos, 0); + } + }; + private static final MountedDispenseBehavior FIRE_CHARGE = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + RandomSource random = context.world.random; + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + SmallFireball fireball = new SmallFireball( + context.world, + x, y, z, + random.nextGaussian() * 0.05 + facing.x + context.motion.x, + random.nextGaussian() * 0.05 + facing.y + context.motion.y, + random.nextGaussian() * 0.05 + facing.z + context.motion.z + ); + fireball.setItem(stack); // copies the stack + context.world.addFreshEntity(fireball); + stack.shrink(1); + return stack; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_BLAZE_FIREBALL, pos, 0); + } + }; + private static final MountedDispenseBehavior BUCKET = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + BlockPos interactionPos = pos.relative(MountedDispenseBehavior.getClosestFacingDirection(facing)); + BlockState state = context.world.getBlockState(interactionPos); + if (!(state.getBlock() instanceof BucketPickup bucketPickup)) { + return super.execute(stack, context, pos, facing); + } + + ItemStack bucket = bucketPickup.pickupBlock(context.world, interactionPos, state); + MountedDispenseBehavior.placeItemInInventory(bucket, context, pos); + stack.shrink(1); + return stack; + } + }; + private static final MountedDispenseBehavior POTIONS = new MountedProjectileDispenseBehavior() { + @Override + protected Projectile getProjectile(Level level, double x, double y, double z, ItemStack stack) { + ThrownPotion potion = new ThrownPotion(level, x, y, z); + potion.setItem(stack); // copies item + return potion; + } + + @Override + protected float getUncertainty() { + return super.getUncertainty() * 0.5f; + } + + @Override + protected float getPower() { + return super.getPower() * 1.25f; + } + }; + private static final MountedDispenseBehavior BOTTLE = new OptionalMountedDispenseBehavior() { + @Override + @Nullable + protected ItemStack doExecute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + BlockPos interactionPos = pos.relative(MountedDispenseBehavior.getClosestFacingDirection(facing)); + BlockState state = context.world.getBlockState(interactionPos); + Block block = state.getBlock(); + + if (block instanceof BeehiveBlock hive && state.is(BlockTags.BEEHIVES) && state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { + hive.releaseBeesAndResetHoneyLevel(context.world, state, interactionPos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); + MountedDispenseBehavior.placeItemInInventory(new ItemStack(Items.HONEY_BOTTLE), context, pos); + stack.shrink(1); + return stack; + } else if (context.world.getFluidState(interactionPos).is(FluidTags.WATER)) { + ItemStack waterBottle = PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER); + MountedDispenseBehavior.placeItemInInventory(waterBottle, context, pos); + stack.shrink(1); + return stack; + } else { + return null; + } + } + }; + + public static void registerDefaults() { + for (SpawnEggItem egg : SpawnEggItem.eggs()) { + MountedDispenseBehavior.REGISTRY.register(egg, SPAWN_EGG); + } + + MountedDispenseBehavior.REGISTRY.register(Items.TNT, TNT); + MountedDispenseBehavior.REGISTRY.register(Items.FIREWORK_ROCKET, FIREWORK); + MountedDispenseBehavior.REGISTRY.register(Items.FIRE_CHARGE, FIRE_CHARGE); + MountedDispenseBehavior.REGISTRY.register(Items.BUCKET, BUCKET); + MountedDispenseBehavior.REGISTRY.register(Items.GLASS_BOTTLE, BOTTLE); + + // potions can't be automatically converted since they use a weird wrapper thing + MountedDispenseBehavior.REGISTRY.register(Items.SPLASH_POTION, POTIONS); + MountedDispenseBehavior.REGISTRY.register(Items.LINGERING_POTION, POTIONS); + } +} diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index d10f60a0d4..d218ff7eeb 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -13,8 +13,6 @@ public class AllMovementBehaviours { MovementBehaviour.REGISTRY.register(Blocks.BELL, new BellMovementBehaviour()); MovementBehaviour.REGISTRY.register(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); MovementBehaviour.REGISTRY.register(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour()); - - DispenserMovementBehaviour.gatherMovedDispenseItemBehaviours(); MovementBehaviour.REGISTRY.register(Blocks.DISPENSER, new DispenserMovementBehaviour()); MovementBehaviour.REGISTRY.register(Blocks.DROPPER, new DropperMovementBehaviour()); } diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index 48bc7c6cf6..859c734744 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -200,6 +200,7 @@ public class AllTags { VALVE_HANDLES, VANILLA_STRIPPED_LOGS, VANILLA_STRIPPED_WOOD, + DISPENSE_BEHAVIOR_WRAP_BLACKLIST, STRIPPED_LOGS(FORGE), STRIPPED_WOOD(FORGE), diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 8c8a8b14a5..ab13776bab 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -174,6 +174,7 @@ public class Create { AllInteractionBehaviours.registerDefaults(); AllContraptionMovementSettings.registerDefaults(); AllOpenPipeEffectHandlers.registerDefaults(); + AllMountedDispenseItemBehaviors.registerDefaults(); // -- AllAdvancements.register(); diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java new file mode 100644 index 0000000000..941b8a0de9 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java @@ -0,0 +1,88 @@ +package com.simibubi.create.api.contraption.dispenser; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; +import net.minecraft.world.Container; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.level.block.entity.HopperBlockEntity; +import net.minecraft.world.phys.Vec3; + +/** + * A parallel to {@link DefaultDispenseItemBehavior}, providing a common, default, extendable dispense implementation. + */ +public class DefaultMountedDispenseBehavior implements MountedDispenseBehavior { + /** + * A reusable instance of the default behavior. + */ + public static final MountedDispenseBehavior INSTANCE = new DefaultMountedDispenseBehavior(); + + @Override + public ItemStack dispense(ItemStack stack, MovementContext context, BlockPos pos) { + Vec3 normal = MountedDispenseBehavior.getDispenserNormal(context); + + Direction closestToFacing = MountedDispenseBehavior.getClosestFacingDirection(normal); + Container inventory = HopperBlockEntity.getContainerAt(context.world, pos.relative(closestToFacing)); + if (inventory == null) { + ItemStack remainder = this.execute(stack, context, pos, normal); + this.playSound(context.world, pos); + this.playAnimation(context.world, pos, closestToFacing); + return remainder; + } else { + ItemStack toInsert = stack.copyWithCount(1); + ItemStack remainder = HopperBlockEntity.addItem(null, inventory, toInsert, closestToFacing.getOpposite()); + if (remainder.isEmpty()) { + stack.shrink(1); + } + } + return stack; + } + + /** + * Dispense the given item. Sounds and particles are already handled. + * @return the remaining items after dispensing one + */ + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + ItemStack toDispense = stack.split(1); + spawnItem(context.world, toDispense, 6, facing, pos, context); + return stack; + } + + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_DISPENSER_DISPENSE, pos, 0); + } + + protected void playAnimation(LevelAccessor level, BlockPos pos, Vec3 facing) { + this.playAnimation(level, pos, MountedDispenseBehavior.getClosestFacingDirection(facing)); + } + + protected void playAnimation(LevelAccessor level, BlockPos pos, Direction direction) { + level.levelEvent(LevelEvent.PARTICLES_SHOOT, pos, direction.get3DDataValue()); + } + + public static void spawnItem(Level level, ItemStack stack, int speed, Vec3 facing, BlockPos pos, MovementContext context) { + double x = pos.getX() + facing.x + .5; + double y = pos.getY() + facing.y + .5; + double z = pos.getZ() + facing.z + .5; + if (MountedDispenseBehavior.getClosestFacingDirection(facing).getAxis() == Direction.Axis.Y) { + y = y - 0.125; + } else { + y = y - 0.15625; + } + + ItemEntity entity = new ItemEntity(level, x, y, z, stack); + double d3 = level.random.nextDouble() * 0.1 + 0.2; + entity.setDeltaMovement( + level.random.nextGaussian() * 0.0075 * speed + facing.x() * d3 + context.motion.x, + level.random.nextGaussian() * 0.0075 * speed + facing.y() * d3 + context.motion.y, + level.random.nextGaussian() * 0.0075 * speed + facing.z() * d3 + context.motion.z + ); + level.addFreshEntity(entity); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java new file mode 100644 index 0000000000..ee58e671c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java @@ -0,0 +1,79 @@ +package com.simibubi.create.api.contraption.dispenser; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.impl.contraption.dispenser.DispenserBehaviorConverter; + +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.DispenseItemBehavior; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +/** + * A parallel to {@link DispenseItemBehavior}, for use by mounted dispensers. + * Create will attempt to wrap existing {@link DispenseItemBehavior}s, but this interface can be used to provide better or fixed behavior. + * @see DefaultMountedDispenseBehavior + * @see MountedProjectileDispenseBehavior + * @see OptionalMountedDispenseBehavior + */ +@FunctionalInterface +public interface MountedDispenseBehavior { + SimpleRegistry REGISTRY = Util.make(() -> { + SimpleRegistry registry = SimpleRegistry.create(); + registry.registerProvider(DispenserBehaviorConverter.INSTANCE); + return registry; + }); + + /** + * Dispense the given stack into the world. + * @param stack the stack to dispense. Safe to modify, behaviors are given a copy + * @param context the MovementContext of the dispenser + * @param pos the BlockPos being visited by the dispenser + * @return the remaining stack after dispensing one item + */ + ItemStack dispense(ItemStack stack, MovementContext context, BlockPos pos); + + // utilities for implementations + + static Vec3 getDispenserNormal(MovementContext ctx) { + Direction facing = ctx.state.getValue(DispenserBlock.FACING); + Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal()); + return ctx.rotation.apply(normal).normalize(); + } + + static Direction getClosestFacingDirection(Vec3 facing) { + return Direction.getNearest(facing.x, facing.y, facing.z); + } + + /** + * Attempt to place an item back into the inventory. This is used in the case of item overflow, such as a stack + * of buckets becoming two separate stacks when one is filled with water. + *

+ * First tries to insert directly into the dispenser inventory. If that fails, it then tries the contraption's + * whole inventory. If that still fails, the stack is dispensed into the world with the default behavior. + * @param stack the stack to store in the inventory + * @param context the MovementContext given to the behavior + * @param pos the position given to the behavior + */ + static void placeItemInInventory(ItemStack stack, MovementContext context, BlockPos pos) { + ItemStack toInsert = stack.copy(); + // try inserting into own inventory first + ItemStack remainder = ItemHandlerHelper.insertItem(context.getItemStorage(), toInsert, false); + if (!remainder.isEmpty()) { + // next, try the whole contraption inventory + CombinedInvWrapper contraption = context.contraption.getStorage().getAllItems(); + ItemStack newRemainder = ItemHandlerHelper.insertItem(contraption, remainder, false); + if (!newRemainder.isEmpty()) { + // if there's *still* something left, dispense into world + DefaultMountedDispenseBehavior.INSTANCE.dispense(remainder, context, pos); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java new file mode 100644 index 0000000000..49a9913ca5 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java @@ -0,0 +1,76 @@ +package com.simibubi.create.api.contraption.dispenser; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.foundation.mixin.accessor.AbstractProjectileDispenseBehaviorAccessor; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.PositionImpl; +import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.phys.Vec3; + +/** + * A parallel to {@link AbstractProjectileDispenseBehavior}, providing a base implementation for projectile-shooting behaviors. + */ +public abstract class MountedProjectileDispenseBehavior extends DefaultMountedDispenseBehavior { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + Projectile projectile = this.getProjectile(context.world, x, y, z, stack.copy()); + if (projectile == null) + return stack; + + Vec3 motion = facing.scale(this.getPower()).add(context.motion); + projectile.shoot(motion.x, motion.y, motion.z, (float) motion.length(), this.getUncertainty()); + context.world.addFreshEntity(projectile); + stack.shrink(1); + return stack; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_DISPENSER_PROJECTILE_LAUNCH, pos, 0); + } + + @Nullable + protected abstract Projectile getProjectile(Level level, double x, double y, double z, ItemStack stack); + + protected float getUncertainty() { + return 6; + } + + protected float getPower() { + return 1.1f; + } + + /** + * Create a mounted behavior wrapper from a vanilla projectile dispense behavior. + */ + public static MountedDispenseBehavior of(AbstractProjectileDispenseBehavior vanillaBehaviour) { + AbstractProjectileDispenseBehaviorAccessor accessor = (AbstractProjectileDispenseBehaviorAccessor) vanillaBehaviour; + return new MountedProjectileDispenseBehavior() { + @Override + protected Projectile getProjectile(Level level, double x, double y, double z, ItemStack stack) { + return accessor.create$callGetProjectile(level, new PositionImpl(x, y, z), stack); + } + + @Override + protected float getUncertainty() { + return accessor.create$callGetUncertainty(); + } + + @Override + protected float getPower() { + return accessor.create$callGetPower(); + } + }; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java new file mode 100644 index 0000000000..4be21e7222 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java @@ -0,0 +1,43 @@ +package com.simibubi.create.api.contraption.dispenser; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.phys.Vec3; + +/** + * A mounted dispenser behavior that might fail, playing the empty sound if it does. + */ +public class OptionalMountedDispenseBehavior extends DefaultMountedDispenseBehavior { + private boolean success; + + @Override + protected final ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + ItemStack remainder = this.doExecute(stack, context, pos, facing); + this.success = remainder != null; + return remainder == null ? stack : remainder; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + if (this.success) { + super.playSound(level, pos); + } else { + level.levelEvent(LevelEvent.SOUND_DISPENSER_FAIL, pos, 0); + } + } + + /** + * Dispense the given item. + * @return the remaining items after dispensing one, or null if it failed + */ + @Nullable + protected ItemStack doExecute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + return super.execute(stack, context, pos, facing); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java deleted file mode 100644 index c9134e0b3f..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -public class DispenseItemLocation { - private final boolean internal; - private final int slot; - - public static final DispenseItemLocation NONE = new DispenseItemLocation(false, -1); - - public DispenseItemLocation(boolean internal, int slot) { - this.internal = internal; - this.slot = slot; - } - - public boolean isInternal() { - return internal; - } - - public int getSlot() { - return slot; - } - - public boolean isEmpty() { - return slot < 0; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java index b82fd1057e..86468d4cd5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java @@ -1,107 +1,16 @@ package com.simibubi.create.content.contraptions.behaviour.dispenser; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.mixin.accessor.DispenserBlockAccessor; - -import org.jetbrains.annotations.Nullable; import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockSource; -import net.minecraft.core.Direction; -import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; -import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; -import net.minecraft.core.dispenser.DispenseItemBehavior; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.DispenserBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; public class DispenserMovementBehaviour extends DropperMovementBehaviour { - private static final Map movedDispenseItemBehaviors = new HashMap<>(); - private static final Set blacklist = new HashSet<>(); - - private static boolean spawnEggsRegistered = false; - - public static void gatherMovedDispenseItemBehaviours() { - IMovedDispenseItemBehaviour.init(); - } - - public static void registerMovedDispenseItemBehaviour(Item item, - IMovedDispenseItemBehaviour movedDispenseItemBehaviour) { - movedDispenseItemBehaviors.put(item, movedDispenseItemBehaviour); - } - - public static DispenseItemBehavior getDispenseMethod(ItemStack itemstack) { - return ((DispenserBlockAccessor) Blocks.DISPENSER).create$callGetDispenseMethod(itemstack); - } - @Override - protected IMovedDispenseItemBehaviour getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { - if (!spawnEggsRegistered) { - spawnEggsRegistered = true; - IMovedDispenseItemBehaviour.initSpawnEggs(); - } - - Item item = stack.getItem(); - // return registered/cached behavior if present - if (movedDispenseItemBehaviors.containsKey(item)) { - return movedDispenseItemBehaviors.get(item); - } - - // if there isn't one, try to create one from a vanilla behavior - if (blacklist.contains(item)) { - // unless it's been blacklisted, which means a behavior was created already and errored - return MovedDefaultDispenseItemBehaviour.INSTANCE; - } - - DispenseItemBehavior behavior = getDispenseMethod(stack); - // no behavior or default, use the moved default - if (behavior == null || behavior.getClass() == DefaultDispenseItemBehavior.class) - return MovedDefaultDispenseItemBehaviour.INSTANCE; - - // projectile-specific behaviors are pretty straightforward to convert - if (behavior instanceof AbstractProjectileDispenseBehavior projectile) { - IMovedDispenseItemBehaviour movedBehaviour = MovedProjectileDispenserBehaviour.of(projectile); - // cache it for later - registerMovedDispenseItemBehaviour(item, movedBehaviour); - return movedBehaviour; - } - - // other behaviors are more convoluted due to BlockSource providing a BlockEntity. - Vec3 normal = getRotatedFacingNormal(context); - Direction nearestFacing = Direction.getNearest(normal.x, normal.y, normal.z); - ContraptionBlockSource source = new ContraptionBlockSource(context, pos, nearestFacing); - IMovedDispenseItemBehaviour movedBehavior = new FallbackMovedDispenseBehavior(item, behavior, source); - registerMovedDispenseItemBehaviour(item, movedBehavior); - return movedBehavior; - } - - private static Vec3 getRotatedFacingNormal(MovementContext ctx) { - Direction facing = ctx.state.getValue(DispenserBlock.FACING); - Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal()); - return ctx.rotation.apply(normal); - } - - private record FallbackMovedDispenseBehavior(Item item, DispenseItemBehavior wrapped, BlockSource source) implements IMovedDispenseItemBehaviour { - @Override - public ItemStack dispense(ItemStack stack, MovementContext context, BlockPos pos) { - ItemStack backup = stack.copy(); - try { - return this.wrapped.dispense(this.source, stack); - } catch (NullPointerException ignored) { - // error due to lack of a BlockEntity. Un-register self to avoid continuing to fail - movedDispenseItemBehaviors.remove(this.item); - blacklist.add(this.item); - return backup; - } - } + protected MountedDispenseBehavior getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { + MountedDispenseBehavior behavior = MountedDispenseBehavior.REGISTRY.get(stack.getItem()); + return behavior != null ? behavior : DefaultMountedDispenseBehavior.INSTANCE; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java index 581ed17556..312faf1388 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java @@ -5,6 +5,8 @@ import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; import com.simibubi.create.api.behaviour.movement.MovementBehaviour; +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.item.ItemHelper; @@ -38,13 +40,13 @@ public class DropperMovementBehaviour implements MovementBehaviour { // copy because dispense behaviors will modify it directly ItemStack stack = storage.getStackInSlot(slot).copy(); - IMovedDispenseItemBehaviour behavior = getDispenseBehavior(context, pos, stack); + MountedDispenseBehavior behavior = getDispenseBehavior(context, pos, stack); ItemStack remainder = behavior.dispense(stack, context, pos); storage.setStackInSlot(slot, remainder); } - protected IMovedDispenseItemBehaviour getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { - return MovedDefaultDispenseItemBehaviour.INSTANCE; + protected MountedDispenseBehavior getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { + return DefaultMountedDispenseBehavior.INSTANCE; } /** diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java deleted file mode 100644 index f1deec3e8c..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import com.simibubi.create.content.contraptions.behaviour.MovementContext; - -import net.minecraft.Util; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.BlockTags; -import net.minecraft.tags.FluidTags; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.item.PrimedTnt; -import net.minecraft.world.entity.projectile.FireworkRocketEntity; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.entity.projectile.SmallFireball; -import net.minecraft.world.entity.projectile.ThrownPotion; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.SpawnEggItem; -import net.minecraft.world.item.alchemy.PotionUtils; -import net.minecraft.world.item.alchemy.Potions; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.BeehiveBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.BucketPickup; -import net.minecraft.world.level.block.entity.BeehiveBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public interface IMovedDispenseItemBehaviour { - - static void initSpawnEggs() { - final IMovedDispenseItemBehaviour spawnEggDispenseBehaviour = new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3 facing) { - if (!(itemStack.getItem() instanceof SpawnEggItem)) - return super.dispenseStack(itemStack, context, pos, facing); - if (context.world instanceof ServerLevel) { - EntityType entityType = ((SpawnEggItem) itemStack.getItem()).getType(itemStack.getTag()); - Entity spawnedEntity = entityType.spawn((ServerLevel) context.world, itemStack, null, - pos.offset(BlockPos.containing(facing.x + .7, facing.y + .7, facing.z + .7)), MobSpawnType.DISPENSER, facing.y < .5, - false); - if (spawnedEntity != null) - spawnedEntity.setDeltaMovement(context.motion.scale(2)); - } - itemStack.shrink(1); - return itemStack; - } - }; - - for (SpawnEggItem spawneggitem : SpawnEggItem.eggs()) - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(spawneggitem, spawnEggDispenseBehaviour); - } - - static void init() { - MovedProjectileDispenserBehaviour movedPotionDispenseItemBehaviour = new MovedProjectileDispenserBehaviour() { - @Override - protected Projectile getProjectileEntity(Level world, double x, double y, double z, ItemStack itemStack) { - return Util.make(new ThrownPotion(world, x, y, z), (p_218411_1_) -> p_218411_1_.setItem(itemStack)); - } - - protected float getProjectileInaccuracy() { - return super.getProjectileInaccuracy() * 0.5F; - } - - protected float getProjectileVelocity() { - return super.getProjectileVelocity() * .5F; - } - }; - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.SPLASH_POTION, - movedPotionDispenseItemBehaviour); - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.LINGERING_POTION, - movedPotionDispenseItemBehaviour); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.TNT, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - PrimedTnt tntentity = new PrimedTnt(context.world, x, y, z, null); - tntentity.push(context.motion.x, context.motion.y, context.motion.z); - context.world.addFreshEntity(tntentity); - context.world.playSound(null, tntentity.getX(), tntentity.getY(), tntentity.getZ(), - SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); - itemStack.shrink(1); - return itemStack; - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.FIREWORK_ROCKET, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - FireworkRocketEntity fireworkrocketentity = - new FireworkRocketEntity(context.world, itemStack, x, y, z, true); - fireworkrocketentity.shoot(facing.x, facing.y, facing.z, 0.5F, 1.0F); - context.world.addFreshEntity(fireworkrocketentity); - itemStack.shrink(1); - return itemStack; - } - - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1004, pos, 0); - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.FIRE_CHARGE, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1018, pos, 0); - } - - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - RandomSource random = context.world.random; - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - context.world.addFreshEntity(Util.make( - new SmallFireball(context.world, x, y, z, - random.nextGaussian() * 0.05D + facing.x + context.motion.x, - random.nextGaussian() * 0.05D + facing.y + context.motion.y, - random.nextGaussian() * 0.05D + facing.z + context.motion.z), - (p_229425_1_) -> p_229425_1_.setItem(itemStack))); - itemStack.shrink(1); - return itemStack; - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.GLASS_BOTTLE, - new MovedOptionalDispenseBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - this.successful = false; - BlockPos interactAt = pos.relative(getClosestFacingDirection(facing)); - BlockState state = context.world.getBlockState(interactAt); - Block block = state.getBlock(); - - if (state.is(BlockTags.BEEHIVES) && state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { - ((BeehiveBlock) block).releaseBeesAndResetHoneyLevel(context.world, state, interactAt, null, - BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); - this.successful = true; - return placeItemInInventory(itemStack, new ItemStack(Items.HONEY_BOTTLE), context, pos, facing); - } else if (context.world.getFluidState(interactAt) - .is(FluidTags.WATER)) { - this.successful = true; - return placeItemInInventory(itemStack, - PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER), context, pos, facing); - } else { - return super.dispenseStack(itemStack, context, pos, facing); - } - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.BUCKET, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - BlockPos interactAt = pos.relative(getClosestFacingDirection(facing)); - BlockState state = context.world.getBlockState(interactAt); - Block block = state.getBlock(); - if (block instanceof BucketPickup) { - ItemStack bucket = ((BucketPickup) block).pickupBlock(context.world, interactAt, state); - return placeItemInInventory(itemStack, bucket, context, pos, facing); - } - return super.dispenseStack(itemStack, context, pos, facing); - } - }); - } - - ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos); -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java deleted file mode 100644 index 641b4556cd..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import com.simibubi.create.content.contraptions.behaviour.MovementContext; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.DispenserBlock; -import net.minecraft.world.level.block.entity.HopperBlockEntity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; - -public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBehaviour { - public static final MovedDefaultDispenseItemBehaviour INSTANCE = new MovedDefaultDispenseItemBehaviour(); - - public static void doDispense(Level p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3 facing, - BlockPos p_82486_4_, MovementContext context) { - double d0 = p_82486_4_.getX() + facing.x + .5; - double d1 = p_82486_4_.getY() + facing.y + .5; - double d2 = p_82486_4_.getZ() + facing.z + .5; - if (Direction.getNearest(facing.x, facing.y, facing.z) - .getAxis() == Direction.Axis.Y) { - d1 = d1 - 0.125D; - } else { - d1 = d1 - 0.15625D; - } - - ItemEntity itementity = new ItemEntity(p_82486_0_, d0, d1, d2, p_82486_1_); - double d3 = p_82486_0_.random.nextDouble() * 0.1D + 0.2D; - itementity.setDeltaMovement( - p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.x() * d3 - + context.motion.x, - p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.y() * d3 - + context.motion.y, - p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.z() * d3 - + context.motion.z); - p_82486_0_.addFreshEntity(itementity); - } - - @Override - public ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos) { - Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING) - .getNormal()); - facingVec = context.rotation.apply(facingVec); - facingVec.normalize(); - - Direction closestToFacing = getClosestFacingDirection(facingVec); - Container inventory = HopperBlockEntity.getContainerAt(context.world, pos.relative(closestToFacing)); - if (inventory == null) { - this.playDispenseSound(context.world, pos); - this.spawnDispenseParticles(context.world, pos, closestToFacing); - return this.dispenseStack(itemStack, context, pos, facingVec); - } else { - if (HopperBlockEntity.addItem(null, inventory, itemStack.copy() - .split(1), closestToFacing.getOpposite()) - .isEmpty()) - itemStack.shrink(1); - return itemStack; - } - } - - /** - * Dispense the specified stack, play the dispense sound and spawn particles. - */ - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3 facing) { - ItemStack itemstack = itemStack.split(1); - doDispense(context.world, itemstack, 6, facing, pos, context); - return itemStack; - } - - /** - * Play the dispense sound from the specified block. - */ - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1000, pos, 0); - } - - /** - * Order clients to display dispense particles from the specified block and - * facing. - */ - protected void spawnDispenseParticles(LevelAccessor world, BlockPos pos, Vec3 facing) { - spawnDispenseParticles(world, pos, getClosestFacingDirection(facing)); - } - - protected void spawnDispenseParticles(LevelAccessor world, BlockPos pos, Direction direction) { - world.levelEvent(2000, pos, direction.get3DDataValue()); - } - - protected Direction getClosestFacingDirection(Vec3 exactFacing) { - return Direction.getNearest(exactFacing.x, exactFacing.y, exactFacing.z); - } - - protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context, - BlockPos pos, Vec3 facing) { - consumedFrom.shrink(1); - - ItemStack toInsert = output.copy(); - // try inserting into own inventory first - ItemStack remainder = ItemHandlerHelper.insertItem(context.getItemStorage(), toInsert, false); - if (!remainder.isEmpty()) { - // next, try the whole contraption inventory - // note that this contains the dispenser inventory. That's fine. - CombinedInvWrapper contraption = context.contraption.getStorage().getAllItems(); - ItemStack newRemainder = ItemHandlerHelper.insertItem(contraption, remainder, false); - if (!newRemainder.isEmpty()) { - // if there's *still* something left, dispense into world - INSTANCE.dispenseStack(remainder, context, pos, facing); - } - } - - return consumedFrom; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java deleted file mode 100644 index 3e9e77ed13..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelAccessor; - -public class MovedOptionalDispenseBehaviour extends MovedDefaultDispenseItemBehaviour { - protected boolean successful = true; - - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(this.successful ? 1000 : 1001, pos, 0); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java deleted file mode 100644 index 2d99d36172..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.mixin.accessor.AbstractProjectileDispenseBehaviorAccessor; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.phys.Vec3; - -public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDispenseItemBehaviour { - - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3 facing) { - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - Projectile projectile = this.getProjectileEntity(context.world, x, y, z, itemStack.copy()); - if (projectile == null) - return itemStack; - Vec3 effectiveMovementVec = facing.scale(getProjectileVelocity()).add(context.motion); - projectile.shoot(effectiveMovementVec.x, effectiveMovementVec.y, effectiveMovementVec.z, (float) effectiveMovementVec.length(), this.getProjectileInaccuracy()); - context.world.addFreshEntity(projectile); - itemStack.shrink(1); - return itemStack; - } - - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1002, pos, 0); - } - - @Nullable - protected abstract Projectile getProjectileEntity(Level world, double x, double y, double z, ItemStack itemStack); - - protected float getProjectileInaccuracy() { - return 6.0F; - } - - protected float getProjectileVelocity() { - return 1.1F; - } - - public static MovedProjectileDispenserBehaviour of(AbstractProjectileDispenseBehavior vanillaBehaviour) { - AbstractProjectileDispenseBehaviorAccessor accessor = (AbstractProjectileDispenseBehaviorAccessor) vanillaBehaviour; - return new MovedProjectileDispenserBehaviour() { - @Override - protected Projectile getProjectileEntity(Level world, double x, double y, double z, ItemStack itemStack) { - return accessor.create$callGetProjectile(world, new SimplePos(x, y, z), itemStack); - } - - @Override - protected float getProjectileInaccuracy() { - return accessor.create$callGetUncertainty(); - } - - @Override - protected float getProjectileVelocity() { - return accessor.create$callGetPower(); - } - }; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java deleted file mode 100644 index 9b8c22acca..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import net.minecraft.core.Position; - -public class SimplePos implements Position { - private final double x; - private final double y; - private final double z; - - public SimplePos(double x, double y, double z) { - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public double x() { - return x; - } - - @Override - public double y() { - return y; - } - - @Override - public double z() { - return z; - } -} diff --git a/src/main/java/com/simibubi/create/impl/contraption/dispenser/DispenserBehaviorConverter.java b/src/main/java/com/simibubi/create/impl/contraption/dispenser/DispenserBehaviorConverter.java new file mode 100644 index 0000000000..84d7720647 --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/contraption/dispenser/DispenserBehaviorConverter.java @@ -0,0 +1,104 @@ +package com.simibubi.create.impl.contraption.dispenser; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedProjectileDispenseBehavior; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.dispenser.ContraptionBlockSource; +import com.simibubi.create.foundation.mixin.accessor.DispenserBlockAccessor; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockSource; +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; +import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; +import net.minecraft.core.dispenser.DispenseItemBehavior; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.TagsUpdatedEvent; +import net.minecraftforge.registries.ForgeRegistries; + +public enum DispenserBehaviorConverter implements SimpleRegistry.Provider { + INSTANCE; + + @Override + @Nullable + public MountedDispenseBehavior get(Item item) { + DispenseItemBehavior vanilla = getDispenseMethod(new ItemStack(item)); + if (vanilla == null) + return null; + + // when the default, return null. The default will be used anyway, avoid caching it for no reason. + if (vanilla.getClass() == DefaultDispenseItemBehavior.class) + return null; + + // if the item is explicitly blocked from having its behavior wrapped, ignore it + if (AllItemTags.DISPENSE_BEHAVIOR_WRAP_BLACKLIST.matches(item)) + return null; + + if (vanilla instanceof AbstractProjectileDispenseBehavior projectile) { + return MountedProjectileDispenseBehavior.of(projectile); + } + + // other behaviors are more dangerous due to BlockSource providing a BlockEntity, which contraptions can't do. + // wrap in a fallback that will watch for errors. + return new FallbackBehavior(item, vanilla); + } + + @Override + public void onRegister(Runnable invalidate) { + // invalidate if the blacklist tag might've changed + MinecraftForge.EVENT_BUS.addListener((TagsUpdatedEvent event) -> { + if (event.shouldUpdateStaticData()) { + invalidate.run(); + } + }); + } + + @Nullable + private static DispenseItemBehavior getDispenseMethod(ItemStack stack) { + return ((DispenserBlockAccessor) Blocks.DISPENSER).create$callGetDispenseMethod(stack); + } + + private static final class FallbackBehavior extends DefaultMountedDispenseBehavior { + private final Item item; + private final DispenseItemBehavior wrapped; + private boolean hasErrored; + + private FallbackBehavior(Item item, DispenseItemBehavior wrapped) { + this.item = item; + this.wrapped = wrapped; + } + + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + if (this.hasErrored) + return stack; + + Direction nearestFacing = MountedDispenseBehavior.getClosestFacingDirection(facing); + BlockSource source = new ContraptionBlockSource(context, pos, nearestFacing); + + try { + // use a copy in case of implosion after modifying it + return this.wrapped.dispense(source, stack.copy()); + } catch (NullPointerException e) { + // likely due to the lack of a BlockEntity + ResourceLocation itemId = ForgeRegistries.ITEMS.getKey(this.item); + String message = "Error dispensing item '" + itemId + "' from contraption, not doing that anymore"; + Create.LOGGER.error(message, e); + this.hasErrored = true; + return stack; + } + } + } +} From 89ba8a76bcaaedb4c6f8e3bbb5970634cb7c4634 Mon Sep 17 00:00:00 2001 From: IThundxr Date: Fri, 21 Feb 2025 16:42:07 -0500 Subject: [PATCH 3/3] CoreModn't --- build.gradle | 31 ++++++++++--------- .../api/registry/CreateBuiltInRegistries.java | 22 ++----------- .../armor/TrimmableArmorModelGenerator.java | 14 +++++---- .../mixin/BuiltInRegistriesMixin.java | 14 +++++++++ .../accessor/BuiltInRegistriesAccessor.java | 15 +++++++++ .../accessor/ItemModelGeneratorsAccessor.java | 17 ++++++++++ .../resources/META-INF/accesstransformer.cfg | 3 -- src/main/resources/META-INF/coremods.json | 3 -- .../resources/coremods/better_registry.js | 28 ----------------- src/main/resources/create.mixins.json | 3 ++ 10 files changed, 76 insertions(+), 74 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/mixin/BuiltInRegistriesMixin.java create mode 100644 src/main/java/com/simibubi/create/foundation/mixin/accessor/BuiltInRegistriesAccessor.java create mode 100644 src/main/java/com/simibubi/create/foundation/mixin/accessor/ItemModelGeneratorsAccessor.java delete mode 100644 src/main/resources/META-INF/coremods.json delete mode 100644 src/main/resources/coremods/better_registry.js diff --git a/build.gradle b/build.gradle index e4298b03e2..38ea4dbd00 100644 --- a/build.gradle +++ b/build.gradle @@ -109,7 +109,7 @@ legacyForge { gameDirectory = project.file('run') systemProperty 'forge.logging.markers', 'REGISTRIES,REGISTRYDUMP' systemProperty 'forge.logging.console.level', 'debug' - programArguments = ["--mod", mod_id, "--all", "--output", file("src/generated/resources/").getAbsolutePath(), "--existing", file("src/main/resources").getAbsolutePath()] + programArguments.addAll("--mod", mod_id as String, "--all", "--output", file("src/generated/resources/").getAbsolutePath(), "--existing", file("src/main/resources").getAbsolutePath()) } gameTestServer { @@ -132,7 +132,8 @@ repositories { maven { url = "https://api.modrinth.com/maven" } maven { url = "https://maven.saps.dev/releases" } // FTB Mods maven { url = "https://maven.architectury.dev" } // Arch API - maven { url = "https://jm.gserv.me/repository/maven-public" // JourneyMap + maven { + url = "https://jm.gserv.me/repository/maven-public" // JourneyMap content { includeGroup "info.journeymap" includeGroup "mysticdrew" @@ -192,11 +193,11 @@ dependencies { modCompileOnly("top.theillusivec4.curios:curios-forge:${curios_version}+${curios_minecraft_version}:api") modRuntimeOnly("top.theillusivec4.curios:curios-forge:${curios_version}+${curios_minecraft_version}") - if (cc_tweaked_enable.toBoolean()) { - compileOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-core-api:${cc_tweaked_version}") + if (cc_tweaked_enable.toBoolean()) { + compileOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-core-api:${cc_tweaked_version}") modCompileOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge-api:${cc_tweaked_version}") modRuntimeOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge:${cc_tweaked_version}") - } + } if (dynamic_trees_enable.toBoolean()) { modCompileOnly("com.ferreusveritas.dynamictrees:DynamicTrees-${dynamic_trees_minecraft_version}:${dynamic_trees_version}") @@ -206,13 +207,13 @@ dependencies { // modImplementation("curse.maven:druidcraft-340991:3101903") // modImplementation("com.railwayteam.railways:railways-1.19.2-1.6.4:all") { transitive = false } - modRuntimeOnly("dev.architectury:architectury-forge:9.1.12") - modImplementation("dev.ftb.mods:ftb-chunks-forge:2001.3.1") - modImplementation("dev.ftb.mods:ftb-teams-forge:2001.3.0") - modImplementation("dev.ftb.mods:ftb-library-forge:2001.2.4") + modRuntimeOnly("dev.architectury:architectury-forge:9.1.12") + modImplementation("dev.ftb.mods:ftb-chunks-forge:2001.3.1") + modImplementation("dev.ftb.mods:ftb-teams-forge:2001.3.0") + modImplementation("dev.ftb.mods:ftb-library-forge:2001.2.4") - modImplementation("curse.maven:journeymap-32274:5457831") - // modImplementation("ignored:journeymap-1.20.1-5.10.1-forge") + modImplementation("curse.maven:journeymap-32274:5457831") + // modImplementation("ignored:journeymap-1.20.1-5.10.1-forge") // modRuntimeOnly("curse.maven:framedblocks-441647:5399211") // modRuntimeOnly("curse.maven:galosphere-631098:4574834") @@ -294,13 +295,13 @@ jar { manifest.attributes([ "MixinConfigs": "create.mixins.json", - "Git-Hash": gitHash + "Git-Hash" : gitHash ]) } tasks.named("sourcesJar") { manifest.attributes([ - "Git-Hash": gitHash + "Git-Hash": gitHash ]) } @@ -346,7 +347,7 @@ String calculateGitHash() { commandLine("git", "rev-parse", "HEAD") } return output.standardOutput.asText.get().trim() - } catch(Throwable ignored) { + } catch (Throwable ignored) { return "unknown" } } @@ -360,7 +361,7 @@ boolean hasUnstaged() { if (!result.isEmpty()) println("Found stageable results:\n ${result}\n") return !result.isEmpty() - } catch(Throwable ignored) { + } catch (Throwable ignored) { return false } } diff --git a/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java b/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java index 7e5182cb85..8e75692974 100644 --- a/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java +++ b/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java @@ -1,7 +1,5 @@ package com.simibubi.create.api.registry; -import java.lang.reflect.Field; - import org.jetbrains.annotations.ApiStatus; import com.mojang.serialization.Lifecycle; @@ -13,11 +11,11 @@ import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType; import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointType; import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; +import com.simibubi.create.foundation.mixin.accessor.BuiltInRegistriesAccessor; import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; import net.minecraft.core.WritableRegistry; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; /** @@ -26,8 +24,6 @@ import net.minecraft.resources.ResourceKey; * @see CreateRegistries */ public class CreateBuiltInRegistries { - private static final WritableRegistry> ROOT_REGISTRY = getRootRegistry(); - public static final Registry ARM_INTERACTION_POINT_TYPE = simple(CreateRegistries.ARM_INTERACTION_POINT_TYPE); public static final Registry FAN_PROCESSING_TYPE = simple(CreateRegistries.FAN_PROCESSING_TYPE); public static final Registry ITEM_ATTRIBUTE_TYPE = simple(CreateRegistries.ITEM_ATTRIBUTE_TYPE); @@ -47,27 +43,15 @@ public class CreateBuiltInRegistries { @SuppressWarnings("unchecked") private static Registry register(ResourceKey> key, WritableRegistry registry) { - ROOT_REGISTRY.register( + BuiltInRegistriesAccessor.create$getWRITABLE_REGISTRY().register( (ResourceKey>) (Object) key, registry, Lifecycle.stable() ); return registry; } - @SuppressWarnings("unchecked") - private static WritableRegistry> getRootRegistry() { - // an accessor can't be used here because BuiltInRegistries is loaded too early during datagen. - try { - Field field = BuiltInRegistries.class.getDeclaredField("WRITABLE_REGISTRY"); - field.setAccessible(true); - return (WritableRegistry>) field.get(null); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Create: Failed to get root registry", e); - } - } - @ApiStatus.Internal public static void init() { // make sure the class is loaded. - // this method is called at the tail of BuiltInRegistries, injected by a coremod. See it for details. + // this method is called at the tail of BuiltInRegistries, injected by BuiltInRegistriesMixin. } } diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java b/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java index 7509cfadd8..08363b4993 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java @@ -5,6 +5,7 @@ import java.lang.invoke.VarHandle; import java.util.Map; import com.simibubi.create.Create; +import com.simibubi.create.foundation.mixin.accessor.ItemModelGeneratorsAccessor; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateItemModelProvider; @@ -14,6 +15,7 @@ import net.minecraft.data.models.model.TextureMapping; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.Item; + import net.minecraftforge.client.model.generators.ItemModelBuilder; import net.minecraftforge.client.model.generators.ModelBuilder; @@ -32,25 +34,25 @@ public class TrimmableArmorModelGenerator { public static void generate(DataGenContext c, RegistrateItemModelProvider p) { T item = c.get(); ItemModelBuilder builder = p.generated(c); - for (ItemModelGenerators.TrimModelData data : ItemModelGenerators.GENERATED_TRIM_MODELS) { + for (ItemModelGenerators.TrimModelData data : ItemModelGeneratorsAccessor.create$getGENERATED_TRIM_MODELS()) { ResourceLocation modelLoc = ModelLocationUtils.getModelLocation(item); ResourceLocation textureLoc = TextureMapping.getItemTexture(item); String trimId = data.name(item.getMaterial()); ResourceLocation trimModelLoc = modelLoc.withSuffix("_" + trimId + "_trim"); ResourceLocation trimLoc = - new ResourceLocation("trims/items/" + item.getType().getName() + "_trim_" + trimId); + new ResourceLocation("trims/items/" + item.getType().getName() + "_trim_" + trimId); String parent = "item/generated"; if (item.getMaterial() == AllArmorMaterials.CARDBOARD) { trimLoc = Create.asResource("trims/items/card_" + item.getType().getName() + "_trim_" + trimId); } ItemModelBuilder itemModel = p.withExistingParent(trimModelLoc.getPath(), parent) - .texture("layer0", textureLoc); + .texture("layer0", textureLoc); Map textures = (Map) TEXTURES_HANDLE.get(itemModel); textures.put("layer1", trimLoc.toString()); builder.override() - .predicate(ItemModelGenerators.TRIM_TYPE_PREDICATE_ID, data.itemModelIndex()) - .model(itemModel) - .end(); + .predicate(ItemModelGenerators.TRIM_TYPE_PREDICATE_ID, data.itemModelIndex()) + .model(itemModel) + .end(); } } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/BuiltInRegistriesMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/BuiltInRegistriesMixin.java new file mode 100644 index 0000000000..475671439c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/BuiltInRegistriesMixin.java @@ -0,0 +1,14 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Mixin; + +import com.simibubi.create.api.registry.CreateBuiltInRegistries; + +import net.minecraft.core.registries.BuiltInRegistries; + +@Mixin(BuiltInRegistries.class) +public class BuiltInRegistriesMixin { + static { + CreateBuiltInRegistries.init(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/accessor/BuiltInRegistriesAccessor.java b/src/main/java/com/simibubi/create/foundation/mixin/accessor/BuiltInRegistriesAccessor.java new file mode 100644 index 0000000000..9646101b52 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/accessor/BuiltInRegistriesAccessor.java @@ -0,0 +1,15 @@ +package com.simibubi.create.foundation.mixin.accessor; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.core.WritableRegistry; +import net.minecraft.core.registries.BuiltInRegistries; + +@Mixin(BuiltInRegistries.class) +public interface BuiltInRegistriesAccessor { + @Accessor("WRITABLE_REGISTRY") + static WritableRegistry> create$getWRITABLE_REGISTRY() { + throw new AssertionError(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/accessor/ItemModelGeneratorsAccessor.java b/src/main/java/com/simibubi/create/foundation/mixin/accessor/ItemModelGeneratorsAccessor.java new file mode 100644 index 0000000000..fb82aa9ec7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/accessor/ItemModelGeneratorsAccessor.java @@ -0,0 +1,17 @@ +package com.simibubi.create.foundation.mixin.accessor; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.data.models.ItemModelGenerators; +import net.minecraft.data.models.ItemModelGenerators.TrimModelData; + +@Mixin(ItemModelGenerators.class) +public interface ItemModelGeneratorsAccessor { + @Accessor("GENERATED_TRIM_MODELS") + static List create$getGENERATED_TRIM_MODELS() { + throw new AssertionError(); + } +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 40641cf0a2..56dcc8a224 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -37,6 +37,3 @@ public net.minecraft.client.gui.components.CommandSuggestions$SuggestionsList ', - 'methodDesc': '()V' - }, - 'transformer': function (method) { - var CreateBuiltInRegistries = "com/simibubi/create/api/registry/CreateBuiltInRegistries"; - - var insn = ASMAPI.buildMethodCall(CreateBuiltInRegistries, "init", "()V", ASMAPI.MethodType.STATIC) - - method.instructions.insertBefore(method.instructions.getLast(), insn) - - return method; - } - } - } -} diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 1376a3728c..1fa07fdd31 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -9,6 +9,7 @@ "mixins": [ "ArmorTrimMixin", "BlockItemMixin", + "BuiltInRegistriesMixin", "ClientboundMapItemDataPacketMixin", "CustomItemUseEffectsMixin", "EntityMixin", @@ -22,11 +23,13 @@ "TestCommandMixin", "WaterWheelFluidSpreadMixin", "accessor.AbstractProjectileDispenseBehaviorAccessor", + "accessor.BuiltInRegistriesAccessor", "accessor.DispenserBlockAccessor", "accessor.FallingBlockEntityAccessor", "accessor.FlowingFluidAccessor", "accessor.FluidInteractionRegistryAccessor", "accessor.GameTestHelperAccessor", + "accessor.ItemModelGeneratorsAccessor", "accessor.LivingEntityAccessor", "accessor.NbtAccounterAccessor", "accessor.ServerLevelAccessor",