Switch Powered furnaces to SlottedContainer, make them reject items which are not used in any recipe (in automation)
This commit is contained in:
parent
fbd34f3414
commit
3e086dcacf
@ -29,33 +29,60 @@ import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
|||||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
import ru.dbotthepony.mc.otm.config.WorkerBalanceValues
|
import ru.dbotthepony.mc.otm.config.WorkerBalanceValues
|
||||||
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
||||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
|
||||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
|
||||||
import ru.dbotthepony.mc.otm.container.balance
|
import ru.dbotthepony.mc.otm.container.balance
|
||||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
import ru.dbotthepony.mc.otm.container.slotted.AutomationFilters
|
||||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
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.immutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
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.PoweredFurnaceMenu
|
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
|
||||||
import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe
|
import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe
|
||||||
import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe
|
import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe
|
||||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||||
import ru.dbotthepony.mc.otm.registry.game.MRecipes
|
import ru.dbotthepony.mc.otm.registry.game.MRecipes
|
||||||
|
import java.time.Duration
|
||||||
|
|
||||||
sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : MatteryCookingRecipe>(
|
sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : MatteryCookingRecipe>(
|
||||||
type: BlockEntityType<*>,
|
type: BlockEntityType<*>,
|
||||||
blockPos: BlockPos,
|
blockPos: BlockPos,
|
||||||
blockState: BlockState,
|
blockState: BlockState,
|
||||||
val recipeType: RecipeType<P>,
|
|
||||||
val secondaryRecipeType: RecipeType<S>?,
|
|
||||||
val config: WorkerBalanceValues,
|
|
||||||
maxJobs: Int = 2
|
maxJobs: Int = 2
|
||||||
) : MatteryWorkerBlockEntity<ItemJob>(type, blockPos, blockState, ItemJob.CODEC, maxJobs) {
|
) : MatteryWorkerBlockEntity<ItemJob>(type, blockPos, blockState, ItemJob.CODEC, maxJobs) {
|
||||||
|
abstract val recipeType: RecipeType<P>
|
||||||
|
abstract val secondaryRecipeType: RecipeType<S>?
|
||||||
|
abstract val config: WorkerBalanceValues
|
||||||
|
|
||||||
final override val upgrades = makeUpgrades(2, UpgradeType.BASIC_PROCESSING)
|
final override val upgrades = makeUpgrades(2, UpgradeType.BASIC_PROCESSING)
|
||||||
final override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config)))
|
final override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config)))
|
||||||
|
|
||||||
val inputs = MatteryContainer(this::itemContainerUpdated, maxJobs)
|
private inner class InputSlot(container: SlottedContainer, slot: Int) : FilteredContainerSlot(container, slot) {
|
||||||
val outputs = MatteryContainer(this::itemContainerUpdated, maxJobs)
|
override fun canAutomationPlaceItem(itemStack: ItemStack): Boolean {
|
||||||
|
if (!super.canAutomationPlaceItem(itemStack))
|
||||||
|
return false
|
||||||
|
|
||||||
|
val level = level ?: return true
|
||||||
|
|
||||||
|
return acceptableItems.get(itemStack.asKey()) {
|
||||||
|
val input = SingleRecipeInput(itemStack)
|
||||||
|
val secondaryRecipeType = secondaryRecipeType
|
||||||
|
|
||||||
|
if (secondaryRecipeType != null && level.recipeManager.byType(secondaryRecipeType).any { it.value.matches(input, level) })
|
||||||
|
return@get true
|
||||||
|
|
||||||
|
return@get level.recipeManager.byType(recipeType).any { it.value.matches(input, level) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(desired: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val inputs = SlottedContainer.simple(maxJobs, ::InputSlot, ::itemContainerUpdated)
|
||||||
|
val outputs = SlottedContainer.simple(maxJobs, AutomationFilters.ONLY_OUT.simpleProvider, ::itemContainerUpdated)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
addDroppableContainer(inputs)
|
addDroppableContainer(inputs)
|
||||||
@ -76,8 +103,8 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
|||||||
val experience = ExperienceStorage(config::maxExperienceStored).also(::addNeighbourListener)
|
val experience = ExperienceStorage(config::maxExperienceStored).also(::addNeighbourListener)
|
||||||
val energyConfig = ConfigurableEnergy(energy)
|
val energyConfig = ConfigurableEnergy(energy)
|
||||||
val itemConfig = ConfigurableItemHandler(
|
val itemConfig = ConfigurableItemHandler(
|
||||||
input = inputs.handler(HandlerFilter.OnlyIn),
|
input = inputs,
|
||||||
output = outputs.handler(HandlerFilter.OnlyOut),
|
output = outputs,
|
||||||
battery = batteryContainer
|
battery = batteryContainer
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -127,13 +154,13 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
|||||||
return JobContainer.noItem()
|
return JobContainer.noItem()
|
||||||
|
|
||||||
val level = level as? ServerLevel ?: return JobContainer.failure()
|
val level = level as? ServerLevel ?: return JobContainer.failure()
|
||||||
|
val secondaryRecipeType = secondaryRecipeType
|
||||||
|
|
||||||
if (secondaryRecipeType != null) {
|
if (secondaryRecipeType != null) {
|
||||||
val recipe = level.recipeManager
|
val recipe = level.recipeManager
|
||||||
.byType(secondaryRecipeType)
|
.byType(secondaryRecipeType)
|
||||||
.iterator()
|
.firstOrNull { it.value.matches(SingleRecipeInput(inputs[id]), level) }
|
||||||
.filter { it.value.matches(SingleRecipeInput(inputs[id]), level) }
|
?.value
|
||||||
.maybe()?.value
|
|
||||||
|
|
||||||
if (recipe != null) {
|
if (recipe != null) {
|
||||||
val toProcess = inputs[id].count.coerceAtMost(1 + upgrades.processingItems)
|
val toProcess = inputs[id].count.coerceAtMost(1 + upgrades.processingItems)
|
||||||
@ -172,24 +199,47 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
|||||||
))
|
))
|
||||||
}.orElse(JobContainer.noItem())
|
}.orElse(JobContainer.noItem())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// shared by all furnace instances, so cache should be large enough
|
||||||
|
private val acceptableItems = SimpleCache<ItemStackKey, Boolean>(16384L, Duration.ofMinutes(1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PoweredFurnaceBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractPoweredFurnaceBlockEntity<SmeltingRecipe, MatteryCookingRecipe>(
|
class PoweredFurnaceBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractPoweredFurnaceBlockEntity<SmeltingRecipe, MatteryCookingRecipe>(MBlockEntities.POWERED_FURNACE, blockPos, blockState) {
|
||||||
MBlockEntities.POWERED_FURNACE, blockPos, blockState, RecipeType.SMELTING, null, MachinesConfig.POWERED_FURNACE) {
|
override val recipeType: RecipeType<SmeltingRecipe>
|
||||||
|
get() = RecipeType.SMELTING
|
||||||
|
override val secondaryRecipeType: RecipeType<MatteryCookingRecipe>?
|
||||||
|
get() = null
|
||||||
|
override val config: WorkerBalanceValues
|
||||||
|
get() = MachinesConfig.POWERED_FURNACE
|
||||||
|
|
||||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
return PoweredFurnaceMenu.furnace(containerID, inventory, this)
|
return PoweredFurnaceMenu.furnace(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PoweredBlastFurnaceBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractPoweredFurnaceBlockEntity<BlastingRecipe, MatteryCookingRecipe>(
|
class PoweredBlastFurnaceBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractPoweredFurnaceBlockEntity<BlastingRecipe, MatteryCookingRecipe>(MBlockEntities.POWERED_BLAST_FURNACE, blockPos, blockState) {
|
||||||
MBlockEntities.POWERED_BLAST_FURNACE, blockPos, blockState, RecipeType.BLASTING, null, MachinesConfig.POWERED_FURNACE) {
|
override val recipeType: RecipeType<BlastingRecipe>
|
||||||
|
get() = RecipeType.BLASTING
|
||||||
|
override val secondaryRecipeType: RecipeType<MatteryCookingRecipe>?
|
||||||
|
get() = null
|
||||||
|
override val config: WorkerBalanceValues
|
||||||
|
get() = MachinesConfig.POWERED_FURNACE
|
||||||
|
|
||||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
return PoweredFurnaceMenu.blasting(containerID, inventory, this)
|
return PoweredFurnaceMenu.blasting(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PoweredSmokerBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractPoweredFurnaceBlockEntity<SmokingRecipe, MicrowaveRecipe>(
|
class PoweredSmokerBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractPoweredFurnaceBlockEntity<SmokingRecipe, MicrowaveRecipe>(MBlockEntities.POWERED_SMOKER, blockPos, blockState) {
|
||||||
MBlockEntities.POWERED_SMOKER, blockPos, blockState, RecipeType.SMOKING, MRecipes.MICROWAVE, MachinesConfig.POWERED_FURNACE) {
|
override val recipeType: RecipeType<SmokingRecipe>
|
||||||
|
get() = RecipeType.SMOKING
|
||||||
|
override val secondaryRecipeType: RecipeType<MicrowaveRecipe>
|
||||||
|
get() = MRecipes.MICROWAVE
|
||||||
|
override val config: WorkerBalanceValues
|
||||||
|
get() = MachinesConfig.POWERED_FURNACE
|
||||||
|
|
||||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
return PoweredFurnaceMenu.smoking(containerID, inventory, this)
|
return PoweredFurnaceMenu.smoking(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
package ru.dbotthepony.mc.otm.menu.tech
|
package ru.dbotthepony.mc.otm.menu.tech
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
import mezz.jei.api.constants.RecipeTypes
|
import mezz.jei.api.constants.RecipeTypes
|
||||||
import mezz.jei.api.recipe.RecipeType
|
import mezz.jei.api.recipe.RecipeType
|
||||||
import net.minecraft.server.level.ServerPlayer
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.world.SimpleContainer
|
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.inventory.MenuType
|
import net.minecraft.world.inventory.MenuType
|
||||||
|
import net.minecraft.world.item.crafting.Recipe
|
||||||
|
import net.minecraft.world.item.crafting.SingleRecipeInput
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.AbstractPoweredFurnaceBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.AbstractPoweredFurnaceBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredBlastFurnaceBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredBlastFurnaceBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredFurnaceBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredFurnaceBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredSmokerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredSmokerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.compat.jei.MicrowaveRecipeCategory
|
import ru.dbotthepony.mc.otm.compat.jei.MicrowaveRecipeCategory
|
||||||
|
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.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.menu.OutputMenuSlot
|
import ru.dbotthepony.mc.otm.menu.OutputMenuSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
|
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
|
||||||
|
import ru.dbotthepony.mc.otm.menu.UserFilteredMenuSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
@ -23,6 +28,7 @@ import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
|
|||||||
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
|
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
|
||||||
import ru.dbotthepony.mc.otm.registry.game.MMenus
|
import ru.dbotthepony.mc.otm.registry.game.MMenus
|
||||||
|
import ru.dbotthepony.mc.otm.registry.game.MRecipes
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
class PoweredFurnaceMenu(
|
class PoweredFurnaceMenu(
|
||||||
@ -31,8 +37,10 @@ class PoweredFurnaceMenu(
|
|||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
tile: AbstractPoweredFurnaceBlockEntity<*, *>? = null
|
tile: AbstractPoweredFurnaceBlockEntity<*, *>? = null
|
||||||
) : AbstractProcessingMachineMenu(type, containerID, inventory, tile) {
|
) : AbstractProcessingMachineMenu(type, containerID, inventory, tile) {
|
||||||
val inputSlots = makeSlots(tile?.inputs ?: SimpleContainer(2), ::MatteryMenuSlot)
|
// we can't make these slots to reject non-smeltable items
|
||||||
val outputSlots = makeSlots(tile?.outputs ?: SimpleContainer(2)) { c, s -> OutputMenuSlot(c, s) { tile?.experience?.popExperience(player as ServerPlayer) } }
|
// since mods may add obscure recipes/ingredients which never test true on client
|
||||||
|
val inputSlots = makeSlots(tile?.inputs ?: SlottedContainer.filtered(2), ::UserFilteredMenuSlot)
|
||||||
|
val outputSlots = makeSlots(tile?.outputs ?: EnhancedContainer(2)) { c, s -> OutputMenuSlot(c, s) { tile?.experience?.popExperience(player as ServerPlayer) } }
|
||||||
val progressGauge = immutableList(2) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) }
|
val progressGauge = immutableList(2) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) }
|
||||||
|
|
||||||
override val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
|
override val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
|
||||||
|
Loading…
Reference in New Issue
Block a user