Update MatteryPlayer to use Enhanced containers instead of Mattery containers
This commit is contained in:
parent
d57371ca13
commit
a2263c5725
@ -10,9 +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 : ISlottedContainer, IItemHandlerModifiable {
|
||||
override fun containerSlot(slot: Int): IAutomatedContainerSlot
|
||||
|
||||
interface IAutomatedContainer<S : IAutomatedContainerSlot> : ISlottedContainer<S>, IItemHandlerModifiable {
|
||||
override fun canPlaceItem(slot: Int, itemStack: ItemStack): Boolean {
|
||||
return containerSlot(slot).canAutomationPlaceItem(itemStack)
|
||||
}
|
||||
|
@ -8,7 +8,17 @@ import ru.dbotthepony.kommons.collect.any
|
||||
/**
|
||||
* Skeletal implementation for containers which revolve around [IContainerSlot]
|
||||
*/
|
||||
interface ISlottedContainer : IEnhancedContainer {
|
||||
interface ISlottedContainer<S : IContainerSlot> : IEnhancedContainer {
|
||||
override fun containerSlot(slot: Int): S
|
||||
|
||||
override fun slotIterator(): Iterator<S> {
|
||||
return super.slotIterator() as Iterator<S>
|
||||
}
|
||||
|
||||
override fun nonEmptySlotIterator(): Iterator<S> {
|
||||
return super.nonEmptySlotIterator() as Iterator<S>
|
||||
}
|
||||
|
||||
override fun setChanged(slot: Int) {
|
||||
containerSlot(slot).setChanged()
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class SlottedContainer(
|
||||
slots: Collection<MarkedSlotProvider<*>>,
|
||||
private val stillValid: Predicate<Player>,
|
||||
private val globalChangeListeners: Array<Runnable>
|
||||
) : IAutomatedContainer, INBTSerializable<Tag> {
|
||||
) : IAutomatedContainer<ContainerSlot>, INBTSerializable<Tag> {
|
||||
interface ISlotGroup<T : ContainerSlot> : List<T> {
|
||||
/**
|
||||
* @see IAutomatedContainer.addItem
|
||||
@ -140,7 +140,7 @@ class SlottedContainer(
|
||||
}
|
||||
}
|
||||
|
||||
override fun containerSlot(slot: Int): IAutomatedContainerSlot {
|
||||
override fun containerSlot(slot: Int): ContainerSlot {
|
||||
return slots[slot]
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
package ru.dbotthepony.mc.otm.player
|
||||
|
||||
import net.minecraft.world.item.Item
|
||||
import ru.dbotthepony.mc.otm.container.EnhancedContainer
|
||||
import ru.dbotthepony.mc.otm.container.IContainerSlot
|
||||
|
||||
class ExopackContainer(size: Int, val player: MatteryPlayer) : EnhancedContainer(size) {
|
||||
private inner class Slot(slot: Int) : IContainerSlot.Simple(slot, this@ExopackContainer), IPlayerInventorySlot {
|
||||
override var shouldCharge: Boolean
|
||||
get() = (PlayerInventoryWrapper.SLOTS + slot) in player.slotsChargeFlag
|
||||
set(value) { if (value) player.slotsChargeFlag.add(PlayerInventoryWrapper.SLOTS + slot) else player.slotsChargeFlag.remove(PlayerInventoryWrapper.SLOTS + slot) }
|
||||
|
||||
override var filter: Item?
|
||||
get() = player.slotFilters[PlayerInventoryWrapper.SLOTS + slot]
|
||||
set(value) { if (value == null) player.slotFilters.remove(PlayerInventoryWrapper.SLOTS + slot) else player.slotFilters[PlayerInventoryWrapper.SLOTS + slot] = value }
|
||||
}
|
||||
|
||||
override fun containerSlot(slot: Int): IPlayerInventorySlot {
|
||||
return Slot(slot)
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.player
|
||||
|
||||
import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot
|
||||
|
||||
interface IPlayerInventorySlot : IFilteredContainerSlot {
|
||||
var shouldCharge: Boolean
|
||||
}
|
@ -2,6 +2,9 @@ package ru.dbotthepony.mc.otm.player
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
||||
import it.unimi.dsi.fastutil.ints.IntSet
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
@ -12,6 +15,7 @@ import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
|
||||
@ -76,12 +80,16 @@ import ru.dbotthepony.mc.otm.config.PlayerConfig
|
||||
import ru.dbotthepony.mc.otm.config.ExopackConfig
|
||||
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
||||
import ru.dbotthepony.mc.otm.container.DynamicallyProxiedContainer
|
||||
import ru.dbotthepony.mc.otm.container.EnhancedContainer
|
||||
import ru.dbotthepony.mc.otm.container.IContainer
|
||||
import ru.dbotthepony.mc.otm.container.IContainerSlot
|
||||
import ru.dbotthepony.mc.otm.container.IEnhancedContainer
|
||||
import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot
|
||||
import ru.dbotthepony.mc.otm.container.IMatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.slotted.ContainerSlot
|
||||
import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer
|
||||
import ru.dbotthepony.mc.otm.container.util.slotIterator
|
||||
import ru.dbotthepony.mc.otm.container.vanishCursedItems
|
||||
import ru.dbotthepony.mc.otm.core.*
|
||||
@ -95,6 +103,7 @@ import ru.dbotthepony.mc.otm.core.nbt.getStringList
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.util.Savetables
|
||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
||||
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
|
||||
import ru.dbotthepony.mc.otm.menu.IItemStackSortingSettings
|
||||
import ru.dbotthepony.mc.otm.network.*
|
||||
@ -158,10 +167,10 @@ class MatteryPlayer(val ply: Player) {
|
||||
val level: Level get() = capability.ply.level()
|
||||
}
|
||||
|
||||
private inner class PlayerMatteryContainer(size: Int) : MatteryContainer(size) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
private inner class PlayerMatteryContainer(size: Int) : EnhancedContainer(size) {
|
||||
override fun notifySlotChanged(slot: Int, old: ItemStack) {
|
||||
if (ply is ServerPlayer) {
|
||||
val item = new.copy()
|
||||
val item = this[slot].copy()
|
||||
|
||||
tickList.once {
|
||||
MatteryInventoryChangeTrigger.trigger(ply, combinedInventory, item)
|
||||
@ -249,22 +258,20 @@ class MatteryPlayer(val ply: Player) {
|
||||
* If you want to properly extend Exopack suit capacity, add your value into this map
|
||||
*/
|
||||
val exopackSlotModifier = UUIDIntModifiersMap(observer = observer@{
|
||||
if (it < 0) {
|
||||
exopackContainer = PlayerMatteryContainer(0)
|
||||
} else {
|
||||
exopackContainer = PlayerMatteryContainer(it)
|
||||
}
|
||||
exopackContainer = ExopackContainer(it.coerceAtLeast(0), this)
|
||||
}, backingMap = this.exopackSlotModifierMap.delegate)
|
||||
|
||||
val regularSlotFilters = immutableList(Inventory.INVENTORY_SIZE) {
|
||||
syncher.add(null, StreamCodecs.ITEM_TYPE.nullable())
|
||||
}
|
||||
|
||||
val slotsChargeFlag = syncher.set(
|
||||
backing = ListenableSet(IntAVLTreeSet()),
|
||||
codec = StreamCodecs.VAR_INT,
|
||||
).delegate
|
||||
|
||||
val slotFilters = syncher.map(
|
||||
backing = ListenableMap(Int2ObjectOpenHashMap()),
|
||||
keyCodec = StreamCodecs.VAR_INT,
|
||||
valueCodec = StreamCodecs.ITEM_TYPE
|
||||
).delegate
|
||||
|
||||
private fun slotChargeToDefault() {
|
||||
// броня
|
||||
slotsChargeFlag.add(36)
|
||||
@ -277,15 +284,12 @@ class MatteryPlayer(val ply: Player) {
|
||||
slotChargeToDefault()
|
||||
}
|
||||
|
||||
private var exopackContainerSynchedFilters: List<Closeable> = listOf()
|
||||
|
||||
/**
|
||||
* Exopack container, which actually store items inside Exopack
|
||||
*/
|
||||
var exopackContainer: MatteryContainer = PlayerMatteryContainer(0)
|
||||
var exopackContainer: ExopackContainer = ExopackContainer(0, this)
|
||||
private set(value) {
|
||||
_exoPackMenu = null
|
||||
exopackContainerSynchedFilters.forEach { it.close() }
|
||||
|
||||
@Suppress("SENSELESS_COMPARISON") // false positive - fields of player can easily be nulls, despite annotations saying otherwise
|
||||
if (ply.containerMenu != null && (ply !is ServerPlayer || ply.connection != null)) {
|
||||
@ -300,7 +304,6 @@ class MatteryPlayer(val ply: Player) {
|
||||
}
|
||||
|
||||
value.deserializeNBT(ply.level().registryAccess(), field.serializeNBT(ply.level().registryAccess()))
|
||||
exopackContainerSynchedFilters = value.synchableFilters.map { syncher.add0(it) }
|
||||
field = value
|
||||
|
||||
_combinedInventory = null
|
||||
@ -312,34 +315,9 @@ class MatteryPlayer(val ply: Player) {
|
||||
private var _combinedInventory2: CombinedContainer? = null
|
||||
private var _combinedInventory3: CombinedContainer? = null
|
||||
|
||||
val wrappedInventory: IMatteryContainer = object : IMatteryContainer, IContainer by DynamicallyProxiedContainer(ply::getInventory) {
|
||||
override fun getSlotFilter(slot: Int): Item? {
|
||||
return regularSlotFilters.getOrNull(slot)?.get()
|
||||
}
|
||||
val wrappedInventory = PlayerInventoryWrapper(this)
|
||||
|
||||
override fun setSlotFilter(slot: Int, filter: Item?): Boolean {
|
||||
regularSlotFilters.getOrNull(slot)?.accept(filter)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun setChanged(slot: Int) {
|
||||
ply.inventory.setChanged()
|
||||
}
|
||||
|
||||
override fun clearSlotFilters() {
|
||||
regularSlotFilters.forEach { it.accept(null) }
|
||||
}
|
||||
|
||||
override fun containerSlot(slot: Int): IFilteredContainerSlot {
|
||||
return object : IContainerSlot.Simple(slot, this), IFilteredContainerSlot {
|
||||
override var filter: Item?
|
||||
get() = regularSlotFilters.getOrNull(slot)?.get()
|
||||
set(value) { regularSlotFilters.getOrNull(slot)?.accept(value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val wrappedItemInventory: IMatteryContainer = object : IMatteryContainer by wrappedInventory {
|
||||
val wrappedItemInventory: IEnhancedContainer = object : IEnhancedContainer by wrappedInventory {
|
||||
override fun getContainerSize(): Int {
|
||||
return 36
|
||||
}
|
||||
@ -955,11 +933,8 @@ class MatteryPlayer(val ply: Player) {
|
||||
}
|
||||
}
|
||||
|
||||
tag["regularSlotFilters"] = ListTag().also {
|
||||
for (filter in regularSlotFilters) {
|
||||
it.add(StringTag.valueOf(filter.value?.registryName?.toString() ?: ""))
|
||||
}
|
||||
}
|
||||
tag["slotFilters"] = filtersCodec.encodeStart(registry.createSerializationContext(NbtOps.INSTANCE), slotFilters.entries.map { it.key to it.value })
|
||||
.getOrThrow { IllegalStateException("Unable to serialize slot filters: $it") }
|
||||
|
||||
tag.putIntArray("slotsChargeFlag", slotsChargeFlag.toIntArray())
|
||||
return tag
|
||||
@ -977,18 +952,16 @@ class MatteryPlayer(val ply: Player) {
|
||||
ExopackSlotsExpandedTrigger.trigger(ply, 0, exopackContainer.containerSize)
|
||||
}
|
||||
|
||||
for (filter in regularSlotFilters) {
|
||||
filter.value = null
|
||||
}
|
||||
|
||||
slotFilters.clear()
|
||||
slotsChargeFlag.clear()
|
||||
|
||||
val regularSlotFilters = tag.getStringList("regularSlotFilters")
|
||||
|
||||
for (i in 0 until regularSlotFilters.size.coerceAtMost(this.regularSlotFilters.size)) {
|
||||
val path = regularSlotFilters[i].asString
|
||||
if (path == "") continue
|
||||
this.regularSlotFilters[i].value = BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(path) ?: continue)
|
||||
if ("slotFilters" in tag) {
|
||||
filtersCodec.decode(registry.createSerializationContext(NbtOps.INSTANCE), tag["slotFilters"])
|
||||
.ifError { LOGGER.error("Unable to deserialize slot filters: ${it.message()}") }
|
||||
.resultOrPartial()
|
||||
.ifPresent {
|
||||
it.first.forEach { (a, b) -> slotFilters[a] = b }
|
||||
}
|
||||
}
|
||||
|
||||
if ("slotsChargeFlag" in tag) {
|
||||
@ -1341,6 +1314,15 @@ class MatteryPlayer(val ply: Player) {
|
||||
|
||||
@Suppress("unused")
|
||||
companion object {
|
||||
private val filtersCodec: Codec<List<Pair<Int, Item>>> = Codec.list(
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
Codec.INT.minRange(0).fieldOf("slot").forGetter { it.first },
|
||||
BuiltInRegistries.ITEM.byNameCodec().fieldOf("filter").forGetter { it.second }
|
||||
).apply(it, ::Pair)
|
||||
}
|
||||
)
|
||||
|
||||
private val offhandSlotRange = IntSet.of(40)
|
||||
|
||||
init {
|
||||
|
@ -0,0 +1,73 @@
|
||||
package ru.dbotthepony.mc.otm.player
|
||||
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.container.ISlottedContainer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.set
|
||||
|
||||
class PlayerInventoryWrapper(val player: MatteryPlayer) : ISlottedContainer<IPlayerInventorySlot> {
|
||||
val inventory: Inventory
|
||||
get() = player.ply.inventory
|
||||
|
||||
private inner class Slot(val slot: Int) : IPlayerInventorySlot {
|
||||
override fun setChanged() {
|
||||
inventory.setChanged()
|
||||
}
|
||||
|
||||
override var filter: Item?
|
||||
get() = player.slotFilters[slot]
|
||||
set(value) { if (value == null) player.slotFilters.remove(slot) else player.slotFilters[slot] = value }
|
||||
override var shouldCharge: Boolean
|
||||
get() = slot in player.slotsChargeFlag
|
||||
set(value) { if (value) player.slotsChargeFlag.add(slot) else player.slotsChargeFlag.remove(slot) }
|
||||
override var item: ItemStack
|
||||
get() = inventory[slot]
|
||||
set(value) { inventory[slot] = value }
|
||||
override val maxStackSize: Int
|
||||
get() = inventory.maxStackSize
|
||||
|
||||
override fun maxStackSize(item: ItemStack): Int {
|
||||
return inventory.getMaxStackSize(item)
|
||||
}
|
||||
|
||||
override fun remove(): ItemStack {
|
||||
return inventory.removeItemNoUpdate(slot)
|
||||
}
|
||||
|
||||
override fun remove(count: Int): ItemStack {
|
||||
return inventory.removeItem(slot, count)
|
||||
}
|
||||
}
|
||||
|
||||
private val slots = Array(SLOTS) { Slot(it) }
|
||||
|
||||
override val hasFilterableSlots: Boolean
|
||||
get() = true
|
||||
|
||||
override fun containerSlot(slot: Int): IPlayerInventorySlot {
|
||||
return slots[slot]
|
||||
}
|
||||
|
||||
override fun clearContent() {
|
||||
slots.forEach { it.remove() }
|
||||
}
|
||||
|
||||
override fun setChanged() {
|
||||
inventory.setChanged()
|
||||
}
|
||||
|
||||
override fun getContainerSize(): Int {
|
||||
return slots.size
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean {
|
||||
return inventory.stillValid(player)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SLOTS = 41
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user