diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt index 8ebffbb02..2f40e9a0b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt @@ -11,6 +11,8 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.container.slotted.AutomationFilters +import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag import ru.dbotthepony.mc.otm.menu.tech.ItemHatchMenu import ru.dbotthepony.mc.otm.registry.game.MBlockEntities @@ -21,12 +23,11 @@ class ItemHatchBlockEntity( blockPos: BlockPos, blockState: BlockState ) : MatteryDeviceBlockEntity(type, blockPos, blockState) { - val container = MatteryContainer(this::markDirtyFast, CAPACITY).also(::addDroppableContainer) - val itemHandler = container.handler(if (isInput) HandlerFilter.OnlyIn else HandlerFilter.OnlyOut) + val container = SlottedContainer.simple(CAPACITY, if (isInput) AutomationFilters.ONLY_IN.filteredProvider else AutomationFilters.ONLY_OUT.filteredProvider, this::markDirtyFast).also(::addDroppableContainer) init { savetables.stateful(::container, INVENTORY_KEY) - exposeGlobally(Capabilities.ItemHandler.BLOCK, itemHandler) + exposeGlobally(Capabilities.ItemHandler.BLOCK, container) } override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt index bc8c6e1aa..934eb8cb9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt @@ -5,6 +5,8 @@ import net.minecraft.core.BlockPos import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.crafting.SingleRecipeInput import net.minecraft.world.level.block.state.BlockState import net.neoforged.neoforge.capabilities.Capabilities import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage @@ -19,12 +21,20 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.balance +import ru.dbotthepony.mc.otm.container.slotted.AutomationFilters +import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot +import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer +import ru.dbotthepony.mc.otm.core.SimpleCache +import ru.dbotthepony.mc.otm.core.collect.any import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.maybe import ru.dbotthepony.mc.otm.core.otmRandom +import ru.dbotthepony.mc.otm.core.util.ItemStackKey +import ru.dbotthepony.mc.otm.core.util.asKey import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu import ru.dbotthepony.mc.otm.registry.game.MBlockEntities import ru.dbotthepony.mc.otm.registry.game.MRecipes +import java.time.Duration class PlatePressBlockEntity( blockPos: BlockPos, @@ -33,14 +43,36 @@ class PlatePressBlockEntity( ) : MatteryWorkerBlockEntity(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, blockPos, blockState, ItemJob.CODEC, if (isTwin) 2 else 1) { override val upgrades = makeUpgrades(if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS))) - val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) - val outputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) + + private inner class InputSlot(container: SlottedContainer, slot: Int) : FilteredContainerSlot(container, slot) { + override fun canAutomationPlaceItem(itemStack: ItemStack): Boolean { + if (!super.canAutomationPlaceItem(itemStack)) + return false + + val level = level ?: return true + val input = SingleRecipeInput(itemStack) + + return cache.get(itemStack.asKey()) { + return@get level.recipeManager + .byType(MRecipes.PLATE_PRESS) + .any { it.value.matches(input, level) } + } + } + + override fun canAutomationTakeItem(desired: Int): Boolean { + return false + } + } + + val inputContainer = SlottedContainer.simple(if (isTwin) 2 else 1, ::InputSlot, this::itemContainerUpdated).also(::addDroppableContainer) + val outputContainer = SlottedContainer.simple(if (isTwin) 2 else 1, AutomationFilters.ONLY_OUT.simpleProvider, this::itemContainerUpdated).also(::addDroppableContainer) val experience = ExperienceStorage(MachinesConfig.PLATE_PRESS::maxExperienceStored).also(::addNeighbourListener) val energyConfig = ConfigurableEnergy(energy) + val itemConfig = ConfigurableItemHandler( - input = inputContainer.handler(HandlerFilter.OnlyIn), - output = outputContainer.handler(HandlerFilter.OnlyOut), + input = inputContainer, + output = outputContainer, ) init { @@ -76,9 +108,7 @@ class PlatePressBlockEntity( val recipe = level.recipeManager .byType(MRecipes.PLATE_PRESS) - .iterator() - .filter { it.value.matches(inputContainer, id) } - .maybe()?.value ?: return JobContainer.noItem() + .firstOrNull { it.value.matches(inputContainer, id) }?.value ?: return JobContainer.noItem() val toProcess = inputContainer[id].count.coerceAtMost(1 + upgrades.processingItems) @@ -100,4 +130,8 @@ class PlatePressBlockEntity( super.tick() } + + companion object { + private val cache = SimpleCache(16384L, Duration.ofMinutes(1L)) + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt index e18661ad1..052984a6c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt @@ -7,6 +7,8 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.inventory.MenuType import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity import ru.dbotthepony.mc.otm.compat.jei.PlatePressRecipeCategory +import ru.dbotthepony.mc.otm.container.EnhancedContainer +import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.menu.OutputMenuSlot import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot @@ -28,8 +30,8 @@ class PlatePressMenu( tile: PlatePressBlockEntity? = null, isTwin: Boolean ) : AbstractProcessingMachineMenu(type, containerID, inventory, tile) { - val inputSlots = makeSlots(tile?.inputContainer ?: SimpleContainer(if (isTwin) 2 else 1), ::MatteryMenuSlot) - val outputSlots = makeSlots(tile?.outputContainer ?: SimpleContainer(if (isTwin) 2 else 1)) { a, b -> OutputMenuSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } } + val inputSlots = makeSlots(tile?.inputContainer ?: SlottedContainer.filtered(if (isTwin) 2 else 1), ::MatteryMenuSlot) + val outputSlots = makeSlots(tile?.outputContainer ?: EnhancedContainer(if (isTwin) 2 else 1)) { a, b -> OutputMenuSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } } val gauges = immutableList(if (isTwin) 2 else 1) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) } override val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)