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 { clear() val read = ArrayList() 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() 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() } } }