diff --git a/changelog.md b/changelog.md index a056aa79..73ab2d3b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,3 @@ -# 3.2.2 +# 3.2.3 -- Fix class loading error (again) \ No newline at end of file +- Implement Attachments on ItemStacks \ No newline at end of file diff --git a/common/src/main/java/earth/terrarium/botarium/common/data/DataManager.java b/common/src/main/java/earth/terrarium/botarium/common/data/DataManager.java index 871494f0..8ddf2c4f 100644 --- a/common/src/main/java/earth/terrarium/botarium/common/data/DataManager.java +++ b/common/src/main/java/earth/terrarium/botarium/common/data/DataManager.java @@ -10,6 +10,12 @@ public interface DataManager { T getData(Object dataHolder); + T getDataOrThrow(Object dataHolder); + + T getDataOrInit(Object dataHolder); + + T getDataOrInit(Object dataHolder, T data); + T setData(Object dataHolder, T data); boolean hasData(Object dataHolder); diff --git a/common/src/test/java/testmod/ManaContainer.java b/common/src/test/java/testmod/ManaContainer.java index 198e48bd..670cecbd 100644 --- a/common/src/test/java/testmod/ManaContainer.java +++ b/common/src/test/java/testmod/ManaContainer.java @@ -1,13 +1,25 @@ package testmod; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import earth.terrarium.botarium.common.generic.utils.AmountBasedContainer; import earth.terrarium.botarium.util.Serializable; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; public class ManaContainer implements AmountBasedContainer, Serializable { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.LONG.fieldOf("Mana").forGetter(ManaContainer::getStoredAmount) + ).apply(instance, ManaContainer::new)); + long storedAmount = 0; + public ManaContainer() {} + + public ManaContainer(long amt) { + storedAmount = amt; + } + @Override public long getStoredAmount() { return storedAmount; diff --git a/common/src/test/java/testmod/TestItem.java b/common/src/test/java/testmod/TestItem.java index 11ff4471..085b79a2 100644 --- a/common/src/test/java/testmod/TestItem.java +++ b/common/src/test/java/testmod/TestItem.java @@ -63,6 +63,11 @@ public void appendHoverText(ItemStack stack, @Nullable Level level, List use(Level level, Player player, Intera if (energyManager != null) { energyManager.setEnergy(100000); } + TestMod.MANA_DATA.getDataOrInit(stack).insert(100, false); } return InteractionResultHolder.success(player.getMainHandItem()); } diff --git a/common/src/test/java/testmod/TestMod.java b/common/src/test/java/testmod/TestMod.java index 8792d770..198afbfc 100644 --- a/common/src/test/java/testmod/TestMod.java +++ b/common/src/test/java/testmod/TestMod.java @@ -1,5 +1,7 @@ package testmod; +import earth.terrarium.botarium.common.data.DataManager; +import earth.terrarium.botarium.common.data.DataManagerRegistry; import earth.terrarium.botarium.common.energy.EnergyApi; import earth.terrarium.botarium.common.energy.impl.SimpleEnergyContainer; import earth.terrarium.botarium.common.energy.impl.UnlimitedEnergyContainer; @@ -37,6 +39,7 @@ public class TestMod { public static final RegistryHolder ITEMS = new RegistryHolder<>(BuiltInRegistries.ITEM, MOD_ID); public static final RegistryHolder FLUIDS = new RegistryHolder<>(BuiltInRegistries.FLUID, MOD_ID); + public static final DataManagerRegistry DATA_REG = DataManagerRegistry.create(MOD_ID); public static final FluidRegistry FLUID_TYPES = new FluidRegistry(MOD_ID); @@ -62,6 +65,7 @@ public class TestMod { public static final BlockContainerLookup MANA_LOOKUP_BLOCK = LookupApi.createBlockLookup(new ResourceLocation(MOD_ID, "mana"), ManaContainer.class); public static final ItemContainerLookup MANA_ITEM_LOOKUP = LookupApi.createItemLookup(new ResourceLocation(MOD_ID, "mana"), ManaContainerItem.class); + public static final DataManager MANA_DATA = DATA_REG.register("mana", ManaContainer::new, ManaContainer.CODEC, true); @SuppressWarnings("unchecked") public static void init() { @@ -72,6 +76,8 @@ public static void init() { FLUID_TYPES.initialize(); FLUIDS.initialize(); + DATA_REG.initialize(); + FluidApi.registerFluidItem(EXAMPLE_ITEM_NO_INTERFACE, stack -> new WrappedItemFluidContainer(stack, new SimpleFluidContainer(FluidConstants.fromMillibuckets(4000), 1, (integer, fluidHolder) -> true))); FluidApi.registerFluidItem(EXAMPLE_ITEM_UNLIMITED, stack -> new WrappedItemFluidContainer(stack, new UnlimitedFluidContainer(TEST_FLUID_SOURCE.get()))); FluidApi.registerFluidBlock(EXAMPLE_BLOCK_UNLIMITED, (level, blockPos, blockState, blockEntity, direction) -> new UnlimitedFluidContainer(TEST_FLUID_SOURCE.get())); diff --git a/fabric/src/main/java/earth/terrarium/botarium/fabric/data/DataUtils.java b/fabric/src/main/java/earth/terrarium/botarium/fabric/data/DataUtils.java new file mode 100644 index 00000000..06385d2a --- /dev/null +++ b/fabric/src/main/java/earth/terrarium/botarium/fabric/data/DataUtils.java @@ -0,0 +1,97 @@ +package earth.terrarium.botarium.fabric.data; + +import com.mojang.serialization.Codec; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; +import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; +import java.util.function.Supplier; + +@SuppressWarnings({"UnstableApiUsage", "unchecked"}) +public class DataUtils { + private static final Logger LOGGER = LoggerFactory.getLogger("botarium-item-data-attachment-impl"); + + public static void copyAttachments(H from, H to, Predicate> filter) { + Map, ?> attachments = from.fabric_getAttachments(); + if (attachments == null) return; + for (var entry : attachments.entrySet()) { + AttachmentType type = (AttachmentType) entry.getKey(); + var serializer = type.persistenceCodec(); + if (serializer != null && filter.test(type)) { + Tag tag = write(type, entry.getValue()); + Object data = read(type, tag); + to.setAttached(type, data); + } + } + } + + public static boolean areAttachmentsCompatible(H first, H second) { + Map, ?> firstAttachments = first.fabric_getAttachments(); + Map, ?> secondAttachments = second.fabric_getAttachments(); + if (firstAttachments == null && secondAttachments == null) return true; + if (secondAttachments == null || firstAttachments == null) return false; + for (var entry : firstAttachments.entrySet()) { + AttachmentType type = (AttachmentType) entry.getKey(); + if (type.persistenceCodec() != null) { + var otherData = secondAttachments.get(type); + Supplier initializer = type.initializer(); + if (otherData == null && initializer != null) + otherData = initializer.get(); + if (!Objects.equals(write(type, entry.getValue()), write(type, otherData))) + return false; + } + } + for (var entry : secondAttachments.entrySet()) { + AttachmentType type = (AttachmentType) entry.getKey(); + if (type.persistenceCodec() != null) { + var data = firstAttachments.get(type); + if (data != null) + continue; // already checked in the first loop + data = type.initializer().get(); + if(!Objects.equals(write(type, entry.getValue()), write(type, data))) return false; + } + } + return true; + } + + public static Tag write(AttachmentType type, T value) { + AtomicReference tag = new AtomicReference<>(new CompoundTag()); + Codec codec = type.persistenceCodec(); + if (codec == null) return tag.get(); + codec.encodeStart(NbtOps.INSTANCE, value) + .get() + .ifRight(partial -> { + LOGGER.warn("Couldn't serialize attachment " + type.identifier() + ", skipping. Error:"); + LOGGER.warn(partial.message()); + }) + .ifLeft(tag::set); + return tag.get(); + } + + public static T read(AttachmentType type, Tag tag) { + AtomicReference value = new AtomicReference<>(null); + Codec codec = type.persistenceCodec(); + if (codec == null) return value.get(); + codec.decode(NbtOps.INSTANCE, tag) + .get() + .ifRight(partial -> { + LOGGER.warn("Couldn't deserialize attachment " + type.identifier() + ", skipping. Error:"); + LOGGER.warn(partial.message()); + }) + .ifLeft(parsed -> value.set(parsed.getFirst())); + + return value.get(); + } + + public static T copy(AttachmentType type, T value) { + return read(type, write(type, value)); + } +} diff --git a/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManager.java b/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManager.java index e122c8c4..e5ed413a 100644 --- a/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManager.java +++ b/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManager.java @@ -21,6 +21,33 @@ public T getData(Object dataHolder) { } } + @Override + public T getDataOrThrow(Object dataHolder) { + if (dataHolder instanceof AttachmentTarget target) { + return target.getAttachedOrThrow(this.attachmentType); + } else { + throw new IllegalArgumentException(dataHolder + " is not an attachment target"); + } + } + + @Override + public T getDataOrInit(Object dataHolder) { + if (dataHolder instanceof AttachmentTarget target) { + return target.getAttachedOrCreate(this.attachmentType); + } else { + throw new IllegalArgumentException(dataHolder + " is not an attachment target"); + } + } + + @Override + public T getDataOrInit(Object dataHolder, T data) { + if (dataHolder instanceof AttachmentTarget target) { + return target.getAttachedOrSet(this.attachmentType, data); + } else { + throw new IllegalArgumentException(dataHolder + " is not an attachment target"); + } + } + @Override public T setData(Object dataHolder, T data) { if (dataHolder instanceof AttachmentTarget target) { diff --git a/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManagerRegistry.java b/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManagerRegistry.java index b98ac38f..0eab7a16 100644 --- a/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManagerRegistry.java +++ b/fabric/src/main/java/earth/terrarium/botarium/fabric/data/FabricDataManagerRegistry.java @@ -4,6 +4,8 @@ import earth.terrarium.botarium.common.data.DataManager; import earth.terrarium.botarium.common.data.DataManagerBuilder; import earth.terrarium.botarium.common.data.DataManagerRegistry; +import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry; +import net.fabricmc.fabric.impl.attachment.AttachmentRegistryImpl; import net.fabricmc.fabric.impl.attachment.AttachmentTypeImpl; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; @@ -23,6 +25,7 @@ public FabricDataManagerRegistry(String modid) { public DataManager register(@NotNull String name, @NotNull Supplier factory, @Nullable Codec codec, boolean copyOnDeath) { ResourceLocation id = new ResourceLocation(modid, name); var type = new AttachmentTypeImpl<>(id, factory, codec, copyOnDeath); + AttachmentRegistryImpl.register(id, type); return new FabricDataManager<>(type); } diff --git a/fabric/src/main/java/earth/terrarium/botarium/fabric/fluid/holder/MutableItemVariant.java b/fabric/src/main/java/earth/terrarium/botarium/fabric/fluid/holder/MutableItemVariant.java deleted file mode 100644 index 95b6b22d..00000000 --- a/fabric/src/main/java/earth/terrarium/botarium/fabric/fluid/holder/MutableItemVariant.java +++ /dev/null @@ -1,42 +0,0 @@ -package earth.terrarium.botarium.fabric.fluid.holder; - -import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.Nullable; - -@SuppressWarnings("UnstableApiUsage") -public class MutableItemVariant implements ItemVariant { - private final ItemStack stack; - - public MutableItemVariant(ItemStack stack) { - this.stack = stack; - } - - @Override - public boolean isBlank() { - return stack.isEmpty(); - } - - @Override - public Item getObject() { - return stack.getItem(); - } - - @Override - public @Nullable CompoundTag getNbt() { - return stack.getTag(); - } - - @Override - public CompoundTag toNbt() { - return stack.save(new CompoundTag()); - } - - @Override - public void toPacket(FriendlyByteBuf buf) { - buf.writeItem(stack); - } -} diff --git a/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemAttachmentHolderMixin.java b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemAttachmentHolderMixin.java new file mode 100644 index 00000000..b2e7e38b --- /dev/null +++ b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemAttachmentHolderMixin.java @@ -0,0 +1,83 @@ +package earth.terrarium.botarium.mixin; + +import com.mojang.serialization.Codec; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; +import net.fabricmc.fabric.impl.attachment.AttachmentSerializingImpl; +import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl; +import net.fabricmc.fabric.impl.transfer.item.ItemVariantImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Objects; + +@SuppressWarnings("UnstableApiUsage") +@Mixin({ItemStack.class, ItemVariantImpl.class}) +public class ItemAttachmentHolderMixin implements AttachmentTargetImpl { + @Unique + @Nullable + private IdentityHashMap, Object> fabric_dataAttachments = null; + + @SuppressWarnings("unchecked") + @Override + @Nullable + public T getAttached(AttachmentType type) { + return fabric_dataAttachments == null ? null : (T) fabric_dataAttachments.get(type); + } + + @SuppressWarnings("unchecked") + @Override + @Nullable + public T setAttached(AttachmentType type, @Nullable T value) { + // Extremely inelegant, but the only alternative is separating out these two mixins and duplicating code + if (value == null) { + if (fabric_dataAttachments == null) { + return null; + } + + T removed = (T) fabric_dataAttachments.remove(type); + + if (fabric_dataAttachments.isEmpty()) { + fabric_dataAttachments = null; + } + + return removed; + } else { + if (fabric_dataAttachments == null) { + fabric_dataAttachments = new IdentityHashMap<>(); + } + + return (T) fabric_dataAttachments.put(type, value); + } + } + + @Override + public boolean hasAttached(AttachmentType type) { + return fabric_dataAttachments != null && fabric_dataAttachments.containsKey(type); + } + + @Override + public void fabric_writeAttachmentsToNbt(CompoundTag nbt) { + AttachmentSerializingImpl.serializeAttachmentData(nbt, fabric_dataAttachments); + } + + @Override + public void fabric_readAttachmentsFromNbt(CompoundTag nbt) { + fabric_dataAttachments = AttachmentSerializingImpl.deserializeAttachmentData(nbt); + } + + @Override + public boolean fabric_hasPersistentAttachments() { + return AttachmentSerializingImpl.hasPersistentAttachments(fabric_dataAttachments); + } + + @Override + public Map, ?> fabric_getAttachments() { + return fabric_dataAttachments; + } + +} diff --git a/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemStackMixin.java b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemStackMixin.java new file mode 100644 index 00000000..226cb1aa --- /dev/null +++ b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemStackMixin.java @@ -0,0 +1,47 @@ +package earth.terrarium.botarium.mixin; + +import earth.terrarium.botarium.fabric.data.DataUtils; +import net.fabricmc.fabric.api.attachment.v1.AttachmentTarget; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; +import net.fabricmc.fabric.impl.attachment.AttachmentEntrypoint; +import net.fabricmc.fabric.impl.attachment.AttachmentSerializingImpl; +import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.IdentityHashMap; +import java.util.Map; + +@SuppressWarnings("UnstableApiUsage") +@Mixin(ItemStack.class) +public class ItemStackMixin implements AttachmentTargetImpl { + @Inject(method = "(Lnet/minecraft/nbt/CompoundTag;)V", at = @At(value = "TAIL")) + public void $botarium_initAttachments(CompoundTag compoundTag, CallbackInfo ci) { + fabric_readAttachmentsFromNbt(compoundTag); + } + + @Inject(method = "save(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "TAIL")) + public void $botarium_saveAttachments(CompoundTag compoundTag, CallbackInfoReturnable cir) { + fabric_writeAttachmentsToNbt(compoundTag); + } + + @Inject(method = "copy", at = @At("RETURN")) + public void $botarium_copyAttachments(CallbackInfoReturnable cir) { + DataUtils.copyAttachments(this, (AttachmentTargetImpl) (Object) cir.getReturnValue(), (ignored) -> true); + } + + @Inject(method = "isSameItemSameTags(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Z", at = @At("RETURN"), cancellable = true) + private static void $botarium_areAttachmentsEqual(ItemStack stack, ItemStack other, CallbackInfoReturnable cir) { + cir.setReturnValue(cir.getReturnValue() && DataUtils.areAttachmentsCompatible((AttachmentTargetImpl) (Object) stack, (AttachmentTargetImpl) (Object) other)); + } +} diff --git a/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemVariantImplMixin.java b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemVariantImplMixin.java new file mode 100644 index 00000000..d5ed2d3d --- /dev/null +++ b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemVariantImplMixin.java @@ -0,0 +1,33 @@ +package earth.terrarium.botarium.mixin; + +import earth.terrarium.botarium.fabric.data.DataUtils; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; +import net.fabricmc.fabric.impl.attachment.AttachmentSerializingImpl; +import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl; +import net.fabricmc.fabric.impl.transfer.item.ItemVariantImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.IdentityHashMap; + +@SuppressWarnings("UnstableApiUsage") +@Mixin(ItemVariantImpl.class) +public class ItemVariantImplMixin implements AttachmentTargetImpl { + + @Inject(method = "toNbt()Lnet/minecraft/nbt/CompoundTag;", at = @At("TAIL")) + public void $botarium_writeAttachments(CallbackInfoReturnable cir) { + fabric_writeAttachmentsToNbt(cir.getReturnValue()); + } + + @Inject(method = "fromNbt(Lnet/minecraft/nbt/CompoundTag;)Lnet/fabricmc/fabric/api/transfer/v1/item/ItemVariant;", at = @At("RETURN")) + private static void $botarium_readAttachments(CompoundTag tag, CallbackInfoReturnable cir) { + if (!cir.getReturnValue().isBlank()) { + ((AttachmentTargetImpl) cir.getReturnValue()).fabric_readAttachmentsFromNbt(tag); + } + } +} diff --git a/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemVariantMixin.java b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemVariantMixin.java new file mode 100644 index 00000000..7595757f --- /dev/null +++ b/fabric/src/main/java/earth/terrarium/botarium/mixin/ItemVariantMixin.java @@ -0,0 +1,31 @@ +package earth.terrarium.botarium.mixin; + +import earth.terrarium.botarium.fabric.data.DataUtils; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; +import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@SuppressWarnings("UnstableApiUsage") +@Mixin(ItemVariant.class) +public interface ItemVariantMixin { + + @Inject(method = "of(Lnet/minecraft/world/item/ItemStack;)Lnet/fabricmc/fabric/api/transfer/v1/item/ItemVariant;", at = @At("RETURN")) + private static void $botarium_copyDataFromStack(ItemStack stack, CallbackInfoReturnable cir) { + DataUtils.copyAttachments((AttachmentTargetImpl) (Object) stack, (AttachmentTargetImpl) cir.getReturnValue(), (ignored) -> false); + } + + @Inject(method = "matches(Lnet/minecraft/world/item/ItemStack;)Z", at = @At("RETURN"), cancellable = true) + default void $botarium_doAttachmentsMatch(ItemStack stack, CallbackInfoReturnable cir) { + cir.setReturnValue(cir.getReturnValue() && DataUtils.areAttachmentsCompatible((AttachmentTargetImpl) (Object) stack, (AttachmentTargetImpl) this)); + } + + @Inject(method = "toStack(I)Lnet/minecraft/world/item/ItemStack;", at = @At("RETURN")) + default void $botarium_copyAttachmentsOntoStack(int count, CallbackInfoReturnable cir) { + DataUtils.copyAttachments((AttachmentTargetImpl) this, (AttachmentTargetImpl) (Object) cir.getReturnValue(), (ignored) -> false); + } +} diff --git a/fabric/src/main/resources/botarium.fabric.mixins.json b/fabric/src/main/resources/botarium.fabric.mixins.json index 373026b0..3c9fc113 100644 --- a/fabric/src/main/resources/botarium.fabric.mixins.json +++ b/fabric/src/main/resources/botarium.fabric.mixins.json @@ -7,6 +7,10 @@ "defaultRequire": 1 }, "mixins": [ - "BlockEntityMixin" + "BlockEntityMixin", + "ItemAttachmentHolderMixin", + "ItemStackMixin", + "ItemVariantImplMixin", + "ItemVariantMixin" ] } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 2461dbb5..c4d44c46 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.jvmargs=-Xmx2G enabledPlatforms=fabric,neoforge -version=3.2.2 +version=3.2.3 group=earth.terrarium.botarium minecraftVersion=1.20.4 parchmentVersion=2023.12.31 diff --git a/neoforge/src/main/java/earth/terrarium/botarium/neoforge/data/NeoDataManager.java b/neoforge/src/main/java/earth/terrarium/botarium/neoforge/data/NeoDataManager.java index 0e70b5ae..ada295b1 100644 --- a/neoforge/src/main/java/earth/terrarium/botarium/neoforge/data/NeoDataManager.java +++ b/neoforge/src/main/java/earth/terrarium/botarium/neoforge/data/NeoDataManager.java @@ -21,6 +21,28 @@ public T getData(Object dataHolder) { } } + @Override + public T getDataOrThrow(Object dataHolder) { + if (!hasData(dataHolder)) { + throw new RuntimeException(dataHolder + "is not initialized"); + } else { + return getData(dataHolder); + } + } + + @Override + public T getDataOrInit(Object dataHolder) { + return getData(dataHolder); + } + + @Override + public T getDataOrInit(Object dataHolder, T data) { + if (!hasData(dataHolder)) { + setData(dataHolder, data); + } + return getData(dataHolder); + } + @Override public T setData(Object dataHolder, T data) { if (dataHolder instanceof AttachmentHolder holder) { diff --git a/neoforge/src/main/java/earth/terrarium/botarium/neoforge/extensions/PlatformItemContainerImpl.java b/neoforge/src/main/java/earth/terrarium/botarium/neoforge/extensions/ItemContainerImpl.java similarity index 96% rename from neoforge/src/main/java/earth/terrarium/botarium/neoforge/extensions/PlatformItemContainerImpl.java rename to neoforge/src/main/java/earth/terrarium/botarium/neoforge/extensions/ItemContainerImpl.java index 2bb2e012..a1559a69 100644 --- a/neoforge/src/main/java/earth/terrarium/botarium/neoforge/extensions/PlatformItemContainerImpl.java +++ b/neoforge/src/main/java/earth/terrarium/botarium/neoforge/extensions/ItemContainerImpl.java @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; @ClassExtension(ItemContainer.class) -public class PlatformItemContainerImpl { +public interface ItemContainerImpl { @ImplementsBaseElement static ItemContainer of(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity entity, @Nullable Direction direction) {