diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt index 08d71f8fc..595d313b2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt @@ -80,12 +80,12 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo input: IItemHandler? = null, output: IItemHandler? = null, battery: IItemHandler? = null, - val frontDefault: ItemHandlerMode = determineDefaultMode(input, output), - val backDefault: ItemHandlerMode = determineDefaultMode(input, output), - val leftDefault: ItemHandlerMode = determineDefaultMode(input, output), - val rightDefault: ItemHandlerMode = determineDefaultMode(input, output), - val topDefault: ItemHandlerMode = determineDefaultMode(input, output), - val bottomDefault: ItemHandlerMode = determineDefaultMode(input, output), + val frontDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.FRONT), + val backDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.BACK), + val leftDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.LEFT), + val rightDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.RIGHT), + val topDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.TOP), + val bottomDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.BOTTOM), ) { val sideless: IItemHandler @@ -281,15 +281,32 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo } companion object { - private fun determineDefaultMode(input: IItemHandler?, output: IItemHandler?): ItemHandlerMode { - if (input == null && output == null) + private fun determineDefaultMode(input: IItemHandler?, output: IItemHandler?, battery: IItemHandler?, side: RelativeSide): ItemHandlerMode { + if (side == RelativeSide.BACK && battery != null) { + return ItemHandlerMode.BATTERY + } + + if (input == null && output == null) { return ItemHandlerMode.DISABLED - else if (input != null && output != null) - return ItemHandlerMode.INPUT_OUTPUT - else if (output != null) - return ItemHandlerMode.OUTPUT - else - return ItemHandlerMode.INPUT + } else if (input != null && output != null) { + return when (side) { + RelativeSide.FRONT, RelativeSide.BACK -> ItemHandlerMode.DISABLED + RelativeSide.RIGHT, RelativeSide.TOP -> ItemHandlerMode.INPUT + RelativeSide.LEFT, RelativeSide.BOTTOM -> ItemHandlerMode.OUTPUT + } + } else if (output != null) { + if (side == RelativeSide.TOP) { + return ItemHandlerMode.DISABLED + } else { + return ItemHandlerMode.OUTPUT + } + } else { + if (side == RelativeSide.BOTTOM) { + return ItemHandlerMode.DISABLED + } else { + return ItemHandlerMode.INPUT + } + } } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt index ff5f138ae..05de98e43 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt @@ -18,6 +18,7 @@ import net.minecraftforge.common.util.LazyOptional import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl import ru.dbotthepony.mc.otm.capability.energy.ItemEnergyStorageImpl +import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.nbt.ifHas @@ -28,6 +29,7 @@ import ru.dbotthepony.mc.otm.core.nbt.set abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) { val batteryContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val batteryItemHandler = batteryContainer.handler(HandlerFilter.Dischargeable) init { savetable(::batteryContainer, BATTERY_KEY) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt index ec0ed5821..327c1bedb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt @@ -31,33 +31,29 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe return ChemicalGeneratorMenu(containerID, inventory, this) } - val container = MatteryContainer(this::setChangedLight, SLOTS).also(::addDroppableContainer) - val energy = GeneratorEnergyStorage(this::setChangedLight, CAPACITY, THROUGHPUT) + val batteryContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val residueContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) + val fuelContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer) - val itemHandler = container.handler(object : HandlerFilter { - override fun canInsert(slot: Int, stack: ItemStack): Boolean { - if (slot == SLOT_INPUT) - return ForgeHooks.getBurnTime(stack, null) > 0 + val batteryItemHandler = batteryContainer.handler(HandlerFilter.Chargeable) + val residueItemHandler = batteryContainer.handler(HandlerFilter.OnlyOut) + val fuelItemHandler = batteryContainer.handler(HandlerFilter.ChemicalFuel) - if (slot == SLOT_RESIDUE) - return false + val energy = GeneratorEnergyStorage(::setChangedLight, CAPACITY, THROUGHPUT) - return stack.getCapability(ForgeCapabilities.ENERGY).isPresent - } - - override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { - if (slot == SLOT_RESIDUE) return true - - return slot == SLOT_BATTERY && - (!stack.getCapability(ForgeCapabilities.ENERGY).isPresent || stack.getCapability(ForgeCapabilities.ENERGY).resolve().get().receiveEnergy(Int.MAX_VALUE, true) <= 0) - } - }) + val itemConfig = ConfigurableItemHandler( + input = fuelItemHandler, + output = residueItemHandler, + battery = batteryItemHandler, + backDefault = ItemHandlerMode.BATTERY) init { savetable(::energy, ENERGY_KEY) - savetable(::container, INVENTORY_KEY) + savetable(::batteryContainer) + savetable(::residueContainer) + savetable(::fuelContainer) + exposeEnergyGlobally(energy) - exposeItemsGlobally(itemHandler) savetables.int(::workTicks, WORK_TICKS_KEY) savetables.int(::workTicksTotal, WORK_TICKS_TOTAL_KEY) @@ -107,25 +103,25 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe } if (workTicks == 0 && !redstoneControl.isBlockedByRedstone && checkFuelSlot) { - if (!container[SLOT_INPUT].isEmpty) { - val ticks = ForgeHooks.getBurnTime(container[SLOT_INPUT], null) - val residue = container[SLOT_INPUT].item.getCraftingRemainingItem(container[SLOT_INPUT].copy().also { it.count = 1 }) - val canPutResidue = residue.isEmpty || container[SLOT_RESIDUE].isEmpty || ItemStack.isSameItemSameTags(container[SLOT_RESIDUE], residue) && container[SLOT_RESIDUE].count < container[2].maxStackSize + if (!fuelContainer[0].isEmpty) { + val ticks = ForgeHooks.getBurnTime(fuelContainer[0], null) + val residue = fuelContainer[0].item.getCraftingRemainingItem(fuelContainer[0].copy().also { it.count = 1 }) + val canPutResidue = residue.isEmpty || residueContainer[0].isEmpty || ItemStack.isSameItemSameTags(residueContainer[0], residue) && residueContainer[0].count < residueContainer[0].maxStackSize if (canPutResidue && ticks >= 4 && (energy.batteryLevel < Decimal.ONE || GENERATION_SPEED * (ticks / 4) + energy.batteryLevel <= energy.maxBatteryLevel)) { workTicksTotal = ticks / 4 workTicks = ticks / 4 - container[SLOT_INPUT].shrink(1) + fuelContainer[0].shrink(1) if (!residue.isEmpty) { - if (container[SLOT_RESIDUE].isEmpty) { - container[SLOT_RESIDUE] = residue + if (residueContainer[0].isEmpty) { + residueContainer[0] = residue } else { - container[SLOT_RESIDUE].count++ + residueContainer[0].count++ } } - container.setChanged(SLOT_INPUT) + fuelContainer.setChanged(0) } } @@ -134,7 +130,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe if (energy.batteryLevel.isZero) return - val item = container[SLOT_BATTERY] + val item = batteryContainer[0] if (!item.isEmpty) { item.energy?.let(this::workWithPower) @@ -155,11 +151,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe private var _GENERATION_SPEED: DecimalConfigValue by WriteOnce() private var _CAPACITY: DecimalConfigValue by WriteOnce() - const val SLOT_INPUT = 0 - const val SLOT_BATTERY = 1 - const val SLOT_RESIDUE = 2 - const val SLOTS = 3 - fun registerConfig(builder: ForgeConfigSpec.Builder) { builder.push(MNames.CHEMICAL_GENERATOR) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt index cc57e14d7..3dd554dbb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt @@ -63,16 +63,6 @@ class ChemicalGeneratorBlock : RotatableMatteryBlock(), EntityBlock { ) { super.appendHoverText(itemStack, p_49817_, tooltips, p_49819_) GeneratorEnergyStorage.appendHoverText(itemStack, p_49817_, tooltips, p_49819_) - - val tag = itemStack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag ?: return - val container = MatteryContainer(ChemicalGeneratorBlockEntity.SLOTS) - tag.map(MatteryBlockEntity.INVENTORY_KEY, container::deserializeNBT) - - if (!container[ChemicalGeneratorBlockEntity.SLOT_BATTERY].isEmpty) { - tooltips.add(TranslatableComponent("otm.item.block.stored_battery", container[ChemicalGeneratorBlockEntity.SLOT_BATTERY].displayName).withStyle(ChatFormatting.GRAY)) - - ItemEnergyStorageImpl.appendHoverText(container[ChemicalGeneratorBlockEntity.SLOT_BATTERY], tooltips) - } } private val shapes = getShapeForEachState(rotationProperty) { BlockShapes.CHEMICAL_GENERATOR.rotateFromNorth(it[rotationProperty]).computeShape() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ChemicalGeneratorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ChemicalGeneratorScreen.kt index b0394c745..1d12426f1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ChemicalGeneratorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ChemicalGeneratorScreen.kt @@ -34,7 +34,7 @@ class ChemicalGeneratorScreen(menu: ChemicalGeneratorMenu, inventory: Inventory, SlotPanel(this, frame, menu.residueSlot, 56f, PROGRESS_SLOT_TOP) SlotPanel(this, frame, menu.fuelSlot, 104f, PROGRESS_SLOT_TOP) - makeDeviceControls(this, frame, redstone = menu.redstone) + makeDeviceControls(this, frame, redstone = menu.redstone, itemConfig = menu.itemConfig) return frame } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt index a0843131a..2089f618e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt @@ -1,6 +1,8 @@ package ru.dbotthepony.mc.otm.container import net.minecraft.world.item.ItemStack +import net.minecraftforge.common.ForgeHooks +import net.minecraftforge.common.capabilities.ForgeCapabilities interface HandlerFilter { fun canInsert(slot: Int, stack: ItemStack): Boolean { @@ -35,4 +37,34 @@ interface HandlerFilter { } object Both : HandlerFilter + + object Dischargeable : HandlerFilter { + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return stack.getCapability(ForgeCapabilities.ENERGY).map { it.canExtract() && it.extractEnergy(Int.MAX_VALUE, true) > 0 }.orElse(false) + } + + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return stack.getCapability(ForgeCapabilities.ENERGY).map { !it.canExtract() || it.extractEnergy(Int.MAX_VALUE, true) <= 0 }.orElse(true) + } + } + + object Chargeable : HandlerFilter { + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return stack.getCapability(ForgeCapabilities.ENERGY).map { it.canReceive() && it.receiveEnergy(Int.MAX_VALUE, true) > 0 }.orElse(false) + } + + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return stack.getCapability(ForgeCapabilities.ENERGY).map { !it.canReceive() || it.receiveEnergy(Int.MAX_VALUE, true) <= 0 }.orElse(true) + } + } + + object ChemicalFuel : HandlerFilter { + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return ForgeHooks.getBurnTime(stack, null) <= 0 + } + + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return ForgeHooks.getBurnTime(stack, null) > 0 + } + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemHandlerPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemHandlerPlayerInput.kt index dcf8aa1de..cc5853ab8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemHandlerPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemHandlerPlayerInput.kt @@ -5,6 +5,9 @@ import ru.dbotthepony.mc.otm.core.immutableMap import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.menu.MatteryMenu +/** + * [allowPull] and [allowPush] controls whenever player is allowed to change these options + */ class ItemHandlerPlayerInput(val menu: MatteryMenu, val allowPull: Boolean = true, val allowPush: Boolean = true) { inner class Piece(val side: RelativeSide) { private val allowedFlags = MatteryDeviceBlockEntity.ItemHandlerMode.values().map { menu.mSynchronizer.bool() to it } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt index 765217587..18ea8fc55 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt @@ -11,6 +11,7 @@ import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback +import ru.dbotthepony.mc.otm.menu.input.ItemHandlerPlayerInput import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus @@ -19,28 +20,28 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t : MatteryMenu(MMenus.CHEMICAL_GENERATOR, id, inv, tile) { val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java) + val itemConfig = ItemHandlerPlayerInput(this, allowPull = false, allowPush = true) init { if (tile != null) { redstone.with(tile.redstoneControl::redstoneSetting) + itemConfig.configure(tile.itemConfig) } } - val container = tile?.container ?: SimpleContainer(3) - - val fuelSlot = object : MatterySlot(container, ChemicalGeneratorBlockEntity.SLOT_INPUT) { + val fuelSlot = object : MatterySlot(tile?.fuelContainer ?: SimpleContainer(1), 0) { override fun mayPlace(itemStack: ItemStack): Boolean { return ForgeHooks.getBurnTime(itemStack, null) > 0 } } - val residueSlot = object : MatterySlot(container, ChemicalGeneratorBlockEntity.SLOT_RESIDUE) { + val residueSlot = object : MatterySlot(tile?.residueContainer ?: SimpleContainer(1), 0) { override fun mayPlace(itemStack: ItemStack): Boolean { return false } } - val batterySlot = object : MatterySlot(container, ChemicalGeneratorBlockEntity.SLOT_BATTERY) { + val batterySlot = object : MatterySlot(tile?.batteryContainer ?: SimpleContainer(1), 0) { override fun mayPlace(itemStack: ItemStack): Boolean { itemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { return it.canReceive() @@ -54,7 +55,6 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t val energy = LevelGaugeWidget(this, tile?.energy) var burnTime by mSynchronizer.int() - override val storageSlots = listOf( addSlot(fuelSlot), addSlot(batterySlot),