From c7a2c7f0f49660d7a8228eb8bf719b2fa192165d Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 28 Mar 2020 00:00:23 -0400 Subject: [PATCH] Add wooden hopper inventory interaction --- .../block/wood/WoodHopperBlockEntity.kt | 151 +++++++++++++++++- .../shadowfacts/extrahoppers/util/blockpos.kt | 8 + 2 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/net/shadowfacts/extrahoppers/util/blockpos.kt diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt index 8392fa7..b25bc44 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt @@ -1,10 +1,155 @@ package net.shadowfacts.extrahoppers.block.wood import net.minecraft.block.entity.BlockEntity +import net.minecraft.block.entity.Hopper +import net.minecraft.block.entity.HopperBlockEntity +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.inventory.Inventories +import net.minecraft.inventory.Inventory +import net.minecraft.inventory.SidedInventory +import net.minecraft.item.ItemStack +import net.minecraft.nbt.CompoundTag +import net.minecraft.util.DefaultedList import net.minecraft.util.Tickable +import net.minecraft.util.math.Direction import net.shadowfacts.extrahoppers.init.EHBlockEntities +import net.shadowfacts.extrahoppers.util.toVec3d -class WoodHopperBlockEntity: BlockEntity(EHBlockEntities.WOOD_HOPPER), Tickable { - override fun tick() { +class WoodHopperBlockEntity: BlockEntity(EHBlockEntities.WOOD_HOPPER), Inventory, Hopper, Tickable { + companion object { + val TRANSFER_COOLDOWN = 40 } -} \ No newline at end of file + + var inventory: DefaultedList = DefaultedList.ofSize(1, ItemStack.EMPTY) + private set + var transferCooldown = -1 + var lastTickTime = 0L + + override fun toTag(tag: CompoundTag): CompoundTag { + Inventories.toTag(tag, inventory) + tag.putInt("transferCooldown", transferCooldown) + return super.toTag(tag) + } + + override fun fromTag(tag: CompoundTag) { + super.fromTag(tag) + inventory.clear() + Inventories.fromTag(tag, inventory) + transferCooldown = tag.getInt("transferCooldown") + } + + override fun tick() { + val world = world + if (world == null || world.isClient) return + + transferCooldown -= 1 + lastTickTime = world.time + if (transferCooldown <= 0) { + transferCooldown = 0 + insertAndExtract() + } + } + + fun insertAndExtract() { + val world = world + if (world == null || world.isClient) return + + var didWork = false + if (!isInvEmpty && insert()) { + didWork = true + } + if (!isFull() && HopperBlockEntity.extract(this)) { + didWork = true + } + + if (didWork) { + transferCooldown = TRANSFER_COOLDOWN + markDirty() + } + } + + fun insert(): Boolean { + val outputInv = getOutputInventory() ?: return false + + val insertionSide = cachedState.get(WoodHopperBlock.FACING).opposite + if (isInventoryFull(outputInv, insertionSide)) return false + + for (slot in 0 until invSize) { + if (getInvStack(slot).isEmpty) continue + + val stackCopy = getInvStack(slot).copy() + + val remaining = HopperBlockEntity.transfer(this, outputInv, takeInvStack(slot, 1), insertionSide) + if (remaining.isEmpty) { + outputInv.markDirty() + return true + } + + setInvStack(slot, stackCopy) + } + + return false + } + + fun isFull(): Boolean { + return inventory.none(ItemStack::isEmpty) + } + + fun getOutputInventory(): Inventory? { + val facing = cachedState.get(WoodHopperBlock.FACING) + return HopperBlockEntity.getInventoryAt(world!!, pos.offset(facing)) + } + + fun inventorySlots(inv: Inventory, side: Direction): Sequence { + return if (inv is SidedInventory) { + inv.getInvAvailableSlots(side).asSequence() + } else { + (0 until inv.invSize).asSequence() + } + } + + fun isInventoryFull(inv: Inventory, side: Direction): Boolean { + val slots = inventorySlots(inv, side) + return slots.map(inv::getInvStack).none(ItemStack::isEmpty) + } + + // Inventory + + override fun getInvSize() = inventory.size + + override fun takeInvStack(slot: Int, amount: Int): ItemStack { + return Inventories.splitStack(inventory, slot, amount) + } + + override fun isInvEmpty() = inventory.isEmpty() + + override fun getInvStack(slot: Int) = inventory[slot] + + override fun clear() { + inventory.clear() + } + + override fun setInvStack(slot: Int, stack: ItemStack) { + inventory[slot] = stack + } + + override fun removeInvStack(slot: Int): ItemStack { + return Inventories.removeStack(inventory, slot) + } + + override fun canPlayerUseInv(player: PlayerEntity): Boolean { + return if (world?.getBlockEntity(pos) != this) { + false + } else { + val distance = player.squaredDistanceTo(this.pos.toVec3d()) + distance < 64 + } + } + + // Hopper + + override fun getHopperX() = pos.x.toDouble() + override fun getHopperY() = pos.y.toDouble() + override fun getHopperZ() = pos.z.toDouble() + +} diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/util/blockpos.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/util/blockpos.kt new file mode 100644 index 0000000..82e02d9 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/util/blockpos.kt @@ -0,0 +1,8 @@ +package net.shadowfacts.extrahoppers.util + +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Vec3d + +fun BlockPos.toVec3d(): Vec3d { + return Vec3d(x + 0.5, y + 0.5, z + 0.5) +}