From 1537f2d6650132bbc381caa9f41efc1ba6cef04a Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Tue, 9 Jun 2026 03:10:54 +0800 Subject: [PATCH 01/14] Code cleanup --- .../capability/BackpackWrapper.kt | 7 +++---- .../upgrade/AdvancedFeedingUpgradeWrapper.kt | 4 ---- .../capability/upgrade/IAdvancedFilterable.kt | 20 ++++++------------- .../capability/upgrade/IBasicFilterable.kt | 4 ++-- .../upgrade/PickupUpgradeWrapper.kt | 2 +- .../upgrade/RestockUpgradeWrapper.kt | 2 +- 6 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt index 94b7ad0..44208ff 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt @@ -1,6 +1,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability import com.cleanroommc.retrosophisticatedbackpacks.backpack.SortType +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IToggleable import com.cleanroommc.retrosophisticatedbackpacks.inventory.BackpackItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.inventory.UpgradeItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem @@ -164,8 +165,7 @@ class BackpackWrapper( val filterUpgrades = gatherCapabilityUpgrades(Capabilities.IFILTER_UPGRADE_CAPABILITY) .filter { it.enabled } - return if (filterUpgrades.isEmpty()) true - else filterUpgrades.any { it.canInsert(stack) } + return filterUpgrades.isEmpty() || filterUpgrades.any { it.canInsert(stack) } } fun canExtract(slotIndex: Int): Boolean { @@ -173,8 +173,7 @@ class BackpackWrapper( val filterUpgrades = gatherCapabilityUpgrades(Capabilities.IFILTER_UPGRADE_CAPABILITY) .filter { it.enabled } - return if (filterUpgrades.isEmpty()) true - else filterUpgrades.any { it.canInsert(stack) } + return filterUpgrades.isEmpty() || filterUpgrades.any { it.canExtract(stack) } } // Setting related diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedFeedingUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedFeedingUpgradeWrapper.kt index 800a51e..05cb37d 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedFeedingUpgradeWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedFeedingUpgradeWrapper.kt @@ -1,20 +1,16 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade -import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackDataFixer import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.inventory.ExposedItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.item.FeedingUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.util.BackpackItemStackHelper import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey -import net.minecraft.item.ItemFood import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.EnumFacing import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.fml.common.Loader import net.minecraftforge.items.IItemHandler -import squeek.applecore.api.AppleCoreAPI class AdvancedFeedingUpgradeWrapper : AdvancedUpgradeWrapper(), IFeedingUpgrade { companion object { diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IAdvancedFilterable.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IAdvancedFilterable.kt index 56a2206..60ce3c0 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IAdvancedFilterable.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IAdvancedFilterable.kt @@ -78,24 +78,16 @@ interface IAdvancedFilterable : IBasicFilterable { if (filterStack.isEmpty) return false - var flag = if (ignoreDurability) { - ItemStack.areItemsEqualIgnoreDurability(filterStack, stack) - } else { - filterStack.isItemEqual(stack) - } - - flag = flag && if (ignoreNBT) { - true - } else { - filterStack.tagCompound == stack.tagCompound - } + var flag = (ignoreDurability && ItemStack.areItemsEqualIgnoreDurability(filterStack, stack)) + || filterStack.isItemEqual(stack) + flag = flag && (ignoreNBT || filterStack.tagCompound == stack.tagCompound) return flag } override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = capability == Capabilities.ADVANCED_FILTERABLE_CAPABILITY || - super.hasCapability(capability, facing) + super.hasCapability(capability, facing) enum class MatchType { ITEM, @@ -110,7 +102,7 @@ interface IAdvancedFilterable : IBasicFilterable { get() = IBasicFilterable.Impl.filterType set(_) {} - override fun checkFilter(itemStack: ItemStack): Boolean = + override fun checkFilter(stack: ItemStack): Boolean = false override var matchType: MatchType @@ -126,4 +118,4 @@ interface IAdvancedFilterable : IBasicFilterable { get() = false set(_) {} } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IBasicFilterable.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IBasicFilterable.kt index 0bb0003..660c020 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IBasicFilterable.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IBasicFilterable.kt @@ -36,7 +36,7 @@ interface IBasicFilterable : ISidelessCapabilityProvider { get() = FilterType.WHITELIST set(_) {} - override fun checkFilter(itemStack: ItemStack): Boolean = + override fun checkFilter(stack: ItemStack): Boolean = false } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/PickupUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/PickupUpgradeWrapper.kt index e1950e6..90aa2f3 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/PickupUpgradeWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/PickupUpgradeWrapper.kt @@ -17,4 +17,4 @@ class PickupUpgradeWrapper : BasicUpgradeWrapper(), IPickupUp capability == Capabilities.PICKUP_UPGRADE_CAPABILITY || super.hasCapability(capability, facing) || super.hasCapability(capability, facing) -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/RestockUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/RestockUpgradeWrapper.kt index 44884c2..28265c2 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/RestockUpgradeWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/RestockUpgradeWrapper.kt @@ -17,4 +17,4 @@ class RestockUpgradeWrapper : BasicUpgradeWrapper(), IRestoc capability == Capabilities.RESTOCK_UPGRADE_CAPABILITY || super.hasCapability(capability, facing) || super.hasCapability(capability, facing) -} \ No newline at end of file +} From 4f2ea3f875efa615a99533890cecd5582b177430 Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Tue, 9 Jun 2026 17:06:19 +0800 Subject: [PATCH 02/14] Initial implementation of void upgrade --- .../capability/Capabilities.java | 9 +++ .../upgrade/AdvancedVoidUpgradeWrapper.kt | 37 ++++++++++ .../capability/upgrade/IVoidUpgrade.kt | 35 +++++++++ .../capability/upgrade/VoidUpgradeWrapper.kt | 44 ++++++++++++ .../client/gui/BackpackPanel.kt | 20 ++++++ .../client/gui/RSBTextures.kt | 6 ++ .../upgrade/AdvancedVoidUpgradeWidget.kt | 49 +++++++++++++ .../gui/widgets/upgrade/VoidUpgradeWidget.kt | 72 +++++++++++++++++++ .../handler/CapabilityHandler.kt | 28 ++++++-- .../retrosophisticatedbackpacks/item/Items.kt | 8 ++- .../item/VoidUpgradeItem.kt | 8 +++ .../sync/UpgradeSlotSH.kt | 14 ++-- .../lang/en_us.lang | 14 ++++ .../lang/zh_tw.lang | 14 ++++ .../models/item/advanced_void_upgrade.json | 6 ++ .../models/item/void_upgrade.json | 6 ++ .../recipes/advanced_void_upgrade.json | 28 ++++++++ .../recipes/void_upgrade.json | 28 ++++++++ 18 files changed, 414 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedVoidUpgradeWidget.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/VoidUpgradeWidget.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/VoidUpgradeItem.kt create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_void_upgrade.json create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/models/item/void_upgrade.json create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/recipes/advanced_void_upgrade.json create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/recipes/void_upgrade.json diff --git a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java index c8e8822..fbe1248 100644 --- a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java +++ b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java @@ -44,6 +44,12 @@ public final class Capabilities { @CapabilityInject(AdvancedFilterUpgradeWrapper.class) public static final @NotNull Capability ADVANCED_FILTER_UPGRADE_WRAPPER_CAPABILITY = null; + @CapabilityInject(VoidUpgradeWrapper.class) + public static final @NotNull Capability VOID_UPGRADE_CAPABILITY = null; + + @CapabilityInject(AdvancedVoidUpgradeWrapper.class) + public static final @NotNull Capability ADVANCED_VOID_UPGRADE_CAPABILITY = null; + // Abstract capabilities @CapabilityInject(UpgradeWrapper.class) public static final @NotNull Capability> UPGRADE_CAPABILITY = null; @@ -71,4 +77,7 @@ public final class Capabilities { @CapabilityInject(IFilterUpgrade.class) public static final @NotNull Capability IFILTER_UPGRADE_CAPABILITY = null; + + @CapabilityInject(IVoidUpgrade.class) + public static final @NotNull Capability IVOID_UPGRADE_CAPABILITY = null; } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt new file mode 100644 index 0000000..80e69e6 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt @@ -0,0 +1,37 @@ +package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.item.VoidUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability + +class AdvancedVoidUpgradeWrapper : AdvancedUpgradeWrapper(), IVoidUpgrade { + override val settingsLangKey: String = "gui.advanced_void_settings".asTranslationKey() + override var transferSource: IVoidUpgrade.TransferSource = IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION + override var voidType: IVoidUpgrade.VoidType = IVoidUpgrade.VoidType.ANY + + override fun canVoid(stack: ItemStack, transferSource: IVoidUpgrade.TransferSource, voidType: IVoidUpgrade.VoidType): Boolean = + checkFilter(stack) && this.voidType == voidType && + (this.transferSource == IVoidUpgrade.TransferSource.ALL || this.transferSource == transferSource) + + override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = + capability == Capabilities.ADVANCED_VOID_UPGRADE_CAPABILITY || + super.hasCapability(capability, facing) || + super.hasCapability(capability, facing) + + override fun serializeNBT(): NBTTagCompound { + val nbt = super.serializeNBT() + nbt.setByte(IVoidUpgrade.TRANSFER_SOURCE_TAG, transferSource.ordinal.toByte()) + nbt.setByte(IVoidUpgrade.VOID_TYPE_TAG, voidType.ordinal.toByte()) + return nbt + } + + override fun deserializeNBT(nbt: NBTTagCompound) { + super.deserializeNBT(nbt) + transferSource = IVoidUpgrade.TransferSource.entries[nbt.getByte(IVoidUpgrade.TRANSFER_SOURCE_TAG).toInt()] + voidType = IVoidUpgrade.VoidType.entries[nbt.getByte(IVoidUpgrade.VOID_TYPE_TAG).toInt()] + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt new file mode 100644 index 0000000..3eba45c --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt @@ -0,0 +1,35 @@ +package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.capability.ISidelessCapabilityProvider +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.INBTSerializable + +sealed interface IVoidUpgrade : ISidelessCapabilityProvider, INBTSerializable { + companion object { + const val TRANSFER_SOURCE_TAG = "TransferSource" + + const val VOID_TYPE_TAG = "VoidType" + } + + var transferSource: TransferSource + var voidType: VoidType + + fun canVoid(stack: ItemStack, transferSource: TransferSource, voidType: VoidType): Boolean + + override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = + capability == Capabilities.IVOID_UPGRADE_CAPABILITY + + enum class TransferSource { + UPGRADE_OR_WORLD_INTERACTION, + ALL + } + + enum class VoidType { + ANY, + OVERFLOW + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt new file mode 100644 index 0000000..28a919c --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt @@ -0,0 +1,44 @@ +package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.item.VoidUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability + +class VoidUpgradeWrapper : BasicUpgradeWrapper(), IVoidUpgrade { + override val settingsLangKey: String = "gui.void_settings".asTranslationKey() + override var transferSource: IVoidUpgrade.TransferSource = IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION + override var voidType: IVoidUpgrade.VoidType = IVoidUpgrade.VoidType.ANY + + override fun canVoid( + stack: ItemStack, + transferSource: IVoidUpgrade.TransferSource, + voidType: IVoidUpgrade.VoidType + ): Boolean = + checkFilter(stack) && this.voidType == voidType && + (this.transferSource == IVoidUpgrade.TransferSource.ALL || this.transferSource == transferSource) + + override fun hasCapability( + capability: Capability<*>, + facing: EnumFacing? + ): Boolean = + capability == Capabilities.VOID_UPGRADE_CAPABILITY || + super.hasCapability(capability, facing) || + super.hasCapability(capability, facing) + + override fun serializeNBT(): NBTTagCompound { + val nbt = super.serializeNBT() + nbt.setByte(IVoidUpgrade.TRANSFER_SOURCE_TAG, transferSource.ordinal.toByte()) + nbt.setByte(IVoidUpgrade.VOID_TYPE_TAG, voidType.ordinal.toByte()) + return nbt + } + + override fun deserializeNBT(nbt: NBTTagCompound) { + super.deserializeNBT(nbt) + transferSource = IVoidUpgrade.TransferSource.entries[nbt.getByte(IVoidUpgrade.TRANSFER_SOURCE_TAG).toInt()] + voidType = IVoidUpgrade.VoidType.entries[nbt.getByte(IVoidUpgrade.VOID_TYPE_TAG).toInt()] + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt index 2ae4a7a..2fbfbea 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt @@ -497,6 +497,26 @@ class BackpackPanel( tabWidget.expandedWidget = FilterUpgradeWidget(slotIndex, wrapper) } + is AdvancedVoidUpgradeWrapper -> { + upgradeSlotGroup.updateAdvancedFilterDelegate(wrapper) + if (updateAndCheckRecreation( + tabWidget.expandedWidget, + wrapper + ) + ) + tabWidget.expandedWidget = AdvancedVoidUpgradeWidget(slotIndex, wrapper) + } + + is VoidUpgradeWrapper -> { + upgradeSlotGroup.updateFilterDelegate(wrapper) + if (updateAndCheckRecreation( + tabWidget.expandedWidget, + wrapper + ) + ) + tabWidget.expandedWidget = VoidUpgradeWidget(slotIndex, wrapper) + } + is IAdvancedFilterable -> { upgradeSlotGroup.updateAdvancedFilterDelegate(wrapper) if (updateAndCheckRecreation>(tabWidget.expandedWidget, wrapper)) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt index 76acc9f..274f2f2 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt @@ -26,6 +26,9 @@ object RSBTextures { val HALF_HEART_ICON = icon("half_heart", 96, 16) val IGNORE_HALF_HEART_ICON = icon("ignore_half_heart", 112, 16) + val VOID_ANY_ICON = icon("void", 208, 16) + val VOID_OVERFLOW_ICON = icon("void_overflow", 224, 16) + val BY_MOD_ID_ICON = icon("by_mod_id", 32, 16) val BY_ITEM_ICON = ItemDrawable(ItemStack(Items.APPLE)) @@ -41,8 +44,11 @@ object RSBTextures { val ALL_FOUR_SLOT_ICON = icon("all_in_four_slot", 16, 80) val NO_SORT_ICON = icon("no_sort", 32, 80) val NONE_FOUR_SLOT_ICON = icon("none_in_four_slot", 48, 80) + val BACK_ICON = icon("back", 64, 80) + val WORKS_IN_GUI_ICON = icon("works_in_gui", 80, 80) val SETTING_ICON = icon("setting", 16, 96) + val NOT_WORK_IN_GUI_ICON = icon("not_work_in_gui", 80, 96) val MATCH_ORE_DICT_ICON = icon("consider_ore_dict", 112, 96) val IGNORE_ORE_DICT_ICON = icon("ignore_ore_dict", 128, 96) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedVoidUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedVoidUpgradeWidget.kt new file mode 100644 index 0000000..4ce68b9 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedVoidUpgradeWidget.kt @@ -0,0 +1,49 @@ +package com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.AdvancedVoidUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.CyclicVariantButtonWidget +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade.VoidUpgradeWidget.Companion.TRANSFER_SOURCE_VARIANTS +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade.VoidUpgradeWidget.Companion.VOID_TYPE_VARIANTS +import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.sync.UpgradeSlotSH +import net.minecraft.item.ItemStack + +class AdvancedVoidUpgradeWidget( + slotIndex: Int, + wrapper: AdvancedVoidUpgradeWrapper +) : AdvancedExpandedTabWidget( + slotIndex, + wrapper, + ItemStack(Items.advancedFilterUpgrade), + wrapper.settingsLangKey, + coveredTabSize = 6 +) { + val transferSourceButton: CyclicVariantButtonWidget + val voidTypeButton: CyclicVariantButtonWidget + + init { + transferSourceButton = CyclicVariantButtonWidget(TRANSFER_SOURCE_VARIANTS, wrapper.transferSource.ordinal) { + this@AdvancedVoidUpgradeWidget.wrapper.transferSource = IVoidUpgrade.TransferSource.entries[it] + updateWrapper() + } + voidTypeButton = CyclicVariantButtonWidget(VOID_TYPE_VARIANTS, wrapper.voidType.ordinal) { + this@AdvancedVoidUpgradeWidget.wrapper.voidType = IVoidUpgrade.VoidType.entries[it] + updateWrapper() + } + + startingRow + .leftRel(0.5f) + .height(20) + .childPadding(2) + .child(transferSourceButton) + .child(voidTypeButton) + } + + fun updateWrapper() { + filterWidget.slotSyncHandler?.syncToServer(UpgradeSlotSH.UPDATE_VOID) { + it.writeEnumValue(this@AdvancedVoidUpgradeWidget.wrapper.transferSource) + it.writeEnumValue(this@AdvancedVoidUpgradeWidget.wrapper.voidType) + } + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/VoidUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/VoidUpgradeWidget.kt new file mode 100644 index 0000000..7799e37 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/VoidUpgradeWidget.kt @@ -0,0 +1,72 @@ +package com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade + +import com.cleanroommc.modularui.api.drawable.IKey +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.VoidUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.RSBTextures +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.CyclicVariantButtonWidget +import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.sync.UpgradeSlotSH +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.item.ItemStack + +class VoidUpgradeWidget( + slotIndex: Int, + wrapper: VoidUpgradeWrapper +) : BasicExpandedTabWidget( + slotIndex, wrapper, + ItemStack(Items.voidUpgrade), + wrapper.settingsLangKey, + coveredTabSize = 5 +) { + companion object { + internal val TRANSFER_SOURCE_VARIANTS = listOf( + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.upgrade_or_world_interaction".asTranslationKey()), + RSBTextures.NOT_WORK_IN_GUI_ICON + ), CyclicVariantButtonWidget.Variant( + IKey.lang("gui.any_interaction".asTranslationKey()), + RSBTextures.WORKS_IN_GUI_ICON + ) + ) + + internal val VOID_TYPE_VARIANTS = listOf( + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.void_any".asTranslationKey()), + RSBTextures.VOID_ANY_ICON + ), + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.void_overflow".asTranslationKey()), + RSBTextures.VOID_OVERFLOW_ICON + ) + ) + } + + val transferSourceButton: CyclicVariantButtonWidget + val voidTypeButton: CyclicVariantButtonWidget + + init { + transferSourceButton = CyclicVariantButtonWidget(TRANSFER_SOURCE_VARIANTS, wrapper.transferSource.ordinal) { + this@VoidUpgradeWidget.wrapper.transferSource = IVoidUpgrade.TransferSource.entries[it] + updateWrapper() + } + voidTypeButton = CyclicVariantButtonWidget(VOID_TYPE_VARIANTS, wrapper.voidType.ordinal) { + this@VoidUpgradeWidget.wrapper.voidType = IVoidUpgrade.VoidType.entries[it] + updateWrapper() + } + + startingRow + .leftRel(0.5f) + .height(20) + .childPadding(2) + .child(transferSourceButton) + .child(voidTypeButton) + } + + fun updateWrapper() { + filterWidget.slotSyncHandler?.syncToServer(UpgradeSlotSH.UPDATE_VOID) { + it.writeEnumValue(this@VoidUpgradeWidget.wrapper.transferSource) + it.writeEnumValue(this@VoidUpgradeWidget.wrapper.voidType) + } + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt index 7229c69..554634f 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt @@ -102,6 +102,18 @@ object CapabilityHandler { ::AdvancedFilterUpgradeWrapper ) + instance.register( + VoidUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::VoidUpgradeWrapper + ) + + instance.register( + AdvancedVoidUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::AdvancedVoidUpgradeWrapper + ) + // Interfaces instance.register( UpgradeWrapper::class.java, @@ -152,6 +164,12 @@ object CapabilityHandler { NOPCapabilityStorage(), ::FilterUpgradeWrapper ) + + instance.register( + IVoidUpgrade::class.java, + NOPCapabilityStorage(), + ::VoidUpgradeWrapper + ) } fun cacheBackpackInventory(backpackWrapper: BackpackWrapper) { @@ -160,17 +178,13 @@ object CapabilityHandler { return } - BACKPACK_INVENTORY_CACHE.put(backpackWrapper.uuid, backpackWrapper) + BACKPACK_INVENTORY_CACHE[backpackWrapper.uuid] = backpackWrapper backpackWrapper.isCached = true RetroSophisticatedBackpacks.LOGGER.info("Backpack ${backpackWrapper.uuid} is cached") } fun updateBackpackInventory(backpackWrapper: BackpackWrapper) { - val backpack = BACKPACK_INVENTORY_CACHE[backpackWrapper.uuid] - - if (backpack == null) { - return - } + val backpack = BACKPACK_INVENTORY_CACHE[backpackWrapper.uuid] ?: return backpack.deserializeNBT(backpackWrapper.serializeNBT()) RetroSophisticatedBackpacks.LOGGER.info("Backpack ${backpackWrapper.uuid} is updated") @@ -224,4 +238,4 @@ object CapabilityHandler { instance.deserializeNBT(nbt as NBTTagCompound) } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt index a84cad0..3b24eb3 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt @@ -117,4 +117,10 @@ object Items { @JvmField val advancedFilterUpgrade = FilterUpgradeItem("advanced_filter_upgrade", ::AdvancedFilterUpgradeWrapper) -} \ No newline at end of file + + @JvmField + val voidUpgrade = VoidUpgradeItem("void_upgrade", ::VoidUpgradeWrapper) + + @JvmField + val advancedVoidUpgrade = VoidUpgradeItem("advanced_void_upgrade", ::AdvancedVoidUpgradeWrapper) +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/VoidUpgradeItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/VoidUpgradeItem.kt new file mode 100644 index 0000000..00237f6 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/VoidUpgradeItem.kt @@ -0,0 +1,8 @@ +package com.cleanroommc.retrosophisticatedbackpacks.item + +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade + +class VoidUpgradeItem( + registryName: String, + wrapperFactory: () -> IVoidUpgrade +) : RankedUpgradeItem(registryName, wrapperFactory) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt index 295692b..36fa95b 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt @@ -3,11 +3,8 @@ package com.cleanroommc.retrosophisticatedbackpacks.sync import com.cleanroommc.modularui.value.sync.ItemSlotSH import com.cleanroommc.modularui.widgets.slot.ModularSlot import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.AdvancedFeedingUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.* import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.CraftingUpgradeWrapper.CraftingDestination -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IAdvancedFilterable -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IBasicFilterable -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IFilterUpgrade import net.minecraft.network.PacketBuffer /** @@ -23,6 +20,7 @@ class UpgradeSlotSH(slot: ModularSlot) : ItemSlotSH(slot) { const val UPDATE_ADVANCED_FEEDING = 10 const val UPDATE_FILTER_WAY = 11 const val UPDATE_CRAFTING_DESTINATION = 12 + const val UPDATE_VOID = 13 } override fun readOnServer(id: Int, buf: PacketBuffer) { @@ -36,6 +34,7 @@ class UpgradeSlotSH(slot: ModularSlot) : ItemSlotSH(slot) { UPDATE_ADVANCED_FEEDING -> updateAdvanceFeedingUpgrade(buf) UPDATE_FILTER_WAY -> updateFilterUpgrade(buf) UPDATE_CRAFTING_DESTINATION -> updateCraftingDestination(buf) + UPDATE_VOID -> updateVoidUpgrade(buf) } } @@ -92,4 +91,11 @@ class UpgradeSlotSH(slot: ModularSlot) : ItemSlotSH(slot) { wrapper.craftingDestination = buf.readEnumValue(CraftingDestination::class.java) } + + private fun updateVoidUpgrade(buf: PacketBuffer) { + val wrapper = slot.stack.getCapability(Capabilities.IVOID_UPGRADE_CAPABILITY, null) ?: return + + wrapper.transferSource = buf.readEnumValue(IVoidUpgrade.TransferSource::class.java) + wrapper.voidType = buf.readEnumValue(IVoidUpgrade.VoidType::class.java) + } } diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang index 02c55e8..49b7762 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang @@ -25,6 +25,8 @@ item.retro_sophisticated_backpacks.restock_upgrade.name=Restock Upgrade item.retro_sophisticated_backpacks.advanced_restock_upgrade.name=Advanced Restock Upgrade item.retro_sophisticated_backpacks.filter_upgrade.name=Filter Upgrade item.retro_sophisticated_backpacks.advanced_filter_upgrade.name=Advanced Filter Upgrade +item.retro_sophisticated_backpacks.void_upgrade.name=Void Upgrade +item.retro_sophisticated_backpacks.advanced_void_upgrade.name=Advanced Void Upgrade # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=Retro Sophisticated Backpacks @@ -68,6 +70,10 @@ retro_sophisticated_backpacks.tooltip.filter_upgrade=Filters inserted items when retro_sophisticated_backpacks.tooltip.advanced_filter_upgrade=Filters inserted items when placing in world with more configurations +retro_sophisticated_backpacks.tooltip.void_upgrade=Voids items selected in filter + +retro_sophisticated_backpacks.tooltip.advanced_void_upgrade=Voids items selected in filter with more configurations + retro_sophisticated_backpacks.tooltip.shift_to_reveal= # Gui Elements @@ -88,6 +94,9 @@ retro_sophisticated_backpacks.gui.advanced_restock_settings=Adv. Restock Setting retro_sophisticated_backpacks.gui.filter_settings=Filter Settings retro_sophisticated_backpacks.gui.advanced_filter_settings=Adv. Filter Settings +retro_sophisticated_backpacks.gui.void_settings=Void Settings +retro_sophisticated_backpacks.gui.advanced_void_settings=Adv. Void Settings + retro_sophisticated_backpacks.gui.crafting_settings=Crafting retro_sophisticated_backpacks.gui.memory_settings=Memory Settings @@ -128,6 +137,11 @@ retro_sophisticated_backpacks.gui.input_output=Input & Output retro_sophisticated_backpacks.gui.input=Input Only retro_sophisticated_backpacks.gui.output=Output Only +retro_sophisticated_backpacks.gui.upgrade_or_world_interaction=Only works with upgrade or in-world interactions +retro_sophisticated_backpacks.gui.any_interaction=Works with any interactions (including GUI) +retro_sophisticated_backpacks.gui.void_any=Voids applicable items +retro_sophisticated_backpacks.gui.void_overflow=Only voids if there's more than a stack + retro_sophisticated_backpacks.gui.sort_inventory=Sort Backpack Inventory retro_sophisticated_backpacks.gui.sort_by_name=Sort By Name retro_sophisticated_backpacks.gui.sort_by_mod_id=Sort By Mod ID diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang index 9f90e90..8dd0620 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang @@ -25,6 +25,8 @@ item.retro_sophisticated_backpacks.restock_upgrade.name=取貨升級 item.retro_sophisticated_backpacks.advanced_restock_upgrade.name=進階取貨升級 item.retro_sophisticated_backpacks.filter_upgrade.name=過濾升級 item.retro_sophisticated_backpacks.advanced_filter_upgrade.name=進階過濾升級 +item.retro_sophisticated_backpacks.void_upgrade.name=虛空升級 +item.retro_sophisticated_backpacks.advanced_void_upgrade.name=進階虛空升級 # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=復古精緻背包 @@ -68,6 +70,10 @@ retro_sophisticated_backpacks.tooltip.filter_upgrade=當放置於世界時過濾 retro_sophisticated_backpacks.tooltip.advanced_filter_upgrade=當放置於世界時根據更多配置過濾輸入的物品 +retro_sophisticated_backpacks.tooltip.void_upgrade=銷毀過濾清單中選定的物品 + +retro_sophisticated_backpacks.tooltip.advanced_void_upgrade=根據更多配置銷毀過濾清單中選定的物品 + retro_sophisticated_backpacks.tooltip.shift_to_reveal=<按 Shift 顯示> # Gui Elements @@ -88,6 +94,9 @@ retro_sophisticated_backpacks.gui.advanced_restock_settings=進階取貨設定 retro_sophisticated_backpacks.gui.filter_settings=過濾設定 retro_sophisticated_backpacks.gui.advanced_filter_settings=進階過濾設定 +retro_sophisticated_backpacks.gui.void_settings=虛空設定 +retro_sophisticated_backpacks.gui.advanced_void_settings=進階虛空設定 + retro_sophisticated_backpacks.gui.crafting_settings=合成 retro_sophisticated_backpacks.gui.memory_settings=記憶設定 @@ -131,6 +140,11 @@ retro_sophisticated_backpacks.gui.input_output=輸入 & 輸出 retro_sophisticated_backpacks.gui.input=僅限輸入 retro_sophisticated_backpacks.gui.output=僅限輸出 +retro_sophisticated_backpacks.gui.upgrade_or_world_interaction=僅啟用於其他升級或世界內的互動 +retro_sophisticated_backpacks.gui.any_interaction=啟用於任何互動(包括 GUI 界面) +retro_sophisticated_backpacks.gui.void_any=銷毀適用的物品 +retro_sophisticated_backpacks.gui.void_overflow=僅在多於 1 組物品時銷毀 + retro_sophisticated_backpacks.gui.sort_inventory=整理背包 retro_sophisticated_backpacks.gui.sort_by_name=根據名稱整理 retro_sophisticated_backpacks.gui.sort_by_mod_id=根據模組 ID 整理 diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_void_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_void_upgrade.json new file mode 100644 index 0000000..be702d2 --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_void_upgrade.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "retro_sophisticated_backpacks:item/advanced_void_upgrade" + } +} diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/models/item/void_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/void_upgrade.json new file mode 100644 index 0000000..4ba262a --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/void_upgrade.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "retro_sophisticated_backpacks:item/void_upgrade" + } +} diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/recipes/advanced_void_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/advanced_void_upgrade.json new file mode 100644 index 0000000..b2bb341 --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/advanced_void_upgrade.json @@ -0,0 +1,28 @@ +{ + "type": "retro_sophisticated_backpacks:upgrade_shaped", + "key": { + "G": { + "type": "forge:ore_dict", + "ore": "ingotGold" + }, + "D": { + "type": "forge:ore_dict", + "ore": "gemDiamond" + }, + "R": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "B": { + "item": "retro_sophisticated_backpacks:void_upgrade" + } + }, + "pattern": [ + " D ", + "GBG", + "RRR" + ], + "result": { + "item": "retro_sophisticated_backpacks:advanced_void_upgrade" + } +} diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/recipes/void_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/void_upgrade.json new file mode 100644 index 0000000..d40ed99 --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/void_upgrade.json @@ -0,0 +1,28 @@ +{ + "type": "minecraft:crafting_shaped", + "key": { + "P": { + "type": "forge:ore_dict", + "ore": "enderpearl" + }, + "O": { + "type": "forge:ore_dict", + "ore": "obsidian" + }, + "R": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "B": { + "item": "retro_sophisticated_backpacks:upgrade_base" + } + }, + "pattern": [ + " P ", + "OBO", + "ROR" + ], + "result": { + "item": "retro_sophisticated_backpacks:void_upgrade" + } +} From 5426473b5df797c4b69dbbe072b40bee44415691 Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Wed, 10 Jun 2026 15:18:05 +0800 Subject: [PATCH 03/14] Implement void upgrade support --- .../backpack/BackpackInventoryHelper.kt | 28 +++++++++++------ .../capability/BackpackWrapper.kt | 14 ++++++++- .../upgrade/AdvancedVoidUpgradeWrapper.kt | 8 +++-- .../capability/upgrade/IVoidUpgrade.kt | 31 ++++++++++++++++++- .../capability/upgrade/VoidUpgradeWrapper.kt | 6 ++-- .../common/gui/BackpackContainer.kt | 17 ++++++++-- .../handler/EntityEventHandler.kt | 8 ++++- .../inventory/BackpackItemStackHandler.kt | 20 +++++++++++- .../tileentity/BackpackTileEntity.kt | 8 ++++- 9 files changed, 116 insertions(+), 24 deletions(-) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/backpack/BackpackInventoryHelper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/backpack/BackpackInventoryHelper.kt index 5be8ba2..6d888e5 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/backpack/BackpackInventoryHelper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/backpack/BackpackInventoryHelper.kt @@ -2,6 +2,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.backpack import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem import net.minecraft.entity.Entity import net.minecraft.inventory.IInventory @@ -135,7 +136,7 @@ object BackpackInventoryHelper { } for (j in 0 until wrapper.backpackInventorySize()) { - stack = wrapper.backpackItemStackHandler.insertItemToMemorySlots(stack, false) + stack = wrapper.backpackItemStackHandler.insertItemToMemorySlotsRespectVoid(stack, false) if (transferMatched && wrapper.getStackInSlot(j).isEmpty) continue @@ -220,23 +221,30 @@ object BackpackInventoryHelper { if (source !is IItemHandlerModifiable) return false - if (isFull(backpackInventory)) - return false - for (i in 0 until source.slots) { val sourceStack = source.getStackInSlot(i) if (sourceStack.isEmpty) continue - var copiedSourceStack = sourceStack.copy() + if (wrapper.canRestock(sourceStack)) { + val processedStack = + wrapper.tryVoid(sourceStack.copy(), IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION) + + if (processedStack.count < sourceStack.count) { + transferred = true + } + + if (processedStack.isEmpty) { + source.setStackInSlot(i, ItemStack.EMPTY) + continue + } - if (wrapper.canRestock(copiedSourceStack)) { - copiedSourceStack = ItemHandlerHelper.insertItemStacked(backpackInventory, copiedSourceStack, false) + val remainder = ItemHandlerHelper.insertItemStacked(backpackInventory, processedStack, false) - if (!ItemStack.areItemStacksEqual(sourceStack, copiedSourceStack)) { + if (!ItemStack.areItemStacksEqual(sourceStack, remainder)) { transferred = true - source.setStackInSlot(i, copiedSourceStack) + source.setStackInSlot(i, remainder) } } } @@ -262,4 +270,4 @@ object BackpackInventoryHelper { return true } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt index 44208ff..2918e35 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt @@ -1,7 +1,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability import com.cleanroommc.retrosophisticatedbackpacks.backpack.SortType -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IToggleable +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.inventory.BackpackItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.inventory.UpgradeItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem @@ -176,6 +176,18 @@ class BackpackWrapper( return filterUpgrades.isEmpty() || filterUpgrades.any { it.canExtract(stack) } } + fun tryVoid(stack: ItemStack, transferSource: IVoidUpgrade.TransferSource): ItemStack { + var currentStack = stack + val upgrades = gatherCapabilityUpgrades(Capabilities.IVOID_UPGRADE_CAPABILITY) + + for (upgrade in upgrades) { + currentStack = upgrade.tryVoid(this, backpackItemStackHandler, currentStack, transferSource) + if (currentStack.isEmpty) return currentStack + } + + return currentStack + } + // Setting related fun isSlotMemorized(slotIndex: Int): Boolean = diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt index 80e69e6..9e8671a 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt @@ -13,9 +13,11 @@ class AdvancedVoidUpgradeWrapper : AdvancedUpgradeWrapper(), IV override var transferSource: IVoidUpgrade.TransferSource = IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION override var voidType: IVoidUpgrade.VoidType = IVoidUpgrade.VoidType.ANY - override fun canVoid(stack: ItemStack, transferSource: IVoidUpgrade.TransferSource, voidType: IVoidUpgrade.VoidType): Boolean = - checkFilter(stack) && this.voidType == voidType && - (this.transferSource == IVoidUpgrade.TransferSource.ALL || this.transferSource == transferSource) + override fun canVoid( + stack: ItemStack, + transferSource: IVoidUpgrade.TransferSource + ): Boolean = + checkFilter(stack) && (this.transferSource == IVoidUpgrade.TransferSource.ALL || this.transferSource == transferSource) override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = capability == Capabilities.ADVANCED_VOID_UPGRADE_CAPABILITY || diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt index 3eba45c..962d5b5 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt @@ -1,5 +1,6 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.capability.ISidelessCapabilityProvider import net.minecraft.item.ItemStack @@ -7,6 +8,8 @@ import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.EnumFacing import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.INBTSerializable +import net.minecraftforge.items.ItemHandlerHelper +import net.minecraftforge.items.ItemStackHandler sealed interface IVoidUpgrade : ISidelessCapabilityProvider, INBTSerializable { companion object { @@ -17,8 +20,34 @@ sealed interface IVoidUpgrade : ISidelessCapabilityProvider, INBTSerializable, facing: EnumFacing?): Boolean = capability == Capabilities.IVOID_UPGRADE_CAPABILITY diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt index 28a919c..e2c4db9 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt @@ -15,11 +15,9 @@ class VoidUpgradeWrapper : BasicUpgradeWrapper(), IVoidUpgrade override fun canVoid( stack: ItemStack, - transferSource: IVoidUpgrade.TransferSource, - voidType: IVoidUpgrade.VoidType + transferSource: IVoidUpgrade.TransferSource ): Boolean = - checkFilter(stack) && this.voidType == voidType && - (this.transferSource == IVoidUpgrade.TransferSource.ALL || this.transferSource == transferSource) + checkFilter(stack) && (this.transferSource == IVoidUpgrade.TransferSource.ALL || this.transferSource == transferSource) override fun hasCapability( capability: Capability<*>, diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackContainer.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackContainer.kt index 513e771..995a236 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackContainer.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackContainer.kt @@ -8,6 +8,7 @@ import com.cleanroommc.modularui.utils.Platform import com.cleanroommc.modularui.widgets.slot.ModularSlot import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.CraftingUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.IndexedInventoryCraftingWrapper import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.IndexedModularCraftingSlot import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.ModularBackpackSlot @@ -26,7 +27,7 @@ import kotlin.math.min class BackpackContainer(private val wrapper: BackpackWrapper, private val backpackSlotIndex: Int?) : ModularContainer() { companion object { - private val DROP_TO_WORLD: Int = -999 + private const val DROP_TO_WORLD: Int = -999 private const val LEFT_MOUSE: Int = 0 private const val RIGHT_MOUSE: Int = 1 } @@ -68,13 +69,23 @@ class BackpackContainer(private val wrapper: BackpackWrapper, private val backpa override fun slotClick(slotId: Int, mouseButton: Int, clickTypeIn: ClickType, player: EntityPlayer): ItemStack { val playerInventory = player.inventory - val heldStack = playerInventory.itemStack + var heldStack = playerInventory.itemStack if (clickTypeIn == ClickType.PICKUP && (mouseButton == LEFT_MOUSE || mouseButton == RIGHT_MOUSE) && (slotId != DROP_TO_WORLD && slotId >= 0) ) { val clickedSlot = getSlot(slotId) + + if (clickedSlot is ModularBackpackSlot && !heldStack.isEmpty) { + heldStack = wrapper.tryVoid(heldStack, IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION) + playerInventory.itemStack = heldStack + if (heldStack.isEmpty) { + detectAndSendChanges() + return ItemStack.EMPTY + } + } + val slotStack = clickedSlot.stack if (clickedSlot is ModularBackpackSlot && !slotStack.isEmpty && heldStack.isEmpty) { @@ -191,6 +202,7 @@ class BackpackContainer(private val wrapper: BackpackWrapper, private val backpa fromStack: ItemStack, vararg slotFilters: (ModularSlot) -> Boolean ): ItemStack { + val fromStack = wrapper.tryVoid(fromStack, IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION) val fromSlotGroup = fromSlot.slotGroup for (slotFilter in slotFilters) { val memorizedSlots = shiftClickSlots.filter(slotFilter) @@ -261,6 +273,7 @@ class BackpackContainer(private val wrapper: BackpackWrapper, private val backpa fromStack: ItemStack, slotFilter: (ModularSlot) -> Boolean ): ItemStack { + val fromStack = wrapper.tryVoid(fromStack, IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION) val fromSlotGroup = fromSlot.slotGroup val memorizedSlots = shiftClickSlots.filter(slotFilter) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt index 47131d0..97ee310 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt @@ -5,6 +5,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks import com.cleanroommc.retrosophisticatedbackpacks.Tags import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackInventoryHelper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiFactory import com.cleanroommc.retrosophisticatedbackpacks.config.Config @@ -107,7 +108,12 @@ object EntityEventHandler { var slotIndex = 0 while (!stack.isEmpty && slotIndex < wrapper.slots) { - stack = wrapper.backpackItemStackHandler.prioritizedInsertion(slotIndex, stack, false) + stack = wrapper.backpackItemStackHandler.prioritizedInsertionRespectVoid( + slotIndex, + stack, + false, + IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION + ) slotIndex++ } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/inventory/BackpackItemStackHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/inventory/BackpackItemStackHandler.kt index dce75d6..3513c4e 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/inventory/BackpackItemStackHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/inventory/BackpackItemStackHandler.kt @@ -1,6 +1,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.inventory import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.config.Config import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem import net.minecraft.item.ItemStack @@ -22,6 +23,16 @@ class BackpackItemStackHandler(size: Int, private val wrapper: BackpackWrapper) override fun getStackLimit(slotIndex: Int, stack: ItemStack): Int = stacks[slotIndex].maxStackSize * wrapper.getTotalStackMultiplier() + fun prioritizedInsertionRespectVoid( + slotIndex: Int, + stack: ItemStack, + simulate: Boolean, + transferSource: IVoidUpgrade.TransferSource + ): ItemStack { + val stack = wrapper.tryVoid(stack, transferSource) + return prioritizedInsertion(slotIndex, stack, simulate) + } + /** * Prioritize insertion by tries inserting on memorized slot first. * @@ -29,9 +40,14 @@ class BackpackItemStackHandler(size: Int, private val wrapper: BackpackWrapper) * gui-based interaction get unexpected insertion result. */ fun prioritizedInsertion(slotIndex: Int, stack: ItemStack, simulate: Boolean): ItemStack { - val stack = insertItemToMemorySlots(stack, simulate) + val stack = insertItemToMemorySlotsRespectVoid(stack, simulate) return insertItem(slotIndex, stack, simulate) } + + fun insertItemToMemorySlotsRespectVoid(stack: ItemStack, simulate: Boolean): ItemStack { + val stack = wrapper.tryVoid(stack, IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION) + return insertItemToMemorySlots(stack, simulate) + } fun insertItemToMemorySlots(stack: ItemStack, simulate: Boolean): ItemStack { var stack = stack @@ -50,6 +66,8 @@ class BackpackItemStackHandler(size: Int, private val wrapper: BackpackWrapper) } override fun insertItem(slot: Int, stack: ItemStack, simulate: Boolean): ItemStack { + val stack = wrapper.tryVoid(stack, IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION) + if (stack.isEmpty) return ItemStack.EMPTY diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/tileentity/BackpackTileEntity.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/tileentity/BackpackTileEntity.kt index 40187d6..0225476 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/tileentity/BackpackTileEntity.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/tileentity/BackpackTileEntity.kt @@ -9,6 +9,7 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.common.gui.BackpackContainer import com.cleanroommc.retrosophisticatedbackpacks.common.gui.BackpackGuiHolder import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey @@ -126,7 +127,12 @@ class BackpackTileEntity(val wrapper: BackpackWrapper = BackpackWrapper()) : stack: ItemStack, simulate: Boolean ): ItemStack = - if (wrapper.canInsert(stack)) wrapper.backpackItemStackHandler.prioritizedInsertion(slot, stack, simulate) + if (wrapper.canInsert(stack)) wrapper.backpackItemStackHandler.prioritizedInsertionRespectVoid( + slot, + stack, + simulate, + IVoidUpgrade.TransferSource.UPGRADE_OR_WORLD_INTERACTION + ) else stack override fun extractItem( From 7069be92d71ba95ec284351d94a137b2a8df9a2e Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 12 Jun 2026 00:00:41 +0800 Subject: [PATCH 04/14] Implement jukebox upgrade (basic) --- .../capability/Capabilities.java | 6 + .../block/BackpackBlock.kt | 6 +- .../capability/BackpackWrapper.kt | 7 +- .../capability/upgrade/IFilterUpgrade.kt | 5 +- .../capability/upgrade/IJukeboxUpgrade.kt | 22 +++ .../upgrade/JukeboxUpgradeWrapper.kt | 34 +++++ .../client/gui/BackpackPanel.kt | 26 +++- .../client/gui/RSBTextures.kt | 3 + .../client/gui/UpgradeSlotUpdateGroup.kt | 26 ++++ .../widgets/upgrade/JukeboxUpgradeWidget.kt | 121 +++++++++++++++ .../client/sound/BackpackSoundManager.kt | 62 ++++++++ .../client/sound/JukeboxUpgradeSound.kt | 60 ++++++++ .../common/gui/BackpackGuiHolder.kt | 1 + .../common/gui/slot/ModularUpgradeSlot.kt | 4 +- .../handler/CapabilityHandler.kt | 12 ++ .../handler/EntityEventHandler.kt | 23 +++ .../handler/NetworkHandler.kt | 15 ++ .../item/BackpackItem.kt | 7 +- .../retrosophisticatedbackpacks/item/Items.kt | 3 + .../item/JukeboxUpgradeItem.kt | 6 + .../network/C2SJukeboxUpgradePacket.kt | 142 ++++++++++++++++++ .../sync/DelegatedCraftingStackHandlerSH.kt | 3 +- .../sync/DelegatedStackHandlerSH.kt | 8 +- .../sync/JukeboxSlotSH.kt | 26 ++++ .../sync/UpgradeSlotSH.kt | 17 ++- .../lang/en_us.lang | 5 + .../lang/zh_tw.lang | 5 + .../models/item/jukebox_upgrade.json | 6 + 28 files changed, 644 insertions(+), 17 deletions(-) create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IJukeboxUpgrade.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/JukeboxUpgradeWrapper.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/JukeboxUpgradeSound.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/JukeboxUpgradeItem.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/models/item/jukebox_upgrade.json diff --git a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java index fbe1248..b06a176 100644 --- a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java +++ b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java @@ -49,6 +49,9 @@ public final class Capabilities { @CapabilityInject(AdvancedVoidUpgradeWrapper.class) public static final @NotNull Capability ADVANCED_VOID_UPGRADE_CAPABILITY = null; + + @CapabilityInject(JukeboxUpgradeWrapper.class) + public static final @NotNull Capability JUKEBOX_UPGRADE_CAPABILITY = null; // Abstract capabilities @CapabilityInject(UpgradeWrapper.class) @@ -80,4 +83,7 @@ public final class Capabilities { @CapabilityInject(IVoidUpgrade.class) public static final @NotNull Capability IVOID_UPGRADE_CAPABILITY = null; + + @CapabilityInject(IJukeboxUpgrade.class) + public static final @NotNull Capability IJUKEBOX_UPGRADE_CAPABILITY = null; } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt index 9604324..8eeec45 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt @@ -3,6 +3,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.block import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackTier import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager import com.cleanroommc.retrosophisticatedbackpacks.handler.RegistryHandler import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity import com.cleanroommc.retrosophisticatedbackpacks.util.IModelRegister @@ -173,10 +174,11 @@ class BackpackBlock( placer: EntityLivingBase, stack: ItemStack ) { - val backpackInventory = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return val tileEntity = worldIn.getTileEntity(pos) as? BackpackTileEntity ?: return - tileEntity.wrapper.deserializeNBT(backpackInventory.serializeNBT()) + tileEntity.wrapper.deserializeNBT(wrapper.serializeNBT()) + BackpackSoundManager.transferPlayingOwnership(null, tileEntity, wrapper) if (stack.hasDisplayName()) tileEntity.setCustomName(stack.displayName) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt index 2918e35..8ff828c 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt @@ -7,6 +7,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.inventory.UpgradeItemStackHan import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem import com.cleanroommc.retrosophisticatedbackpacks.item.ExponentialStackUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.InceptionUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.StackUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.util.BackpackItemStackHelper import net.minecraft.entity.player.EntityPlayer @@ -129,6 +130,10 @@ class BackpackWrapper( return true } + + fun canAddJukeboxUpgrade(): Boolean = + upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance() + .isEmpty() fun canNestBackpack(): Boolean = upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance().any() @@ -163,7 +168,6 @@ class BackpackWrapper( fun canInsert(stack: ItemStack): Boolean { val filterUpgrades = gatherCapabilityUpgrades(Capabilities.IFILTER_UPGRADE_CAPABILITY) - .filter { it.enabled } return filterUpgrades.isEmpty() || filterUpgrades.any { it.canInsert(stack) } } @@ -171,7 +175,6 @@ class BackpackWrapper( fun canExtract(slotIndex: Int): Boolean { val stack = getStackInSlot(slotIndex) val filterUpgrades = gatherCapabilityUpgrades(Capabilities.IFILTER_UPGRADE_CAPABILITY) - .filter { it.enabled } return filterUpgrades.isEmpty() || filterUpgrades.any { it.canExtract(stack) } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IFilterUpgrade.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IFilterUpgrade.kt index 206c234..0cbd8a2 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IFilterUpgrade.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IFilterUpgrade.kt @@ -8,7 +8,7 @@ import net.minecraft.util.EnumFacing import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.INBTSerializable -sealed interface IFilterUpgrade : ISidelessCapabilityProvider, IToggleable, INBTSerializable { +sealed interface IFilterUpgrade : ISidelessCapabilityProvider, INBTSerializable { companion object { const val FILTER_WAY_TAG = "FilterWay" } @@ -22,10 +22,9 @@ sealed interface IFilterUpgrade : ISidelessCapabilityProvider, IToggleable, INBT override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = capability == Capabilities.IFILTER_UPGRADE_CAPABILITY - enum class FilterWayType { IN_OUT, IN, OUT; } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IJukeboxUpgrade.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IJukeboxUpgrade.kt new file mode 100644 index 0000000..f9ca32e --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IJukeboxUpgrade.kt @@ -0,0 +1,22 @@ +package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.capability.ISidelessCapabilityProvider +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.INBTSerializable +import net.minecraftforge.items.ItemStackHandler + +sealed interface IJukeboxUpgrade : ISidelessCapabilityProvider, INBTSerializable { + companion object { + const val RECORDS_TAG = "Records" + const val CURRENT_PLAYING_INDEX_TAG = "CurrentPlayingIndex" + } + + val records: ItemStackHandler + var currentPlayingIndex: Int + + override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = + capability == Capabilities.IJUKEBOX_UPGRADE_CAPABILITY +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/JukeboxUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/JukeboxUpgradeWrapper.kt new file mode 100644 index 0000000..2410476 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/JukeboxUpgradeWrapper.kt @@ -0,0 +1,34 @@ +package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.items.ItemStackHandler + +class JukeboxUpgradeWrapper : UpgradeWrapper(), IJukeboxUpgrade { + override val settingsLangKey: String = "gui.jukebox_settings".asTranslationKey() + override val records: ItemStackHandler = ItemStackHandler(12) + override var currentPlayingIndex: Int = 0 + + override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = + capability == Capabilities.JUKEBOX_UPGRADE_CAPABILITY || + super.hasCapability(capability, facing) || + super.hasCapability(capability, facing) + + override fun serializeNBT(): NBTTagCompound { + val nbt = super.serializeNBT() + val recordsNBT = records.serializeNBT() + nbt.setTag(IJukeboxUpgrade.RECORDS_TAG, recordsNBT) + nbt.setInteger(IJukeboxUpgrade.CURRENT_PLAYING_INDEX_TAG, currentPlayingIndex) + return nbt + } + + override fun deserializeNBT(nbt: NBTTagCompound) { + super.deserializeNBT(nbt) + records.deserializeNBT(nbt.getCompoundTag(IJukeboxUpgrade.RECORDS_TAG)) + currentPlayingIndex = nbt.getInteger(IJukeboxUpgrade.CURRENT_PLAYING_INDEX_TAG) + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt index 2fbfbea..9c11d68 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt @@ -51,7 +51,9 @@ class BackpackPanel( internal val player: EntityPlayer, internal val tileEntity: BackpackTileEntity?, internal val syncManager: PanelSyncManager, - internal val backpackWrapper: BackpackWrapper + internal val backpackWrapper: BackpackWrapper, + internal val inventoryType: PlayerInventoryGuiData.InventoryType?, + internal val backpackSlotIndex: Int?, ) : ModularPanel("backpack_gui") { companion object { private const val SLOT_SIZE = 18 @@ -88,10 +90,11 @@ class BackpackPanel( wrapper: BackpackWrapper, width: Int, height: Int, + inventoryType: PlayerInventoryGuiData.InventoryType? = null, backpackSlotIndex: Int? = null, ): BackpackPanel { val panel = - BackpackPanel(player, tileEntity, syncManager, wrapper) + BackpackPanel(player, tileEntity, syncManager, wrapper, inventoryType, backpackSlotIndex) .size(width, height) as BackpackPanel syncManager.bindPlayerInventory(player) @@ -138,7 +141,7 @@ class BackpackPanel( backpackWrapper, it ).slotGroup("upgrade_inventory") - val syncHandler = UpgradeSlotSH(upgradeSlot) + val syncHandler = UpgradeSlotSH(upgradeSlot, backpackWrapper) val index = it upgradeSlot.changeListener { lastStack, _, isClient, init -> if (isClient) @@ -517,6 +520,23 @@ class BackpackPanel( tabWidget.expandedWidget = VoidUpgradeWidget(slotIndex, wrapper) } + is JukeboxUpgradeWrapper -> { + upgradeSlotGroup.updateJukeboxDelegate(wrapper) + if (updateAndCheckRecreation( + tabWidget.expandedWidget, + wrapper + ) + ) + tabWidget.expandedWidget = JukeboxUpgradeWidget( + slotIndex, + wrapper, + player, + tileEntity, + inventoryType, + backpackSlotIndex + ) + } + is IAdvancedFilterable -> { upgradeSlotGroup.updateAdvancedFilterDelegate(wrapper) if (updateAndCheckRecreation>(tabWidget.expandedWidget, wrapper)) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt index 274f2f2..59ffb35 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt @@ -39,6 +39,9 @@ object RSBTextures { val ADD_ICON = icon("add", 96, 32) val REMOVE_ICON = icon("remove", 112, 32) val BRAIN_ICON = icon("brain", 128, 32) + + val STOP_ICON = icon("stop", 0, 64) + val PLAY_ICON = icon("play", 16, 64) val ONE_IN_FOUR_SLOT_ICON = icon("one_in_four_slot", 0, 80) val ALL_FOUR_SLOT_ICON = icon("all_in_four_slot", 16, 80) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt index 2c6da7a..46465f1 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt @@ -8,6 +8,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.CraftingUpgradeWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IAdvancedFilterable import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IBasicFilterable +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.JukeboxUpgradeWrapper import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.CraftingSlotInfo import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.IndexedModularCraftingSlot import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.ModularFilterSlot @@ -15,6 +16,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.sync.DelegatedCraftingStackHa import com.cleanroommc.retrosophisticatedbackpacks.sync.DelegatedStackHandlerSH import com.cleanroommc.retrosophisticatedbackpacks.sync.FilterSlotSH import com.cleanroommc.retrosophisticatedbackpacks.sync.FoodFilterSlotSH +import com.cleanroommc.retrosophisticatedbackpacks.sync.JukeboxSlotSH class UpgradeSlotUpdateGroup( private val panel: BackpackPanel, @@ -38,6 +40,10 @@ class UpgradeSlotUpdateGroup( val craftingOutputSlot: ModularCraftingSlot val craftingInfo: CraftingSlotInfo + + // Jukebox slots + val jukeboxStackHandler = DelegatedStackHandlerSH(wrapper, slotIndex, 12) + var jukeboxSlots: Array init { val syncManager = panel.syncManager @@ -139,6 +145,21 @@ class UpgradeSlotUpdateGroup( craftingInfo = CraftingSlotInfo(craftingMatrixSlots, craftingOutputSlot) syncManager.registerSlotGroup(SlotGroup("crafting_result_$slotIndex", 1, false)) + + syncManager.syncValue("jukebox_delegation_$slotIndex", jukeboxStackHandler) + jukeboxSlots = Array(12) { + val slot = ModularSlot(jukeboxStackHandler.delegatedStackHandler, it) + slot.slotGroup("jukebox_slots_$slotIndex") + + syncManager.syncValue( + "jukebox_slot_$slotIndex", + it, + JukeboxSlotSH(slot, wrapper) + ) + + slot + } + syncManager.registerSlotGroup(SlotGroup("jukebox_slots_$slotIndex", 4, false)) } fun updateFilterDelegate(wrapper: IBasicFilterable) { @@ -155,5 +176,10 @@ class UpgradeSlotUpdateGroup( craftingStackHandler.setDelegatedStackHandler(wrapper::craftMatrix) craftingStackHandler.syncToServer(DelegatedCraftingStackHandlerSH.UPDATE_CRAFTING) } + + fun updateJukeboxDelegate(wrapper: JukeboxUpgradeWrapper) { + jukeboxStackHandler.setDelegatedStackHandler(wrapper::records) + jukeboxStackHandler.syncToServer(DelegatedStackHandlerSH.UPDATE_JUKEBOX) + } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt new file mode 100644 index 0000000..36d1bd4 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt @@ -0,0 +1,121 @@ +package com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade + +import com.cleanroommc.modularui.widgets.ButtonWidget +import com.cleanroommc.modularui.widgets.SlotGroupWidget +import com.cleanroommc.modularui.widgets.layout.Row +import com.cleanroommc.modularui.widgets.slot.ItemSlot +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.JukeboxUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.RSBTextures +import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler +import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.network.C2SJukeboxUpgradePacket +import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemRecord +import net.minecraft.item.ItemStack + +class JukeboxUpgradeWidget( + slotIndex: Int, + wrapper: JukeboxUpgradeWrapper, + playerEntity: EntityPlayer, + tileEntity: BackpackTileEntity?, + inventoryType: PlayerInventoryGuiData.InventoryType?, + slotIndexInInv: Int? +) : + ExpandedUpgradeTabWidget( + slotIndex, + wrapper, + 3, + ItemStack(Items.jukeboxUpgrade), + wrapper.settingsLangKey + ) { + private val recordSlot: ItemSlot + private val buttonRow: Row + private val stopButton: ButtonWidget<*> + private val playButton: ButtonWidget<*> + + init { + val JukeboxSlotGroupsWidget = SlotGroupWidget().name("jukebox_slots_$slotIndex").disableSortButtons() + JukeboxSlotGroupsWidget.flex().coverChildren().leftRel(0.5F).top(32) + + recordSlot = + ItemSlot().syncHandler("jukebox_slot_$slotIndex", 0) + .name("jukebox_slot_0") + + JukeboxSlotGroupsWidget.child(recordSlot) + + buttonRow = Row() + .leftRel(0.5F) + .top(28) + .coverChildrenWidth() + .childPadding(2) as Row + + stopButton = ButtonWidget().name("stop_button") + .onMousePressed { + val record = wrapper.records.getStackInSlot(0) + val item = record.item + + if (record.isEmpty || item !is ItemRecord) + return@onMousePressed false + + if (tileEntity != null) { + NetworkHandler.INSTANCE.sendToServer( + C2SJukeboxUpgradePacket.Stationary( + C2SJukeboxUpgradePacket.PlayingAction.STOP, + item.sound.soundName.toString(), + tileEntity.pos + ) + ) + } else { + NetworkHandler.INSTANCE.sendToServer( + C2SJukeboxUpgradePacket.Moving( + C2SJukeboxUpgradePacket.PlayingAction.STOP, + item.sound.soundName.toString(), + inventoryType!!, + slotIndexInInv!! + ) + ) + } + + true + } + .overlay(RSBTextures.STOP_ICON) + playButton = ButtonWidget().name("play_button") + .onMousePressed { + val record = wrapper.records.getStackInSlot(0) + val item = record.item + + if (record.isEmpty || item !is ItemRecord) + return@onMousePressed false + + if (tileEntity != null) { + NetworkHandler.INSTANCE.sendToServer( + C2SJukeboxUpgradePacket.Stationary( + C2SJukeboxUpgradePacket.PlayingAction.PLAY, + item.sound.soundName.toString(), + tileEntity.pos + ) + ) + } else { + NetworkHandler.INSTANCE.sendToServer( + C2SJukeboxUpgradePacket.Moving( + C2SJukeboxUpgradePacket.PlayingAction.PLAY, + item.sound.soundName.toString(), + inventoryType!!, + slotIndexInInv!! + ) + ) + } + + true + } + .overlay(RSBTextures.PLAY_ICON) + + buttonRow.child(stopButton) + .child(playButton) + + child(JukeboxSlotGroupsWidget) + .child(buttonRow) + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt new file mode 100644 index 0000000..6c55f22 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt @@ -0,0 +1,62 @@ +package com.cleanroommc.retrosophisticatedbackpacks.client.sound + +import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper +import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import net.minecraft.client.Minecraft +import net.minecraft.client.audio.ISound +import net.minecraft.entity.Entity +import net.minecraft.util.ResourceLocation +import net.minecraft.util.SoundEvent +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly +import java.util.* + +@SideOnly(Side.CLIENT) +object BackpackSoundManager { + private val activeSounds = Object2ObjectOpenHashMap() + + fun playRecordFromPlayer(entity: Entity, wrapper: BackpackWrapper, soundRegistryName: String) { + val soundEvent = SoundEvent.REGISTRY.getObject(ResourceLocation(soundRegistryName)) ?: return + + stopRecord(wrapper) + + val soundToPlay = JukeboxUpgradeSound(entity, null, soundEvent) + registerAndPlay(wrapper, soundToPlay) + } + + fun playRecordFromTileEntity(tileEntity: BackpackTileEntity, wrapper: BackpackWrapper, soundRegistryName: String) { + val soundEvent = SoundEvent.REGISTRY.getObject(ResourceLocation(soundRegistryName)) ?: return + + stopRecord(wrapper) + + val soundToPlay = JukeboxUpgradeSound(null, tileEntity, soundEvent) + registerAndPlay(wrapper, soundToPlay) + } + + fun transferPlayingOwnership(entity: Entity?, tileEntity: BackpackTileEntity?, wrapper: BackpackWrapper) { + val sound = activeSounds[wrapper.uuid] as? JukeboxUpgradeSound? ?: return + + if (entity == null && tileEntity == null || + entity != null && tileEntity != null + ) { + RetroSophisticatedBackpacks.LOGGER.error("Unable to transfer playing ownership of backpack") + return + } + + sound.hostEntity = entity + sound.hostTileEntity = tileEntity + } + + private fun registerAndPlay(wrapper: BackpackWrapper, sound: ISound) { + activeSounds[wrapper.uuid] = sound + Minecraft.getMinecraft().soundHandler.playSound(sound) + } + + fun stopRecord(wrapper: BackpackWrapper) { + val sound = activeSounds.remove(wrapper.uuid) ?: return + + Minecraft.getMinecraft().soundHandler.stopSound(sound) + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/JukeboxUpgradeSound.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/JukeboxUpgradeSound.kt new file mode 100644 index 0000000..9b47a52 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/JukeboxUpgradeSound.kt @@ -0,0 +1,60 @@ +package com.cleanroommc.retrosophisticatedbackpacks.client.sound + +import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks +import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity +import net.minecraft.client.audio.MovingSound +import net.minecraft.entity.Entity +import net.minecraft.util.SoundCategory +import net.minecraft.util.SoundEvent +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly + +@SideOnly(Side.CLIENT) +class JukeboxUpgradeSound(var hostEntity: Entity?, var hostTileEntity: BackpackTileEntity?, recordSound: SoundEvent) : + MovingSound(recordSound, SoundCategory.RECORDS) { + + init { + repeat = false + volume = 4f + pitch = 1f + } + + override fun update() { + val hostEntity = this.hostEntity + val hostTileEntity = this.hostTileEntity + + when { + hostEntity != null -> { + if (hostEntity.isDead) { + stopPlaying() + return + } + + xPosF = hostEntity.posX.toFloat() + yPosF = hostEntity.posY.toFloat() + zPosF = hostEntity.posZ.toFloat() + } + hostTileEntity != null -> { + val pos = hostTileEntity.pos + + if (hostTileEntity.isInvalid) { + stopPlaying() + return + } + + xPosF = pos.x.toFloat() + yPosF = pos.y.toFloat() + zPosF = pos.z.toFloat() + } + else -> { + RetroSophisticatedBackpacks.LOGGER.error("JukeboxUpgradeSound has no host entity or tile entity") + stopPlaying() + return + } + } + } + + fun stopPlaying() { + donePlaying = true + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackGuiHolder.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackGuiHolder.kt index 4a437cf..94d7c18 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackGuiHolder.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/BackpackGuiHolder.kt @@ -34,6 +34,7 @@ sealed class BackpackGuiHolder(protected val backpackWrapper: BackpackWrapper) { backpackWrapper, 14 + rowSize * SLOT_SIZE, 112 + colSize * SLOT_SIZE, + inventoryType, inventoryType?.let { if (it == InventoryType.PLAYER_INVENTORY) slotIndex else null }, ) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt index cf5900b..5ff398c 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt @@ -5,6 +5,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.client.gui.BackpackPanel import com.cleanroommc.retrosophisticatedbackpacks.item.ExponentialStackUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.InceptionUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.StackUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.UpgradeItem import net.minecraft.entity.player.EntityPlayer @@ -51,6 +52,7 @@ class ModularUpgradeSlot( override fun isItemValid(stack: ItemStack): Boolean = when (val item = stack.item) { is StackUpgradeItem -> wrapper.canAddStackUpgrade(item.multiplier()) is ExponentialStackUpgradeItem -> wrapper.canAddExponentialStackUpgrade() + is JukeboxUpgradeItem -> wrapper.canAddJukeboxUpgrade() else -> item is UpgradeItem } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt index 554634f..c64b7a8 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt @@ -113,6 +113,12 @@ object CapabilityHandler { CapabilityStorageProvider(), ::AdvancedVoidUpgradeWrapper ) + + instance.register( + JukeboxUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::JukeboxUpgradeWrapper + ) // Interfaces instance.register( @@ -170,6 +176,12 @@ object CapabilityHandler { NOPCapabilityStorage(), ::VoidUpgradeWrapper ) + + instance.register( + IJukeboxUpgrade::class.java, + NOPCapabilityStorage(), + ::JukeboxUpgradeWrapper + ) } fun cacheBackpackInventory(backpackWrapper: BackpackWrapper) { diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt index 97ee310..ae7d9e2 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt @@ -6,6 +6,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.Tags import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackInventoryHelper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiFactory import com.cleanroommc.retrosophisticatedbackpacks.config.Config @@ -20,6 +21,7 @@ import net.minecraft.inventory.EntityEquipmentSlot import net.minecraft.item.ItemStack import net.minecraft.util.EnumActionResult import net.minecraft.util.SoundCategory +import net.minecraftforge.event.entity.EntityJoinWorldEvent import net.minecraftforge.event.entity.living.LivingSpawnEvent import net.minecraftforge.event.entity.player.EntityItemPickupEvent import net.minecraftforge.event.entity.player.PlayerInteractEvent @@ -60,6 +62,11 @@ object EntityEventHandler { val player = event.entityPlayer val inventory = player.inventory var stack = event.item.item.copy() + + if (stack.item is BackpackItem) { + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + BackpackSoundManager.transferPlayingOwnership(player, null, wrapper) + } stack = attemptPickup(InvWrapper(inventory), stack) @@ -125,6 +132,22 @@ object EntityEventHandler { return stack } + @SubscribeEvent + @JvmStatic + fun onEntityJoinWorld(event: EntityJoinWorldEvent) { + val entity = event.entity + + if (entity !is EntityItem) return + + val stack = entity.item + + if (stack.item !is BackpackItem) return + + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + + BackpackSoundManager.transferPlayingOwnership(entity, null, wrapper) + } + @SubscribeEvent @JvmStatic fun onPlayerInteract(event: PlayerInteractEvent.EntityInteract) { diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt index fbd54b2..0d01c7b 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt @@ -1,5 +1,6 @@ package com.cleanroommc.retrosophisticatedbackpacks.handler +import com.cleanroommc.retrosophisticatedbackpacks.network.C2SJukeboxUpgradePacket import com.cleanroommc.retrosophisticatedbackpacks.network.C2SOpenBackpackPacket import net.minecraftforge.fml.common.network.NetworkRegistry import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper @@ -23,5 +24,19 @@ object NetworkHandler { idGenerator.next(), Side.SERVER ) + + INSTANCE.registerMessage( + C2SJukeboxUpgradePacket.Moving.Handler::class.java, + C2SJukeboxUpgradePacket.Moving::class.java, + idGenerator.next(), + Side.SERVER + ) + + INSTANCE.registerMessage( + C2SJukeboxUpgradePacket.Stationary.Handler::class.java, + C2SJukeboxUpgradePacket.Stationary::class.java, + idGenerator.next(), + Side.SERVER + ) } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt index 2fc0695..a9a7112 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt @@ -170,7 +170,10 @@ class BackpackItem( override fun initCapabilities(stack: ItemStack, nbt: NBTTagCompound?): ICapabilityProvider { val wrapper = BackpackWrapper(numberOfSlots, numberOfUpgradeSlots) - nbt?.let(wrapper::deserializeNBT) + if (nbt != null) { + val data = if (nbt.hasKey("Parent")) nbt.getCompoundTag("Parent") else nbt + wrapper.deserializeNBT(data) + } return wrapper } @@ -283,7 +286,7 @@ class BackpackItem( val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null)!! val slotIndex = if (data.inventoryType == InventoryType.PLAYER_INVENTORY) data.slotIndex else null uiSettings.customContainer { BackpackContainer(wrapper, slotIndex) } - uiSettings.canInteractWith { + uiSettings.canInteractWith { if (data.targetEntity.isDead) false else it.getDistance(data.targetEntity) <= 4.0 } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt index 3b24eb3..065f904 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt @@ -123,4 +123,7 @@ object Items { @JvmField val advancedVoidUpgrade = VoidUpgradeItem("advanced_void_upgrade", ::AdvancedVoidUpgradeWrapper) + + @JvmField + val jukeboxUpgrade = JukeboxUpgradeItem("jukebox_upgrade", ::JukeboxUpgradeWrapper) } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/JukeboxUpgradeItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/JukeboxUpgradeItem.kt new file mode 100644 index 0000000..40c1a42 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/JukeboxUpgradeItem.kt @@ -0,0 +1,6 @@ +package com.cleanroommc.retrosophisticatedbackpacks.item + +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IJukeboxUpgrade + +class JukeboxUpgradeItem(val registryName: String, wrapperFactory: () -> IJukeboxUpgrade) : + RankedUpgradeItem(registryName, wrapperFactory) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt new file mode 100644 index 0000000..f6474a5 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt @@ -0,0 +1,142 @@ +package com.cleanroommc.retrosophisticatedbackpacks.network + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData +import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity +import io.netty.buffer.ByteBuf +import net.minecraft.util.math.BlockPos +import net.minecraftforge.fml.common.network.ByteBufUtils +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext + +sealed class C2SJukeboxUpgradePacket() : IRefinedMessage { + protected var action: PlayingAction = PlayingAction.PLAY + protected var soundRegistryName: String? = null + + override fun toBytes(buf: ByteBuf) { + buf.writeInt(action.ordinal) + ByteBufUtils.writeUTF8String(buf, soundRegistryName) + } + + override fun fromBytes(buf: ByteBuf) { + action = PlayingAction.entries[buf.readInt()] + soundRegistryName = ByteBufUtils.readUTF8String(buf) + } + + class Moving() : C2SJukeboxUpgradePacket() { + private var inventoryType: PlayerInventoryGuiData.InventoryType = + PlayerInventoryGuiData.InventoryType.PLAYER_INVENTORY + private var slotIndex: Int = 0 + + constructor( + action: PlayingAction, + soundRegistryName: String, + inventoryType: PlayerInventoryGuiData.InventoryType, + slotIndex: Int + ) : this() { + this.action = action + this.soundRegistryName = soundRegistryName + this.inventoryType = inventoryType + this.slotIndex = slotIndex + } + + override fun toBytes(buf: ByteBuf) { + super.toBytes(buf) + buf.writeInt(inventoryType.ordinal) + buf.writeInt(slotIndex) + } + + override fun fromBytes(buf: ByteBuf) { + super.fromBytes(buf) + inventoryType = PlayerInventoryGuiData.InventoryType.entries[buf.readInt()] + slotIndex = buf.readInt() + } + + class Handler : INoReplyMessageHandler { + override fun onMessage( + message: Moving, + ctx: MessageContext + ): IRefinedMessage? { + val player = ctx.serverHandler.player + val world = player.serverWorld + val soundRegistryName = message.soundRegistryName ?: return null + + world.addScheduledTask { + val stack = when (message.inventoryType) { + PlayerInventoryGuiData.InventoryType.PLAYER_INVENTORY -> + player.inventory.getStackInSlot(message.slotIndex) + + PlayerInventoryGuiData.InventoryType.PLAYER_BAUBLES -> + player.inventoryContainer.getSlot(message.slotIndex).stack + } + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return@addScheduledTask + + when (message.action) { + PlayingAction.PLAY -> + BackpackSoundManager.playRecordFromPlayer(player, wrapper, soundRegistryName) + + PlayingAction.STOP -> + BackpackSoundManager.stopRecord(wrapper) + } + } + + return null + } + } + } + + class Stationary() : C2SJukeboxUpgradePacket() { + private var pos: BlockPos = BlockPos.ORIGIN + + constructor( + action: PlayingAction, + soundRegistryName: String, + pos: BlockPos + ) : this() { + this.action = action + this.soundRegistryName = soundRegistryName + this.pos = pos + } + + override fun toBytes(buf: ByteBuf) { + super.toBytes(buf) + buf.writeLong(pos.toLong()) + } + + override fun fromBytes(buf: ByteBuf) { + super.fromBytes(buf) + pos = BlockPos.fromLong(buf.readLong()) + } + + class Handler : INoReplyMessageHandler { + override fun onMessage( + message: Stationary, + ctx: MessageContext + ): IRefinedMessage? { + val player = ctx.serverHandler.player + val world = player.serverWorld + val tileEntity = world.getTileEntity(message.pos) as? BackpackTileEntity? ?: return null + val soundRegistryName = message.soundRegistryName ?: return null + + world.addScheduledTask { + val wrapper = + tileEntity.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return@addScheduledTask + + when (message.action) { + PlayingAction.PLAY -> + BackpackSoundManager.playRecordFromTileEntity(tileEntity, wrapper, soundRegistryName) + + PlayingAction.STOP -> + BackpackSoundManager.stopRecord(wrapper) + } + } + + return null + } + } + } + + enum class PlayingAction { + PLAY, STOP + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedCraftingStackHandlerSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedCraftingStackHandlerSH.kt index ba6a857..e9e3cec 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedCraftingStackHandlerSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedCraftingStackHandlerSH.kt @@ -63,7 +63,6 @@ class DelegatedCraftingStackHandlerSH( wrapper.craftMatrix.setStackInSlot(9, buf.readItemStack()) } } - } override fun readOnServer(id: Int, buf: PacketBuffer) { @@ -83,4 +82,4 @@ class DelegatedCraftingStackHandlerSH( } } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedStackHandlerSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedStackHandlerSH.kt index ab43d58..e483719 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedStackHandlerSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/DelegatedStackHandlerSH.kt @@ -20,6 +20,7 @@ open class DelegatedStackHandlerSH( ) : SyncHandler() { companion object { const val UPDATE_FILTERABLE = 0 + const val UPDATE_JUKEBOX = 1 } var delegatedStackHandler: DelegatedItemHandler = DelegatedItemHandler(EmptyHandler::INSTANCE, wrappedSlotAmount) @@ -40,6 +41,11 @@ open class DelegatedStackHandlerSH( setDelegatedStackHandler(wrapper::filterItems) } + UPDATE_JUKEBOX -> { + val wrapper = stack.getCapability(Capabilities.IJUKEBOX_UPGRADE_CAPABILITY, null) ?: return + + setDelegatedStackHandler(wrapper::records) + } } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt new file mode 100644 index 0000000..22c640b --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt @@ -0,0 +1,26 @@ +package com.cleanroommc.retrosophisticatedbackpacks.sync + +import com.cleanroommc.modularui.value.sync.ItemSlotSH +import com.cleanroommc.modularui.widgets.slot.ModularSlot +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import net.minecraft.client.Minecraft +import net.minecraft.item.ItemRecord +import net.minecraft.item.ItemStack + +class JukeboxSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : ItemSlotSH(slot) { + private var initialUpdated = false + + override fun isItemValid(itemStack: ItemStack): Boolean = + itemStack.item is ItemRecord + + override fun onSlotUpdate(stack: ItemStack, onlyAmountChanged: Boolean, client: Boolean, init: Boolean) { + // Special handling for the initial update of slot, since the update does not actually change the record in the + // slot + if (initialUpdated && (!isItemValid(stack) || Minecraft.getMinecraft().player.inventory.itemStack.item != stack.item)) + BackpackSoundManager.stopRecord(wrapper) + else + initialUpdated = true + super.onSlotUpdate(stack, onlyAmountChanged, client, init) + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt index 36fa95b..e06c5c7 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt @@ -2,16 +2,20 @@ package com.cleanroommc.retrosophisticatedbackpacks.sync import com.cleanroommc.modularui.value.sync.ItemSlotSH import com.cleanroommc.modularui.widgets.slot.ModularSlot +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.* import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.CraftingUpgradeWrapper.CraftingDestination +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem +import net.minecraft.item.ItemStack import net.minecraft.network.PacketBuffer /** * Used to synchronize upgrade item's capability, this is only fired from client to reflect client's action to server * side. */ -class UpgradeSlotSH(slot: ModularSlot) : ItemSlotSH(slot) { +class UpgradeSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : ItemSlotSH(slot) { companion object { const val UPDATE_UPGRADE_TAB_STATE = 6 const val UPDATE_UPGRADE_TOGGLE = 7 @@ -23,6 +27,17 @@ class UpgradeSlotSH(slot: ModularSlot) : ItemSlotSH(slot) { const val UPDATE_VOID = 13 } + private var initialUpdated = false + + override fun onSlotUpdate(stack: ItemStack, onlyAmountChanged: Boolean, client: Boolean, init: Boolean) { + if (initialUpdated && stack.item !is JukeboxUpgradeItem) + BackpackSoundManager.stopRecord(wrapper) + else + initialUpdated = true + + super.onSlotUpdate(stack, onlyAmountChanged, client, init) + } + override fun readOnServer(id: Int, buf: PacketBuffer) { super.readOnServer(id, buf) diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang index 49b7762..390da63 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang @@ -27,6 +27,7 @@ item.retro_sophisticated_backpacks.filter_upgrade.name=Filter Upgrade item.retro_sophisticated_backpacks.advanced_filter_upgrade.name=Advanced Filter Upgrade item.retro_sophisticated_backpacks.void_upgrade.name=Void Upgrade item.retro_sophisticated_backpacks.advanced_void_upgrade.name=Advanced Void Upgrade +item.retro_sophisticated_backpacks.jukebox_upgrade.name=Jukebox Upgrade # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=Retro Sophisticated Backpacks @@ -74,6 +75,8 @@ retro_sophisticated_backpacks.tooltip.void_upgrade=Voids items selected in filte retro_sophisticated_backpacks.tooltip.advanced_void_upgrade=Voids items selected in filter with more configurations +retro_sophisticated_backpacks.tooltip.jukebox_upgrade=Plays discs in your backpack! + retro_sophisticated_backpacks.tooltip.shift_to_reveal= # Gui Elements @@ -99,6 +102,8 @@ retro_sophisticated_backpacks.gui.advanced_void_settings=Adv. Void Settings retro_sophisticated_backpacks.gui.crafting_settings=Crafting +retro_sophisticated_backpacks.gui.jukebox_settings=Jukebox Interface + retro_sophisticated_backpacks.gui.memory_settings=Memory Settings retro_sophisticated_backpacks.gui.sorting_settings=Sorting Settings diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang index 8dd0620..3badd2c 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang @@ -27,6 +27,7 @@ item.retro_sophisticated_backpacks.filter_upgrade.name=過濾升級 item.retro_sophisticated_backpacks.advanced_filter_upgrade.name=進階過濾升級 item.retro_sophisticated_backpacks.void_upgrade.name=虛空升級 item.retro_sophisticated_backpacks.advanced_void_upgrade.name=進階虛空升級 +item.retro_sophisticated_backpacks.jukebox_upgrade.name=唱片機升級 # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=復古精緻背包 @@ -74,6 +75,8 @@ retro_sophisticated_backpacks.tooltip.void_upgrade=銷毀過濾清單中選定 retro_sophisticated_backpacks.tooltip.advanced_void_upgrade=根據更多配置銷毀過濾清單中選定的物品 +retro_sophisticated_backpacks.tooltip.jukebox_upgrade=在背包中播放唱片! + retro_sophisticated_backpacks.tooltip.shift_to_reveal=<按 Shift 顯示> # Gui Elements @@ -99,6 +102,8 @@ retro_sophisticated_backpacks.gui.advanced_void_settings=進階虛空設定 retro_sophisticated_backpacks.gui.crafting_settings=合成 +retro_sophisticated_backpacks.gui.jukebox_settings=唱片機 + retro_sophisticated_backpacks.gui.memory_settings=記憶設定 retro_sophisticated_backpacks.gui.sorting_settings=整理設定 diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/models/item/jukebox_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/jukebox_upgrade.json new file mode 100644 index 0000000..28244a8 --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/jukebox_upgrade.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "retro_sophisticated_backpacks:item/jukebox_upgrade" + } +} From 654de2286c946735fdd7d92f3e8bc59d567b318b Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 12 Jun 2026 03:01:15 +0800 Subject: [PATCH 05/14] Fix jukebox sound syncing --- .../block/BackpackBlock.kt | 15 +- .../client/gui/BackpackPanel.kt | 3 +- .../widgets/upgrade/JukeboxUpgradeWidget.kt | 46 ++--- .../handler/EntityEventHandler.kt | 33 ++- .../handler/NetworkHandler.kt | 24 ++- .../item/BackpackItem.kt | 20 +- .../network/C2CJukeboxUpgradePacket.kt | 195 ++++++++++++++++++ .../network/C2SJukeboxUpgradePacket.kt | 142 ------------- .../sync/JukeboxSlotSH.kt | 7 +- .../sync/UpgradeSlotSH.kt | 5 +- .../recipes/jukebox_upgrade.json | 27 +++ 11 files changed, 303 insertions(+), 214 deletions(-) create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt delete mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/recipes/jukebox_upgrade.json diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt index 8eeec45..880a3e4 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt @@ -3,8 +3,9 @@ package com.cleanroommc.retrosophisticatedbackpacks.block import com.cleanroommc.retrosophisticatedbackpacks.RetroSophisticatedBackpacks import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackTier import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities -import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler import com.cleanroommc.retrosophisticatedbackpacks.handler.RegistryHandler +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity import com.cleanroommc.retrosophisticatedbackpacks.util.IModelRegister import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey @@ -178,7 +179,15 @@ class BackpackBlock( val tileEntity = worldIn.getTileEntity(pos) as? BackpackTileEntity ?: return tileEntity.wrapper.deserializeNBT(wrapper.serializeNBT()) - BackpackSoundManager.transferPlayingOwnership(null, tileEntity, wrapper) + + if (worldIn.isRemote) + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Stationary( + C2CJukeboxUpgradePacket.PlayingAction.TRANSFER, + "", + tileEntity.getPos() + ) + ) if (stack.hasDisplayName()) tileEntity.setCustomName(stack.displayName) @@ -243,7 +252,7 @@ class BackpackBlock( val tileEntityBackpackInventory = tileEntity.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return val stackBackpackInventory = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return stackBackpackInventory.deserializeNBT(tileEntityBackpackInventory.serializeNBT()) - + if (tileEntity.hasCustomName()) stack.setStackDisplayName(tileEntity.name) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt index 9c11d68..9049705 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt @@ -529,11 +529,10 @@ class BackpackPanel( ) tabWidget.expandedWidget = JukeboxUpgradeWidget( slotIndex, + backpackWrapper, wrapper, player, tileEntity, - inventoryType, - backpackSlotIndex ) } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt index 36d1bd4..04bf47a 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt @@ -4,12 +4,12 @@ import com.cleanroommc.modularui.widgets.ButtonWidget import com.cleanroommc.modularui.widgets.SlotGroupWidget import com.cleanroommc.modularui.widgets.layout.Row import com.cleanroommc.modularui.widgets.slot.ItemSlot +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.JukeboxUpgradeWrapper import com.cleanroommc.retrosophisticatedbackpacks.client.gui.RSBTextures -import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler import com.cleanroommc.retrosophisticatedbackpacks.item.Items -import com.cleanroommc.retrosophisticatedbackpacks.network.C2SJukeboxUpgradePacket +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemRecord @@ -17,11 +17,10 @@ import net.minecraft.item.ItemStack class JukeboxUpgradeWidget( slotIndex: Int, + backpackWrapper: BackpackWrapper, wrapper: JukeboxUpgradeWrapper, playerEntity: EntityPlayer, - tileEntity: BackpackTileEntity?, - inventoryType: PlayerInventoryGuiData.InventoryType?, - slotIndexInInv: Int? + tileEntity: BackpackTileEntity? ) : ExpandedUpgradeTabWidget( slotIndex, @@ -38,13 +37,13 @@ class JukeboxUpgradeWidget( init { val JukeboxSlotGroupsWidget = SlotGroupWidget().name("jukebox_slots_$slotIndex").disableSortButtons() JukeboxSlotGroupsWidget.flex().coverChildren().leftRel(0.5F).top(32) - + recordSlot = ItemSlot().syncHandler("jukebox_slot_$slotIndex", 0) .name("jukebox_slot_0") JukeboxSlotGroupsWidget.child(recordSlot) - + buttonRow = Row() .leftRel(0.5F) .top(28) @@ -53,28 +52,13 @@ class JukeboxUpgradeWidget( stopButton = ButtonWidget().name("stop_button") .onMousePressed { - val record = wrapper.records.getStackInSlot(0) - val item = record.item - - if (record.isEmpty || item !is ItemRecord) - return@onMousePressed false - if (tileEntity != null) { NetworkHandler.INSTANCE.sendToServer( - C2SJukeboxUpgradePacket.Stationary( - C2SJukeboxUpgradePacket.PlayingAction.STOP, - item.sound.soundName.toString(), - tileEntity.pos - ) + C2CJukeboxUpgradePacket.Stationary.stopPlaying(tileEntity.pos) ) } else { NetworkHandler.INSTANCE.sendToServer( - C2SJukeboxUpgradePacket.Moving( - C2SJukeboxUpgradePacket.PlayingAction.STOP, - item.sound.soundName.toString(), - inventoryType!!, - slotIndexInInv!! - ) + C2CJukeboxUpgradePacket.Moving.stopPlaying(backpackWrapper) ) } @@ -91,19 +75,19 @@ class JukeboxUpgradeWidget( if (tileEntity != null) { NetworkHandler.INSTANCE.sendToServer( - C2SJukeboxUpgradePacket.Stationary( - C2SJukeboxUpgradePacket.PlayingAction.PLAY, + C2CJukeboxUpgradePacket.Stationary( + C2CJukeboxUpgradePacket.PlayingAction.PLAY, item.sound.soundName.toString(), tileEntity.pos ) ) } else { NetworkHandler.INSTANCE.sendToServer( - C2SJukeboxUpgradePacket.Moving( - C2SJukeboxUpgradePacket.PlayingAction.PLAY, + C2CJukeboxUpgradePacket.Moving( + C2CJukeboxUpgradePacket.PlayingAction.PLAY, item.sound.soundName.toString(), - inventoryType!!, - slotIndexInInv!! + backpackWrapper, + playerEntity.entityId ) ) } @@ -114,7 +98,7 @@ class JukeboxUpgradeWidget( buttonRow.child(stopButton) .child(playButton) - + child(JukeboxSlotGroupsWidget) .child(buttonRow) } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt index ae7d9e2..c5f7a8c 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt @@ -6,12 +6,12 @@ import com.cleanroommc.retrosophisticatedbackpacks.Tags import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackInventoryHelper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade -import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiFactory import com.cleanroommc.retrosophisticatedbackpacks.config.Config import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket import net.minecraft.entity.EntityList import net.minecraft.entity.EntityLiving import net.minecraft.entity.EntityLivingBase @@ -21,7 +21,6 @@ import net.minecraft.inventory.EntityEquipmentSlot import net.minecraft.item.ItemStack import net.minecraft.util.EnumActionResult import net.minecraft.util.SoundCategory -import net.minecraftforge.event.entity.EntityJoinWorldEvent import net.minecraftforge.event.entity.living.LivingSpawnEvent import net.minecraftforge.event.entity.player.EntityItemPickupEvent import net.minecraftforge.event.entity.player.PlayerInteractEvent @@ -62,10 +61,18 @@ object EntityEventHandler { val player = event.entityPlayer val inventory = player.inventory var stack = event.item.item.copy() - - if (stack.item is BackpackItem) { + + if (stack.item is BackpackItem && !player.world.isRemote) { val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return - BackpackSoundManager.transferPlayingOwnership(player, null, wrapper) + NetworkHandler.INSTANCE.sendToDimension( + C2CJukeboxUpgradePacket.Moving( + C2CJukeboxUpgradePacket.PlayingAction.TRANSFER, + null, + wrapper, + player.entityId + ), + player.world.provider.dimension + ) } stack = attemptPickup(InvWrapper(inventory), stack) @@ -132,22 +139,6 @@ object EntityEventHandler { return stack } - @SubscribeEvent - @JvmStatic - fun onEntityJoinWorld(event: EntityJoinWorldEvent) { - val entity = event.entity - - if (entity !is EntityItem) return - - val stack = entity.item - - if (stack.item !is BackpackItem) return - - val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return - - BackpackSoundManager.transferPlayingOwnership(entity, null, wrapper) - } - @SubscribeEvent @JvmStatic fun onPlayerInteract(event: PlayerInteractEvent.EntityInteract) { diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt index 0d01c7b..707595a 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt @@ -1,6 +1,6 @@ package com.cleanroommc.retrosophisticatedbackpacks.handler -import com.cleanroommc.retrosophisticatedbackpacks.network.C2SJukeboxUpgradePacket +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket import com.cleanroommc.retrosophisticatedbackpacks.network.C2SOpenBackpackPacket import net.minecraftforge.fml.common.network.NetworkRegistry import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper @@ -26,17 +26,31 @@ object NetworkHandler { ) INSTANCE.registerMessage( - C2SJukeboxUpgradePacket.Moving.Handler::class.java, - C2SJukeboxUpgradePacket.Moving::class.java, + C2CJukeboxUpgradePacket.Moving.ServerHandler::class.java, + C2CJukeboxUpgradePacket.Moving::class.java, idGenerator.next(), Side.SERVER ) INSTANCE.registerMessage( - C2SJukeboxUpgradePacket.Stationary.Handler::class.java, - C2SJukeboxUpgradePacket.Stationary::class.java, + C2CJukeboxUpgradePacket.Moving.ClientHandler::class.java, + C2CJukeboxUpgradePacket.Moving::class.java, + idGenerator.next(), + Side.CLIENT + ) + + INSTANCE.registerMessage( + C2CJukeboxUpgradePacket.Stationary.ServerHandler::class.java, + C2CJukeboxUpgradePacket.Stationary::class.java, idGenerator.next(), Side.SERVER ) + + INSTANCE.registerMessage( + C2CJukeboxUpgradePacket.Stationary.ClientHandler::class.java, + C2CJukeboxUpgradePacket.Stationary::class.java, + idGenerator.next(), + Side.CLIENT + ) } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt index a9a7112..ded8b12 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt @@ -15,6 +15,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.block.BackpackBlock import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.client.BackpackBipedModel +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager import com.cleanroommc.retrosophisticatedbackpacks.common.gui.BackpackContainer import com.cleanroommc.retrosophisticatedbackpacks.common.gui.BackpackGuiHolder import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData @@ -29,6 +30,7 @@ import net.minecraft.client.renderer.GlStateManager import net.minecraft.client.util.ITooltipFlag import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase +import net.minecraft.entity.item.EntityItem import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayerMP import net.minecraft.init.SoundEvents @@ -178,16 +180,24 @@ class BackpackItem( } override fun onUpdate(stack: ItemStack, worldIn: World, entityIn: Entity, itemSlot: Int, isSelected: Boolean) { - if (!worldIn.isRemote && entityIn is EntityPlayerMP) { - val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + + if (!wrapper.isCached) + CapabilityHandler.cacheBackpackInventory(wrapper) + if (!worldIn.isRemote && entityIn is EntityPlayerMP) { if (entityIn.ticksExisted % 20 == 0) wrapper.feed(entityIn, wrapper) + } + } - // Only cache on server - if (!wrapper.isCached) - CapabilityHandler.cacheBackpackInventory(wrapper) + override fun onEntityItemUpdate(entityItem: EntityItem): Boolean { + if (entityItem.world.isRemote) { + val wrapper = entityItem.item.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return false + BackpackSoundManager.transferPlayingOwnership(entityItem, null, wrapper) } + + return super.onEntityItemUpdate(entityItem) } override fun isValidArmor(stack: ItemStack, armorType: EntityEquipmentSlot, entity: Entity): Boolean = diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt new file mode 100644 index 0000000..1dfe699 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt @@ -0,0 +1,195 @@ +package com.cleanroommc.retrosophisticatedbackpacks.network + +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.handler.CapabilityHandler +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler +import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity +import io.netty.buffer.ByteBuf +import net.minecraft.client.Minecraft +import net.minecraft.util.math.BlockPos +import net.minecraftforge.fml.common.network.ByteBufUtils +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext +import java.util.* + +sealed class C2CJukeboxUpgradePacket : IRefinedMessage { + protected var action: PlayingAction = PlayingAction.PLAY + protected var soundRegistryName: String = "" + + override fun toBytes(buf: ByteBuf) { + buf.writeInt(action.ordinal) + ByteBufUtils.writeUTF8String(buf, soundRegistryName) + } + + override fun fromBytes(buf: ByteBuf) { + action = PlayingAction.entries[buf.readInt()] + soundRegistryName = ByteBufUtils.readUTF8String(buf) + } + + class Moving() : C2CJukeboxUpgradePacket() { + private var backpackUUID: UUID = UUID.randomUUID() + private var entityID: Int = 0 + + companion object { + fun stopPlaying(wrapper: BackpackWrapper): Moving = + Moving( + PlayingAction.STOP, + null, + wrapper, + 0 + ) + } + + constructor( + action: PlayingAction, + soundRegistryName: String?, + wrapper: BackpackWrapper, + entityID: Int + ) : this() { + this.action = action + this.soundRegistryName = soundRegistryName ?: "" + this.backpackUUID = wrapper.uuid + this.entityID = entityID + } + + override fun toBytes(buf: ByteBuf) { + super.toBytes(buf) + buf.writeLong(backpackUUID.mostSignificantBits) + buf.writeLong(backpackUUID.leastSignificantBits) + buf.writeInt(entityID) + } + + override fun fromBytes(buf: ByteBuf) { + super.fromBytes(buf) + val most = buf.readLong() + val least = buf.readLong() + backpackUUID = UUID(most, least) + entityID = buf.readInt() + } + + class ServerHandler : IRefinedMessageHandler { + override fun onMessage( + message: Moving, + ctx: MessageContext + ): Moving? { + NetworkHandler.INSTANCE.sendToDimension(message, ctx.serverHandler.player.world.provider.dimension) + return null + } + } + + class ClientHandler : INoReplyMessageHandler { + override fun onMessage( + message: Moving, + ctx: MessageContext + ): IRefinedMessage? { + val mc = Minecraft.getMinecraft() + + mc.addScheduledTask { + val world = mc.player.world ?: return@addScheduledTask + val wrapper = + CapabilityHandler.BACKPACK_INVENTORY_CACHE[message.backpackUUID] ?: return@addScheduledTask + + when (message.action) { + PlayingAction.PLAY -> { + val entity = world.getEntityByID(message.entityID) ?: return@addScheduledTask + + BackpackSoundManager.playRecordFromPlayer(entity, wrapper, message.soundRegistryName) + } + + PlayingAction.STOP -> + BackpackSoundManager.stopRecord(wrapper) + + PlayingAction.TRANSFER -> { + val entity = world.getEntityByID(message.entityID) ?: return@addScheduledTask + + BackpackSoundManager.transferPlayingOwnership(entity, null, wrapper) + } + } + } + + return null + } + } + } + + class Stationary() : C2CJukeboxUpgradePacket() { + private var pos: BlockPos = BlockPos.ORIGIN + + companion object { + fun stopPlaying(pos: BlockPos): Stationary = + Stationary( + PlayingAction.STOP, + null, + pos, + ) + } + + constructor( + action: PlayingAction, + soundRegistryName: String?, + pos: BlockPos + ) : this() { + this.action = action + this.soundRegistryName = soundRegistryName ?: "" + this.pos = pos + } + + override fun toBytes(buf: ByteBuf) { + super.toBytes(buf) + buf.writeLong(pos.toLong()) + } + + override fun fromBytes(buf: ByteBuf) { + super.fromBytes(buf) + pos = BlockPos.fromLong(buf.readLong()) + } + + class ServerHandler : IRefinedMessageHandler { + override fun onMessage( + message: Stationary, + ctx: MessageContext + ): Stationary? { + NetworkHandler.INSTANCE.sendToDimension(message, ctx.serverHandler.player.world.provider.dimension) + return null + } + } + + class ClientHandler : INoReplyMessageHandler { + override fun onMessage( + message: Stationary, + ctx: MessageContext + ): IRefinedMessage? { + val mc = Minecraft.getMinecraft() + + mc.addScheduledTask { + val world = mc.player.world ?: return@addScheduledTask + val tileEntity = world.getTileEntity(message.pos) as? BackpackTileEntity? ?: return@addScheduledTask + val wrapper = + tileEntity.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return@addScheduledTask + + when (message.action) { + PlayingAction.PLAY -> + BackpackSoundManager.playRecordFromTileEntity( + tileEntity, + wrapper, + message.soundRegistryName + ) + + PlayingAction.STOP -> + BackpackSoundManager.stopRecord(wrapper) + + PlayingAction.TRANSFER -> + BackpackSoundManager.transferPlayingOwnership(null, tileEntity, wrapper) + } + } + + return null + } + } + } + + enum class PlayingAction { + PLAY, STOP, TRANSFER + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt deleted file mode 100644 index f6474a5..0000000 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2SJukeboxUpgradePacket.kt +++ /dev/null @@ -1,142 +0,0 @@ -package com.cleanroommc.retrosophisticatedbackpacks.network - -import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities -import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager -import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData -import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity -import io.netty.buffer.ByteBuf -import net.minecraft.util.math.BlockPos -import net.minecraftforge.fml.common.network.ByteBufUtils -import net.minecraftforge.fml.common.network.simpleimpl.MessageContext - -sealed class C2SJukeboxUpgradePacket() : IRefinedMessage { - protected var action: PlayingAction = PlayingAction.PLAY - protected var soundRegistryName: String? = null - - override fun toBytes(buf: ByteBuf) { - buf.writeInt(action.ordinal) - ByteBufUtils.writeUTF8String(buf, soundRegistryName) - } - - override fun fromBytes(buf: ByteBuf) { - action = PlayingAction.entries[buf.readInt()] - soundRegistryName = ByteBufUtils.readUTF8String(buf) - } - - class Moving() : C2SJukeboxUpgradePacket() { - private var inventoryType: PlayerInventoryGuiData.InventoryType = - PlayerInventoryGuiData.InventoryType.PLAYER_INVENTORY - private var slotIndex: Int = 0 - - constructor( - action: PlayingAction, - soundRegistryName: String, - inventoryType: PlayerInventoryGuiData.InventoryType, - slotIndex: Int - ) : this() { - this.action = action - this.soundRegistryName = soundRegistryName - this.inventoryType = inventoryType - this.slotIndex = slotIndex - } - - override fun toBytes(buf: ByteBuf) { - super.toBytes(buf) - buf.writeInt(inventoryType.ordinal) - buf.writeInt(slotIndex) - } - - override fun fromBytes(buf: ByteBuf) { - super.fromBytes(buf) - inventoryType = PlayerInventoryGuiData.InventoryType.entries[buf.readInt()] - slotIndex = buf.readInt() - } - - class Handler : INoReplyMessageHandler { - override fun onMessage( - message: Moving, - ctx: MessageContext - ): IRefinedMessage? { - val player = ctx.serverHandler.player - val world = player.serverWorld - val soundRegistryName = message.soundRegistryName ?: return null - - world.addScheduledTask { - val stack = when (message.inventoryType) { - PlayerInventoryGuiData.InventoryType.PLAYER_INVENTORY -> - player.inventory.getStackInSlot(message.slotIndex) - - PlayerInventoryGuiData.InventoryType.PLAYER_BAUBLES -> - player.inventoryContainer.getSlot(message.slotIndex).stack - } - val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return@addScheduledTask - - when (message.action) { - PlayingAction.PLAY -> - BackpackSoundManager.playRecordFromPlayer(player, wrapper, soundRegistryName) - - PlayingAction.STOP -> - BackpackSoundManager.stopRecord(wrapper) - } - } - - return null - } - } - } - - class Stationary() : C2SJukeboxUpgradePacket() { - private var pos: BlockPos = BlockPos.ORIGIN - - constructor( - action: PlayingAction, - soundRegistryName: String, - pos: BlockPos - ) : this() { - this.action = action - this.soundRegistryName = soundRegistryName - this.pos = pos - } - - override fun toBytes(buf: ByteBuf) { - super.toBytes(buf) - buf.writeLong(pos.toLong()) - } - - override fun fromBytes(buf: ByteBuf) { - super.fromBytes(buf) - pos = BlockPos.fromLong(buf.readLong()) - } - - class Handler : INoReplyMessageHandler { - override fun onMessage( - message: Stationary, - ctx: MessageContext - ): IRefinedMessage? { - val player = ctx.serverHandler.player - val world = player.serverWorld - val tileEntity = world.getTileEntity(message.pos) as? BackpackTileEntity? ?: return null - val soundRegistryName = message.soundRegistryName ?: return null - - world.addScheduledTask { - val wrapper = - tileEntity.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return@addScheduledTask - - when (message.action) { - PlayingAction.PLAY -> - BackpackSoundManager.playRecordFromTileEntity(tileEntity, wrapper, soundRegistryName) - - PlayingAction.STOP -> - BackpackSoundManager.stopRecord(wrapper) - } - } - - return null - } - } - } - - enum class PlayingAction { - PLAY, STOP - } -} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt index 22c640b..6ae8048 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt @@ -3,14 +3,15 @@ package com.cleanroommc.retrosophisticatedbackpacks.sync import com.cleanroommc.modularui.value.sync.ItemSlotSH import com.cleanroommc.modularui.widgets.slot.ModularSlot import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper -import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket import net.minecraft.client.Minecraft import net.minecraft.item.ItemRecord import net.minecraft.item.ItemStack class JukeboxSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : ItemSlotSH(slot) { private var initialUpdated = false - + override fun isItemValid(itemStack: ItemStack): Boolean = itemStack.item is ItemRecord @@ -18,7 +19,7 @@ class JukeboxSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : I // Special handling for the initial update of slot, since the update does not actually change the record in the // slot if (initialUpdated && (!isItemValid(stack) || Minecraft.getMinecraft().player.inventory.itemStack.item != stack.item)) - BackpackSoundManager.stopRecord(wrapper) + NetworkHandler.INSTANCE.sendToServer(C2CJukeboxUpgradePacket.Moving.stopPlaying(wrapper)) else initialUpdated = true super.onSlotUpdate(stack, onlyAmountChanged, client, init) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt index e06c5c7..da28623 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt @@ -6,8 +6,9 @@ import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.* import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.CraftingUpgradeWrapper.CraftingDestination -import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket import net.minecraft.item.ItemStack import net.minecraft.network.PacketBuffer @@ -31,7 +32,7 @@ class UpgradeSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : I override fun onSlotUpdate(stack: ItemStack, onlyAmountChanged: Boolean, client: Boolean, init: Boolean) { if (initialUpdated && stack.item !is JukeboxUpgradeItem) - BackpackSoundManager.stopRecord(wrapper) + NetworkHandler.INSTANCE.sendToServer(C2CJukeboxUpgradePacket.Moving.stopPlaying(wrapper)) else initialUpdated = true diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/recipes/jukebox_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/jukebox_upgrade.json new file mode 100644 index 0000000..f80a31b --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/jukebox_upgrade.json @@ -0,0 +1,27 @@ +{ + "type": "minecraft:crafting_shaped", + "key": { + "P": { + "item": "minecraft:jukebox" + }, + "S": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "R": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "B": { + "item": "retro_sophisticated_backpacks:upgrade_base" + } + }, + "pattern": [ + " P ", + "SBS", + " R " + ], + "result": { + "item": "retro_sophisticated_backpacks:jukebox_upgrade" + } +} From a0e4b3d8737903d049145f9789f18bbaa8228963 Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Sat, 13 Jun 2026 11:48:29 +0800 Subject: [PATCH 06/14] Add advanced jukebox upgrade --- .../capability/Capabilities.java | 3 + .../capability/BackpackWrapper.kt | 16 +- .../upgrade/AdvancedJukeboxUpgradeWrapper.kt | 121 +++++++++ .../client/gui/BackpackPanel.kt | 16 ++ .../client/gui/RSBTextures.kt | 7 + .../client/gui/UpgradeSlotUpdateGroup.kt | 14 +- .../widgets/upgrade/AdvancedFilterWidget.kt | 4 +- .../upgrade/AdvancedJukeboxUpgradeWidget.kt | 256 ++++++++++++++++++ .../client/sound/BackpackSoundManager.kt | 15 + .../common/gui/slot/ModularUpgradeSlot.kt | 2 +- .../handler/CapabilityHandler.kt | 6 + .../handler/ClientEventHandler.kt | 28 ++ .../retrosophisticatedbackpacks/item/Items.kt | 3 + .../network/C2CJukeboxUpgradePacket.kt | 2 +- .../sync/JukeboxSlotSH.kt | 2 +- .../sync/UpgradeSlotSH.kt | 10 + .../lang/en_us.lang | 5 +- .../lang/zh_tw.lang | 3 + .../models/item/advanced_jukebox_upgrade.json | 6 + 19 files changed, 501 insertions(+), 18 deletions(-) create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/ClientEventHandler.kt create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_jukebox_upgrade.json diff --git a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java index b06a176..e4b4dd7 100644 --- a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java +++ b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java @@ -52,6 +52,9 @@ public final class Capabilities { @CapabilityInject(JukeboxUpgradeWrapper.class) public static final @NotNull Capability JUKEBOX_UPGRADE_CAPABILITY = null; + + @CapabilityInject(AdvancedJukeboxUpgradeWrapper.class) + public static final @NotNull Capability ADVANCED_JUKEBOX_UPGRADE_CAPABILITY = null; // Abstract capabilities @CapabilityInject(UpgradeWrapper.class) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt index 8ff828c..70720de 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt @@ -1,6 +1,9 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability +import com.azul.crs.client.Utils.uuid import com.cleanroommc.retrosophisticatedbackpacks.backpack.SortType +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.AdvancedJukeboxUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IJukeboxUpgrade import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.inventory.BackpackItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.inventory.UpgradeItemStackHandler @@ -23,7 +26,6 @@ import java.util.* class BackpackWrapper( var backpackInventorySize: () -> Int = { 27 }, var upgradeSlotsSize: () -> Int = { 1 }, - var uuid: UUID = UUID.randomUUID(), ) : IItemHandler, ISidelessCapabilityProvider, INBTSerializable { companion object { private const val BACKPACK_INVENTORY_TAG = "BackpackInventory" @@ -45,7 +47,10 @@ class BackpackWrapper( const val DEFAULT_ACCENT_COLOR: Int = -0x9dd1e6 } + + var uuid: UUID? = null var isCached: Boolean = false + var backpackItemStackHandler = BackpackItemStackHandler(backpackInventorySize(), this) var upgradeItemStackHandler = UpgradeItemStackHandler(upgradeSlotsSize()) var sortType: SortType = SortType.BY_NAME @@ -190,6 +195,9 @@ class BackpackWrapper( return currentStack } + + fun getJukeboxUpgrade(): IJukeboxUpgrade? = + gatherCapabilityUpgrades(Capabilities.IJUKEBOX_UPGRADE_CAPABILITY).firstOrNull() // Setting related @@ -270,6 +278,8 @@ class BackpackWrapper( nbt.setTag(UPGRADE_SLOTS_TAG, upgradesNbt) nbt.setInteger(BACKPACK_INVENTORY_SIZE_TAG, backpackInventorySize()) nbt.setInteger(UPGRADE_SLOTS_SIZE_TAG, upgradeSlotsSize()) + if (uuid != null) + nbt.setUniqueId(UUID_TAG, uuid!!) nbt.setInteger(MAIN_COLOR_TAG, mainColor) nbt.setInteger(ACCENT_COLOR_TAG, accentColor) @@ -289,7 +299,6 @@ class BackpackWrapper( backpackItemStackHandler.sortLockedSlots.map { if (it) 1 else 0 }.map(Int::toByte).toByteArray() ) - nbt.setUniqueId(UUID_TAG, uuid) return nbt } @@ -299,7 +308,8 @@ class BackpackWrapper( if (nbt.hasKey(UPGRADE_SLOTS_SIZE_TAG)) upgradeSlotsSize = { nbt.getInteger(UPGRADE_SLOTS_SIZE_TAG) } - uuid = nbt.getUniqueId(UUID_TAG)!! + if (nbt.hasUniqueId(UUID_TAG)) + uuid = nbt.getUniqueId(UUID_TAG) backpackItemStackHandler = BackpackItemStackHandler(backpackInventorySize(), this) upgradeItemStackHandler = UpgradeItemStackHandler(upgradeSlotsSize()) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt new file mode 100644 index 0000000..7dabd24 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt @@ -0,0 +1,121 @@ +package com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade + +import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.inventory.ExposedItemStackHandler +import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability + +class AdvancedJukeboxUpgradeWrapper : UpgradeWrapper(), IJukeboxUpgrade { + companion object { + private const val SHUFFLE_TAG = "Shuffle" + private const val REPEAT_TAG = "Repeat" + } + + override val settingsLangKey: String = "gui.jukebox_settings".asTranslationKey() + override val records: ExposedItemStackHandler = ExposedItemStackHandler(12) + override var currentPlayingIndex: Int = 0 + + var playByShuffle: Boolean = false + var playRepeat: RepeatType = RepeatType.NONE + + // Gets next record to play and respects shuffle and repeat settings, calling this method will advance the playing index + fun getNextRecordForPlaying(): ItemStack { + val records = records.inventory + val indices = records.indices + + val nextIndex = if (playByShuffle && playRepeat != RepeatType.ONE) { + indices.filter { !records[it].isEmpty }.randomOrNull() ?: -1 + } else { + when (playRepeat) { + RepeatType.NONE -> { + indices.drop(currentPlayingIndex + 1).find { !records[it].isEmpty } ?: -1 + } + + RepeatType.ALL -> { + indices.drop(currentPlayingIndex + 1).find { !records[it].isEmpty } + ?: indices.take(currentPlayingIndex + 1).find { !records[it].isEmpty } ?: -1 + } + + RepeatType.ONE -> { + if (!records[currentPlayingIndex].isEmpty) currentPlayingIndex + else indices.drop(currentPlayingIndex + 1).find { !records[it].isEmpty } + ?: indices.take(currentPlayingIndex + 1).find { !records[it].isEmpty } ?: -1 + } + } + } + + if (nextIndex == -1) { + currentPlayingIndex = 0 + return ItemStack.EMPTY + } + + val record = records[nextIndex].copy() + currentPlayingIndex = nextIndex + return record + } + + // Gets previous record to play and respects shuffle and repeat settings, calling this method will advance the playing index + fun getPreviousRecordForPlaying(): ItemStack { + val records = records.inventory + + val prevIndex = when (playRepeat) { + RepeatType.NONE -> { + (currentPlayingIndex - 1 downTo 0).find { !records[it].isEmpty } ?: -1 + } + + RepeatType.ALL -> { + (currentPlayingIndex - 1 downTo 0).find { !records[it].isEmpty } + ?: (records.size - 1 downTo 0).find { !records[it].isEmpty } ?: -1 + } + + RepeatType.ONE -> { + if (!records[currentPlayingIndex].isEmpty) currentPlayingIndex + else (currentPlayingIndex - 2 downTo 0).find { !records[it].isEmpty } + ?: (records.size - 1 downTo currentPlayingIndex).find { !records[it].isEmpty } ?: -1 + } + } + + if (prevIndex == -1) { + currentPlayingIndex = 0 + return ItemStack.EMPTY + } + + val record = records[prevIndex].copy() + currentPlayingIndex = prevIndex + + return record + } + + override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean = + capability == Capabilities.ADVANCED_JUKEBOX_UPGRADE_CAPABILITY || + super.hasCapability(capability, facing) || + super.hasCapability(capability, facing) + + override fun serializeNBT(): NBTTagCompound { + val nbt = super.serializeNBT() + val recordsNBT = records.serializeNBT() + nbt.setTag(IJukeboxUpgrade.RECORDS_TAG, recordsNBT) + nbt.setInteger(IJukeboxUpgrade.CURRENT_PLAYING_INDEX_TAG, currentPlayingIndex) + nbt.setBoolean(SHUFFLE_TAG, playByShuffle) + nbt.setByte(REPEAT_TAG, playRepeat.ordinal.toByte()) + return nbt + } + + override fun deserializeNBT(nbt: NBTTagCompound) { + super.deserializeNBT(nbt) + records.deserializeNBT(nbt.getCompoundTag(IJukeboxUpgrade.RECORDS_TAG)) + currentPlayingIndex = nbt.getInteger(IJukeboxUpgrade.CURRENT_PLAYING_INDEX_TAG) + playByShuffle = nbt.getBoolean(SHUFFLE_TAG) + playRepeat = RepeatType.entries[nbt.getByte(REPEAT_TAG).toInt()] + } + + enum class RepeatType { + NONE, + ALL, + ONE + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt index 9049705..06e9cd6 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt @@ -520,6 +520,22 @@ class BackpackPanel( tabWidget.expandedWidget = VoidUpgradeWidget(slotIndex, wrapper) } + is AdvancedJukeboxUpgradeWrapper -> { + upgradeSlotGroup.updateJukeboxDelegate(wrapper) + if (updateAndCheckRecreation( + tabWidget.expandedWidget, + wrapper + ) + ) + tabWidget.expandedWidget = AdvancedJukeboxUpgradeWidget( + slotIndex, + backpackWrapper, + wrapper, + player, + tileEntity, + ) + } + is JukeboxUpgradeWrapper -> { upgradeSlotGroup.updateJukeboxDelegate(wrapper) if (updateAndCheckRecreation( diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt index 59ffb35..09a75e6 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/RSBTextures.kt @@ -49,8 +49,15 @@ object RSBTextures { val NONE_FOUR_SLOT_ICON = icon("none_in_four_slot", 48, 80) val BACK_ICON = icon("back", 64, 80) val WORKS_IN_GUI_ICON = icon("works_in_gui", 80, 80) + val SHUFFLE_ICON = icon("reshuffle", 96, 80) + val NO_SHUFFLE_ICON = icon("no_reshuffle", 112, 80) + val REPEAT_ICON = icon("repeat", 128, 80) + val REPEAT_ONE_ICON = icon("repeat_one", 144, 80) + val NO_REPEAT_ICON = icon("no_repeat", 160, 80) val SETTING_ICON = icon("setting", 16, 96) + val SKIP_FORWARD_ICON = icon("skip_forward", 32, 96) + val SKIP_BACKWARD_ICON = icon("skip_backward", 48, 96) val NOT_WORK_IN_GUI_ICON = icon("not_work_in_gui", 80, 96) val MATCH_ORE_DICT_ICON = icon("consider_ore_dict", 112, 96) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt index 46465f1..8ab3adb 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/UpgradeSlotUpdateGroup.kt @@ -8,15 +8,11 @@ import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.CraftingUpgradeWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IAdvancedFilterable import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IBasicFilterable -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.JukeboxUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IJukeboxUpgrade import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.CraftingSlotInfo import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.IndexedModularCraftingSlot import com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot.ModularFilterSlot -import com.cleanroommc.retrosophisticatedbackpacks.sync.DelegatedCraftingStackHandlerSH -import com.cleanroommc.retrosophisticatedbackpacks.sync.DelegatedStackHandlerSH -import com.cleanroommc.retrosophisticatedbackpacks.sync.FilterSlotSH -import com.cleanroommc.retrosophisticatedbackpacks.sync.FoodFilterSlotSH -import com.cleanroommc.retrosophisticatedbackpacks.sync.JukeboxSlotSH +import com.cleanroommc.retrosophisticatedbackpacks.sync.* class UpgradeSlotUpdateGroup( private val panel: BackpackPanel, @@ -40,7 +36,7 @@ class UpgradeSlotUpdateGroup( val craftingOutputSlot: ModularCraftingSlot val craftingInfo: CraftingSlotInfo - + // Jukebox slots val jukeboxStackHandler = DelegatedStackHandlerSH(wrapper, slotIndex, 12) var jukeboxSlots: Array @@ -176,8 +172,8 @@ class UpgradeSlotUpdateGroup( craftingStackHandler.setDelegatedStackHandler(wrapper::craftMatrix) craftingStackHandler.syncToServer(DelegatedCraftingStackHandlerSH.UPDATE_CRAFTING) } - - fun updateJukeboxDelegate(wrapper: JukeboxUpgradeWrapper) { + + fun updateJukeboxDelegate(wrapper: IJukeboxUpgrade) { jukeboxStackHandler.setDelegatedStackHandler(wrapper::records) jukeboxStackHandler.syncToServer(DelegatedStackHandlerSH.UPDATE_JUKEBOX) } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedFilterWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedFilterWidget.kt index 472d496..e175b2e 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedFilterWidget.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedFilterWidget.kt @@ -212,7 +212,7 @@ class AdvancedFilterWidget( val slotGroup = SlotGroupWidget().name("${syncKey}s") slotGroup.coverChildren().leftRel(0.5f) slotGroup.disableSortButtons() - filterSlots = mutableListOf() + filterSlots = mutableListOf() for (i in 0 until 16) { val slot = @@ -391,4 +391,4 @@ class AdvancedFilterWidget( } } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt new file mode 100644 index 0000000..8ec9e9c --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt @@ -0,0 +1,256 @@ +package com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade + +import com.cleanroommc.modularui.api.drawable.IKey +import com.cleanroommc.modularui.drawable.GuiDraw +import com.cleanroommc.modularui.utils.Color +import com.cleanroommc.modularui.widgets.ButtonWidget +import com.cleanroommc.modularui.widgets.SlotGroupWidget +import com.cleanroommc.modularui.widgets.layout.Row +import com.cleanroommc.modularui.widgets.slot.ItemSlot +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.AdvancedJukeboxUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.RSBTextures +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.CyclicVariantButtonWidget +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler +import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket +import com.cleanroommc.retrosophisticatedbackpacks.sync.UpgradeSlotSH +import com.cleanroommc.retrosophisticatedbackpacks.tileentity.BackpackTileEntity +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemRecord +import net.minecraft.item.ItemStack + +class AdvancedJukeboxUpgradeWidget( + slotIndex: Int, + private val backpackWrapper: BackpackWrapper, + wrapper: AdvancedJukeboxUpgradeWrapper, + private val playerEntity: EntityPlayer, + private val tileEntity: BackpackTileEntity? +) : + ExpandedUpgradeTabWidget( + slotIndex, + wrapper, + 5, + ItemStack(Items.advancedJukeboxUpgrade), + wrapper.settingsLangKey + ) { + companion object { + private val SHUFFLE_VARIANTS = listOf( + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.no_shuffle".asTranslationKey()), + RSBTextures.NO_SHUFFLE_ICON + ), + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.shuffle".asTranslationKey()), + RSBTextures.SHUFFLE_ICON + ) + ) + + private val REPEAT_VARIANTS = listOf( + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.no_repeat".asTranslationKey()), + RSBTextures.NO_REPEAT_ICON + ), + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.repeat".asTranslationKey()), + RSBTextures.REPEAT_ICON + ), + CyclicVariantButtonWidget.Variant( + IKey.lang("gui.repeat_one".asTranslationKey()), + RSBTextures.REPEAT_ONE_ICON + ), + ) + + private val SELECTED_SLOT_COLOR = Color.withAlpha(Color.LIGHT_GREEN.main, 0x60) + } + + private val recordSlots: Array + + private val topButtonRow: Row + private val previousButton: ButtonWidget<*> + private val stopButton: ButtonWidget<*> + private val playButton: ButtonWidget<*> + private val nextButton: ButtonWidget<*> + + private val bottomButtonRow: Row + private val shuffleButton: CyclicVariantButtonWidget + private val repeatButton: CyclicVariantButtonWidget + + init { + width(90) + + val JukeboxSlotGroupsWidget = SlotGroupWidget().name("jukebox_slots_$slotIndex").disableSortButtons() + JukeboxSlotGroupsWidget.flex().coverChildren().leftRel(0.5F).top(28) + + recordSlots = Array(12) { + val slot = JukeboxItemSlot(it) + .syncHandler("jukebox_slot_$slotIndex", it) + .pos(it % 4 * 18, it / 4 * 18) + .name("jukebox_slot_$it") as JukeboxItemSlot + + JukeboxSlotGroupsWidget.child(slot) + slot + } + + topButtonRow = Row() + .leftRel(0.5F) + .top(30) + .coverChildrenWidth() + .childPadding(2) as Row + + previousButton = ButtonWidget() + .onMousePressed { + val record = wrapper.getPreviousRecordForPlaying() + updateWrapper() + + if (BackpackSoundManager.isPlaying(backpackWrapper)) { + when (val item = record.item) { + is ItemRecord -> { + playRecord(item) + true + } + + else -> false + } + } else { + true + } + } + .overlay(RSBTextures.SKIP_BACKWARD_ICON).name("previous_button") + stopButton = ButtonWidget() + .onMousePressed { + if (tileEntity != null) { + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Stationary.stopPlaying(tileEntity.pos) + ) + } else { + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Moving.stopPlaying(backpackWrapper) + ) + } + + true + } + .overlay(RSBTextures.STOP_ICON).name("stop_button") + playButton = ButtonWidget() + .onMousePressed { + var record = wrapper.records.getStackInSlot(wrapper.currentPlayingIndex) + + // Check if the current playing index points to an empty slot + // if so, set it to the first non-empty slot + if (record.isEmpty) { + for (i in 0 until wrapper.records.slots) { + record = wrapper.records.getStackInSlot(i) + + if (!record.isEmpty) { + wrapper.currentPlayingIndex = i + break + } + } + + if (record.isEmpty) { + // Fallback: if there are no records left, reset the index to 0 + wrapper.currentPlayingIndex = 0 + } + + updateWrapper() + } + + when (val item = record.item) { + is ItemRecord -> { + playRecord(item) + true + } + + else -> false + } + } + .overlay(RSBTextures.PLAY_ICON).name("play_button") + nextButton = ButtonWidget() + .onMousePressed { + val record = wrapper.getNextRecordForPlaying() + updateWrapper() + + if (BackpackSoundManager.isPlaying(backpackWrapper)) { + when (val item = record.item) { + is ItemRecord -> { + playRecord(item) + true + } + + else -> false + } + } else { + true + } + } + .overlay(RSBTextures.SKIP_FORWARD_ICON).name("next_button") + + topButtonRow.child(previousButton) + .child(stopButton) + .child(playButton) + .child(nextButton) + + bottomButtonRow = Row() + .leftRel(0.5F) + .top(56) + .coverChildrenWidth() + .childPadding(8) as Row + + shuffleButton = CyclicVariantButtonWidget(SHUFFLE_VARIANTS, if (wrapper.playByShuffle) 1 else 0) { + wrapper.playByShuffle = it == 1 + updateWrapper() + }.name("shuffle_button") + repeatButton = CyclicVariantButtonWidget(REPEAT_VARIANTS, wrapper.playRepeat.ordinal) { + wrapper.playRepeat = AdvancedJukeboxUpgradeWrapper.RepeatType.entries[it] + updateWrapper() + }.name("repeat_button") + + bottomButtonRow.child(shuffleButton) + .child(repeatButton) + + child(JukeboxSlotGroupsWidget) + .child(topButtonRow) + .child(bottomButtonRow) + } + + private fun playRecord(item: ItemRecord) { + if (tileEntity != null) { + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Stationary( + C2CJukeboxUpgradePacket.PlayingAction.PLAY, + item.sound.soundName.toString(), + tileEntity.pos + ) + ) + } else { + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Moving( + C2CJukeboxUpgradePacket.PlayingAction.PLAY, + item.sound.soundName.toString(), + backpackWrapper, + playerEntity.entityId + ) + ) + } + } + + private fun updateWrapper() { + slotSyncHandler?.syncToServer(UpgradeSlotSH.UPDATE_ADVANCED_JUKEBOX) { + it.writeInt(wrapper.currentPlayingIndex) + it.writeBoolean(wrapper.playByShuffle) + it.writeEnumValue(wrapper.playRepeat) + } + } + + private inner class JukeboxItemSlot(private val slotIndex: Int) : ItemSlot() { + override fun drawOverlay() { + super.drawOverlay() + if (BackpackSoundManager.isPlaying(backpackWrapper) && slotIndex == wrapper.currentPlayingIndex) { + GuiDraw.drawRect(1f, 1f, 16f, 16f, SELECTED_SLOT_COLOR) + } + } + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt index 6c55f22..21ef88f 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt @@ -50,6 +50,11 @@ object BackpackSoundManager { } private fun registerAndPlay(wrapper: BackpackWrapper, sound: ISound) { + val previousSound = activeSounds[wrapper.uuid] + + if (previousSound != null) + Minecraft.getMinecraft().soundHandler.stopSound(previousSound) + activeSounds[wrapper.uuid] = sound Minecraft.getMinecraft().soundHandler.playSound(sound) } @@ -59,4 +64,14 @@ object BackpackSoundManager { Minecraft.getMinecraft().soundHandler.stopSound(sound) } + + fun isPlaying(wrapper: BackpackWrapper): Boolean { + val sound = activeSounds[wrapper.uuid] ?: return false + + return Minecraft.getMinecraft().soundHandler.isSoundPlaying(sound) + } + + fun clear() { + activeSounds.clear() + } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt index 5ff398c..51f641c 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt @@ -52,7 +52,7 @@ class ModularUpgradeSlot( override fun isItemValid(stack: ItemStack): Boolean = when (val item = stack.item) { is StackUpgradeItem -> wrapper.canAddStackUpgrade(item.multiplier()) is ExponentialStackUpgradeItem -> wrapper.canAddExponentialStackUpgrade() - is JukeboxUpgradeItem -> wrapper.canAddJukeboxUpgrade() + is JukeboxUpgradeItem -> wrapper.canAddJukeboxUpgrade() || this.stack.item is JukeboxUpgradeItem else -> item is UpgradeItem } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt index c64b7a8..9c1ee76 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt @@ -119,6 +119,12 @@ object CapabilityHandler { CapabilityStorageProvider(), ::JukeboxUpgradeWrapper ) + + instance.register( + AdvancedJukeboxUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::AdvancedJukeboxUpgradeWrapper + ) // Interfaces instance.register( diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/ClientEventHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/ClientEventHandler.kt new file mode 100644 index 0000000..0c3e1d3 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/ClientEventHandler.kt @@ -0,0 +1,28 @@ +package com.cleanroommc.retrosophisticatedbackpacks.handler + +import com.cleanroommc.retrosophisticatedbackpacks.Tags +import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.Mod +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.network.FMLNetworkEvent +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly + +@Mod.EventBusSubscriber(Side.CLIENT, modid = Tags.MOD_ID) +object ClientEventHandler { + @SubscribeEvent + @JvmStatic + @SideOnly(Side.CLIENT) + fun onClientDisconnect(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) { + BackpackSoundManager.clear() + } + + @SubscribeEvent + @JvmStatic + @SideOnly(Side.CLIENT) + fun onClientWorldUnload(event: WorldEvent.Unload) { + BackpackSoundManager.clear() + CapabilityHandler.BACKPACK_INVENTORY_CACHE.clear() + } +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt index 065f904..995da07 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt @@ -126,4 +126,7 @@ object Items { @JvmField val jukeboxUpgrade = JukeboxUpgradeItem("jukebox_upgrade", ::JukeboxUpgradeWrapper) + + @JvmField + val advancedJukeboxUpgrade = JukeboxUpgradeItem("advanced_jukebox_upgrade", ::AdvancedJukeboxUpgradeWrapper) } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt index 1dfe699..ef93237 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt @@ -49,7 +49,7 @@ sealed class C2CJukeboxUpgradePacket : IRefinedMessage { ) : this() { this.action = action this.soundRegistryName = soundRegistryName ?: "" - this.backpackUUID = wrapper.uuid + this.backpackUUID = wrapper.uuid!! this.entityID = entityID } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt index 6ae8048..9008301 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt @@ -18,7 +18,7 @@ class JukeboxSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : I override fun onSlotUpdate(stack: ItemStack, onlyAmountChanged: Boolean, client: Boolean, init: Boolean) { // Special handling for the initial update of slot, since the update does not actually change the record in the // slot - if (initialUpdated && (!isItemValid(stack) || Minecraft.getMinecraft().player.inventory.itemStack.item != stack.item)) + if (initialUpdated) NetworkHandler.INSTANCE.sendToServer(C2CJukeboxUpgradePacket.Moving.stopPlaying(wrapper)) else initialUpdated = true diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt index da28623..2dd0245 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt @@ -26,6 +26,7 @@ class UpgradeSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : I const val UPDATE_FILTER_WAY = 11 const val UPDATE_CRAFTING_DESTINATION = 12 const val UPDATE_VOID = 13 + const val UPDATE_ADVANCED_JUKEBOX = 14 } private var initialUpdated = false @@ -51,6 +52,7 @@ class UpgradeSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : I UPDATE_FILTER_WAY -> updateFilterUpgrade(buf) UPDATE_CRAFTING_DESTINATION -> updateCraftingDestination(buf) UPDATE_VOID -> updateVoidUpgrade(buf) + UPDATE_ADVANCED_JUKEBOX -> updateAdvancedJukeboxUpgrade(buf) } } @@ -114,4 +116,12 @@ class UpgradeSlotSH(slot: ModularSlot, private val wrapper: BackpackWrapper) : I wrapper.transferSource = buf.readEnumValue(IVoidUpgrade.TransferSource::class.java) wrapper.voidType = buf.readEnumValue(IVoidUpgrade.VoidType::class.java) } + + private fun updateAdvancedJukeboxUpgrade(buf: PacketBuffer) { + val wrapper = slot.stack.getCapability(Capabilities.ADVANCED_JUKEBOX_UPGRADE_CAPABILITY, null) ?: return + + wrapper.currentPlayingIndex = buf.readInt() + wrapper.playByShuffle = buf.readBoolean() + wrapper.playRepeat = buf.readEnumValue(AdvancedJukeboxUpgradeWrapper.RepeatType::class.java) + } } diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang index 390da63..ffdc985 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang @@ -28,6 +28,7 @@ item.retro_sophisticated_backpacks.advanced_filter_upgrade.name=Advanced Filter item.retro_sophisticated_backpacks.void_upgrade.name=Void Upgrade item.retro_sophisticated_backpacks.advanced_void_upgrade.name=Advanced Void Upgrade item.retro_sophisticated_backpacks.jukebox_upgrade.name=Jukebox Upgrade +item.retro_sophisticated_backpacks.advanced_jukebox_upgrade.name=Advanced Jukebox Upgrade # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=Retro Sophisticated Backpacks @@ -75,7 +76,9 @@ retro_sophisticated_backpacks.tooltip.void_upgrade=Voids items selected in filte retro_sophisticated_backpacks.tooltip.advanced_void_upgrade=Voids items selected in filter with more configurations -retro_sophisticated_backpacks.tooltip.jukebox_upgrade=Plays discs in your backpack! +retro_sophisticated_backpacks.tooltip.jukebox_upgrade=Plays disc in your backpack! + +retro_sophisticated_backpacks.tooltip.advanced_jukebox_upgrade=Plays discs in your backpack with more options! retro_sophisticated_backpacks.tooltip.shift_to_reveal= diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang index 3badd2c..791c240 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang @@ -28,6 +28,7 @@ item.retro_sophisticated_backpacks.advanced_filter_upgrade.name=進階過濾升 item.retro_sophisticated_backpacks.void_upgrade.name=虛空升級 item.retro_sophisticated_backpacks.advanced_void_upgrade.name=進階虛空升級 item.retro_sophisticated_backpacks.jukebox_upgrade.name=唱片機升級 +item.retro_sophisticated_backpacks.advanced_jukebox_upgrade.name=進階唱片機升級 # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=復古精緻背包 @@ -77,6 +78,8 @@ retro_sophisticated_backpacks.tooltip.advanced_void_upgrade=根據更多配置 retro_sophisticated_backpacks.tooltip.jukebox_upgrade=在背包中播放唱片! +retro_sophisticated_backpacks.tooltip.advanced_jukebox_upgrade=在背包中播放唱片,還有更多選項! + retro_sophisticated_backpacks.tooltip.shift_to_reveal=<按 Shift 顯示> # Gui Elements diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_jukebox_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_jukebox_upgrade.json new file mode 100644 index 0000000..bb0429b --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/advanced_jukebox_upgrade.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "retro_sophisticated_backpacks:item/advanced_jukebox_upgrade" + } +} From 440ad8e01358c84eebbf548ddc4c2d8bc81a44cd Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Thu, 18 Jun 2026 18:30:03 +0800 Subject: [PATCH 07/14] Upgrade Forgelin Continuous to 2.4.0.0 - Fix missing un-dyeing recipe --- gradle.properties | 4 ++-- .../crafting/DyeingRecipeRegistry.kt | 23 ++++++++++++------- .../retrosophisticatedbackpacks/util/Utils.kt | 8 +++++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index 103e745..b6b9307 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,8 +11,8 @@ archives_base_name = RetroSophisticatedBackpacks # If any properties changes below this line, run `gradlew setupDecompWorkspace` and refresh gradle again to ensure everything is working correctly. # Kotlin Options -kotlin_version = 2.3.0 -forgelin_continuous_version = 2.3.0.0 +kotlin_version = 2.4.0 +forgelin_continuous_version = 2.4.0.0 # Boilerplate Options use_mixins = true diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/crafting/DyeingRecipeRegistry.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/crafting/DyeingRecipeRegistry.kt index 07eefcd..38e61fd 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/crafting/DyeingRecipeRegistry.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/crafting/DyeingRecipeRegistry.kt @@ -1,9 +1,11 @@ package com.cleanroommc.retrosophisticatedbackpacks.crafting import com.cleanroommc.retrosophisticatedbackpacks.Tags +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem import com.cleanroommc.retrosophisticatedbackpacks.mixin.EnumDyeColorAccessor +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.cast import net.minecraft.item.EnumDyeColor import net.minecraft.item.ItemStack import net.minecraft.item.crafting.IRecipe @@ -35,16 +37,11 @@ object DyeingRecipeRegistry { mainColor: EnumDyeColor?, accentColor: EnumDyeColor? ): IRecipe? { - if (mainColor == null && accentColor == null) - return null - val backpackStack = ItemStack(backpackItem, 1) val backpackWrapper = backpackStack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return null - if (mainColor is EnumDyeColorAccessor) - backpackWrapper.mainColor = mainColor.`rsb$getColorValue`() - if (accentColor is EnumDyeColorAccessor) - backpackWrapper.accentColor = accentColor.`rsb$getColorValue`() + backpackWrapper.mainColor = mainColor?.cast()?.`rsb$getColorValue`() ?: BackpackWrapper.DEFAULT_MAIN_COLOR + backpackWrapper.accentColor = accentColor?.cast()?.`rsb$getColorValue`() ?: BackpackWrapper.DEFAULT_ACCENT_COLOR return if (mainColor != null && accentColor != null) { constructRecipe( @@ -87,7 +84,17 @@ object DyeingRecipeRegistry { 'D', "dye${DYES[accentColor.dyeDamage]}", ) - } else null + } else { + constructRecipe( + ResourceLocation(Tags.MOD_ID, "${backpackItem.registryName?.path}_dye_none"), + backpackStack, + " ", + " B ", + " ", + 'B', + ItemStack(backpackItem, 1), + ) + } } fun constructRecipe(name: ResourceLocation, output: ItemStack, vararg params: Any): IRecipe { diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/util/Utils.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/util/Utils.kt index dc73bfd..8825adf 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/util/Utils.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/util/Utils.kt @@ -50,4 +50,12 @@ object Utils { fun WidgetThemeEntry?.getThemeOrDefault(): WidgetTheme = this?.theme ?: WidgetTheme.getDefault().theme + + @Suppress("UNCHECKED_CAST") + fun Any.unsafeCast(): R? = + this as? R + + @Suppress("UNCHECKED_CAST") + fun Any.cast(): R = + this as R } From 2fcd5b67758994e6411f1a891e01fae06e8d024e Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Thu, 18 Jun 2026 23:12:14 +0800 Subject: [PATCH 08/14] Cleanup --- .../upgrade/AdvancedJukeboxUpgradeWrapper.kt | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt index 7dabd24..de93498 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt @@ -26,24 +26,25 @@ class AdvancedJukeboxUpgradeWrapper : UpgradeWrapper(), IJuk fun getNextRecordForPlaying(): ItemStack { val records = records.inventory val indices = records.indices + val predicate = { i: Int -> !records[i].isEmpty } val nextIndex = if (playByShuffle && playRepeat != RepeatType.ONE) { - indices.filter { !records[it].isEmpty }.randomOrNull() ?: -1 + indices.filter(predicate).randomOrNull() ?: -1 } else { when (playRepeat) { RepeatType.NONE -> { - indices.drop(currentPlayingIndex + 1).find { !records[it].isEmpty } ?: -1 + indices.drop(currentPlayingIndex + 1).find(predicate) ?: -1 } RepeatType.ALL -> { - indices.drop(currentPlayingIndex + 1).find { !records[it].isEmpty } - ?: indices.take(currentPlayingIndex + 1).find { !records[it].isEmpty } ?: -1 + indices.drop(currentPlayingIndex + 1).find(predicate) + ?: indices.take(currentPlayingIndex + 1).find(predicate) ?: -1 } RepeatType.ONE -> { if (!records[currentPlayingIndex].isEmpty) currentPlayingIndex - else indices.drop(currentPlayingIndex + 1).find { !records[it].isEmpty } - ?: indices.take(currentPlayingIndex + 1).find { !records[it].isEmpty } ?: -1 + else indices.drop(currentPlayingIndex + 1).find(predicate) + ?: indices.take(currentPlayingIndex + 1).find(predicate) ?: -1 } } } @@ -61,21 +62,22 @@ class AdvancedJukeboxUpgradeWrapper : UpgradeWrapper(), IJuk // Gets previous record to play and respects shuffle and repeat settings, calling this method will advance the playing index fun getPreviousRecordForPlaying(): ItemStack { val records = records.inventory + val predicate = { i: Int -> !records[i].isEmpty } val prevIndex = when (playRepeat) { RepeatType.NONE -> { - (currentPlayingIndex - 1 downTo 0).find { !records[it].isEmpty } ?: -1 + (currentPlayingIndex - 1 downTo 0).find(predicate) ?: -1 } RepeatType.ALL -> { - (currentPlayingIndex - 1 downTo 0).find { !records[it].isEmpty } - ?: (records.size - 1 downTo 0).find { !records[it].isEmpty } ?: -1 + (currentPlayingIndex - 1 downTo 0).find(predicate) + ?: (records.size - 1 downTo 0).find(predicate) ?: -1 } RepeatType.ONE -> { if (!records[currentPlayingIndex].isEmpty) currentPlayingIndex - else (currentPlayingIndex - 2 downTo 0).find { !records[it].isEmpty } - ?: (records.size - 1 downTo currentPlayingIndex).find { !records[it].isEmpty } ?: -1 + else (currentPlayingIndex - 2 downTo 0).find(predicate) + ?: (records.size - 1 downTo currentPlayingIndex).find(predicate) ?: -1 } } From a4cd7b2cca21fcf29221d0daf85bdb4c7312b64b Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 19 Jun 2026 03:28:25 +0800 Subject: [PATCH 09/14] Fix backpack model color rendering --- .../client/BackpackBipedModel.kt | 2 +- .../retrosophisticatedbackpacks/item/BackpackItem.kt | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/BackpackBipedModel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/BackpackBipedModel.kt index c0afe2d..5490abe 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/BackpackBipedModel.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/BackpackBipedModel.kt @@ -10,7 +10,7 @@ import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.SideOnly @SideOnly(Side.CLIENT) -class BackpackBipedModel(private val backpackItemStack: ItemStack) : ModelBiped() { +class BackpackBipedModel(var backpackItemStack: ItemStack) : ModelBiped() { companion object { fun renderBackpack(backpackItemStack: ItemStack, entityIn: Entity) { GlStateManager.translate(0.0, 0.3, 0.15) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt index ded8b12..af39388 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt @@ -213,8 +213,10 @@ class BackpackItem( default: ModelBiped ): ModelBiped? { if (armorSlot == EntityEquipmentSlot.CHEST) { - val model = if (cachedBipedModel != null) cachedBipedModel - else { + val model = if (cachedBipedModel != null) { + cachedBipedModel!!.backpackItemStack = itemStack + cachedBipedModel + } else { cachedBipedModel = BackpackBipedModel(itemStack) cachedBipedModel } From 1b02e8f2ddcb7fdba4850d42fccc7f39a5d7dc11 Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 19 Jun 2026 03:28:53 +0800 Subject: [PATCH 10/14] Fix upgrade tab state handling --- .../client/gui/BackpackPanel.kt | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt index 06e9cd6..136557c 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt @@ -407,15 +407,21 @@ class BackpackPanel( if (wrapper.isTabOpened) { if (openedTabIndex != null) { - wrapper.isTabOpened = false - upgradeSlotSyncHandlers[slotIndex].syncToServer(UpgradeSlotSH.UPDATE_UPGRADE_TAB_STATE) { - it.writeBoolean(false) + val toCloseIndex = if (slotIndex == index) openedTabIndex else slotIndex + val toCloseWrapper = + upgradeSlotWidgets[toCloseIndex].slot.stack.getCapability(Capabilities.UPGRADE_CAPABILITY, null) + if (toCloseWrapper != null) { + toCloseWrapper.isTabOpened = false + upgradeSlotSyncHandlers[toCloseIndex].syncToServer(UpgradeSlotSH.UPDATE_UPGRADE_TAB_STATE) { + it.writeBoolean(false) + } } - - return + if (toCloseIndex == openedTabIndex) { + openedTabIndex = slotIndex + } + } else { + openedTabIndex = slotIndex } - - openedTabIndex = slotIndex } } // Shifted forward to account for settings tab. @@ -587,8 +593,8 @@ class BackpackPanel( tabWidgets.size ) - for (tabIndex in openedTabIndex + 1 until upperboundIndex) { - tabWidgets[tabIndex].isEnabled = false + for (tIndex in openedTabIndex + 1 until upperboundIndex) { + tabWidgets[tIndex].isEnabled = false } } From 17cc348fafedb90aff53af50d9346005695ff37c Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 19 Jun 2026 03:50:39 +0800 Subject: [PATCH 11/14] Complete missing lang keys --- .../upgrade/AdvancedJukeboxUpgradeWidget.kt | 17 +++++++++++++++++ .../gui/widgets/upgrade/JukeboxUpgradeWidget.kt | 11 +++++++++++ .../lang/en_us.lang | 10 ++++++++++ .../lang/zh_tw.lang | 10 ++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt index 8ec9e9c..0a01838 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt @@ -2,6 +2,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade import com.cleanroommc.modularui.api.drawable.IKey import com.cleanroommc.modularui.drawable.GuiDraw +import com.cleanroommc.modularui.screen.RichTooltip import com.cleanroommc.modularui.utils.Color import com.cleanroommc.modularui.widgets.ButtonWidget import com.cleanroommc.modularui.widgets.SlotGroupWidget @@ -119,6 +120,10 @@ class AdvancedJukeboxUpgradeWidget( } } .overlay(RSBTextures.SKIP_BACKWARD_ICON).name("previous_button") + .tooltipStatic { + it.addLine(IKey.lang("gui.previous".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } stopButton = ButtonWidget() .onMousePressed { if (tileEntity != null) { @@ -134,6 +139,10 @@ class AdvancedJukeboxUpgradeWidget( true } .overlay(RSBTextures.STOP_ICON).name("stop_button") + .tooltipStatic { + it.addLine(IKey.lang("gui.stop".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } playButton = ButtonWidget() .onMousePressed { var record = wrapper.records.getStackInSlot(wrapper.currentPlayingIndex) @@ -168,6 +177,10 @@ class AdvancedJukeboxUpgradeWidget( } } .overlay(RSBTextures.PLAY_ICON).name("play_button") + .tooltipStatic { + it.addLine(IKey.lang("gui.play".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } nextButton = ButtonWidget() .onMousePressed { val record = wrapper.getNextRecordForPlaying() @@ -187,6 +200,10 @@ class AdvancedJukeboxUpgradeWidget( } } .overlay(RSBTextures.SKIP_FORWARD_ICON).name("next_button") + .tooltipStatic { + it.addLine(IKey.lang("gui.next".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } topButtonRow.child(previousButton) .child(stopButton) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt index 04bf47a..f8d2461 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt @@ -1,6 +1,9 @@ package com.cleanroommc.retrosophisticatedbackpacks.client.gui.widgets.upgrade +import com.cleanroommc.modularui.api.drawable.IKey +import com.cleanroommc.modularui.screen.RichTooltip import com.cleanroommc.modularui.widgets.ButtonWidget +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey import com.cleanroommc.modularui.widgets.SlotGroupWidget import com.cleanroommc.modularui.widgets.layout.Row import com.cleanroommc.modularui.widgets.slot.ItemSlot @@ -65,6 +68,10 @@ class JukeboxUpgradeWidget( true } .overlay(RSBTextures.STOP_ICON) + .tooltipStatic { + it.addLine(IKey.lang("gui.stop".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } playButton = ButtonWidget().name("play_button") .onMousePressed { val record = wrapper.records.getStackInSlot(0) @@ -95,6 +102,10 @@ class JukeboxUpgradeWidget( true } .overlay(RSBTextures.PLAY_ICON) + .tooltipStatic { + it.addLine(IKey.lang("gui.play".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } buttonRow.child(stopButton) .child(playButton) diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang index ffdc985..f1a673f 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang @@ -159,6 +159,16 @@ retro_sophisticated_backpacks.gui.sort_by_ore_dict=Sort By Ore Dictionary retro_sophisticated_backpacks.gui.craft_into_backpack=Shift Click Result Into Backpack retro_sophisticated_backpacks.gui.craft_into_player_inventory=Shift Click Result Into Player's Inventory +retro_sophisticated_backpacks.gui.play=Play +retro_sophisticated_backpacks.gui.stop=Stop +retro_sophisticated_backpacks.gui.previous=Previous Track +retro_sophisticated_backpacks.gui.next=Next Track +retro_sophisticated_backpacks.gui.no_shuffle=No Shuffle +retro_sophisticated_backpacks.gui.shuffle=Shuffle +retro_sophisticated_backpacks.gui.no_repeat=No Repeat +retro_sophisticated_backpacks.gui.repeat=Repeat +retro_sophisticated_backpacks.gui.repeat_one=Repeat One + retro_sophisticated_backpacks.gui.transfer_to_player_inv=Transfer All Items to Player Inventory retro_sophisticated_backpacks.gui.transfer_to_player_inv_matched_1=Transfer Matched Items to Player Inventory retro_sophisticated_backpacks.gui.transfer_to_player_inv_matched_2=Shift To Transfer All diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang index 791c240..ebc29ae 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang @@ -166,6 +166,16 @@ retro_sophisticated_backpacks.gui.transfer_to_backpack_inv=轉移所有物品至 retro_sophisticated_backpacks.gui.transfer_to_backpack_inv_matched_1=轉移對應物品至背包物品欄 retro_sophisticated_backpacks.gui.transfer_to_backpack_inv_matched_2=Shift 以轉移全部 +retro_sophisticated_backpacks.gui.play=播放 +retro_sophisticated_backpacks.gui.stop=停止 +retro_sophisticated_backpacks.gui.previous=上一首 +retro_sophisticated_backpacks.gui.next=下一首 +retro_sophisticated_backpacks.gui.no_shuffle=無隨機播放 +retro_sophisticated_backpacks.gui.shuffle=隨機播放 +retro_sophisticated_backpacks.gui.no_repeat=無循環 +retro_sophisticated_backpacks.gui.repeat=列表循環 +retro_sophisticated_backpacks.gui.repeat_one=單曲循環 + retro_sophisticated_backpacks.gui.settings=設定 retro_sophisticated_backpacks.gui.configuration_tab=設定介面 From d746ba95493be092464e04b70bf30a87c816376c Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 19 Jun 2026 04:16:13 +0800 Subject: [PATCH 12/14] Updates README.md --- README.md | 22 ++++++++++++++++--- .../gui/widgets/CyclicVariantButtonWidget.kt | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2607f1a..bb6d3e7 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ Here is a list of implemented feature and considered features to be implemented: ### Upgrades - [x] stack upgrade - - [x] exponential stack upgrade (RSB exclusive) - [x] inception upgrade - [x] pickup upgrade (b/a) - [x] feeding upgrade (b/a) @@ -42,10 +41,27 @@ Here is a list of implemented feature and considered features to be implemented: - [x] restock upgrade (b/a) - [x] filter upgrade (b/a) - [ ] magnet upgrade (b/a) -- [ ] void upgrade (b/a) +- [x] void upgrade (b/a) - [x] crafting upgrade - [ ] everlasting upgrade -- [ ] jukebox upgrade (low priority) +- [x] jukebox upgrade (b/a) +- [ ] refill upgrade (b/a) +- [ ] compacting upgrade (b/a) +- [ ] tool swapper upgrade (b/a) +- [ ] pump upgrade (b/a) +- [ ] experience pump upgrade +- [ ] tank upgrade +- [ ] battery upgrade +- [ ] anvil upgrade + +## RSB Exclusive Features + +### Upgrades + +- [x] exponential stack upgrade + - Changes behavior of stack upgrade to be exponentially increasing. +- [ ] armor plate upgrade (from leather to diamond) + - Adds armor value to the backpack when equipped. ## Disclaimer diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt index a519dd4..56241b4 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt @@ -67,4 +67,4 @@ class CyclicVariantButtonWidget( } data class Variant(val name: IKey, val drawable: IDrawable) -} \ No newline at end of file +} From 94a3ccc572620590c1b6743da3be8f090dd5cb68 Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 19 Jun 2026 04:34:04 +0800 Subject: [PATCH 13/14] Add more tooltip status --- .../item/BackpackItem.kt | 31 +++++++++++++++++++ .../lang/en_us.lang | 4 +++ .../lang/zh_tw.lang | 4 +++ 3 files changed, 39 insertions(+) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt index af39388..3ed2a78 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt @@ -14,6 +14,7 @@ import com.cleanroommc.retrosophisticatedbackpacks.backpack.BackpackTier import com.cleanroommc.retrosophisticatedbackpacks.block.BackpackBlock import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.Capabilities +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IToggleable import com.cleanroommc.retrosophisticatedbackpacks.client.BackpackBipedModel import com.cleanroommc.retrosophisticatedbackpacks.client.sound.BackpackSoundManager import com.cleanroommc.retrosophisticatedbackpacks.common.gui.BackpackContainer @@ -284,6 +285,36 @@ class BackpackItem( TextComponentString(stackHint).setStyle(Style().setColor(TextFormatting.RED)).formattedText ).formattedText ) + + for (i in 0 until wrapper.upgradeSlotsSize()) { + val upgradeStack = wrapper.upgradeItemStackHandler.getStackInSlot(i) + + if (upgradeStack.isEmpty) + continue + + val upgradeWrapper = upgradeStack.getCapability(Capabilities.UPGRADE_CAPABILITY, null) ?: continue + + if (upgradeWrapper is IToggleable) { + val toggledColor = if (upgradeWrapper.enabled) TextFormatting.GREEN else TextFormatting.RED + + tooltip.add( + TextComponentTranslation( + "tooltip.backpack.upgrade_slot.toggleable".asTranslationKey(), + upgradeStack.displayName, + TextComponentTranslation("tooltip.upgrade.state.${upgradeWrapper.enabled}".asTranslationKey()).setStyle( + Style().setColor(toggledColor) + ).formattedText + ).setStyle(Style().setColor(TextFormatting.GRAY)).formattedText + ) + } else { + tooltip.add( + TextComponentTranslation( + "tooltip.backpack.upgrade_slot.default".asTranslationKey(), + upgradeStack.displayName + ).setStyle(Style().setColor(TextFormatting.GRAY)).formattedText + ) + } + } } else { tooltip.add(TextComponentTranslation("tooltip.shift_to_reveal".asTranslationKey()).formattedText) } diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang index f1a673f..0ac7488 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang @@ -41,6 +41,10 @@ retro_sophisticated_backpacks.key.category=Retro Sophisticated Backpacks retro_sophisticated_backpacks.tooltip.backpack.inventory_size=Inventory size: %d retro_sophisticated_backpacks.tooltip.backpack.upgrade_slots_size=Upgrade slots: %d retro_sophisticated_backpacks.tooltip.backpack.stack_multiplier=-> Stack multiplier: %d %s +retro_sophisticated_backpacks.tooltip.backpack.upgrade_slot.toggleable=-> %s: %s +retro_sophisticated_backpacks.tooltip.backpack.upgrade_slot.default=-> %s +retro_sophisticated_backpacks.tooltip.upgrade.state.true=Enabled +retro_sophisticated_backpacks.tooltip.upgrade.state.false=Disabled retro_sophisticated_backpacks.tooltip.upgrade_base=It does nothing! Feel free to put it in your upgrade slots! diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang index ebc29ae..4562c6c 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang @@ -41,6 +41,10 @@ retro_sophisticated_backpacks.key.category=復古精緻背包 retro_sophisticated_backpacks.tooltip.backpack.inventory_size=背包容量: %d retro_sophisticated_backpacks.tooltip.backpack.upgrade_slots_size=升級插槽: %d retro_sophisticated_backpacks.tooltip.backpack.stack_multiplier=-> 當前堆疊倍率: %d %s +retro_sophisticated_backpacks.tooltip.backpack.upgrade_slot.toggleable=-> %s: %s +retro_sophisticated_backpacks.tooltip.backpack.upgrade_slot.default=-> %s +retro_sophisticated_backpacks.tooltip.upgrade.state.true=已啟用 +retro_sophisticated_backpacks.tooltip.upgrade.state.false=已停用 retro_sophisticated_backpacks.tooltip.upgrade_base=沒有效果!你大可放在升級插槽! From a0c4f5d0c0523aac45324739a3d5345c9176c3fb Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 19 Jun 2026 23:55:43 +0800 Subject: [PATCH 14/14] Add Everlasting Upgrade - Add more information in backpack tooltip - Fix UUID registration issue --- README.md | 1 + .../mixin/EntityAccessor.java | 11 ++++ .../block/BackpackBlock.kt | 16 ++++- .../capability/BackpackWrapper.kt | 18 ++++-- .../gui/widgets/CyclicVariantButtonWidget.kt | 10 ++- .../common/gui/slot/ModularUpgradeSlot.kt | 13 ++-- .../handler/CapabilityHandler.kt | 13 ++-- .../handler/EntityEventHandler.kt | 24 +++++++ .../item/BackpackItem.kt | 64 ++++++++++++++++++- .../item/EverlastingUpgradeItem.kt | 3 + .../retrosophisticatedbackpacks/item/Items.kt | 3 + .../lang/en_us.lang | 3 + .../lang/zh_tw.lang | 3 + .../models/item/everlasting_upgrade.json | 6 ++ .../recipes/everlasting_upgrade.json | 23 +++++++ .../mixin.retro_sophisticated_backpacks.json | 1 + 16 files changed, 184 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/cleanroommc/retrosophisticatedbackpacks/mixin/EntityAccessor.java create mode 100644 src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/EverlastingUpgradeItem.kt create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/models/item/everlasting_upgrade.json create mode 100644 src/main/resources/assets/retro_sophisticated_backpacks/recipes/everlasting_upgrade.json diff --git a/README.md b/README.md index bb6d3e7..d8d933c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Here is a list of implemented feature and considered features to be implemented: - [ ] Lockable by player - [x] Backpack model render on player's back when equipped - Supported on vanilla and Bauble, BaubleEx is not supported yet. + - Supported to be opened by other players when equipped. - [x] Dyeing ### Upgrades diff --git a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/mixin/EntityAccessor.java b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/mixin/EntityAccessor.java new file mode 100644 index 0000000..f638651 --- /dev/null +++ b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/mixin/EntityAccessor.java @@ -0,0 +1,11 @@ +package com.cleanroommc.retrosophisticatedbackpacks.mixin; + +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Entity.class) +public interface EntityAccessor { + @Accessor("isImmuneToFire") + void rsb$setIsImmuneToFire(boolean isImmuneToFire); +} diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt index 880a3e4..4fa60cf 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt @@ -20,6 +20,7 @@ import net.minecraft.block.properties.PropertyDirection import net.minecraft.block.state.BlockFaceShape import net.minecraft.block.state.BlockStateContainer import net.minecraft.block.state.IBlockState +import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.player.EntityPlayer import net.minecraft.init.SoundEvents @@ -29,6 +30,7 @@ import net.minecraft.tileentity.TileEntity import net.minecraft.util.* import net.minecraft.util.math.AxisAlignedBB import net.minecraft.util.math.BlockPos +import net.minecraft.world.Explosion import net.minecraft.world.IBlockAccess import net.minecraft.world.World import net.minecraftforge.fml.common.Optional @@ -46,7 +48,7 @@ class BackpackBlock( val RIGHT_TANK: PropertyBool = PropertyBool.create("right_tank") val BATTERY: PropertyBool = PropertyBool.create("battery") val FACING: PropertyDirection = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL) - const val BEDROCK_RESISTANCE = 3600000 + const val BEDROCK_RESISTANCE = 6000000.0F private val BOOL_PROPERTIES = arrayOf(LEFT_TANK, RIGHT_TANK, BATTERY) } @@ -157,7 +159,17 @@ class BackpackBlock( } override fun getPushReaction(state: IBlockState): EnumPushReaction = - EnumPushReaction.DESTROY + EnumPushReaction.NORMAL + + override fun getExplosionResistance(world: World, pos: BlockPos, exploder: Entity?, explosion: Explosion): Float { + val wrapper = world.getTileEntity(pos)?.getCapability(Capabilities.BACKPACK_CAPABILITY, null) + + if (wrapper != null && wrapper.hasEverlastingJukeboxUpgrade()) { + return BEDROCK_RESISTANCE + } + + return super.getExplosionResistance(world, pos, exploder, explosion) + } override fun hasComparatorInputOverride(state: IBlockState): Boolean = true diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt index 70720de..a50eefb 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt @@ -1,13 +1,12 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability -import com.azul.crs.client.Utils.uuid import com.cleanroommc.retrosophisticatedbackpacks.backpack.SortType -import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.AdvancedJukeboxUpgradeWrapper import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IJukeboxUpgrade import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.IVoidUpgrade import com.cleanroommc.retrosophisticatedbackpacks.inventory.BackpackItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.inventory.UpgradeItemStackHandler import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem +import com.cleanroommc.retrosophisticatedbackpacks.item.EverlastingUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.ExponentialStackUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.InceptionUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem @@ -21,6 +20,7 @@ import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.items.CapabilityItemHandler import net.minecraftforge.items.IItemHandler +import net.minecraftforge.fml.common.FMLCommonHandler import java.util.* class BackpackWrapper( @@ -49,6 +49,12 @@ class BackpackWrapper( var uuid: UUID? = null + get() { + if (field == null && FMLCommonHandler.instance().effectiveSide.isServer) { + field = UUID.randomUUID() + } + return field + } var isCached: Boolean = false var backpackItemStackHandler = BackpackItemStackHandler(backpackInventorySize(), this) @@ -136,9 +142,13 @@ class BackpackWrapper( return true } - fun canAddJukeboxUpgrade(): Boolean = + fun hasJukeboxUpgrade(): Boolean = upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance() - .isEmpty() + .isNotEmpty() + + fun hasEverlastingJukeboxUpgrade(): Boolean = + upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance() + .isNotEmpty() fun canNestBackpack(): Boolean = upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance().any() diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt index 56241b4..cb4805f 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt @@ -48,16 +48,14 @@ class CyclicVariantButtonWidget( override fun draw(context: ModularGuiContext?, widgetTheme: WidgetThemeEntry<*>?) { if (hasCustomTexture) { - if (isHovering) { - hoveredTexture.draw(context, 0, 0, buttonWidth, buttonHeight, widgetTheme.getThemeOrDefault()) - } else { - notHoveredTexture.draw(context, 0, 0, buttonWidth, buttonHeight, widgetTheme.getThemeOrDefault()) - } + val texture = if (isHovering) hoveredTexture else notHoveredTexture + + texture.draw(context, 0, 0, buttonWidth, buttonHeight, widgetTheme.getThemeOrDefault()) } super.draw(context, widgetTheme) } - override fun drawOverlay(context: ModularGuiContext?, widgetTheme: WidgetThemeEntry<*>?) { + override fun drawOverlay(context: ModularGuiContext, widgetTheme: WidgetThemeEntry<*>?) { super.drawOverlay(context, widgetTheme) val drawable = variants[index].drawable diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt index 51f641c..f5ad680 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/common/gui/slot/ModularUpgradeSlot.kt @@ -3,11 +3,7 @@ package com.cleanroommc.retrosophisticatedbackpacks.common.gui.slot import com.cleanroommc.modularui.widgets.slot.ModularSlot import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper import com.cleanroommc.retrosophisticatedbackpacks.client.gui.BackpackPanel -import com.cleanroommc.retrosophisticatedbackpacks.item.ExponentialStackUpgradeItem -import com.cleanroommc.retrosophisticatedbackpacks.item.InceptionUpgradeItem -import com.cleanroommc.retrosophisticatedbackpacks.item.JukeboxUpgradeItem -import com.cleanroommc.retrosophisticatedbackpacks.item.StackUpgradeItem -import com.cleanroommc.retrosophisticatedbackpacks.item.UpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.item.* import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -50,9 +46,10 @@ class ModularUpgradeSlot( 1 override fun isItemValid(stack: ItemStack): Boolean = when (val item = stack.item) { - is StackUpgradeItem -> wrapper.canAddStackUpgrade(item.multiplier()) - is ExponentialStackUpgradeItem -> wrapper.canAddExponentialStackUpgrade() - is JukeboxUpgradeItem -> wrapper.canAddJukeboxUpgrade() || this.stack.item is JukeboxUpgradeItem + is StackUpgradeItem -> wrapper.canAddStackUpgrade(item.multiplier()) || this.stack.item::class.java == item::class.java + is ExponentialStackUpgradeItem -> wrapper.canAddExponentialStackUpgrade() || this.stack.item is ExponentialStackUpgradeItem + is EverlastingUpgradeItem -> !wrapper.hasEverlastingJukeboxUpgrade() || this.stack.item is EverlastingUpgradeItem + is JukeboxUpgradeItem -> !wrapper.hasJukeboxUpgrade() || this.stack.item is JukeboxUpgradeItem else -> item is UpgradeItem } } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt index 9c1ee76..ddc2465 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt @@ -191,21 +191,24 @@ object CapabilityHandler { } fun cacheBackpackInventory(backpackWrapper: BackpackWrapper) { - if (BACKPACK_INVENTORY_CACHE.containsKey(backpackWrapper.uuid)) { + val uuid = backpackWrapper.uuid ?: return + + if (BACKPACK_INVENTORY_CACHE.containsKey(uuid)) { backpackWrapper.isCached = true return } - BACKPACK_INVENTORY_CACHE[backpackWrapper.uuid] = backpackWrapper + BACKPACK_INVENTORY_CACHE[uuid] = backpackWrapper backpackWrapper.isCached = true - RetroSophisticatedBackpacks.LOGGER.info("Backpack ${backpackWrapper.uuid} is cached") + RetroSophisticatedBackpacks.LOGGER.info("Backpack $uuid is cached") } fun updateBackpackInventory(backpackWrapper: BackpackWrapper) { - val backpack = BACKPACK_INVENTORY_CACHE[backpackWrapper.uuid] ?: return + val uuid = backpackWrapper.uuid ?: return + val backpack = BACKPACK_INVENTORY_CACHE[uuid] ?: return backpack.deserializeNBT(backpackWrapper.serializeNBT()) - RetroSophisticatedBackpacks.LOGGER.info("Backpack ${backpackWrapper.uuid} is updated") + RetroSophisticatedBackpacks.LOGGER.info("Backpack $uuid is updated") } private interface RefinedStorage : Capability.IStorage { diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt index c5f7a8c..6f982a2 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt @@ -11,7 +11,9 @@ import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGui import com.cleanroommc.retrosophisticatedbackpacks.config.Config import com.cleanroommc.retrosophisticatedbackpacks.item.BackpackItem import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.mixin.EntityAccessor import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket +import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.cast import net.minecraft.entity.EntityList import net.minecraft.entity.EntityLiving import net.minecraft.entity.EntityLivingBase @@ -21,6 +23,7 @@ import net.minecraft.inventory.EntityEquipmentSlot import net.minecraft.item.ItemStack import net.minecraft.util.EnumActionResult import net.minecraft.util.SoundCategory +import net.minecraftforge.event.entity.EntityJoinWorldEvent import net.minecraftforge.event.entity.living.LivingSpawnEvent import net.minecraftforge.event.entity.player.EntityItemPickupEvent import net.minecraftforge.event.entity.player.PlayerInteractEvent @@ -251,5 +254,26 @@ object EntityEventHandler { } } + @SubscribeEvent + @JvmStatic + fun onEntityJoinWorld(event: EntityJoinWorldEvent) { + val entity = event.entity + + if (entity is EntityItem) { + val stack = entity.item + val item = stack.item + + if (item is BackpackItem) { + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + + if (wrapper.hasEverlastingJukeboxUpgrade()) { + entity.setEntityInvulnerable(true) + entity.lifespan = Integer.MAX_VALUE + entity.cast().`rsb$setIsImmuneToFire`(true) + } + } + } + } + private data class BackpackChances(val backpack: BackpackItem, val spawnChance: Float, val dropChance: Float) } diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt index 3ed2a78..a451292 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt @@ -26,6 +26,8 @@ import com.cleanroommc.retrosophisticatedbackpacks.handler.CapabilityHandler import com.cleanroommc.retrosophisticatedbackpacks.handler.RegistryHandler import com.cleanroommc.retrosophisticatedbackpacks.util.IModelRegister import com.cleanroommc.retrosophisticatedbackpacks.util.Utils.asTranslationKey +import net.minecraft.block.BlockLiquid +import net.minecraft.block.state.IBlockState import net.minecraft.client.model.ModelBiped import net.minecraft.client.renderer.GlStateManager import net.minecraft.client.util.ITooltipFlag @@ -47,6 +49,7 @@ import net.minecraft.util.text.TextComponentTranslation import net.minecraft.util.text.TextFormatting import net.minecraft.world.World import net.minecraftforge.common.capabilities.ICapabilityProvider +import net.minecraftforge.fluids.IFluidBlock import net.minecraftforge.fml.common.Optional import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.SideOnly @@ -60,6 +63,13 @@ class BackpackItem( val numberOfUpgradeSlots: () -> Int, val tier: BackpackTier, ) : ItemBlock(backpackBlock), IModelRegister, IGuiHolder, IBauble, IRenderBauble { + companion object { + private const val FLOATING_HEIGHT = 0.25 + + private fun isFluid(state: IBlockState): Boolean = + state.material.isLiquid || state.block is BlockLiquid || state.block is IFluidBlock + } + // FIXME: Later when adding tank upgrade and its corresponding model, we should change this implementation to // hashmap, and the key would depends on the count of tanks upgrades private var cachedBipedModel: BackpackBipedModel? = null @@ -193,11 +203,59 @@ class BackpackItem( } override fun onEntityItemUpdate(entityItem: EntityItem): Boolean { + val wrapper = entityItem.item.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return false + if (entityItem.world.isRemote) { - val wrapper = entityItem.item.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return false BackpackSoundManager.transferPlayingOwnership(entityItem, null, wrapper) } + if (wrapper.hasEverlastingJukeboxUpgrade()) { + // Tries to levitate the item to the top of the void / fluid + val pos = BlockPos(entityItem.posX, entityItem.posY, entityItem.posZ) + val posBelow = BlockPos(entityItem.posX, entityItem.posY - 0.1, entityItem.posZ) + var targetY: Double? = null + + if (entityItem.posY <= FLOATING_HEIGHT) { + targetY = FLOATING_HEIGHT + } else if (isFluid(entityItem.world.getBlockState(pos)) || isFluid(entityItem.world.getBlockState(posBelow))) { + var topFluidPos = if (isFluid(entityItem.world.getBlockState(pos))) pos else posBelow + while (isFluid(entityItem.world.getBlockState(topFluidPos.up()))) { + topFluidPos = topFluidPos.up() + if (topFluidPos.y >= 256) break + } + targetY = topFluidPos.y.toDouble() + 1.0 + } + + if (targetY != null) { + entityItem.setNoGravity(true) + if (entityItem.posY < targetY) { + entityItem.motionY = 0.08 + } + if (entityItem.posY + entityItem.motionY >= targetY) { + if (targetY == FLOATING_HEIGHT) { + entityItem.setPosition(entityItem.posX, targetY, entityItem.posZ) + entityItem.motionX = .0 + entityItem.motionY = .0 + entityItem.motionZ = .0 + } else { + entityItem.setPosition(entityItem.posX, targetY, entityItem.posZ) + entityItem.motionY = .0 + } + } + } else { + entityItem.setNoGravity(false) + } + + // Spawns villager happy particles to indicate the everlasting upgrade is active + if (entityItem.world.isRemote && entityItem.world.rand.nextInt(8) == 0) { + val x = entityItem.posX + (entityItem.world.rand.nextDouble() - .5) * .6 + val y = entityItem.posY + entityItem.world.rand.nextDouble() * .6 + val z = entityItem.posZ + (entityItem.world.rand.nextDouble() - .5) * .6 + + entityItem.world.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, x, y, z, .0, .0, .0) + } + } + return super.onEntityItemUpdate(entityItem) } @@ -292,7 +350,7 @@ class BackpackItem( if (upgradeStack.isEmpty) continue - val upgradeWrapper = upgradeStack.getCapability(Capabilities.UPGRADE_CAPABILITY, null) ?: continue + val upgradeWrapper = upgradeStack.getCapability(Capabilities.UPGRADE_CAPABILITY, null) if (upgradeWrapper is IToggleable) { val toggledColor = if (upgradeWrapper.enabled) TextFormatting.GREEN else TextFormatting.RED @@ -306,7 +364,7 @@ class BackpackItem( ).formattedText ).setStyle(Style().setColor(TextFormatting.GRAY)).formattedText ) - } else { + } else if (upgradeStack.item is UpgradeItem) { tooltip.add( TextComponentTranslation( "tooltip.backpack.upgrade_slot.default".asTranslationKey(), diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/EverlastingUpgradeItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/EverlastingUpgradeItem.kt new file mode 100644 index 0000000..4724a45 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/EverlastingUpgradeItem.kt @@ -0,0 +1,3 @@ +package com.cleanroommc.retrosophisticatedbackpacks.item + +class EverlastingUpgradeItem(registryName: String) : UpgradeItem(registryName) diff --git a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt index 995da07..6e50f4f 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/Items.kt @@ -81,6 +81,9 @@ object Items { @JvmField val stackUpgradeTier4 = StackUpgradeItem("stack_upgrade_tier_4", Config.stackUpgrade::obsidianMultiplier) + + @JvmField + val everlastingUpgrade = EverlastingUpgradeItem("everlasting_upgrade") @JvmField val craftingUpgrade = CraftingUpgradeItem("crafting_upgrade") diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang index 0ac7488..1b2a055 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/en_us.lang @@ -13,6 +13,7 @@ item.retro_sophisticated_backpacks.stack_upgrade_tier_2.name=Stack Upgrade Tier item.retro_sophisticated_backpacks.stack_upgrade_tier_3.name=Stack Upgrade Tier 3 item.retro_sophisticated_backpacks.stack_upgrade_tier_4.name=Stack Upgrade Tier 4 item.retro_sophisticated_backpacks.exponential_stack_upgrade.name=Exponential Stack Upgrade +item.retro_sophisticated_backpacks.everlasting_upgrade.name=Everlasting Upgrade item.retro_sophisticated_backpacks.crafting_upgrade.name=Crafting Upgrade item.retro_sophisticated_backpacks.inception_upgrade.name=Inception Upgrade item.retro_sophisticated_backpacks.pickup_upgrade.name=Pickup Upgrade @@ -52,6 +53,8 @@ retro_sophisticated_backpacks.tooltip.stack_upgrade=Multiplies stack size by %d retro_sophisticated_backpacks.tooltip.exponential_stack_upgrade=Stack multipliers will stack by multiplying instead of adding +retro_sophisticated_backpacks.tooltip.everlasting_upgrade=Makes your backpack undestructible! + retro_sophisticated_backpacks.tooltip.crafting_upgrade=Adds additional crafting grid to side of backpack retro_sophisticated_backpacks.tooltip.inception_upgrade=Allows backpacks to be stored inside backpack diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang index 4562c6c..c7cb1af 100644 --- a/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang +++ b/src/main/resources/assets/retro_sophisticated_backpacks/lang/zh_tw.lang @@ -13,6 +13,7 @@ item.retro_sophisticated_backpacks.stack_upgrade_tier_2.name=堆疊升級 T2 item.retro_sophisticated_backpacks.stack_upgrade_tier_3.name=堆疊升級 T3 item.retro_sophisticated_backpacks.stack_upgrade_tier_4.name=堆疊升級 T4 item.retro_sophisticated_backpacks.exponential_stack_upgrade.name=指數堆疊升級 +item.retro_sophisticated_backpacks.everlasting_upgrade.name=永恆升級 item.retro_sophisticated_backpacks.crafting_upgrade.name=合成升級 item.retro_sophisticated_backpacks.inception_upgrade.name=嵌套升級 item.retro_sophisticated_backpacks.pickup_upgrade.name=拾取升級 @@ -52,6 +53,8 @@ retro_sophisticated_backpacks.tooltip.stack_upgrade=提供堆疊倍率 x%d retro_sophisticated_backpacks.tooltip.exponential_stack_upgrade=堆疊倍率會以相乘堆疊而非相加 +retro_sophisticated_backpacks.tooltip.everlasting_upgrade=讓你的背包堅不可摧! + retro_sophisticated_backpacks.tooltip.crafting_upgrade=在背包旁增加額外的合成欄 retro_sophisticated_backpacks.tooltip.inception_upgrade=允許將背包放入背包 diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/models/item/everlasting_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/everlasting_upgrade.json new file mode 100644 index 0000000..b022c53 --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/models/item/everlasting_upgrade.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "retro_sophisticated_backpacks:item/everlasting_upgrade" + } +} diff --git a/src/main/resources/assets/retro_sophisticated_backpacks/recipes/everlasting_upgrade.json b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/everlasting_upgrade.json new file mode 100644 index 0000000..64f7be5 --- /dev/null +++ b/src/main/resources/assets/retro_sophisticated_backpacks/recipes/everlasting_upgrade.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "key": { + "C": { + "item": "minecraft:end_crystal" + }, + "S": { + "type": "forge:ore_dict", + "ore": "netherStar" + }, + "B": { + "item": "retro_sophisticated_backpacks:upgrade_base" + } + }, + "pattern": [ + "CSC", + "SBS", + "CSC" + ], + "result": { + "item": "retro_sophisticated_backpacks:everlasting_upgrade" + } +} diff --git a/src/main/resources/mixin.retro_sophisticated_backpacks.json b/src/main/resources/mixin.retro_sophisticated_backpacks.json index 2d79ed8..45975f0 100644 --- a/src/main/resources/mixin.retro_sophisticated_backpacks.json +++ b/src/main/resources/mixin.retro_sophisticated_backpacks.json @@ -5,6 +5,7 @@ "minVersion": "0.8", "compatibilityLevel": "JAVA_8", "mixins": [ + "EntityAccessor", "EnumDyeColorAccessor" ], "client": [