Advanced hopper start and update to latest Forge

This commit is contained in:
Shadowfacts 2017-07-01 18:15:22 -04:00
parent b99726610f
commit a5545be406
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
40 changed files with 1043 additions and 475 deletions

View File

@ -54,7 +54,7 @@ repositories {
jcenter()
maven {
name "shadowfacts"
url "http://mvn.rx14.co.uk/shadowfacts/"
url "http://maven.shadowfacts.net/"
}
maven {
url "http://dvs1.progwml6.com/files/maven"

View File

@ -3,11 +3,11 @@ group = net.shadowfacts
archivesBaseName = ExtraHoppers
mc_version = 1.12
mcp_mappings = snapshot_20170615
forge_version = 14.21.0.2333
mcp_mappings = snapshot_20170701
forge_version = 14.21.1.2387
kotlin_version = 1.1.2-4
shadowmc_version = 3.8.0-SNAPSHOT
shadowmc_version = 3.8.1-SNAPSHOT
forgelin_version = 1.5.0
jei_version = 4.6.0.61
jei_version = 4.7.0.67

View File

@ -1,18 +1,23 @@
package net.shadowfacts.extrahoppers
import net.minecraft.block.Block
import net.minecraft.item.Item
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.RegistryEvent
import net.minecraftforge.fml.client.registry.ClientRegistry
import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.common.event.FMLMissingMappingsEvent
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.network.NetworkRegistry
import net.minecraftforge.fml.common.registry.GameRegistry
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
import net.shadowfacts.extrahoppers.block.ModBlocks
import net.shadowfacts.extrahoppers.block.advanced.TileEntityAdvancedHopper
import net.shadowfacts.extrahoppers.block.fluid.TESRFluidHopper
import net.shadowfacts.extrahoppers.block.fluid.TileEntityFluidHopper
import net.shadowfacts.extrahoppers.block.inverted.TileEntityInvertedHopper
import net.shadowfacts.extrahoppers.block.wooden.TileEntityWoodenHopper
import net.shadowfacts.extrahoppers.block.wooden_fluid.TileEntityWoodenFluidHopper
import net.shadowfacts.extrahoppers.event.ClientEventHandler
import net.shadowfacts.extrahoppers.gui.GUIHandler
@ -31,8 +36,6 @@ object ExtraHoppers {
EHConfig.init(event.modConfigurationDirectory)
EHConfig.save()
blocks.init()
NetworkRegistry.INSTANCE.registerGuiHandler(ExtraHoppers, GUIHandler)
}
@ -45,17 +48,51 @@ object ExtraHoppers {
MinecraftForge.EVENT_BUS.register(ClientEventHandler)
}
@Mod.EventHandler
fun missingMappings(event: FMLMissingMappingsEvent) {
event.get().forEach {
if (it.name == "funnels:funnel") {
if (it.type == GameRegistry.Type.BLOCK) {
it.remap(blocks.fluidHopper)
} else {
it.remap(Item.getItemFromBlock(blocks.fluidHopper))
}
}
@Mod.EventBusSubscriber
object RegistrationHandler {
@JvmStatic
@SubscribeEvent
fun registerBlocks(event: RegistryEvent.Register<Block>) {
event.registry.registerAll(
blocks.invertedHopper,
blocks.fluidHopper,
blocks.invertedFluidHopper,
blocks.advancedFluidHopper,
blocks.invertedAdvancedFluidHopper,
blocks.woodenHopper,
blocks.invertedWoodenHopper,
blocks.woodenFluidHopper,
blocks.invertedWoodenFluidHopper,
blocks.advancedHopper,
blocks.invertedAdvancedHopper
)
GameRegistry.registerTileEntity(TileEntityInvertedHopper::class.java, blocks.invertedHopper.registryName.toString())
GameRegistry.registerTileEntity(TileEntityFluidHopper::class.java, blocks.fluidHopper.registryName.toString())
GameRegistry.registerTileEntity(TileEntityWoodenHopper::class.java, blocks.woodenHopper.registryName.toString())
GameRegistry.registerTileEntity(TileEntityWoodenFluidHopper::class.java, blocks.woodenFluidHopper.registryName.toString())
GameRegistry.registerTileEntity(TileEntityAdvancedHopper::class.java, blocks.advancedHopper.registryName.toString())
}
@JvmStatic
@SubscribeEvent
fun registerItems(event: RegistryEvent.Register<Item>) {
event.registry.registerAll(
blocks.invertedHopper.createItemBlock(),
blocks.fluidHopper.createItemBlock(),
blocks.invertedFluidHopper.createItemBlock(),
blocks.advancedFluidHopper.createItemBlock(),
blocks.invertedAdvancedFluidHopper.createItemBlock(),
blocks.woodenHopper.createItemBlock(),
blocks.invertedWoodenHopper.createItemBlock(),
blocks.woodenFluidHopper.createItemBlock(),
blocks.invertedWoodenFluidHopper.createItemBlock(),
blocks.advancedHopper.createItemBlock(),
blocks.invertedAdvancedHopper.createItemBlock()
)
}
}
}

View File

@ -1,42 +1,26 @@
package net.shadowfacts.extrahoppers.block
import net.minecraftforge.fml.common.registry.GameRegistry
import net.shadowfacts.extrahoppers.block.advanced.BlockAdvancedHopper
import net.shadowfacts.extrahoppers.block.fluid.BlockFluidHopper
import net.shadowfacts.extrahoppers.block.fluid.TileEntityFluidHopper
import net.shadowfacts.extrahoppers.block.inverted.BlockInvertedHopper
import net.shadowfacts.extrahoppers.block.inverted.TileEntityInvertedHopper
import net.shadowfacts.extrahoppers.block.wooden.BlockWoodenHopper
import net.shadowfacts.extrahoppers.block.wooden.TileEntityWoodenHopper
import net.shadowfacts.extrahoppers.block.wooden_fluid.BlockWoodenFluidHopper
import net.shadowfacts.extrahoppers.block.wooden_fluid.TileEntityWoodenFluidHopper
import net.shadowfacts.shadowmc.block.ModBlocks
/**
* @author shadowfacts
*/
object ModBlocks: ModBlocks() {
object ModBlocks {
val invertedHopper = BlockInvertedHopper()
val fluidHopper = BlockFluidHopper(false)
val invertedFluidHopper = BlockFluidHopper(true)
val fluidHopper = BlockFluidHopper(false, false)
val invertedFluidHopper = BlockFluidHopper(true, false)
val advancedFluidHopper = BlockFluidHopper(false, true)
val invertedAdvancedFluidHopper = BlockFluidHopper(true, true)
val woodenHopper = BlockWoodenHopper(false)
val invertedWoodenHopper = BlockWoodenHopper(true)
val woodenFluidHopper = BlockWoodenFluidHopper(false)
val invertedWoodenFluidHopper = BlockWoodenFluidHopper(true)
override fun init() {
register(invertedHopper)
register(fluidHopper)
register(invertedFluidHopper)
register(woodenHopper)
register(invertedWoodenHopper)
register(woodenFluidHopper)
register(invertedWoodenFluidHopper)
GameRegistry.registerTileEntity(TileEntityInvertedHopper::class.java, invertedHopper.registryName.toString())
GameRegistry.registerTileEntityWithAlternatives(TileEntityFluidHopper::class.java, fluidHopper.registryName.toString(), "funnels:funnel")
GameRegistry.registerTileEntity(TileEntityWoodenHopper::class.java, woodenHopper.registryName.toString())
GameRegistry.registerTileEntity(TileEntityWoodenFluidHopper::class.java, woodenFluidHopper.registryName.toString())
}
val advancedHopper = BlockAdvancedHopper(false)
val invertedAdvancedHopper = BlockAdvancedHopper(true)
}

View File

@ -0,0 +1,45 @@
package net.shadowfacts.extrahoppers.block.advanced
import net.minecraft.block.SoundType
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.items.ItemHandlerHelper
import net.shadowfacts.extrahoppers.ExtraHoppers
import net.shadowfacts.extrahoppers.block.base.BlockHopperBase
import net.shadowfacts.extrahoppers.gui.GUIHandler
/**
* @author shadowfacts
*/
class BlockAdvancedHopper(inverted: Boolean): BlockHopperBase<TileEntityAdvancedHopper>(inverted, true, "hopper") {
init {
setHardness(3.5f)
setResistance(8f)
soundType = SoundType.METAL
}
@Deprecated("")
override fun hasComparatorInputOverride(state: IBlockState?): Boolean {
return true
}
@Deprecated("")
override fun getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int {
return ItemHandlerHelper.calcRedstoneFromInventory(getTileEntity(world, pos).inventory)
}
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.ADVANCED_HOPPER, world, pos.x, pos.y, pos.z)
return true
}
override fun createTileEntity(world: World, state: IBlockState): TileEntityAdvancedHopper {
return TileEntityAdvancedHopper(inverted)
}
}

View File

@ -0,0 +1,17 @@
package net.shadowfacts.extrahoppers.block.advanced
import net.minecraft.item.ItemStack
import net.shadowfacts.extrahoppers.block.inventory.TileEntityInventoryHopper
import net.shadowfacts.extrahoppers.util.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.ItemFilter
/**
* @author shadowfacts
*/
class TileEntityAdvancedHopper(inverted: Boolean): TileEntityInventoryHopper(inverted, true, 5) {
override var filter: Filter<ItemStack> = ItemFilter(6)
constructor(): this(false)
}

View File

@ -18,7 +18,7 @@ import net.shadowfacts.shadowmc.tileentity.BaseTileEntity
/**
* @author shadowfacts
*/
abstract class BlockHopperBase<out TE: BaseTileEntity>(val inverted: Boolean, name: String, material: Material = Material.ROCK): BlockTE<TE>(if (inverted) "inverted_$name" else name, material = material) {
abstract class BlockHopperBase<out TE: BaseTileEntity>(val inverted: Boolean, val advanced: Boolean, name: String, material: Material = Material.ROCK): BlockTE<TE>(getName(inverted, advanced, name), material = material) {
companion object {
val FACING: PropertyDirection = PropertyDirection.create("facing")
@ -28,6 +28,13 @@ abstract class BlockHopperBase<out TE: BaseTileEntity>(val inverted: Boolean, na
val NORTH_AABB = AxisAlignedBB(0.0, 0.0, 0.875, 1.0, 1.0, 1.0)
val WEST_AABB = AxisAlignedBB(0.875, 0.0, 0.0, 1.0, 1.0, 1.0)
val EAST_AABB = AxisAlignedBB(0.0, 0.0, 0.0, 0.125, 1.0, 1.0)
private fun getName(inverted: Boolean, advanced: Boolean, name: String): String {
var name = name
if (advanced) name = "advanced_$name"
if (inverted) name = "inverted_$name"
return name
}
}
init {

View File

@ -1,37 +0,0 @@
package net.shadowfacts.extrahoppers.block.base
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.extrahoppers.block.inverted.TileEntityInvertedHopper
import net.shadowfacts.shadowmc.inventory.ContainerBase
/**
* @author shadowfacts
*/
class ContainerInvertedHopper(hopper: TileEntityInvertedHopper, playerInv: InventoryPlayer, pos: BlockPos): ContainerBase(pos) {
init {
for (i in 0.until(hopper.inventory.slots)) {
addSlotToContainer(SlotHopper(hopper, i, 44 + i * 18, 21))
}
for (l in 0..2) {
for (k in 0..8) {
addSlotToContainer(Slot(playerInv, k + l * 9 + 9, 8 + k * 18, l * 18 + 52))
}
}
for (i1 in 0..8) {
addSlotToContainer(Slot(playerInv, i1, 8 + i1 * 18, 110))
}
}
private class SlotHopper(val hopper: TileEntityInvertedHopper, index: Int, x: Int, y: Int): SlotItemHandler(hopper.inventory, index, x, y) {
override fun onSlotChanged() {
hopper.markDirty()
}
}
}

View File

@ -2,30 +2,76 @@ package net.shadowfacts.extrahoppers.block.base
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
import net.shadowfacts.extrahoppers.util.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.FilterMode
import net.shadowfacts.shadowmc.ShadowMC
import net.shadowfacts.shadowmc.network.PacketRequestTEUpdate
import net.shadowfacts.shadowmc.tileentity.BaseTileEntity
import net.shadowfacts.shadowmc.util.RedstoneMode
/**
* @author shadowfacts
*/
abstract class TileEntityHopperBase(var inverted: Boolean): BaseTileEntity() {
abstract class TileEntityHopperBase<T>(var inverted: Boolean, var advanced: Boolean): BaseTileEntity() {
constructor(): this(false)
var mode = RedstoneMode.LOW
private var prevPowered = false
fun isPowered(): Boolean {
return world.isBlockPowered(pos)
var filterMode = FilterMode.WHITELIST
abstract var filter: Filter<T>
constructor(): this(false, false)
override fun onLoad() {
if (world.isRemote) {
ShadowMC.network.sendToServer(PacketRequestTEUpdate(this))
}
}
protected open fun checkRedstone(): Boolean {
val powered = world.isBlockPowered(pos)
if (advanced) {
val res = when (mode) {
RedstoneMode.LOW -> !powered
RedstoneMode.HIGH -> powered
RedstoneMode.PULSE -> !prevPowered && powered
RedstoneMode.NEVER -> false
else -> true
}
prevPowered = powered
return res
} else {
return !powered
}
}
fun getHopperFacing(): EnumFacing {
return world.getBlockState(pos).getValue(BlockHopperBase.FACING)
}
fun filterAccepts(it: T): Boolean {
if (!advanced) return true
return when (filterMode) {
FilterMode.WHITELIST -> filter.accepts(it)
FilterMode.BLACKLIST -> !filter.accepts(it)
}
}
override fun writeToNBT(tag: NBTTagCompound): NBTTagCompound {
tag.setBoolean("inverted", inverted)
tag.setBoolean("advanced", advanced)
tag.setString("mode", mode.name)
tag.setString("filterMode", filterMode.name)
filter.writeToNBT(tag)
return super.writeToNBT(tag)
}
override fun readFromNBT(tag: NBTTagCompound) {
inverted = tag.getBoolean("inverted")
advanced = tag.getBoolean("advanced")
if (tag.hasKey("mode")) mode = RedstoneMode.valueOf(tag.getString("mode"))
if (tag.hasKey("filterMode")) filterMode = FilterMode.valueOf(tag.getString("filterMode"))
filter.readFromNBT(tag)
super.readFromNBT(tag)
}

View File

@ -21,7 +21,7 @@ import net.shadowfacts.extrahoppers.gui.GUIHandler
/**
* @author shadowfacts
*/
open class BlockFluidHopper(inverted: Boolean, name: String = "fluid_hopper", material: Material = Material.IRON): BlockHopperBase<TileEntityFluidHopper>(inverted, name, material = material) {
open class BlockFluidHopper(inverted: Boolean, advanced: Boolean, name: String = "fluid_hopper", material: Material = Material.IRON): BlockHopperBase<TileEntityFluidHopper>(inverted, advanced, name, material = material) {
init {
setHardness(3.5f)
@ -35,7 +35,7 @@ open class BlockFluidHopper(inverted: Boolean, name: String = "fluid_hopper", ma
}
@Deprecated("")
override fun getComparatorInputOverride(blockState: IBlockState, world: World, pos: BlockPos): Int {
override fun getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int {
val tank = getTileEntity(world, pos).tank
if (tank.fluidAmount == 0) {
return 0
@ -57,11 +57,13 @@ open class BlockFluidHopper(inverted: Boolean, name: String = "fluid_hopper", ma
}
override fun addInformation(stack: ItemStack, world: World?, tooltip: MutableList<String>, flag: ITooltipFlag) {
tooltip.add(I18n.format("tile.extrahoppers:fluid_hopper.tooltip"))
if (!advanced) {
tooltip.add(I18n.format("tile.extrahoppers:fluid_hopper.tooltip"))
}
}
override fun createTileEntity(world: World, state: IBlockState): TileEntityFluidHopper {
return TileEntityFluidHopper(inverted)
return TileEntityFluidHopper(inverted, advanced)
}
}

View File

@ -4,6 +4,7 @@ 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.extrahoppers.gui.element.UIFilterButton
import net.shadowfacts.extrahoppers.gui.element.UIFluidIndicator
import net.shadowfacts.shadowmc.ui.dsl.container
@ -34,6 +35,21 @@ object GUIFluidHopper {
height = 166 / 2
add(UIFluidIndicator(hopper.tank, "fluidIndicator"))
if (hopper.advanced) {
buttonRedstoneMode {
id = "mode"
mode = hopper.mode
callback = {
hopper.mode = it
hopper.sync()
}
}
add(UIFilterButton({
// TODO
}, "filter"))
}
}
}

View File

@ -15,7 +15,7 @@ import org.lwjgl.opengl.GL11
*/
object TESRFluidHopper: TileEntitySpecialRenderer<TileEntityFluidHopper>() {
override fun renderTileEntityAt(te: TileEntityFluidHopper, x: Double, y: Double, z: Double, partialTicks: Float, destroyStage: Int, alpha: Float) {
override fun render(te: TileEntityFluidHopper, x: Double, y: Double, z: Double, partialTicks: Float, destroyStage: Int, alpha: Float) {
val pos = if (te.inverted) te.pos.down() else te.pos.up()
if (te.tank.fluid != null && !te.world.getBlockState(pos).isSideSolid(te.world, pos, EnumFacing.DOWN)) {

View File

@ -13,6 +13,8 @@ import net.minecraftforge.fml.common.network.NetworkRegistry
import net.shadowfacts.extrahoppers.EHConfig
import net.shadowfacts.extrahoppers.block.base.TileEntityHopperBase
import net.shadowfacts.extrahoppers.util.FluidUtils
import net.shadowfacts.extrahoppers.util.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.FluidFilter
import net.shadowfacts.shadowmc.ShadowMC
import net.shadowfacts.shadowmc.network.PacketRequestTEUpdate
import net.shadowfacts.shadowmc.network.PacketUpdateTE
@ -20,21 +22,24 @@ import net.shadowfacts.shadowmc.network.PacketUpdateTE
/**
* @author shadowfacts
*/
open class TileEntityFluidHopper(inverted: Boolean): TileEntityHopperBase(inverted), ITickable {
constructor(): this(false)
open class TileEntityFluidHopper(inverted: Boolean, advanced: Boolean): TileEntityHopperBase<FluidStack>(inverted, advanced), ITickable {
companion object {
val HANDLER_COOLDOWN = 8
val WORLD_COOLDOWN = 40
}
override var filter: Filter<FluidStack> = FluidFilter(6)
constructor(): this(false, false)
internal var tank = object: FluidTank(EHConfig.fhSize) {
override fun onContentsChanged() {
save()
}
override fun canFillFluidType(fluid: FluidStack?): Boolean {
// return fluid == null || (fluidValiator(fluid) && filterAccepts(fluid))
return fluid == null || fluidValiator(fluid)
}
}
@ -57,14 +62,14 @@ open class TileEntityFluidHopper(inverted: Boolean): TileEntityHopperBase(invert
override fun update() {
if (!world.isRemote) {
if (isPowered()) return
handlerCooldown--
worldCooldown--
if (!checkRedstone()) return
if (handlerCooldown <= 0) {
handleFluidHandlers()
}
worldCooldown--
if (worldCooldown <= 0) {
handleWorld()
}

View File

@ -0,0 +1,65 @@
package net.shadowfacts.extrahoppers.block.inventory
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.ClickType
import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
import net.minecraft.util.math.BlockPos
import net.minecraftforge.items.SlotItemHandler
import net.shadowfacts.extrahoppers.util.SlotItemFilter
import net.shadowfacts.shadowmc.inventory.ContainerBase
/**
* @author shadowfacts
*/
class ContainerInventoryHopper(val hopper: TileEntityInventoryHopper, playerInv: InventoryPlayer, pos: BlockPos): ContainerBase(pos) {
init {
for (i in 0.until(hopper.inventory.slots)) {
addSlotToContainer(SlotHopper(hopper, i, 44 + i * 18, 21))
}
for (i in 0..2) {
addSlotToContainer(SlotItemFilter(hopper, i, -62 + i * 18, 12))
}
for (i in 0..2) {
addSlotToContainer(SlotItemFilter(hopper, i + 3, -62 + i * 18, 33))
}
for (l in 0..2) {
for (k in 0..8) {
addSlotToContainer(Slot(playerInv, k + l * 9 + 9, 8 + k * 18, l * 18 + 52))
}
}
for (i1 in 0..8) {
addSlotToContainer(Slot(playerInv, i1, 8 + i1 * 18, 110))
}
}
override fun slotClick(id: Int, dragType: Int, type: ClickType, player: EntityPlayer): ItemStack {
if (id in hopper.inventory.slots..hopper.inventory.slots + 5) {
if (type == ClickType.PICKUP || type == ClickType.PICKUP_ALL || type == ClickType.SWAP) {
hopper.filter.setFromStack(id - hopper.inventory.slots, player.inventory.itemStack)
hopper.markDirty()
}
return ItemStack.EMPTY
}
return super.slotClick(id, dragType, type, player)
}
override fun transferStackInSlot(player: EntityPlayer, index: Int): ItemStack {
if (index in hopper.inventory.slots..hopper.inventory.slots + 5) {
return ItemStack.EMPTY
}
return super.transferStackInSlot(player, index)
}
private class SlotHopper(val hopper: TileEntityInventoryHopper, index: Int, x: Int, y: Int): SlotItemHandler(hopper.inventory, index, x, y) {
override fun onSlotChanged() {
hopper.markDirty()
}
}
}

View File

@ -0,0 +1,80 @@
package net.shadowfacts.extrahoppers.block.inventory
import net.minecraft.inventory.Container
import net.minecraft.inventory.Slot
import net.minecraft.util.ResourceLocation
import net.shadowfacts.extrahoppers.MOD_ID
import net.shadowfacts.extrahoppers.gui.element.UIFilterButton
import net.shadowfacts.extrahoppers.util.filter.FilterMode
import net.shadowfacts.extrahoppers.util.filter.ItemFilter
import net.shadowfacts.shadowmc.ui.element.UIRect
import net.shadowfacts.shadowmc.ui.element.button.UIButtonEnum
import net.shadowfacts.shadowmc.ui.element.button.UIButtonRedstoneMode
import net.shadowfacts.shadowmc.ui.element.button.UIImage
import net.shadowfacts.shadowmc.ui.element.view.UIFixedView
import net.shadowfacts.shadowmc.ui.element.view.UIStackView
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
import net.shadowfacts.shadowmc.ui.style.stylesheet.StylesheetParser
import java.util.function.Consumer
import java.util.function.Function
/**
* @author shadowfacts
*/
class GUIInventoryHopper(container: Container, tile: TileEntityInventoryHopper): UIContainerWrapper(container) {
private val BG = ResourceLocation("minecraft", "textures/gui/container/hopper.png")
private val FILTER_BG = ResourceLocation(MOD_ID, "textures/gui/filter.png")
init {
add(UIFixedView(176 + 83 * 2, 133, "root").apply {
add(UIImage(BG, 176, 133, "bg"))
if (tile.advanced) {
add(UIFixedView(176, 60, "top").apply {
add(UIFilterButton({
// TODO
}, "filter"))
add(UIButtonRedstoneMode(tile.mode, Consumer {
tile.mode = it
tile.sync()
}, "mode"))
})
add(UIFixedView(83, 86, "filter-container").apply {
add(UIImage(FILTER_BG, 83, 86, "filter-bg"))
// add(UIFixedView(52, 37, "filter-slots").apply {
// for (i in 0..2) {
// add(UIItemFilterSlot(tile, i, "filter-slot-$i", "filter-slot-top"))
// }
// for (i in 3..5) {
// add(UIItemFilterSlot(tile, i, "filter-slot-$i", "filter-slot-bottom"))
// }
// })
add(UIFixedView(83, 34, "filter-bottom").apply {
add(UIButtonEnum<FilterMode>(tile.filterMode, Function(FilterMode::localize), Consumer {
tile.filterMode = it.value
tile.sync()
}, "filter-mode"))
})
})
}
})
val style = StylesheetParser.load("$MOD_ID:inventory_hopper")
val sheet = StylesheetParser.parse(style)
children.forEach(sheet::style)
layout()
xSize = 176
ySize = 133
}
}

View File

@ -0,0 +1,207 @@
package net.shadowfacts.extrahoppers.block.inventory
import net.minecraft.entity.item.EntityItem
import net.minecraft.inventory.IInventory
import net.minecraft.inventory.ISidedInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
import net.minecraft.util.ITickable
import net.minecraft.util.math.AxisAlignedBB
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.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.ItemFilter
import net.shadowfacts.extrahoppers.util.insert
import net.shadowfacts.forgelin.extensions.get
import net.shadowfacts.forgelin.extensions.isEmpty
/**
* @author shadowfacts
*/
abstract class TileEntityInventoryHopper(inverted: Boolean, advanced: Boolean, size: Int): TileEntityHopperBase<ItemStack>(inverted, advanced), ITickable {
companion object {
val COOLDOWN = 8
}
val inventory = object: ItemStackHandler(size) {
override fun insertItem(slot: Int, stack: ItemStack, simulate: Boolean): ItemStack {
if (!filterAccepts(stack)) return stack
return super.insertItem(slot, stack, simulate)
}
}
var cooldown = COOLDOWN
val box by lazy {
if (inverted) {
AxisAlignedBB(pos.x - 0.5, pos.y - 1.5, pos.z - 0.5, pos.x + 0.5, pos.y.toDouble(), pos.z + 0.5)
} else {
AxisAlignedBB(pos.x - 0.5, pos.y.toDouble(), pos.z - 0.5, pos.x + 0.5, pos.y + 1.5, pos.z + 0.5)
}
}
override fun writeToNBT(tag: NBTTagCompound): NBTTagCompound {
tag.setTag("inventory", inventory.serializeNBT())
return super.writeToNBT(tag)
}
override fun readFromNBT(tag: NBTTagCompound) {
inventory.deserializeNBT(tag.getCompoundTag("inventory"))
super.readFromNBT(tag)
}
override fun update() {
if (!world.isRemote) {
cooldown--
if (!checkRedstone()) return
if (cooldown <= 0) {
val pulled = pull()
val pushed = push()
if (pulled || pushed) {
cooldown = COOLDOWN
markDirty()
}
}
}
}
private fun push(): Boolean {
if (!inventory.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) {
for (slot in 0.until(inventory.slots)) {
if (inventory[slot].isEmpty) continue
val remainder = tile.insert(inventory.extractItem(slot, 1, true), i)
if (remainder.isEmpty) {
inventory.extractItem(slot, 1, false)
return true
}
}
}
} else if (tile is IInventory) {
for (i in 0.until(tile.sizeInventory)) {
for (slot in 0.until(inventory.slots)) {
if (inventory[slot].isEmpty) continue
val remainder = tile.insert(inventory.extractItem(slot, 1, true), i)
if (remainder.isEmpty) {
inventory.extractItem(slot, 1, false)
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)) {
for (slot in 0.until(inventory.slots)) {
if (inventory[slot].isEmpty) continue
val remainder = handler.insertItem(i, inventory.extractItem(slot, 1, true), false)
if (remainder.isEmpty) {
inventory.extractItem(slot, 1, false)
return true
}
}
}
}
}
return false
}
private fun pull(): Boolean {
val items = world.getEntitiesWithinAABB(EntityItem::class.java, box)
for (item in items) {
for (slot in 0.until(inventory.slots)) {
val result = inventory.insertItem(slot, item.item, true)
if (result.count != item.item.count) {
inventory.insertItem(slot, item.item, false)
if (result.isEmpty) {
item.setDead()
} else {
item.item = result
}
return true
}
}
}
// val facing = getHopperFacing()
val side = if (inverted) EnumFacing.DOWN else EnumFacing.UP
val tile = world.getTileEntity(pos.offset(side))
if (tile is ISidedInventory) {
val slots = tile.getSlotsForFace(side.opposite)
for (i in slots) {
for (slot in 0.until(inventory.slots)) {
val current = tile[i]
if (!current.isEmpty) {
val copy = current.copy()
copy.count = 1
val remainder = inventory.insertItem(slot, copy, false)
if (remainder.isEmpty) {
current.shrink(1)
return true
}
}
}
}
} else if (tile is IInventory) {
for (i in 0.until(tile.sizeInventory)) {
for (slot in 0.until(inventory.slots)) {
val current = tile[i]
if (!current.isEmpty) {
val copy = current.copy()
copy.count = 1
val remainder = inventory.insertItem(slot, copy, false)
if (remainder.isEmpty) {
current.shrink(1)
return true
}
}
}
}
} else if (tile != null && tile.hasCapability(ITEM_HANDLER_CAPABILITY, side.opposite)) {
val handler = tile.getCapability(ITEM_HANDLER_CAPABILITY, side.opposite)!!
for (i in 0.until(handler.slots)) {
for (slot in 0.until(inventory.slots)) {
val remainder = inventory.insertItem(slot, handler.extractItem(i, 1, true), false)
if (remainder.isEmpty()) {
handler.extractItem(i, 1, false)
return true
}
}
}
}
return false
}
override fun hasCapability(capability: Capability<*>, facing: EnumFacing?): Boolean {
if (capability == ITEM_HANDLER_CAPABILITY) {
val side = if (inverted) EnumFacing.DOWN else EnumFacing.UP
return facing == side || facing == getHopperFacing()
}
return super.hasCapability(capability, facing)
}
override fun <T: Any?> getCapability(capability: Capability<T>, facing: EnumFacing?): T? {
if (capability == ITEM_HANDLER_CAPABILITY) {
val side = if (inverted) EnumFacing.DOWN else EnumFacing.UP
if (facing == side || facing == getHopperFacing()) {
return inventory as T
}
}
return super.getCapability(capability, facing)
}
}

View File

@ -16,7 +16,7 @@ import net.shadowfacts.extrahoppers.gui.GUIHandler
/**
* @author shadowfacts
*/
class BlockInvertedHopper: BlockHopperBase<TileEntityInvertedHopper>(true, "hopper", Material.IRON) {
class BlockInvertedHopper: BlockHopperBase<TileEntityInvertedHopper>(true, false, "hopper", Material.IRON) {
init {
setHardness(3.5f)
@ -30,7 +30,7 @@ class BlockInvertedHopper: BlockHopperBase<TileEntityInvertedHopper>(true, "hopp
}
@Deprecated("")
override fun getComparatorInputOverride(blockState: IBlockState, world: World, pos: BlockPos): Int {
override fun getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int {
return ItemHandlerHelper.calcRedstoneFromInventory(getTileEntity(world, pos).inventory)
}

View File

@ -1,26 +0,0 @@
package net.shadowfacts.extrahoppers.block.inverted
import net.minecraft.inventory.Container
import net.minecraft.util.ResourceLocation
import net.shadowfacts.shadowmc.ui.element.button.UIImage
import net.shadowfacts.shadowmc.ui.element.view.UIFixedView
import net.shadowfacts.shadowmc.ui.mcwrapper.UIContainerWrapper
/**
* @author shadowfacts
*/
class GUIInvertedHopper(container: Container): UIContainerWrapper(container) {
private val BG = ResourceLocation("minecraft", "textures/gui/container/hopper.png")
init {
add(UIFixedView(176, 133, "root").apply {
add(UIImage(BG, 176, 133, "bg"))
})
layout()
xSize = 176
ySize = 133
}
}

View File

@ -1,184 +1,15 @@
package net.shadowfacts.extrahoppers.block.inverted
import net.minecraft.entity.item.EntityItem
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.minecraft.util.math.AxisAlignedBB
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
import net.shadowfacts.forgelin.extensions.isEmpty
import net.minecraft.item.ItemStack
import net.shadowfacts.extrahoppers.block.inventory.TileEntityInventoryHopper
import net.shadowfacts.extrahoppers.util.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.NoOpFilter
/**
* @author shadowfacts
*/
class TileEntityInvertedHopper: TileEntityHopperBase(true), ITickable {
class TileEntityInvertedHopper: TileEntityInventoryHopper(true, false, 5) {
companion object {
val COOLDOWN = 8
}
val inventory = ItemStackHandler(5)
var cooldown = COOLDOWN
override fun update() {
if (!world.isRemote) {
if (isPowered()) return
cooldown--
if (cooldown <= 0) {
val pulled = pull()
val pushed = push()
if (pulled || pushed) {
cooldown = COOLDOWN
markDirty()
}
}
}
}
private fun push(): Boolean {
if (!inventory.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) {
for (slot in 0.until(inventory.slots)) {
val remainder = tile.insert(inventory.extractItem(slot, 1, true), i)
if (remainder.isEmpty) {
inventory.extractItem(slot, 1, false)
return true
}
}
}
} else if (tile is IInventory) {
for (i in 0.until(tile.sizeInventory)) {
for (slot in 0.until(inventory.slots)) {
val remainder = tile.insert(inventory.extractItem(slot, 1, true), i)
if (remainder.isEmpty) {
inventory.extractItem(slot, 1, false)
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)) {
for (slot in 0.until(inventory.slots)) {
val remainder = handler.insertItem(i, inventory.extractItem(slot, 1, true), false)
if (remainder.isEmpty) {
inventory.extractItem(slot, 1, false)
return true
}
}
}
}
}
return false
}
private fun pull(): Boolean {
val items = world.getEntitiesWithinAABB(EntityItem::class.java, AxisAlignedBB(pos.x.toDouble(), pos.y - 0.5, pos.z.toDouble(), pos.x + 1.0, pos.y + 0.5, pos.z + 1.0))
for (item in items) {
for (slot in 0.until(inventory.slots)) {
val result = inventory.insertItem(slot, item.item, true)
if (result.count != item.item.count) {
inventory.insertItem(slot, item.item, false)
if (result.isEmpty) {
item.setDead()
} else {
item.item = result
}
return true
}
}
}
val tile = world.getTileEntity(pos.down())
if (tile is ISidedInventory) {
val slots = tile.getSlotsForFace(EnumFacing.UP)
for (i in slots) {
for (slot in 0.until(inventory.slots)) {
val current = tile[i]
if (!current.isEmpty) {
val copy = current.copy()
copy.count = 1
val remainder = inventory.insertItem(slot, copy, false)
if (remainder.isEmpty) {
current.shrink(1)
return true
}
}
}
}
} else if (tile is IInventory) {
for (i in 0.until(tile.sizeInventory)) {
for (slot in 0.until(inventory.slots)) {
val current = tile[i]
if (!current.isEmpty) {
val copy = current.copy()
copy.count = 1
val remainder = inventory.insertItem(slot, copy, false)
if (remainder.isEmpty) {
current.shrink(1)
return true
}
}
}
}
} else if (tile != null && tile.hasCapability(ITEM_HANDLER_CAPABILITY, EnumFacing.UP)) {
val handler = tile.getCapability(ITEM_HANDLER_CAPABILITY, EnumFacing.UP)!!
for (i in 0.until(handler.slots)) {
for (slot in 0.until(inventory.slots)) {
val remainder = inventory.insertItem(slot, handler.extractItem(i, 1, true), false)
if (remainder.isEmpty) {
handler.extractItem(i, 1, false)
return true
}
}
}
}
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.DOWN || facing == getHopperFacing()
}
return super.hasCapability(capability, facing)
}
override fun <T: Any?> getCapability(capability: Capability<T>, facing: EnumFacing?): T? {
if (capability == ITEM_HANDLER_CAPABILITY) {
if (facing == EnumFacing.DOWN || facing == getHopperFacing()) {
return inventory as T
}
}
return super.getCapability(capability, facing)
}
override var filter: Filter<ItemStack> = NoOpFilter
}

View File

@ -15,7 +15,7 @@ import net.shadowfacts.extrahoppers.gui.GUIHandler
/**
* @author shadowfacts
*/
class BlockWoodenHopper(inverted: Boolean): BlockHopperBase<TileEntityWoodenHopper>(inverted, "wooden_hopper", Material.WOOD) {
class BlockWoodenHopper(inverted: Boolean): BlockHopperBase<TileEntityWoodenHopper>(inverted, false, "wooden_hopper", Material.WOOD) {
init {
setHardness(1.5f)

View File

@ -1,173 +1,18 @@
package net.shadowfacts.extrahoppers.block.wooden
import net.minecraft.entity.item.EntityItem
import net.minecraft.inventory.IInventory
import net.minecraft.inventory.ISidedInventory
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
import net.minecraft.item.ItemStack
import net.minecraft.util.ITickable
import net.minecraft.util.math.AxisAlignedBB
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
import net.shadowfacts.extrahoppers.block.inventory.TileEntityInventoryHopper
import net.shadowfacts.extrahoppers.util.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.NoOpFilter
/**
* @author shadowfacts
*/
class TileEntityWoodenHopper(inverted: Boolean): TileEntityHopperBase(inverted), ITickable {
class TileEntityWoodenHopper(inverted: Boolean): TileEntityInventoryHopper(inverted, false, 1), ITickable {
companion object {
val COOLDOWN = 24
}
val inventory = ItemStackHandler(1)
var cooldown = COOLDOWN
override var filter: Filter<ItemStack> = NoOpFilter
constructor(): this(false)
override fun update() {
if (!world.isRemote) {
if (isPowered()) return
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)
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)
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)
return true
}
}
}
}
return false
}
private fun pull(): Boolean {
val yOffset = if (inverted) -1 else 0
val items = world.getEntitiesWithinAABB(EntityItem::class.java, AxisAlignedBB(pos.x.toDouble(), pos.y + 0.5 + yOffset, pos.z.toDouble(), pos.x + 1.0, pos.y + 1.5 + yOffset, pos.z + 1.0))
for (item in items) {
val result = inventory.insertItem(0, item.item, true)
if (result.count != item.item.count) {
inventory.insertItem(0, item.item, false)
if (result.isEmpty) {
item.setDead()
} else {
item.item = result
}
return true
}
}
val tile = world.getTileEntity(if (inverted) pos.down() else pos.up())
val side = if (inverted) EnumFacing.UP else EnumFacing.DOWN
if (tile is ISidedInventory) {
val slots = tile.getSlotsForFace(side)
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)
return true
}
}
}
} 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)
return true
}
}
}
} else if (tile != null && tile.hasCapability(ITEM_HANDLER_CAPABILITY, side)) {
val handler = tile.getCapability(ITEM_HANDLER_CAPABILITY, side)!!
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)
return true
}
}
}
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 == (if (inverted) EnumFacing.DOWN else EnumFacing.UP) || facing == getHopperFacing()
}
return super.hasCapability(capability, facing)
}
override fun <T: Any?> getCapability(capability: Capability<T>, facing: EnumFacing?): T? {
if (capability == ITEM_HANDLER_CAPABILITY) {
if (facing == (if (inverted) EnumFacing.DOWN else EnumFacing.UP) || facing == getHopperFacing()) {
return inventory as T
}
}
return super.getCapability(capability, facing)
}
}

View File

@ -18,7 +18,7 @@ import net.shadowfacts.extrahoppers.gui.GUIHandler
/**
* @author shadowfacts
*/
class BlockWoodenFluidHopper(inverted: Boolean): BlockFluidHopper(inverted, name = "wooden_fluid_hopper", material = Material.WOOD) {
class BlockWoodenFluidHopper(inverted: Boolean): BlockFluidHopper(inverted, false, name = "wooden_fluid_hopper", material = Material.WOOD) {
init {
setHardness(1.5f)

View File

@ -3,14 +3,18 @@ package net.shadowfacts.extrahoppers.block.wooden_fluid
import net.minecraftforge.fluids.FluidStack
import net.shadowfacts.extrahoppers.EHConfig
import net.shadowfacts.extrahoppers.block.fluid.TileEntityFluidHopper
import net.shadowfacts.extrahoppers.util.filter.Filter
import net.shadowfacts.extrahoppers.util.filter.NoOpFilter
/**
* @author shadowfacts
*/
class TileEntityWoodenFluidHopper(inverted: Boolean): TileEntityFluidHopper(inverted) {
class TileEntityWoodenFluidHopper(inverted: Boolean): TileEntityFluidHopper(inverted, false) {
constructor(): this(false)
override var filter: Filter<FluidStack> = NoOpFilter
override val fluidValiator: (FluidStack) -> Boolean = { it.fluid.temperature <= EHConfig.wfhMaxTemperature }
constructor(): this(false)
}

View File

@ -15,11 +15,6 @@ class EHGUIFactory: IModGuiFactory {
override fun createConfigGui(parentScreen: GuiScreen) = EHConfigGUI(parentScreen)
@Deprecated("")
override fun mainConfigGuiClass() = EHConfigGUI::class.java
override fun runtimeGuiCategories() = null