diff --git a/README.md b/README.md index 2607f1a..d8d933c 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,12 @@ 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 - [x] stack upgrade - - [x] exponential stack upgrade (RSB exclusive) - [x] inception upgrade - [x] pickup upgrade (b/a) - [x] feeding upgrade (b/a) @@ -42,10 +42,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/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/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java index c8e8822..e4b4dd7 100644 --- a/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java +++ b/src/main/java/com/cleanroommc/retrosophisticatedbackpacks/capability/Capabilities.java @@ -44,6 +44,18 @@ 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; + + @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) public static final @NotNull Capability> UPGRADE_CAPABILITY = null; @@ -71,4 +83,10 @@ 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; + + @CapabilityInject(IJukeboxUpgrade.class) + public static final @NotNull Capability IJUKEBOX_UPGRADE_CAPABILITY = null; } 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/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/block/BackpackBlock.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt index 9604324..4fa60cf 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/block/BackpackBlock.kt @@ -3,7 +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.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 @@ -18,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 @@ -27,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 @@ -44,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) } @@ -155,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 @@ -173,10 +187,19 @@ 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()) + + if (worldIn.isRemote) + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Stationary( + C2CJukeboxUpgradePacket.PlayingAction.TRANSFER, + "", + tileEntity.getPos() + ) + ) if (stack.hasDisplayName()) tileEntity.setCustomName(stack.displayName) @@ -241,7 +264,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/capability/BackpackWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt index 94b7ad0..a50eefb 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/BackpackWrapper.kt @@ -1,11 +1,15 @@ package com.cleanroommc.retrosophisticatedbackpacks.capability import com.cleanroommc.retrosophisticatedbackpacks.backpack.SortType +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 import com.cleanroommc.retrosophisticatedbackpacks.item.StackUpgradeItem import com.cleanroommc.retrosophisticatedbackpacks.util.BackpackItemStackHelper import net.minecraft.entity.player.EntityPlayer @@ -16,12 +20,12 @@ 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( 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" @@ -43,7 +47,16 @@ class BackpackWrapper( const val DEFAULT_ACCENT_COLOR: Int = -0x9dd1e6 } + + 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) var upgradeItemStackHandler = UpgradeItemStackHandler(upgradeSlotsSize()) var sortType: SortType = SortType.BY_NAME @@ -128,6 +141,14 @@ class BackpackWrapper( return true } + + fun hasJukeboxUpgrade(): Boolean = + upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance() + .isNotEmpty() + + fun hasEverlastingJukeboxUpgrade(): Boolean = + upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance() + .isNotEmpty() fun canNestBackpack(): Boolean = upgradeItemStackHandler.inventory.map(ItemStack::getItem).filterIsInstance().any() @@ -162,20 +183,31 @@ class BackpackWrapper( fun canInsert(stack: ItemStack): Boolean { 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 { val stack = getStackInSlot(slotIndex) 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) } + } + + 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 } + + fun getJukeboxUpgrade(): IJukeboxUpgrade? = + gatherCapabilityUpgrades(Capabilities.IJUKEBOX_UPGRADE_CAPABILITY).firstOrNull() // Setting related @@ -256,6 +288,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) @@ -275,7 +309,6 @@ class BackpackWrapper( backpackItemStackHandler.sortLockedSlots.map { if (it) 1 else 0 }.map(Int::toByte).toByteArray() ) - nbt.setUniqueId(UUID_TAG, uuid) return nbt } @@ -285,7 +318,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/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/AdvancedJukeboxUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt new file mode 100644 index 0000000..de93498 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedJukeboxUpgradeWrapper.kt @@ -0,0 +1,123 @@ +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 predicate = { i: Int -> !records[i].isEmpty } + + val nextIndex = if (playByShuffle && playRepeat != RepeatType.ONE) { + indices.filter(predicate).randomOrNull() ?: -1 + } else { + when (playRepeat) { + RepeatType.NONE -> { + indices.drop(currentPlayingIndex + 1).find(predicate) ?: -1 + } + + RepeatType.ALL -> { + 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(predicate) + ?: indices.take(currentPlayingIndex + 1).find(predicate) ?: -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 predicate = { i: Int -> !records[i].isEmpty } + + val prevIndex = when (playRepeat) { + RepeatType.NONE -> { + (currentPlayingIndex - 1 downTo 0).find(predicate) ?: -1 + } + + RepeatType.ALL -> { + (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(predicate) + ?: (records.size - 1 downTo currentPlayingIndex).find(predicate) ?: -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/capability/upgrade/AdvancedVoidUpgradeWrapper.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt new file mode 100644 index 0000000..9e8671a --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/AdvancedVoidUpgradeWrapper.kt @@ -0,0 +1,39 @@ +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 + ): 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 || + 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/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/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/IVoidUpgrade.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt new file mode 100644 index 0000000..962d5b5 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/IVoidUpgrade.kt @@ -0,0 +1,64 @@ +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 +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 { + const val TRANSFER_SOURCE_TAG = "TransferSource" + + const val VOID_TYPE_TAG = "VoidType" + } + + var transferSource: TransferSource + var voidType: VoidType + + fun canVoid(stack: ItemStack, transferSource: TransferSource): Boolean + + fun tryVoid( + wrapper: BackpackWrapper, + inventory: ItemStackHandler, + stack: ItemStack, + transferSource: TransferSource + ): ItemStack { + if (!canVoid(stack, transferSource)) return stack + + return if (voidType == VoidType.OVERFLOW) { + var totalCount = 0 + for (i in 0 until inventory.slots) { + val s = inventory.getStackInSlot(i) + if (ItemHandlerHelper.canItemStacksStack(stack, s)) { + totalCount += s.count + } + } + + val maxCapacity = stack.maxStackSize * wrapper.getTotalStackMultiplier() + val canFit = maxCapacity - totalCount + + if (canFit <= 0) ItemStack.EMPTY + else if (stack.count <= canFit) stack + else ItemHandlerHelper.copyStackWithSize(stack, canFit) + } else ItemStack.EMPTY + } + + 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/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/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 +} 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..e2c4db9 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/capability/upgrade/VoidUpgradeWrapper.kt @@ -0,0 +1,42 @@ +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 + ): Boolean = + checkFilter(stack) && (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/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/client/gui/BackpackPanel.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/BackpackPanel.kt index 2ae4a7a..136557c 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) @@ -404,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. @@ -497,6 +506,58 @@ 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 AdvancedJukeboxUpgradeWrapper -> { + upgradeSlotGroup.updateJukeboxDelegate(wrapper) + if (updateAndCheckRecreation( + tabWidget.expandedWidget, + wrapper + ) + ) + tabWidget.expandedWidget = AdvancedJukeboxUpgradeWidget( + slotIndex, + backpackWrapper, + wrapper, + player, + tileEntity, + ) + } + + is JukeboxUpgradeWrapper -> { + upgradeSlotGroup.updateJukeboxDelegate(wrapper) + if (updateAndCheckRecreation( + tabWidget.expandedWidget, + wrapper + ) + ) + tabWidget.expandedWidget = JukeboxUpgradeWidget( + slotIndex, + backpackWrapper, + wrapper, + player, + tileEntity, + ) + } + is IAdvancedFilterable -> { upgradeSlotGroup.updateAdvancedFilterDelegate(wrapper) if (updateAndCheckRecreation>(tabWidget.expandedWidget, wrapper)) @@ -532,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 } } 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..09a75e6 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)) @@ -36,13 +39,26 @@ 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) 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 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) val IGNORE_ORE_DICT_ICON = icon("ignore_ore_dict", 128, 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 2c6da7a..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,13 +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.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.* class UpgradeSlotUpdateGroup( private val panel: BackpackPanel, @@ -39,6 +37,10 @@ class UpgradeSlotUpdateGroup( val craftingInfo: CraftingSlotInfo + // Jukebox slots + val jukeboxStackHandler = DelegatedStackHandlerSH(wrapper, slotIndex, 12) + var jukeboxSlots: Array + init { val syncManager = panel.syncManager @@ -139,6 +141,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) { @@ -156,4 +173,9 @@ class UpgradeSlotUpdateGroup( craftingStackHandler.syncToServer(DelegatedCraftingStackHandlerSH.UPDATE_CRAFTING) } + 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/CyclicVariantButtonWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/CyclicVariantButtonWidget.kt index a519dd4..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 @@ -67,4 +65,4 @@ class CyclicVariantButtonWidget( } data class Variant(val name: IKey, val drawable: IDrawable) -} \ No newline at end of file +} 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..0a01838 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/AdvancedJukeboxUpgradeWidget.kt @@ -0,0 +1,273 @@ +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 +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") + .tooltipStatic { + it.addLine(IKey.lang("gui.previous".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } + 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") + .tooltipStatic { + it.addLine(IKey.lang("gui.stop".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } + 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") + .tooltipStatic { + it.addLine(IKey.lang("gui.play".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } + 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") + .tooltipStatic { + it.addLine(IKey.lang("gui.next".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } + + 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/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/JukeboxUpgradeWidget.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt new file mode 100644 index 0000000..f8d2461 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/gui/widgets/upgrade/JukeboxUpgradeWidget.kt @@ -0,0 +1,116 @@ +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 +import com.cleanroommc.retrosophisticatedbackpacks.capability.BackpackWrapper +import com.cleanroommc.retrosophisticatedbackpacks.capability.upgrade.JukeboxUpgradeWrapper +import com.cleanroommc.retrosophisticatedbackpacks.client.gui.RSBTextures +import com.cleanroommc.retrosophisticatedbackpacks.handler.NetworkHandler +import com.cleanroommc.retrosophisticatedbackpacks.item.Items +import com.cleanroommc.retrosophisticatedbackpacks.network.C2CJukeboxUpgradePacket +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, + backpackWrapper: BackpackWrapper, + wrapper: JukeboxUpgradeWrapper, + playerEntity: EntityPlayer, + tileEntity: BackpackTileEntity? +) : + 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 { + if (tileEntity != null) { + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Stationary.stopPlaying(tileEntity.pos) + ) + } else { + NetworkHandler.INSTANCE.sendToServer( + C2CJukeboxUpgradePacket.Moving.stopPlaying(backpackWrapper) + ) + } + + 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) + val item = record.item + + if (record.isEmpty || item !is ItemRecord) + return@onMousePressed false + + 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 + ) + ) + } + + true + } + .overlay(RSBTextures.PLAY_ICON) + .tooltipStatic { + it.addLine(IKey.lang("gui.play".asTranslationKey())) + .pos(RichTooltip.Pos.NEXT_TO_MOUSE) + } + + buttonRow.child(stopButton) + .child(playButton) + + child(JukeboxSlotGroupsWidget) + .child(buttonRow) + } +} 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/client/sound/BackpackSoundManager.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt new file mode 100644 index 0000000..21ef88f --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/client/sound/BackpackSoundManager.kt @@ -0,0 +1,77 @@ +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) { + val previousSound = activeSounds[wrapper.uuid] + + if (previousSound != null) + Minecraft.getMinecraft().soundHandler.stopSound(previousSound) + + 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) + } + + 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/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/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/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..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,10 +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.StackUpgradeItem -import com.cleanroommc.retrosophisticatedbackpacks.item.UpgradeItem +import com.cleanroommc.retrosophisticatedbackpacks.item.* import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -49,8 +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 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 } -} \ No newline at end of file +} 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/handler/CapabilityHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt index 7229c69..ddc2465 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/CapabilityHandler.kt @@ -102,6 +102,30 @@ object CapabilityHandler { ::AdvancedFilterUpgradeWrapper ) + instance.register( + VoidUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::VoidUpgradeWrapper + ) + + instance.register( + AdvancedVoidUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::AdvancedVoidUpgradeWrapper + ) + + instance.register( + JukeboxUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::JukeboxUpgradeWrapper + ) + + instance.register( + AdvancedJukeboxUpgradeWrapper::class.java, + CapabilityStorageProvider(), + ::AdvancedJukeboxUpgradeWrapper + ) + // Interfaces instance.register( UpgradeWrapper::class.java, @@ -152,28 +176,39 @@ object CapabilityHandler { NOPCapabilityStorage(), ::FilterUpgradeWrapper ) + + instance.register( + IVoidUpgrade::class.java, + NOPCapabilityStorage(), + ::VoidUpgradeWrapper + ) + + instance.register( + IJukeboxUpgrade::class.java, + NOPCapabilityStorage(), + ::JukeboxUpgradeWrapper + ) } 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.put(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] - - if (backpack == null) { - 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 { @@ -224,4 +259,4 @@ object CapabilityHandler { instance.deserializeNBT(nbt as NBTTagCompound) } } -} \ No newline at end of file +} 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/handler/EntityEventHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt index 47131d0..6f982a2 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/EntityEventHandler.kt @@ -5,11 +5,15 @@ 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 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 @@ -19,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 @@ -60,6 +65,19 @@ object EntityEventHandler { val inventory = player.inventory var stack = event.item.item.copy() + if (stack.item is BackpackItem && !player.world.isRemote) { + val wrapper = stack.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return + NetworkHandler.INSTANCE.sendToDimension( + C2CJukeboxUpgradePacket.Moving( + C2CJukeboxUpgradePacket.PlayingAction.TRANSFER, + null, + wrapper, + player.entityId + ), + player.world.provider.dimension + ) + } + stack = attemptPickup(InvWrapper(inventory), stack) if (!stack.isEmpty && RetroSophisticatedBackpacks.baublesLoaded) { @@ -107,7 +125,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++ } @@ -231,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/handler/NetworkHandler.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/handler/NetworkHandler.kt index fbd54b2..707595a 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.C2CJukeboxUpgradePacket import com.cleanroommc.retrosophisticatedbackpacks.network.C2SOpenBackpackPacket import net.minecraftforge.fml.common.network.NetworkRegistry import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper @@ -23,5 +24,33 @@ object NetworkHandler { idGenerator.next(), Side.SERVER ) + + INSTANCE.registerMessage( + C2CJukeboxUpgradePacket.Moving.ServerHandler::class.java, + C2CJukeboxUpgradePacket.Moving::class.java, + idGenerator.next(), + Side.SERVER + ) + + INSTANCE.registerMessage( + 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/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/item/BackpackItem.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt index 2fc0695..a451292 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/item/BackpackItem.kt @@ -14,7 +14,9 @@ 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 import com.cleanroommc.retrosophisticatedbackpacks.common.gui.BackpackGuiHolder import com.cleanroommc.retrosophisticatedbackpacks.common.gui.PlayerInventoryGuiData @@ -24,11 +26,14 @@ 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 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 @@ -44,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 @@ -57,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 @@ -170,21 +183,80 @@ 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 } 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) + } + } + + override fun onEntityItemUpdate(entityItem: EntityItem): Boolean { + val wrapper = entityItem.item.getCapability(Capabilities.BACKPACK_CAPABILITY, null) ?: return false - // Only cache on server - if (!wrapper.isCached) - CapabilityHandler.cacheBackpackInventory(wrapper) + if (entityItem.world.isRemote) { + 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) } override fun isValidArmor(stack: ItemStack, armorType: EntityEquipmentSlot, entity: Entity): Boolean = @@ -200,8 +272,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 } @@ -269,6 +343,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) + + 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 if (upgradeStack.item is UpgradeItem) { + 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) } @@ -283,7 +387,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/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 a84cad0..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") @@ -117,4 +120,16 @@ 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) + + @JvmField + val jukeboxUpgrade = JukeboxUpgradeItem("jukebox_upgrade", ::JukeboxUpgradeWrapper) + + @JvmField + val advancedJukeboxUpgrade = JukeboxUpgradeItem("advanced_jukebox_upgrade", ::AdvancedJukeboxUpgradeWrapper) +} 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/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/network/C2CJukeboxUpgradePacket.kt b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/network/C2CJukeboxUpgradePacket.kt new file mode 100644 index 0000000..ef93237 --- /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/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..9008301 --- /dev/null +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/JukeboxSlotSH.kt @@ -0,0 +1,27 @@ +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.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 + + 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) + 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 295692b..2dd0245 100644 --- a/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt +++ b/src/main/kotlin/com/cleanroommc/retrosophisticatedbackpacks/sync/UpgradeSlotSH.kt @@ -2,19 +2,21 @@ 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.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 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 /** * 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 +25,19 @@ 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 + const val UPDATE_ADVANCED_JUKEBOX = 14 + } + + private var initialUpdated = false + + override fun onSlotUpdate(stack: ItemStack, onlyAmountChanged: Boolean, client: Boolean, init: Boolean) { + if (initialUpdated && stack.item !is JukeboxUpgradeItem) + NetworkHandler.INSTANCE.sendToServer(C2CJukeboxUpgradePacket.Moving.stopPlaying(wrapper)) + else + initialUpdated = true + + super.onSlotUpdate(stack, onlyAmountChanged, client, init) } override fun readOnServer(id: Int, buf: PacketBuffer) { @@ -36,6 +51,8 @@ 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) + UPDATE_ADVANCED_JUKEBOX -> updateAdvancedJukeboxUpgrade(buf) } } @@ -92,4 +109,19 @@ 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) + } + + 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/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( 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 } 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..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 @@ -25,6 +26,10 @@ 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 +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 @@ -37,6 +42,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! @@ -44,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 @@ -68,6 +79,14 @@ 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.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= # Gui Elements @@ -88,8 +107,13 @@ 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.jukebox_settings=Jukebox Interface + retro_sophisticated_backpacks.gui.memory_settings=Memory Settings retro_sophisticated_backpacks.gui.sorting_settings=Sorting Settings @@ -128,6 +152,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 @@ -137,6 +166,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 9f90e90..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=拾取升級 @@ -25,6 +26,10 @@ 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=進階虛空升級 +item.retro_sophisticated_backpacks.jukebox_upgrade.name=唱片機升級 +item.retro_sophisticated_backpacks.advanced_jukebox_upgrade.name=進階唱片機升級 # Creative Tabs itemGroup.retro_sophisticated_backpacks.creative_tab=復古精緻背包 @@ -37,6 +42,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=沒有效果!你大可放在升級插槽! @@ -44,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=允許將背包放入背包 @@ -68,6 +79,14 @@ 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.jukebox_upgrade=在背包中播放唱片! + +retro_sophisticated_backpacks.tooltip.advanced_jukebox_upgrade=在背包中播放唱片,還有更多選項! + retro_sophisticated_backpacks.tooltip.shift_to_reveal=<按 Shift 顯示> # Gui Elements @@ -88,8 +107,13 @@ 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.jukebox_settings=唱片機 + retro_sophisticated_backpacks.gui.memory_settings=記憶設定 retro_sophisticated_backpacks.gui.sorting_settings=整理設定 @@ -131,6 +155,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 整理 @@ -144,6 +173,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=設定介面 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" + } +} 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/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/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" + } +} 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/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/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" + } +} 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" + } +} 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": [