KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/item/IContainer.kt
2024-04-21 22:26:02 +07:00

189 lines
3.6 KiB
Kotlin

package ru.dbotthepony.kstarbound.item
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.item.ItemDescriptor
import java.util.random.RandomGenerator
interface IContainer {
var size: Int
operator fun get(index: Int): ItemStack
operator fun set(index: Int, value: ItemStack)
fun ageItems(by: Double): Boolean {
var any = false
for (i in 0 until size) {
val (newItem, hasAdvanced) = this[i].advanceAge(by)
any = hasAdvanced || any
if (newItem != null) {
this[i] = newItem
}
}
return any
}
fun hasCountOfItem(item: ItemDescriptor, exactMatch: Boolean = false): Long {
var count = 0L
for (i in 0 until size) {
if (this[i].matches(item, exactMatch)) {
count += this[i].size
}
}
return count
}
fun hasCountOfItem(item: ItemStack, exactMatch: Boolean = false): Long {
var count = 0L
for (i in 0 until size) {
if (this[i].matches(item, exactMatch)) {
count += this[i].size
}
}
return count
}
fun shuffle(random: RandomGenerator) {
for (i in 0 until size) {
val rand = random.nextInt(size)
val a = this[i]
val b = this[rand]
this[rand] = a
this[i] = b
}
}
// puts item into container, returns remaining not put items
fun add(item: ItemStack, simulate: Boolean = false): ItemStack {
val copy = item.copy()
// first, try to put into not empty slots first
for (i in 0 until size) {
val itemThere = this[i]
if (itemThere.isStackable(copy)) {
val newCount = (itemThere.size + copy.size).coerceAtMost(itemThere.maxStackSize)
val diff = newCount - itemThere.size
copy.size -= diff
if (!simulate)
itemThere.size += diff
if (copy.isEmpty)
return ItemStack.EMPTY
}
}
// then try to move into empty slots
for (i in 0 until size) {
val itemThere = this[i]
if (itemThere.isEmpty) {
if (copy.size > copy.maxStackSize) {
if (!simulate)
this[i] = copy.copy(copy.maxStackSize)
copy.size -= copy.maxStackSize
} else {
if (!simulate)
this[i] = copy
return ItemStack.EMPTY
}
}
}
return copy
}
fun clear()
fun toJson(store: Boolean = false): JsonArray {
val result = JsonArray(size)
if (store) {
Starbound.storeJson {
for (i in 0 until size) {
result.add(this[i].toJson())
}
}
} else {
for (i in 0 until size) {
result.add(this[i].toJson())
}
}
return result
}
fun fromJson(json: JsonElement, resize: Boolean = false): List<ItemStack> {
clear()
val read = ArrayList<ItemStack>()
val array = json.asJsonArray
var nonEmpty = 0
for (i in 0 until array.size()) {
val item = ItemDescriptor(array[i])
if (item.isNotEmpty)
nonEmpty++
read.add(item.build())
}
if (read.size > size) {
// we have a problem
if (resize) {
// no problem
size = read.size
for ((i, item) in read.withIndex()) {
this[i] = item
}
return emptyList()
} else {
// first, put items to their place if they are within container size
for (i in 0 until size) {
this[i] = read[i]
}
// second, try to move remaining item into empty or stackable slots
val lost = ArrayList<ItemStack>()
for (i in size until read.size) {
val remaining = add(read[i])
if (remaining.isNotEmpty) {
lost.add(remaining)
}
}
// if we weren't capable of putting excess items into container, then what a shame.
return lost
}
} else {
if (read.size < size && resize)
size = read.size
for ((i, item) in read.withIndex()) {
this[i] = item
}
return emptyList()
}
}
}