diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt index b68cca149..d978031c2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/SlottedContainer.kt @@ -8,11 +8,15 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag +import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.player.Player import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.neoforged.neoforge.common.util.INBTSerializable import org.apache.logging.log4j.LogManager +import ru.dbotthepony.mc.otm.core.isNotEmpty +import ru.dbotthepony.mc.otm.core.math.set +import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.data.codec.minRange import java.util.function.Predicate @@ -111,6 +115,36 @@ class SlottedContainer( } private val lostItems = ArrayList() + private var provider: HolderLookup.Provider? = null + + fun takeLostItems(): List { + if (lostItems.isEmpty()) + return listOf() + + val provider = provider?.createSerializationContext(NbtOps.INSTANCE) ?: return listOf() + val result = ArrayList() + + for (entry in lostItems) { + if ("item" in entry) { + ItemStack.OPTIONAL_CODEC.decode(provider, entry["item"]) + .ifError { LOGGER.warn("Unable to deserialize 'lost' item: ${it.message()}") } + .ifSuccess { if (it.first.isNotEmpty) result.add(it.first) } + } + } + + lostItems.clear() + return result + } + + fun takeLostItems(player: ServerPlayer) { + for (stack in takeLostItems()) { + player.inventory.add(stack) + + if (stack.isNotEmpty) { + player.drop(stack, false, false) + } + } + } override fun serializeNBT(provider: HolderLookup.Provider): ListTag { return ListTag().also { @@ -137,6 +171,16 @@ class SlottedContainer( for ((item, slot) in items) { if (slot in 0 until containerSize) { slots[slot].item = item + } else if (item.isNotEmpty) { + ItemStack.CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), item) + .ifError { LOGGER.warn("Unable to serialize 'lost' item: ${it.message()}") } + .ifSuccess { s -> + this.provider = provider + + lostItems.add(CompoundTag().also { + it["item"] = s + }) + } } } @@ -162,6 +206,7 @@ class SlottedContainer( slots[i].deserializeNBT(provider, element) } else { lostItems.add(element) + this.provider = provider } } } else {