diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/ModRecipes.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/ModRecipes.kt index 9de1281..7d91742 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/ModRecipes.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/ModRecipes.kt @@ -11,6 +11,7 @@ object ModRecipes { fun init() { GameRegistry.addRecipe(ShapedOreRecipe(ExtraHoppers.blocks.fluidHopper, "I I", "I I", " B ", 'I', "ingotIron", 'B', Items.BUCKET)) + GameRegistry.addRecipe(ShapedOreRecipe(ExtraHoppers.blocks.woodenHopper, "W W", "W W", " W ", 'W', "plankWood")) } } \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/ModBlocks.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/ModBlocks.kt index 58fa895..03d0fe9 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/block/ModBlocks.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/ModBlocks.kt @@ -2,6 +2,7 @@ package net.shadowfacts.extrahoppers.block import net.minecraft.block.Block import net.shadowfacts.extrahoppers.block.fluid.BlockFluidHopper +import net.shadowfacts.extrahoppers.block.wooden.BlockWoodenHopper import net.shadowfacts.shadowmc.block.ModBlocks /** @@ -10,9 +11,11 @@ import net.shadowfacts.shadowmc.block.ModBlocks object ModBlocks: ModBlocks() { val fluidHopper = BlockFluidHopper() + val woodenHopper = BlockWoodenHopper() override fun init() { register(fluidHopper) + register(woodenHopper) } override fun register(block: T): T { diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/BlockWoodenHopper.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/BlockWoodenHopper.kt new file mode 100644 index 0000000..c245fea --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/BlockWoodenHopper.kt @@ -0,0 +1,40 @@ +package net.shadowfacts.extrahoppers.block.wooden + +import net.minecraft.block.SoundType +import net.minecraft.block.material.Material +import net.minecraft.block.state.IBlockState +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.util.EnumFacing +import net.minecraft.util.EnumHand +import net.minecraft.util.math.BlockPos +import net.minecraft.world.World +import net.minecraftforge.fml.common.registry.GameRegistry +import net.shadowfacts.extrahoppers.ExtraHoppers +import net.shadowfacts.extrahoppers.block.base.BlockHopperBase +import net.shadowfacts.extrahoppers.gui.GUIHandler + +/** + * @author shadowfacts + */ +class BlockWoodenHopper: BlockHopperBase("wooden_hopper", Material.WOOD) { + + init { + setHardness(1.5f) + setResistance(4f) + soundType = SoundType.WOOD + } + + override fun onBlockActivated(world: World, pos: BlockPos, state: IBlockState, player: EntityPlayer, hand: EnumHand, facing: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean { + player.openGui(ExtraHoppers, GUIHandler.WOODEN_HOPPER, world, pos.x, pos.y, pos.z) + return true + } + + override fun registerTileEntity() { + GameRegistry.registerTileEntity(TileEntityWoodenHopper::class.java, registryName.toString()) + } + + override fun createTileEntity(world: World, state: IBlockState): TileEntityWoodenHopper { + return TileEntityWoodenHopper() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/ContainerWoodenHopper.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/ContainerWoodenHopper.kt new file mode 100644 index 0000000..ecf7b53 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/ContainerWoodenHopper.kt @@ -0,0 +1,32 @@ +package net.shadowfacts.extrahoppers.block.wooden + +import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.inventory.Slot +import net.minecraft.util.math.BlockPos +import net.minecraftforge.items.SlotItemHandler +import net.shadowfacts.shadowmc.inventory.ContainerBase + +/** + * @author shadowfacts + */ +class ContainerWoodenHopper(hopper: TileEntityWoodenHopper, playerInv: InventoryPlayer, pos: BlockPos): ContainerBase(pos) { + + init { + addSlotToContainer(object: SlotItemHandler(hopper.inventory, 0, 80, 21) { + override fun onSlotChanged() { + hopper.markDirty() + } + }) + + for (l in 0..2) { + for (k in 0..8) { + this.addSlotToContainer(Slot(playerInv, k + l * 9 + 9, 8 + k * 18, l * 18 + 52)) + } + } + + for (i1 in 0..8) { + this.addSlotToContainer(Slot(playerInv, i1, 8 + i1 * 18, 110)) + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/GUIWoodenHopper.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/GUIWoodenHopper.kt new file mode 100644 index 0000000..764b7e8 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/GUIWoodenHopper.kt @@ -0,0 +1,52 @@ +package net.shadowfacts.extrahoppers.block.wooden + +import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.inventory.Container +import net.minecraft.util.ResourceLocation +import net.shadowfacts.extrahoppers.MOD_ID +import net.shadowfacts.shadowmc.ui.dsl.* +import net.shadowfacts.shadowmc.ui.element.button.UIImage +import net.shadowfacts.shadowmc.ui.element.view.UIFixedView +import net.shadowfacts.shadowmc.ui.mcwrapper.UIContainerWrapper +import net.shadowfacts.shadowmc.ui.style.UIAttribute +import net.shadowfacts.shadowmc.ui.style.UIHorizontalLayoutMode +import net.shadowfacts.shadowmc.ui.style.UIVerticalLayoutMode + +/** + * @author shadowfacts + */ +class GUIWoodenHopper(container: Container): UIContainerWrapper(container) { + + private val BG = ResourceLocation(MOD_ID, "textures/gui/wooden_hopper.png") + + init { + val fixed = UIFixedView(176, 133, "root") + val bg = UIImage(BG, 176, 133, "bg") + fixed.add(bg) + add(fixed) + layout() + + xSize = 176 + ySize = 133 + } + +// private fun container(): GuiContainer + +// fun create(container: Container): GuiContainer { +// return container(container) { +// fixed { +// id = "root" +// width = 176 +// height = 133 +// +// image { +// id = "bg" +// width = 176 +// height = 133 +// texture = BG +// } +// } +// } +// } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/TileEntityWoodenHopper.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/TileEntityWoodenHopper.kt new file mode 100644 index 0000000..a87f8d0 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wooden/TileEntityWoodenHopper.kt @@ -0,0 +1,155 @@ +package net.shadowfacts.extrahoppers.block.wooden + +import net.minecraft.inventory.IInventory +import net.minecraft.inventory.ISidedInventory +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraft.util.ITickable +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY +import net.minecraftforge.items.ItemStackHandler +import net.shadowfacts.extrahoppers.block.base.TileEntityHopperBase +import net.shadowfacts.extrahoppers.util.insert +import net.shadowfacts.forgelin.extensions.get + +/** + * @author shadowfacts + */ +class TileEntityWoodenHopper: TileEntityHopperBase(), ITickable { + + companion object { + val COOLDOWN = 24 + } + + val inventory = ItemStackHandler(1) + + var cooldown: Int = COOLDOWN + + override fun update() { + if (!world.isRemote) { +// TODO: redstone + cooldown-- + if (cooldown <= 0) { + val pulled = pull() + val pushed = push() + + if (pulled || pushed) { + cooldown = COOLDOWN + markDirty() + } + } + } + } + + private fun push(): Boolean { + if (!inventory[0].isEmpty) { + val facing = getHopperFacing() + val tile = world.getTileEntity(pos.offset(facing)) + + if (tile is ISidedInventory) { + val slots = tile.getSlotsForFace(facing.opposite) + for (i in slots) { + val remainder = tile.insert(inventory.extractItem(0, 1, true), i) + if (remainder.isEmpty) { + inventory.extractItem(0, 1, false) + break + } + } + return true + } else if (tile is IInventory) { + for (i in 0.until(tile.sizeInventory)) { + val remainder = tile.insert(inventory.extractItem(0, 1, true), i) + if (remainder.isEmpty) { + inventory.extractItem(0, 1, false) + break + } + } + return true + } else if (tile != null && tile.hasCapability(ITEM_HANDLER_CAPABILITY, facing.opposite)) { + val handler = tile.getCapability(ITEM_HANDLER_CAPABILITY, facing.opposite)!! + for (i in 0.until(handler.slots)) { + val remainder = handler.insertItem(i, inventory.extractItem(0, 1, true), false) + if (remainder.isEmpty) { + inventory.extractItem(0, 1, false) + break + } + } + return true + } + } + return false + } + + private fun pull(): Boolean { + val tile = world.getTileEntity(pos.up()) + + if (tile is ISidedInventory) { + val slots = tile.getSlotsForFace(EnumFacing.DOWN) + for (i in slots) { + val current = tile[i] + if (!current.isEmpty) { + val copy = current.copy() + copy.count = 1 + val remainder = inventory.insertItem(0, copy, false) + if (remainder.isEmpty) { + current.shrink(1) + break + } + } + } + } else if (tile is IInventory) { + for (i in 0.until(tile.sizeInventory)) { + val current = tile[i] + if (!current.isEmpty) { + val copy = current.copy() + copy.count = 1 + val remainder = inventory.insertItem(0, copy, false) + if (remainder.isEmpty) { + current.shrink(1) + break + } + } + } + } else if (tile != null && tile.hasCapability(ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN)) { + val handler = tile.getCapability(ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN)!! + for (i in 0.until(handler.slots)) { + val remainder = inventory.insertItem(0, handler.extractItem(i, 1, true), false) + if (remainder.isEmpty) { + handler.extractItem(i, 1, false) + break + } + } + } + + return false + } + + override fun writeToNBT(tag: NBTTagCompound): NBTTagCompound { + tag.setTag("inventory", inventory.serializeNBT()) + tag.setInteger("cooldown", cooldown) + return super.writeToNBT(tag) + } + + override fun readFromNBT(tag: NBTTagCompound) { + inventory.deserializeNBT(tag.getCompoundTag("inventory")) + cooldown = tag.getInteger("cooldown") + super.readFromNBT(tag) + } + + override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean { + if (capability == ITEM_HANDLER_CAPABILITY) { + return facing == EnumFacing.UP || facing == getHopperFacing() + } + return super.hasCapability(capability, facing) + } + + override fun getCapability(capability: Capability, facing: EnumFacing?): T? { + if (capability == ITEM_HANDLER_CAPABILITY) { + if (facing == EnumFacing.UP || facing == getHopperFacing()) { + return inventory as T + } + } + return super.getCapability(capability, facing) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/gui/GUIHandler.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/gui/GUIHandler.kt index a910822..6e1c908 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/gui/GUIHandler.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/gui/GUIHandler.kt @@ -5,6 +5,9 @@ import net.minecraft.inventory.Container import net.minecraft.util.math.BlockPos import net.minecraft.world.World import net.minecraftforge.fml.common.network.IGuiHandler +import net.shadowfacts.extrahoppers.block.wooden.ContainerWoodenHopper +import net.shadowfacts.extrahoppers.block.wooden.GUIWoodenHopper +import net.shadowfacts.extrahoppers.block.wooden.TileEntityWoodenHopper /** * @author shadowfacts @@ -12,9 +15,11 @@ import net.minecraftforge.fml.common.network.IGuiHandler object GUIHandler: IGuiHandler { val FLUID_HOPPER = 0 + val WOODEN_HOPPER = 1 override fun getClientGuiElement(ID: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): Any? { return when (ID) { + WOODEN_HOPPER -> GUIWoodenHopper(getServerGuiElement(ID, player, world, x, y, z)!!) else -> null } } @@ -22,6 +27,7 @@ object GUIHandler: IGuiHandler { override fun getServerGuiElement(ID: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): Container? { val pos = BlockPos(x, y, z) return when (ID) { + WOODEN_HOPPER -> ContainerWoodenHopper(world.getTileEntity(pos) as TileEntityWoodenHopper, player.inventory, pos) else -> null } } diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/util/InventoryUtils.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/util/InventoryUtils.kt new file mode 100644 index 0000000..884c6be --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/util/InventoryUtils.kt @@ -0,0 +1,44 @@ +package net.shadowfacts.extrahoppers.util + +import net.minecraft.inventory.IInventory +import net.minecraft.item.ItemStack +import net.minecraftforge.items.ItemHandlerHelper +import net.shadowfacts.forgelin.extensions.get +import net.shadowfacts.forgelin.extensions.set + +/** + * @author shadowfacts + */ + +/** + * Attempts to insert the given [ItemStack] into this [IInventory] + * @param stack The stack to insert + * @param slot The slot to insert into + * @return The remained of the stack that couldn't been inserted + */ +fun IInventory.insert(stack: ItemStack, slot: Int): ItemStack { + if (stack.isEmpty) { + return stack + } + val existing = this[slot] + var limit = inventoryStackLimit + if (!existing.isEmpty) { + if (!ItemHandlerHelper.canItemStacksStack(stack, existing)) { + return stack + } + limit -= existing.count + } + + if (limit <= 0) { + return stack + } + + val reachedLimit = stack.count > limit + + if (existing.isEmpty) { + this[slot] = if (reachedLimit) ItemHandlerHelper.copyStackWithSize(stack, limit) else stack + } else { + existing.grow(if (reachedLimit) limit else stack.count) + } + return if (reachedLimit) ItemHandlerHelper.copyStackWithSize(stack, stack.count - limit) else ItemStack.EMPTY +} \ No newline at end of file diff --git a/src/main/resources/assets/extrahoppers/blockstates/wooden_hopper.json b/src/main/resources/assets/extrahoppers/blockstates/wooden_hopper.json new file mode 100644 index 0000000..e83c9e5 --- /dev/null +++ b/src/main/resources/assets/extrahoppers/blockstates/wooden_hopper.json @@ -0,0 +1,37 @@ +{ + "forge_marker": 1, + "defaults": { + "textures": { + "particle": "blocks/planks_oak", + "top": "blocks/planks_oak", + "side": "blocks/planks_oak", + "inside": "blocks/planks_oak" + } + }, + "variants": { + "inventory": { + "model": "hopper_down", + "transform": "forge:default-block" + }, + "facing": { + "down": { + "model": "hopper_down" + }, + "north": { + "model": "hopper_side" + }, + "south": { + "model": "hopper_side", + "y": 180 + }, + "west": { + "model": "hopper_side", + "y": 270 + }, + "east": { + "model": "hopper_side", + "y": 90 + } + } + } +} diff --git a/src/main/resources/assets/extrahoppers/lang/en_US.lang b/src/main/resources/assets/extrahoppers/lang/en_US.lang index e1054e6..d8cbb0d 100644 --- a/src/main/resources/assets/extrahoppers/lang/en_US.lang +++ b/src/main/resources/assets/extrahoppers/lang/en_US.lang @@ -1,5 +1,6 @@ tile.extrahoppers:fluid_hopper.name=Fluid Hopper tile.extrahoppers:fluid_hopper.tooltip=Formerly the Funnel +tile.extrahoppers:wooden_hopper.name=Wooden Hopper extrahoppers.config.gui.title=Extra Hoppers Config extrahoppers.config.gui.category.general=General \ No newline at end of file diff --git a/src/main/resources/assets/extrahoppers/textures/gui/wooden_hopper.png b/src/main/resources/assets/extrahoppers/textures/gui/wooden_hopper.png new file mode 100644 index 0000000..7037919 Binary files /dev/null and b/src/main/resources/assets/extrahoppers/textures/gui/wooden_hopper.png differ