Move Fluid tank to SlottedContainer, and make it accept slot filters
This commit is contained in:
parent
1702f95370
commit
66a4adecf9
@ -21,6 +21,11 @@ import ru.dbotthepony.mc.otm.config.ItemsConfig
|
|||||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||||
import ru.dbotthepony.mc.otm.container.get
|
import ru.dbotthepony.mc.otm.container.get
|
||||||
|
import ru.dbotthepony.mc.otm.container.slotted.AutomationFilter
|
||||||
|
import ru.dbotthepony.mc.otm.container.slotted.AutomationFilters
|
||||||
|
import ru.dbotthepony.mc.otm.container.slotted.ContainerSlot
|
||||||
|
import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot
|
||||||
|
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
|
||||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.core.isNotSameAs
|
import ru.dbotthepony.mc.otm.core.isNotSameAs
|
||||||
import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu
|
import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu
|
||||||
@ -37,28 +42,42 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
}
|
}
|
||||||
}), FluidStack.OPTIONAL_STREAM_CODEC.wrap()))
|
}), FluidStack.OPTIONAL_STREAM_CODEC.wrap()))
|
||||||
|
|
||||||
val fillInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
|
private inner class FillSlot(container: SlottedContainer, slot: Int) : FilteredContainerSlot(container, slot) {
|
||||||
val drainInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
|
override fun canAutomationPlaceItem(itemStack: ItemStack): Boolean {
|
||||||
val output = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
|
if (!super.canAutomationPlaceItem(itemStack))
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (fluid.isEmpty) {
|
||||||
|
return itemStack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.tanks > 0 } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemStack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.fill(fluid[0], IFluidHandler.FluidAction.SIMULATE) > 0 } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(desired: Int): Boolean {
|
||||||
|
return super.canAutomationTakeItem(desired) && !canAutomationPlaceItem(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val inputContainer = SlottedContainer.Builder()
|
||||||
|
.add(DRAIN_TAG, AutomationFilters.DRAINABLE_FLUID_CONTAINERS.filteredProvider)
|
||||||
|
.add(FILL_TAG, ::FillSlot)
|
||||||
|
.onChanged(::markDirtyFast)
|
||||||
|
.build()
|
||||||
|
.also(::addDroppableContainer)
|
||||||
|
|
||||||
|
val outputContainer = SlottedContainer.Builder()
|
||||||
|
.add(AutomationFilters.ONLY_OUT.simpleProvider)
|
||||||
|
.onChanged(::markDirtyFast)
|
||||||
|
.build()
|
||||||
|
.also(::addDroppableContainer)
|
||||||
|
|
||||||
|
private val fillSlot = inputContainer[FILL_TAG]
|
||||||
|
private val drainSlot = inputContainer[DRAIN_TAG]
|
||||||
|
|
||||||
val itemConfig = ConfigurableItemHandler(
|
val itemConfig = ConfigurableItemHandler(
|
||||||
input = CombinedItemHandler(
|
input = inputContainer,
|
||||||
drainInput.handler(HandlerFilter.DrainableFluidContainers),
|
output = outputContainer,
|
||||||
fillInput.handler(object : HandlerFilter {
|
|
||||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
|
||||||
if (fluid.isEmpty) {
|
|
||||||
return stack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.tanks > 0 } ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
return stack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.fill(fluid[0], IFluidHandler.FluidAction.SIMULATE) > 0 } ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
|
||||||
return !canInsert(slot, stack)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
),
|
|
||||||
output = output.handler(HandlerFilter.OnlyOut),
|
|
||||||
frontDefault = ItemHandlerMode.INPUT_OUTPUT,
|
frontDefault = ItemHandlerMode.INPUT_OUTPUT,
|
||||||
backDefault = ItemHandlerMode.INPUT_OUTPUT,
|
backDefault = ItemHandlerMode.INPUT_OUTPUT,
|
||||||
leftDefault = ItemHandlerMode.INPUT_OUTPUT,
|
leftDefault = ItemHandlerMode.INPUT_OUTPUT,
|
||||||
@ -71,20 +90,19 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
savetables.stateful(::fluid, FLUID_KEY)
|
savetables.stateful(::fluid, FLUID_KEY)
|
||||||
savetables.stateful(::fillInput)
|
savetables.stateful(::inputContainer)
|
||||||
savetables.stateful(::drainInput)
|
savetables.stateful(::outputContainer)
|
||||||
savetables.stateful(::output)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drainItem() {
|
private fun drainItem() {
|
||||||
val item = drainInput[0]
|
val item = drainSlot.item
|
||||||
|
|
||||||
if (item.isNotEmpty) {
|
if (item.isNotEmpty) {
|
||||||
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(Capabilities.FluidHandler.ITEM)
|
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(Capabilities.FluidHandler.ITEM)
|
||||||
|
|
||||||
if (cap == null) {
|
if (cap == null) {
|
||||||
if (output.consumeItem(item, simulate = false)) {
|
if (outputContainer.consumeItem(item, simulate = false)) {
|
||||||
drainInput.setChanged(0)
|
drainSlot.setChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -95,17 +113,17 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
val moved0 = moveFluid(source = cap, destination = fluid)
|
val moved0 = moveFluid(source = cap, destination = fluid)
|
||||||
|
|
||||||
if (moved0.isNotEmpty) {
|
if (moved0.isNotEmpty) {
|
||||||
drainInput[0] = cap.container
|
drainSlot.item = cap.container
|
||||||
|
|
||||||
if (output.consumeItem(drainInput[0], simulate = false)) {
|
if (outputContainer.consumeItem(drainSlot.item, simulate = false)) {
|
||||||
drainInput.setChanged(0)
|
drainSlot.setChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val moved0 = moveFluid(source = cap, destination = fluid, actuallyFill = false)
|
val moved0 = moveFluid(source = cap, destination = fluid, actuallyFill = false)
|
||||||
|
|
||||||
if (moved0.isNotEmpty) {
|
if (moved0.isNotEmpty) {
|
||||||
if (output.consumeItem(cap.container, simulate = true)) {
|
if (outputContainer.consumeItem(cap.container, simulate = true)) {
|
||||||
val cap1 = item.copyWithCount(1).getCapability(Capabilities.FluidHandler.ITEM) ?: throw ConcurrentModificationException()
|
val cap1 = item.copyWithCount(1).getCapability(Capabilities.FluidHandler.ITEM) ?: throw ConcurrentModificationException()
|
||||||
|
|
||||||
val moved1 = moveFluid(source = cap1, destination = fluid)
|
val moved1 = moveFluid(source = cap1, destination = fluid)
|
||||||
@ -114,9 +132,9 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
LOGGER.error("Error moving fluids in Fluid tank at $blockPos: moved $moved0 during simulation from ${cap.container}, moved $moved1 from ${cap1.container} during execution. This is likely a bug in OTM or other mod!")
|
LOGGER.error("Error moving fluids in Fluid tank at $blockPos: moved $moved0 during simulation from ${cap.container}, moved $moved1 from ${cap1.container} during execution. This is likely a bug in OTM or other mod!")
|
||||||
} else {
|
} else {
|
||||||
item.count--
|
item.count--
|
||||||
drainInput.setChanged(0)
|
drainSlot.setChanged()
|
||||||
|
|
||||||
if (!output.consumeItem(cap1.container, simulate = false)) {
|
if (!outputContainer.consumeItem(cap1.container, simulate = false)) {
|
||||||
LOGGER.error("Unable to insert ${cap1.container} into output slot of Fluid tank at $blockPos, popping item in world instead to avoid item loss! This is likely a bug in OTM or other mod!")
|
LOGGER.error("Unable to insert ${cap1.container} into output slot of Fluid tank at $blockPos, popping item in world instead to avoid item loss! This is likely a bug in OTM or other mod!")
|
||||||
(level as? ServerLevel)?.addFreshEntity(ItemEntity(level!!, blockPos.x.toDouble(), blockPos.y.toDouble(), blockPos.z.toDouble(), cap1.container))
|
(level as? ServerLevel)?.addFreshEntity(ItemEntity(level!!, blockPos.x.toDouble(), blockPos.y.toDouble(), blockPos.z.toDouble(), cap1.container))
|
||||||
}
|
}
|
||||||
@ -129,14 +147,14 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun fillItem() {
|
private fun fillItem() {
|
||||||
val item = fillInput[0]
|
val item = fillSlot.item
|
||||||
|
|
||||||
if (item.isNotEmpty) {
|
if (item.isNotEmpty) {
|
||||||
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(Capabilities.FluidHandler.ITEM)
|
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(Capabilities.FluidHandler.ITEM)
|
||||||
|
|
||||||
if (cap == null) {
|
if (cap == null) {
|
||||||
if (output.consumeItem(item, simulate = false)) {
|
if (outputContainer.consumeItem(item, simulate = false)) {
|
||||||
fillInput.setChanged(0)
|
fillSlot.setChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -147,17 +165,17 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
val moved0 = moveFluid(source = fluid, destination = cap)
|
val moved0 = moveFluid(source = fluid, destination = cap)
|
||||||
|
|
||||||
if (moved0.isNotEmpty) {
|
if (moved0.isNotEmpty) {
|
||||||
fillInput[0] = cap.container
|
fillSlot.item = cap.container
|
||||||
|
|
||||||
if (output.consumeItem(fillInput[0], simulate = false)) {
|
if (outputContainer.consumeItem(fillSlot.item, simulate = false)) {
|
||||||
fillInput.setChanged(0)
|
fillSlot.setChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val moved0 = moveFluid(source = fluid, destination = cap, actuallyDrain = false)
|
val moved0 = moveFluid(source = fluid, destination = cap, actuallyDrain = false)
|
||||||
|
|
||||||
if (moved0.isNotEmpty) {
|
if (moved0.isNotEmpty) {
|
||||||
if (output.consumeItem(cap.container, simulate = true)) {
|
if (outputContainer.consumeItem(cap.container, simulate = true)) {
|
||||||
val cap1 = item.copyWithCount(1).getCapability(Capabilities.FluidHandler.ITEM) ?: throw ConcurrentModificationException()
|
val cap1 = item.copyWithCount(1).getCapability(Capabilities.FluidHandler.ITEM) ?: throw ConcurrentModificationException()
|
||||||
|
|
||||||
val moved1 = moveFluid(source = fluid, destination = cap1)
|
val moved1 = moveFluid(source = fluid, destination = cap1)
|
||||||
@ -166,9 +184,9 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
LOGGER.error("Error moving fluids in Fluid tank at $blockPos: moved $moved0 during simulation from ${cap.container}, moved $moved1 from ${cap1.container} during execution. This is likely a bug in OTM or other mod!")
|
LOGGER.error("Error moving fluids in Fluid tank at $blockPos: moved $moved0 during simulation from ${cap.container}, moved $moved1 from ${cap1.container} during execution. This is likely a bug in OTM or other mod!")
|
||||||
} else {
|
} else {
|
||||||
item.count--
|
item.count--
|
||||||
fillInput.setChanged(0)
|
fillSlot.setChanged()
|
||||||
|
|
||||||
if (!output.consumeItem(cap1.container, simulate = false)) {
|
if (!outputContainer.consumeItem(cap1.container, simulate = false)) {
|
||||||
LOGGER.error("Unable to insert ${cap1.container} into output slot of Fluid tank at $blockPos, popping item in world instead to avoid item loss! This is likely a bug in OTM or other mod!")
|
LOGGER.error("Unable to insert ${cap1.container} into output slot of Fluid tank at $blockPos, popping item in world instead to avoid item loss! This is likely a bug in OTM or other mod!")
|
||||||
(level as? ServerLevel)?.addFreshEntity(ItemEntity(level!!, blockPos.x.toDouble(), blockPos.y.toDouble(), blockPos.z.toDouble(), cap1.container))
|
(level as? ServerLevel)?.addFreshEntity(ItemEntity(level!!, blockPos.x.toDouble(), blockPos.y.toDouble(), blockPos.z.toDouble(), cap1.container))
|
||||||
}
|
}
|
||||||
@ -194,5 +212,8 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
companion object {
|
companion object {
|
||||||
const val FLUID_KEY = "fluid"
|
const val FLUID_KEY = "fluid"
|
||||||
private val LOGGER = LogManager.getLogger()
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
|
||||||
|
private val FILL_TAG = SlottedContainer.tag<FilteredContainerSlot>()
|
||||||
|
private val DRAIN_TAG = SlottedContainer.tag<FilteredContainerSlot>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
|
|||||||
import ru.dbotthepony.mc.otm.client.screen.panels.makeCuriosPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.makeCuriosPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.SpritePanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.SpritePanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.slot.UserFilteredSlotPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.FluidGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.FluidGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu
|
import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu
|
||||||
@ -25,8 +26,8 @@ class FluidTankScreen(menu: FluidTankMenu, inventory: Inventory, title: Componen
|
|||||||
val s = SpritePanel(this, frame, ProgressGaugePanel.GAUGE_BACKGROUND, x = 30f, y = 30f)
|
val s = SpritePanel(this, frame, ProgressGaugePanel.GAUGE_BACKGROUND, x = 30f, y = 30f)
|
||||||
SpritePanel(this, frame, ProgressGaugePanel.GAUGE_BACKGROUND, x = 30f, y = 55f, winding = UVWindingOrder.FLOP)
|
SpritePanel(this, frame, ProgressGaugePanel.GAUGE_BACKGROUND, x = 30f, y = 55f, winding = UVWindingOrder.FLOP)
|
||||||
|
|
||||||
SlotPanel(this, frame, menu.fillInput, x = 30f + s.width + 4f, y = 28f)
|
UserFilteredSlotPanel(this, frame, menu.fillInput, x = 30f + s.width + 4f, y = 28f)
|
||||||
SlotPanel(this, frame, menu.drainInput, x = 30f + s.width + 4f, y = 53f)
|
UserFilteredSlotPanel(this, frame, menu.drainInput, x = 30f + s.width + 4f, y = 53f)
|
||||||
|
|
||||||
SlotPanel(this, frame, menu.output, x = 30f + s.width + 4f + 20f, y = 53f)
|
SlotPanel(this, frame, menu.output, x = 30f + s.width + 4f + 20f, y = 53f)
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.container.slotted
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
|
||||||
|
fun interface AutomationPlaceItem<in S : ContainerSlot> {
|
||||||
|
fun canAutomationPlaceItem(self: S, itemStack: ItemStack): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface AutomationTakeItem<in S : ContainerSlot> {
|
||||||
|
fun canAutomationTakeItem(self: S, desired: Int): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface AutomationModifyPlaceCount<in S : ContainerSlot> {
|
||||||
|
fun modifyAutomationPlaceCount(self: S, itemStack: ItemStack): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface AutomationModifyExtractionCount<in S : ContainerSlot> {
|
||||||
|
fun modifyAutomationExtractionCount(self: S, desired: Int): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AutomationFilter<in S : ContainerSlot> : AutomationPlaceItem<S>, AutomationTakeItem<S>, AutomationModifyPlaceCount<S>, AutomationModifyExtractionCount<S> {
|
||||||
|
override fun modifyAutomationPlaceCount(self: S, itemStack: ItemStack): Int {
|
||||||
|
return itemStack.count
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun modifyAutomationExtractionCount(self: S, desired: Int): Int {
|
||||||
|
return desired
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <S : ContainerSlot, T : S> AutomationFilter<S>.and(other: AutomationFilter<T>): AutomationFilter<T> {
|
||||||
|
return object : AutomationFilter<T> {
|
||||||
|
override fun canAutomationPlaceItem(self: T, itemStack: ItemStack): Boolean {
|
||||||
|
return this@and.canAutomationPlaceItem(self, itemStack) && other.canAutomationPlaceItem(self, itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: T, desired: Int): Boolean {
|
||||||
|
return this@and.canAutomationTakeItem(self, desired) && other.canAutomationTakeItem(self, desired)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun modifyAutomationPlaceCount(self: T, itemStack: ItemStack): Int {
|
||||||
|
return this@and.modifyAutomationPlaceCount(self, itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun modifyAutomationExtractionCount(self: T, desired: Int): Int {
|
||||||
|
return this@and.modifyAutomationExtractionCount(self, desired)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.container.slotted
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.neoforged.neoforge.capabilities.Capabilities
|
||||||
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
|
import ru.dbotthepony.mc.otm.capability.fluid.stream
|
||||||
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
|
||||||
|
enum class AutomationFilters : AutomationFilter<ContainerSlot> {
|
||||||
|
ONLY_OUT {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ONLY_IN {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ALLOW {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
DENY {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
FLUID_CONTAINERS {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.tanks > 0 } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
DRAINABLE_FLUID_CONTAINERS {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.stream().anyMatch { it.isNotEmpty } } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return !canAutomationPlaceItem(self, self.item)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
DICHARGEABLE {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(Capabilities.EnergyStorage.ITEM)?.let { it.canExtract() && it.extractEnergy(Int.MAX_VALUE, true) > 0 } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return self.item.getCapability(Capabilities.EnergyStorage.ITEM)?.let { !it.canExtract() || it.extractEnergy(Int.MAX_VALUE, true) <= 0 } ?: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
CHARGEABLE {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(Capabilities.EnergyStorage.ITEM)?.let { it.canReceive() && it.receiveEnergy(Int.MAX_VALUE, true) > 0 } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return self.item.getCapability(Capabilities.EnergyStorage.ITEM)?.let { !it.canReceive() || it.receiveEnergy(Int.MAX_VALUE, true) <= 0 } ?: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
CHEMICAL_FUEL {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getBurnTime(null) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return self.item.getBurnTime(null) <= 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
IS_PATTERN {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(MatteryCapability.PATTERN_ITEM) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
MATTER_PROVIDERS {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(MatteryCapability.MATTER_ITEM)
|
||||||
|
?.let { it.matterFlow.output && it.extractMatterChecked(Decimal.POSITIVE_INFINITY, true) > Decimal.ZERO }
|
||||||
|
?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return self.item.getCapability(MatteryCapability.MATTER_ITEM)
|
||||||
|
?.let { !it.matterFlow.output || it.extractMatterChecked(Decimal.POSITIVE_INFINITY, true) <= Decimal.ZERO }
|
||||||
|
?: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
MATTER_CONSUMERS {
|
||||||
|
override fun canAutomationPlaceItem(self: ContainerSlot, itemStack: ItemStack): Boolean {
|
||||||
|
return itemStack.getCapability(MatteryCapability.MATTER_ITEM)
|
||||||
|
?.let { it.matterFlow.input && it.receiveMatterChecked(Decimal.POSITIVE_INFINITY, true) > Decimal.ZERO }
|
||||||
|
?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAutomationTakeItem(self: ContainerSlot, desired: Int): Boolean {
|
||||||
|
return self.item.getCapability(MatteryCapability.MATTER_ITEM)
|
||||||
|
?.let { !it.matterFlow.input || it.receiveMatterChecked(Decimal.POSITIVE_INFINITY, true) <= Decimal.ZERO }
|
||||||
|
?: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
val simpleProvider: SlottedContainer.SlotProvider<ContainerSlot> by lazy {
|
||||||
|
ContainerSlot.Simple(filter = this)
|
||||||
|
}
|
||||||
|
|
||||||
|
val filteredProvider: SlottedContainer.SlotProvider<FilteredContainerSlot> by lazy {
|
||||||
|
FilteredContainerSlot.Simple(filter = this)
|
||||||
|
}
|
||||||
|
}
|
@ -52,7 +52,13 @@ open class ContainerSlot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun observeChanges(): Boolean {
|
fun observeChanges(): Boolean {
|
||||||
if (observedItem.count != item.count || !ItemStack.isSameItemSameComponents(item, observedItem)) {
|
if (observedItem.isNotEmpty && item.isEmpty) {
|
||||||
|
notifyChanged(observedItem)
|
||||||
|
observedItem = ItemStack.EMPTY
|
||||||
|
_item = ItemStack.EMPTY
|
||||||
|
container.notifyChanged()
|
||||||
|
return true
|
||||||
|
} else if (observedItem.count != item.count || !ItemStack.isSameItemSameComponents(item, observedItem)) {
|
||||||
notifyChanged(observedItem)
|
notifyChanged(observedItem)
|
||||||
observedItem = item.copy()
|
observedItem = item.copy()
|
||||||
container.notifyChanged()
|
container.notifyChanged()
|
||||||
@ -117,6 +123,12 @@ open class ContainerSlot(
|
|||||||
private val modifyAutomationPlaceCount: AutomationModifyPlaceCount<ContainerSlot> = AutomationModifyPlaceCount { _, item -> item.count },
|
private val modifyAutomationPlaceCount: AutomationModifyPlaceCount<ContainerSlot> = AutomationModifyPlaceCount { _, item -> item.count },
|
||||||
private val modifyAutomationExtractionCount: AutomationModifyExtractionCount<ContainerSlot> = AutomationModifyExtractionCount { _, desired -> desired },
|
private val modifyAutomationExtractionCount: AutomationModifyExtractionCount<ContainerSlot> = AutomationModifyExtractionCount { _, desired -> desired },
|
||||||
) : SlottedContainer.SlotProvider<ContainerSlot> {
|
) : SlottedContainer.SlotProvider<ContainerSlot> {
|
||||||
|
constructor(
|
||||||
|
listener: (new: ItemStack, old: ItemStack) -> Unit = { _, _ -> },
|
||||||
|
maxStackSize: Int = Item.DEFAULT_MAX_STACK_SIZE,
|
||||||
|
filter: AutomationFilter<ContainerSlot> = AutomationFilters.ALLOW
|
||||||
|
) : this(listener, maxStackSize, filter, filter, filter, filter)
|
||||||
|
|
||||||
private open inner class Instance(container: SlottedContainer, slot: Int) : ContainerSlot(container, slot) {
|
private open inner class Instance(container: SlottedContainer, slot: Int) : ContainerSlot(container, slot) {
|
||||||
override val maxStackSize: Int
|
override val maxStackSize: Int
|
||||||
get() = this@Simple.maxStackSize
|
get() = this@Simple.maxStackSize
|
||||||
|
@ -9,6 +9,7 @@ import net.minecraft.world.item.ItemStack
|
|||||||
import ru.dbotthepony.mc.otm.container.IFilteredAutomatedContainerSlot
|
import ru.dbotthepony.mc.otm.container.IFilteredAutomatedContainerSlot
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
|
import java.util.Collections
|
||||||
|
|
||||||
open class FilteredContainerSlot(
|
open class FilteredContainerSlot(
|
||||||
container: SlottedContainer,
|
container: SlottedContainer,
|
||||||
@ -50,6 +51,12 @@ open class FilteredContainerSlot(
|
|||||||
private val modifyAutomationPlaceCount: AutomationModifyPlaceCount<FilteredContainerSlot> = AutomationModifyPlaceCount { _, item -> item.count },
|
private val modifyAutomationPlaceCount: AutomationModifyPlaceCount<FilteredContainerSlot> = AutomationModifyPlaceCount { _, item -> item.count },
|
||||||
private val modifyAutomationExtractionCount: AutomationModifyExtractionCount<FilteredContainerSlot> = AutomationModifyExtractionCount { _, desired -> desired },
|
private val modifyAutomationExtractionCount: AutomationModifyExtractionCount<FilteredContainerSlot> = AutomationModifyExtractionCount { _, desired -> desired },
|
||||||
) : SlottedContainer.SlotProvider<FilteredContainerSlot> {
|
) : SlottedContainer.SlotProvider<FilteredContainerSlot> {
|
||||||
|
constructor(
|
||||||
|
listener: (new: ItemStack, old: ItemStack) -> Unit = { _, _ -> },
|
||||||
|
maxStackSize: Int = Item.DEFAULT_MAX_STACK_SIZE,
|
||||||
|
filter: AutomationFilter<FilteredContainerSlot> = AutomationFilters.ALLOW
|
||||||
|
) : this(listener, maxStackSize, filter, filter, filter, filter)
|
||||||
|
|
||||||
private open inner class Instance(container: SlottedContainer, slot: Int) : FilteredContainerSlot(container, slot) {
|
private open inner class Instance(container: SlottedContainer, slot: Int) : FilteredContainerSlot(container, slot) {
|
||||||
override val maxStackSize: Int
|
override val maxStackSize: Int
|
||||||
get() = this@Simple.maxStackSize
|
get() = this@Simple.maxStackSize
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.container.slotted
|
|
||||||
|
|
||||||
import net.minecraft.world.item.ItemStack
|
|
||||||
|
|
||||||
fun interface AutomationPlaceItem<S : ContainerSlot> {
|
|
||||||
fun canAutomationPlaceItem(self: S, itemStack: ItemStack): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
fun interface AutomationTakeItem<S : ContainerSlot> {
|
|
||||||
fun canAutomationTakeItem(self: S, desired: Int): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
fun interface AutomationModifyPlaceCount<S : ContainerSlot> {
|
|
||||||
fun modifyAutomationPlaceCount(self: S, itemStack: ItemStack): Int
|
|
||||||
}
|
|
||||||
|
|
||||||
fun interface AutomationModifyExtractionCount<S : ContainerSlot> {
|
|
||||||
fun modifyAutomationExtractionCount(self: S, desired: Int): Int
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
package ru.dbotthepony.mc.otm.menu.decorative
|
package ru.dbotthepony.mc.otm.menu.decorative
|
||||||
|
|
||||||
import net.minecraft.world.SimpleContainer
|
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities
|
import net.neoforged.neoforge.capabilities.Capabilities
|
||||||
@ -8,9 +7,10 @@ import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
|||||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||||
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.isNotEmpty
|
import ru.dbotthepony.mc.otm.capability.isNotEmpty
|
||||||
|
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
|
||||||
import ru.dbotthepony.mc.otm.menu.OutputMenuSlot
|
import ru.dbotthepony.mc.otm.menu.OutputMenuSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
|
import ru.dbotthepony.mc.otm.menu.UserFilteredMenuSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
@ -24,14 +24,16 @@ class FluidTankMenu(containerId: Int, inventory: Inventory, tile: FluidTankBlock
|
|||||||
val redstoneConfig = EnumInputWithFeedback<RedstoneSetting>(this)
|
val redstoneConfig = EnumInputWithFeedback<RedstoneSetting>(this)
|
||||||
val fluidConfig = FluidConfigPlayerInput(this, tile?.fluidConfig)
|
val fluidConfig = FluidConfigPlayerInput(this, tile?.fluidConfig)
|
||||||
|
|
||||||
val drainInput = object : MatteryMenuSlot(tile?.drainInput ?: SimpleContainer(1), 0) {
|
private val inputContainer = tile?.inputContainer ?: SlottedContainer.filtered(2)
|
||||||
|
|
||||||
|
val drainInput = object : UserFilteredMenuSlot(inputContainer, 0) {
|
||||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
return super.mayPlace(itemStack) &&
|
return super.mayPlace(itemStack) &&
|
||||||
(itemStack.getCapability(Capabilities.FluidHandler.ITEM)?.isNotEmpty ?: false)
|
(itemStack.getCapability(Capabilities.FluidHandler.ITEM)?.isNotEmpty ?: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val fillInput = object : MatteryMenuSlot(tile?.fillInput ?: SimpleContainer(1), 0) {
|
val fillInput = object : UserFilteredMenuSlot(inputContainer, 1) {
|
||||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
return super.mayPlace(itemStack) &&
|
return super.mayPlace(itemStack) &&
|
||||||
(if (itemStack.count <= 1) itemStack
|
(if (itemStack.count <= 1) itemStack
|
||||||
@ -46,7 +48,7 @@ class FluidTankMenu(containerId: Int, inventory: Inventory, tile: FluidTankBlock
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val output = OutputMenuSlot(tile?.output ?: SimpleContainer(1), 0)
|
val output = OutputMenuSlot(tile?.outputContainer ?: SlottedContainer.simple(1), 0)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// сначала слот на заполнение из бака
|
// сначала слот на заполнение из бака
|
||||||
|
Loading…
Reference in New Issue
Block a user