Add generic param to CombinedContainer

This commit is contained in:
DBotThePony 2025-03-14 19:06:49 +07:00
parent 90a22a093d
commit 2943026dd5
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 53 additions and 55 deletions

View File

@ -96,42 +96,42 @@ class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, IItemMonitorPla
enum class IngredientPriority(override val component: Component, icon: Lazy<IGUIRenderable>, override val winding: UVWindingOrder = UVWindingOrder.NORMAL) : Setting {
// Refill everything from system
SYSTEM(TranslatableComponent("otm.gui.item_monitor.refill_source.system"), lazy { Widgets8.WHITE_ARROW_DOWN }, UVWindingOrder.FLIP) {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer?, id: UUID?): Boolean {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer<*>?, id: UUID?): Boolean {
return takeOne(id, view)
}
},
// Refill everything from player's inventory
INVENTORY(TranslatableComponent("otm.gui.item_monitor.refill_source.inventory"), lazy { Widgets8.WHITE_ARROW_DOWN }) {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer?, id: UUID?): Boolean {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer<*>?, id: UUID?): Boolean {
return takeOne(inventory, item)
}
},
// Refill everything from system, if can't refill from player's inventory
SYSTEM_FIRST(TranslatableComponent("otm.gui.item_monitor.refill_source.system_first"), lazy { Widgets8.ARROW_SIDEWAYS }, UVWindingOrder.FLIP) {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer?, id: UUID?): Boolean {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer<*>?, id: UUID?): Boolean {
return takeOne(id, view) || takeOne(inventory, item)
}
},
// Refill everything from player's inventory, if can't refill from system
INVENTORY_FIRST(TranslatableComponent("otm.gui.item_monitor.refill_source.inventory_first"), lazy { Widgets8.ARROW_SIDEWAYS }) {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer?, id: UUID?): Boolean {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer<*>?, id: UUID?): Boolean {
return takeOne(inventory, item) || takeOne(id, view)
}
},
// Do not refill (?)
DO_NOT(TranslatableComponent("otm.gui.item_monitor.refill_source.do_not"), lazy { Widgets8.MINUS }) {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer?, id: UUID?): Boolean {
override fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer<*>?, id: UUID?): Boolean {
return false
}
};
override val icon: IGUIRenderable by icon
abstract fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer?, id: UUID?): Boolean
abstract fun takeOne(item: ItemStack, view: IStorageProvider<ItemStorageStack>?, inventory: CombinedContainer<*>?, id: UUID?): Boolean
}
enum class ResultTarget(override val component: Component, icon: Lazy<IGUIRenderable>, override val winding: UVWindingOrder = UVWindingOrder.NORMAL) : Setting {

View File

@ -23,20 +23,20 @@ import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.stream
import java.util.stream.Stream
class CombinedContainer(containers: Stream<Pair<IEnhancedContainer<*>, Iterable<Int>>>) : ISlottedContainer<IContainerSlot> {
constructor(vararg containers: IEnhancedContainer<*>) : this(containers.stream().map { it to (0 until it.containerSize) })
constructor(containers: Collection<IEnhancedContainer<*>>) : this(containers.stream().map { it to (0 until it.containerSize) })
class CombinedContainer<S : IContainerSlot>(containers: Stream<Pair<IEnhancedContainer<S>, Iterable<Int>>>) : ISlottedContainer<S> {
constructor(vararg containers: IEnhancedContainer<S>) : this(containers.stream().map { it to (0 until it.containerSize) })
constructor(containers: Collection<IEnhancedContainer<S>>) : this(containers.stream().map { it to (0 until it.containerSize) })
private val slots: ImmutableList<IContainerSlot>
private val slotsMap: ImmutableMap<Container, List<IContainerSlot>>
private val slots: ImmutableList<S>
private val slotsMap: ImmutableMap<Container, List<S>>
private val containers: ImmutableSet<Container>
private val fullCoverage: ImmutableList<Container>
private val notFullCoverage: ImmutableMap<Container, List<IContainerSlot>>
private val notFullCoverage: ImmutableMap<Container, List<S>>
init {
val list = ImmutableList.Builder<IContainerSlot>()
val list = ImmutableList.Builder<S>()
val validationMap = Reference2ObjectOpenHashMap<Container, IntSet>()
val slotsMap = Reference2ObjectOpenHashMap<Container, ArrayList<IContainerSlot>>()
val slotsMap = Reference2ObjectOpenHashMap<Container, ArrayList<S>>()
var i = 0
for ((container, slots) in containers) {
@ -116,11 +116,11 @@ class CombinedContainer(containers: Stream<Pair<IEnhancedContainer<*>, Iterable<
)
}
override fun slotIterator(): Iterator<IContainerSlot> {
override fun slotIterator(): Iterator<S> {
return slots.iterator()
}
override fun containerSlot(slot: Int): IContainerSlot {
override fun containerSlot(slot: Int): S {
return slots[slot]
}
@ -128,62 +128,62 @@ class CombinedContainer(containers: Stream<Pair<IEnhancedContainer<*>, Iterable<
slots[slot].setChanged()
}
class Builder {
private val values = ArrayList<Pair<IEnhancedContainer<*>, Iterable<Int>>>()
class Builder<S : IContainerSlot> {
private val values = ArrayList<Pair<IEnhancedContainer<S>, Iterable<Int>>>()
fun add(container: Container): Builder {
fun add(container: Container): Builder<S> {
return add(IEnhancedContainer.wrap(container))
}
fun add(container: Container, slots: Iterator<Int>): Builder {
fun add(container: Container, slots: Iterator<Int>): Builder<S> {
return add(IEnhancedContainer.wrap(container), slots)
}
fun add(container: Container, slot: Int): Builder {
fun add(container: Container, slot: Int): Builder<S> {
return add(IEnhancedContainer.wrap(container), slot)
}
fun add(container: Container, from: Int, to: Int): Builder {
fun add(container: Container, from: Int, to: Int): Builder<S> {
return add(IEnhancedContainer.wrap(container), from, to)
}
fun add(container: Container, slots: Iterable<Int>): Builder {
fun add(container: Container, slots: Iterable<Int>): Builder<S> {
return add(IEnhancedContainer.wrap(container), slots)
}
fun add(container: IEnhancedContainer<*>): Builder {
fun add(container: IEnhancedContainer<S>): Builder<S> {
values.add(container to container.slotRange)
return this
}
fun add(container: IEnhancedContainer<*>, slots: Iterator<Int>): Builder {
fun add(container: IEnhancedContainer<S>, slots: Iterator<Int>): Builder<S> {
values.add(container to IntArrayList(slots))
return this
}
fun add(container: IEnhancedContainer<*>, slot: Int): Builder {
fun add(container: IEnhancedContainer<S>, slot: Int): Builder<S> {
values.add(container to intArrayOf(slot).asIterable())
return this
}
fun add(container: IEnhancedContainer<*>, from: Int, to: Int): Builder {
fun add(container: IEnhancedContainer<S>, from: Int, to: Int): Builder<S> {
values.add(container to (from .. to))
return this
}
fun add(container: IEnhancedContainer<*>, slots: Iterable<Int>): Builder {
fun add(container: IEnhancedContainer<S>, slots: Iterable<Int>): Builder<S> {
values.add(container to slots)
return this
}
fun build(): CombinedContainer {
fun build(): CombinedContainer<S> {
return CombinedContainer(values.stream())
}
}
companion object {
fun fromMenuSlots(slots: Iterator<net.minecraft.world.inventory.Slot>): CombinedContainer {
val builder = Builder()
fun fromMenuSlots(slots: Iterator<net.minecraft.world.inventory.Slot>): CombinedContainer<IContainerSlot> {
val builder = Builder<IContainerSlot>()
for (slot in slots) {
builder.add(slot.container, slot.slotIndex)

View File

@ -23,7 +23,7 @@ import ru.dbotthepony.mc.otm.core.nbt.set
* This is supposed to be counterpart to [SimpleContainer] of Minecraft itself, with more features
* and improved performance (inside [IEnhancedContainer] defined methods).
*/
abstract class EnhancedContainer<S : IContainerSlot>(private val size: Int) : IEnhancedContainer<S>, INBTSerializable<CompoundTag> {
abstract class EnhancedContainer<out S : IContainerSlot>(private val size: Int) : IEnhancedContainer<S>, INBTSerializable<CompoundTag> {
private val items = Array(size) { ItemStack.EMPTY }
private val observedItems = Array(size) { ItemStack.EMPTY }

View File

@ -10,7 +10,7 @@ import net.neoforged.neoforge.items.IItemHandlerModifiable
* Reinforced [ISlottedContainer] which slots are [IAutomatedContainerSlot]s, which
* subsequently allow this container to implement [IItemHandler]
*/
interface IAutomatedContainer<S : IAutomatedContainerSlot> : ISlottedContainer<S>, IItemHandlerModifiable {
interface IAutomatedContainer<out S : IAutomatedContainerSlot> : ISlottedContainer<S>, IItemHandlerModifiable {
override fun canPlaceItem(slot: Int, itemStack: ItemStack): Boolean {
return containerSlot(slot).canAutomationPlaceItem(itemStack)
}

View File

@ -24,7 +24,7 @@ import java.util.stream.StreamSupport
* This is useful because it allows to interact with actually enhanced and regular containers through unified interface,
* and actual implementations of this interface are likely to provide efficient method implementations in place of derived/emulated ones.
*/
interface IEnhancedContainer<S : IContainerSlot> : Container, RecipeInput, Iterable<ItemStack>, StackedContentsCompatible {
interface IEnhancedContainer<out S : IContainerSlot> : Container, RecipeInput, Iterable<ItemStack>, StackedContentsCompatible {
// https://youtrack.jetbrains.com/issue/KT-55080/Change-the-behavior-of-inheritance-delegation-to-delegates-implementing-Java-interfaces-with-default-methods
override fun getMaxStackSize(): Int {
return super.getMaxStackSize()

View File

@ -4,7 +4,7 @@ import net.minecraft.world.entity.player.StackedContents
import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack
interface IEnhancedCraftingContainer<S : IContainerSlot> : IEnhancedContainer<S>, CraftingContainer {
interface IEnhancedCraftingContainer<out S : IContainerSlot> : IEnhancedContainer<S>, CraftingContainer {
override fun getItems(): MutableList<ItemStack> {
return toList()
}
@ -13,7 +13,7 @@ interface IEnhancedCraftingContainer<S : IContainerSlot> : IEnhancedContainer<S>
forEach { contents.accountSimpleStack(it) }
}
class Wrapper<C : IEnhancedContainer<S>, S : IContainerSlot>(val parent: C, private val width: Int, private val height: Int) : IEnhancedCraftingContainer<S>, IEnhancedContainer<S> by parent {
class Wrapper<out C : IEnhancedContainer<S>, out S : IContainerSlot>(val parent: C, private val width: Int, private val height: Int) : IEnhancedCraftingContainer<S>, IEnhancedContainer<S> by parent {
init {
require(width * height == parent.containerSize) { "Crafting container dimensions ($width x $height) do not match container size provided (${parent.containerSize})" }
}

View File

@ -8,7 +8,7 @@ import ru.dbotthepony.kommons.collect.any
/**
* Skeletal implementation for containers which revolve around [IContainerSlot]
*/
interface ISlottedContainer<S : IContainerSlot> : IEnhancedContainer<S> {
interface ISlottedContainer<out S : IContainerSlot> : IEnhancedContainer<S> {
override fun setChanged(slot: Int) {
containerSlot(slot).setChanged()
}

View File

@ -39,6 +39,7 @@ import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot
import ru.dbotthepony.mc.otm.container.IEnhancedContainer
import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot
import ru.dbotthepony.mc.otm.container.computeSortedIndices
import ru.dbotthepony.mc.otm.container.sortWithIndices
@ -59,6 +60,7 @@ import ru.dbotthepony.mc.otm.network.readByteListUnbounded
import ru.dbotthepony.mc.otm.network.syncher.SynchableGroup
import ru.dbotthepony.mc.otm.network.wrap
import ru.dbotthepony.mc.otm.network.writeByteListUnbounded
import ru.dbotthepony.mc.otm.player.IPlayerInventorySlot
import java.util.*
import java.util.function.BooleanSupplier
import java.util.function.Consumer
@ -225,7 +227,7 @@ abstract class MatteryMenu(
protected var inventorySlotIndexStart = 0
protected var inventorySlotIndexEnd = 0
open inner class InventorySlot(container: Container, index: Int) : UserFilteredMenuSlot(container, index, 0, 0) {
open inner class InventorySlot(container: IEnhancedContainer<IPlayerInventorySlot>, index: Int) : UserFilteredMenuSlot(container, index, 0, 0) {
override fun mayPlace(itemStack: ItemStack): Boolean {
return !isInventorySlotLocked(index) && super.mayPlace(itemStack)
}
@ -238,19 +240,15 @@ abstract class MatteryMenu(
private set
init {
val mattery = player.matteryPlayer
if (mattery.hasExopack) {
chargeFlag = Delegate.Of(
getter = { slotIndex in mattery.slotsChargeFlag },
setter = booleanInput(true) { if (mattery.hasExopack) { if (it) mattery.slotsChargeFlag.add(slotIndex) else mattery.slotsChargeFlag.remove(slotIndex) } }::accept
)
if (player.matteryPlayer.hasExopack) {
val slot = container.containerSlot(index)
chargeFlag = Delegate.Of(slot::shouldCharge)
}
}
}
open inner class EquipmentMenuSlot(container: Container, index: Int, val type: net.minecraft.world.entity.EquipmentSlot) : InventorySlot(container, index) {
constructor(type: net.minecraft.world.entity.EquipmentSlot) : this(inventory, 34 + type.ordinal, type)
open inner class EquipmentMenuSlot(container: IEnhancedContainer<IPlayerInventorySlot>, index: Int, val type: net.minecraft.world.entity.EquipmentSlot) : InventorySlot(container, index) {
constructor(type: net.minecraft.world.entity.EquipmentSlot) : this(player.matteryPlayer.wrappedInventory, 34 + type.ordinal, type)
override fun setByPlayer(newItem: ItemStack, oldItem: ItemStack) {
inventory.player.onEquipItem(type, oldItem, newItem)
@ -280,7 +278,7 @@ abstract class MatteryMenu(
autoCreateInventoryFrame = autoFrame
offhandSlot = object : InventorySlot(inventory, 40) {
offhandSlot = object : InventorySlot(player.matteryPlayer.wrappedInventory, 40) {
override fun setByPlayer(newItem: ItemStack, oldItem: ItemStack) {
inventory.player.onEquipItem(net.minecraft.world.entity.EquipmentSlot.OFFHAND, oldItem, newItem)
super.setByPlayer(newItem, oldItem)

View File

@ -295,9 +295,9 @@ class MatteryPlayer(val ply: Player) {
_combinedInventory3 = null
}
private var _combinedInventory: CombinedContainer? = null
private var _combinedInventory2: CombinedContainer? = null
private var _combinedInventory3: CombinedContainer? = null
private var _combinedInventory: CombinedContainer<IPlayerInventorySlot>? = null
private var _combinedInventory2: CombinedContainer<IPlayerInventorySlot>? = null
private var _combinedInventory3: CombinedContainer<IPlayerInventorySlot>? = null
val wrappedInventory = PlayerInventoryWrapper(this)
@ -307,7 +307,7 @@ class MatteryPlayer(val ply: Player) {
}
}
val combinedInventory: CombinedContainer
val combinedInventory: CombinedContainer<IPlayerInventorySlot>
get() {
if (_combinedInventory == null)
_combinedInventory = CombinedContainer(wrappedInventory, exopackContainer)
@ -315,7 +315,7 @@ class MatteryPlayer(val ply: Player) {
return _combinedInventory!!
}
val inventoryAndExopack: CombinedContainer
val inventoryAndExopack: CombinedContainer<IPlayerInventorySlot>
get() {
if (_combinedInventory2 == null)
_combinedInventory2 = CombinedContainer(wrappedItemInventory, exopackContainer)
@ -323,10 +323,10 @@ class MatteryPlayer(val ply: Player) {
return _combinedInventory2!!
}
val inventoryAndExopackNoHotbar: CombinedContainer
val inventoryAndExopackNoHotbar: CombinedContainer<IPlayerInventorySlot>
get() {
if (_combinedInventory3 == null)
_combinedInventory3 = CombinedContainer.Builder()
_combinedInventory3 = CombinedContainer.Builder<IPlayerInventorySlot>()
.add(wrappedItemInventory, 9 .. 35)
.add(exopackContainer).build()