Synchronized maps, update save keys, exosuit inventory upgrades as items

This commit is contained in:
DBotThePony 2022-09-05 23:13:48 +07:00
parent 2915ef675b
commit e7653d559f
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 555 additions and 48 deletions

View File

@ -56,10 +56,17 @@ private fun misc(provider: MatteryLanguageProvider) {
gui("exosuit.already_activated", "You already have exosuit following you") gui("exosuit.already_activated", "You already have exosuit following you")
gui("exosuit_upgrades.no_exosuit", "This piece of technology seems to be of no use to you.... Or is it?!")
gui("exosuit_upgrades.already_activated", "Upgrade is already active!")
gui("exosuit_upgrades.slots_upgrade", "Using this will permanently grant %s slots in ExoSuit inventory.")
gui("power_supplier.active_nodes", "Currently demanding nodes: %s") gui("power_supplier.active_nodes", "Currently demanding nodes: %s")
misc("battery.single_use", "Single use battery, can not be recharged.") misc("battery.single_use", "Single use battery, can not be recharged.")
misc("exosuit_upgrades.slots_upgraded", "Your exosuit has permanently gained %s slots")
misc("exosuit.granted1", "As you keep pressing fingerprint reader, you are getting hurt in finger.") misc("exosuit.granted1", "As you keep pressing fingerprint reader, you are getting hurt in finger.")
misc("exosuit.granted2", "After you raise your finger, fingerprint reader glows very bright.") misc("exosuit.granted2", "After you raise your finger, fingerprint reader glows very bright.")
misc("exosuit.granted3", "Then, fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.") misc("exosuit.granted3", "Then, fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.")

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability package ru.dbotthepony.mc.otm.capability
import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.core.Direction import net.minecraft.core.Direction
@ -64,6 +65,26 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
var hasExoSuit by synchronizer.bool() var hasExoSuit by synchronizer.bool()
private val exoSuitSlotCountModifiersMap: MutableMap<UUID, Int> by synchronizer.Map(
keyCodec = UUIDValueCodec,
valueCodec = IntValueCodec,
backingMap = Object2IntAVLTreeMap(),
callback = {
this.exoSuitSlotCountModifiers.recompute()
}
)
val exoSuitSlotCountModifiers = UUIDIntModifiersMap(observer = observer@{
if (ply !is ServerPlayer)
return@observer
if (it < 0) {
exoSuitSlotCount = 0
} else {
exoSuitSlotCount = it
}
}, backingMap = this.exoSuitSlotCountModifiersMap)
var exoSuitSlotCount by synchronizer.int(setter = setter@{ value, access, _ -> var exoSuitSlotCount by synchronizer.int(setter = setter@{ value, access, _ ->
require(value >= 0) { "Invalid slot count $value" } require(value >= 0) { "Invalid slot count $value" }
@ -334,37 +355,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
override fun serializeNBT(): CompoundTag { override fun serializeNBT(): CompoundTag {
val tag = CompoundTag() val tag = CompoundTag()
tag["androidEnergy"] = androidEnergy.serializeNBT() // iteration
val featureList = ListTag()
for (feature in features.values) {
val featureNbt = feature.serializeNBT()
featureNbt["id"] = feature.type.registryName!!.toString()
featureList.add(featureNbt)
}
tag["features"] = featureList
tag["is_android"] = isAndroid
tag["will_become_android"] = willBecomeAndroid
val list = ListTag()
for ((type, instance) in research) {
val researchTag = instance.serializeNBT()
researchTag["id"] = type.registryName!!.toString()
list.add(researchTag)
}
tag["research"] = list
tag["iteration"] = iteration tag["iteration"] = iteration
tag["should_send_iteration"] = shouldSendIteration tag["shouldSendIteration"] = shouldSendIteration
tag["death_log"] = ListTag().also { tag["deathLog"] = ListTag().also {
for ((ticks, component) in deathLog) { for ((ticks, component) in deathLog) {
it.add(CompoundTag().also { it.add(CompoundTag().also {
it["ticks"] = ticks it["ticks"] = ticks
@ -373,21 +368,47 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
} }
} }
tag["exo_suit_slot_count"] = exoSuitSlotCount // exosuit
tag["has_exo_suit"] = hasExoSuit tag["hasExoSuit"] = hasExoSuit
tag["exo_suit_inventory"] = exoSuitContainer.serializeNBT() tag["exoSuitContainer"] = exoSuitContainer.serializeNBT()
tag["exo_suit_crafting_upgraded"] = isExoSuitCraftingUpgraded tag["isExoSuitCraftingUpgraded"] = isExoSuitCraftingUpgraded
tag["exoSuitSlotCountModifiers"] = exoSuitSlotCountModifiers.serializeNBT()
// android
tag["androidEnergy"] = androidEnergy.serializeNBT()
tag["isAndroid"] = isAndroid
tag["willBecomeAndroid"] = willBecomeAndroid
val featureList = ListTag()
val researchList = ListTag()
for (feature in features.values) {
featureList.add(feature.serializeNBT().also {
it["id"] = feature.type.registryName!!.toString()
})
}
for ((type, instance) in research) {
researchList.add(instance.serializeNBT().also {
it["id"] = type.registryName!!.toString()
})
}
tag["features"] = featureList
tag["research"] = researchList
return tag return tag
} }
override fun deserializeNBT(tag: CompoundTag) { override fun deserializeNBT(tag: CompoundTag) {
// iterations
iteration = tag.getInt("iteration") iteration = tag.getInt("iteration")
shouldSendIteration = tag.getBoolean("should_send_iteration") shouldSendIteration = tag.getBoolean("shouldSendIteration")
deathLog.clear() deathLog.clear()
for (value in tag.getCompoundList("death_log")) { for (value in tag.getCompoundList("deathLog")) {
val component = Component.Serializer.fromJson(value.getString("component")) val component = Component.Serializer.fromJson(value.getString("component"))
if (component != null) { if (component != null) {
@ -395,9 +416,21 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
} }
} }
// exosuit
hasExoSuit = tag.getBoolean("hasExoSuit")
exoSuitContainer.deserializeNBT(tag["exoSuitContainer"])
isExoSuitCraftingUpgraded = tag.getBoolean("isExoSuitCraftingUpgraded")
tag.map("exoSuitSlotCountModifiers", exoSuitSlotCountModifiers::deserializeNBT)
// android
isAndroid = tag.getBoolean("isAndroid")
willBecomeAndroid = tag.getBoolean("willBecomeAndroid")
tag.map("androidEnergy", androidEnergy::deserializeNBT) tag.map("androidEnergy", androidEnergy::deserializeNBT)
features.clear() features.clear()
research.clear()
for (featureTag in tag.getCompoundList("features")) { for (featureTag in tag.getCompoundList("features")) {
val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(featureTag.getString("id"))) val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(featureTag.getString("id")))
@ -414,10 +447,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
} }
} }
isAndroid = tag.getBoolean("is_android")
willBecomeAndroid = tag.getBoolean("will_become_android")
research.clear()
for (researchTag in tag.getCompoundList("research")) { for (researchTag in tag.getCompoundList("research")) {
val research = MRegistry.ANDROID_RESEARCH.getValue(ResourceLocation(researchTag.getString("id"))) val research = MRegistry.ANDROID_RESEARCH.getValue(ResourceLocation(researchTag.getString("id")))
@ -427,11 +456,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
this.research[research] = instance this.research[research] = instance
} }
} }
hasExoSuit = tag.getBoolean("has_exo_suit")
exoSuitSlotCount = tag.getInt("exo_suit_slot_count")
exoSuitContainer.deserializeNBT(tag["exo_suit_inventory"])
isExoSuitCraftingUpgraded = tag.getBoolean("exo_suit_crafting_upgraded")
} }
fun dropBattery() { fun dropBattery() {

View File

@ -0,0 +1,96 @@
package ru.dbotthepony.mc.otm.capability
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.core.contains
import java.util.UUID
class UUIDIntModifiersMap(private val observer: (Int) -> Unit, private val backingMap: MutableMap<UUID, Int> = HashMap()) : INBTSerializable<ListTag> {
var value: Int = 0
private set
fun recompute() {
var value = 0
for (mapValue in backingMap.values) {
value += mapValue
}
if (this.value != value) {
this.value = value
observer.invoke(value)
}
}
operator fun set(key: UUID, value: Int): Boolean {
val old = backingMap.put(key, value)
if (old == value) {
return false
}
this.value += value - (old ?: 0)
observer.invoke(this.value)
return true
}
operator fun get(key: UUID): Int? {
return backingMap[key]
}
operator fun contains(key: UUID): Boolean {
return backingMap.containsKey(key)
}
fun remove(key: UUID): Boolean {
if (!backingMap.containsKey(key)) {
return false
}
val old = backingMap.remove(key) ?: return true
value -= old
return true
}
fun clear() {
backingMap.clear()
val old = this.value
this.value = 0
if (old != this.value) {
observer.invoke(this.value)
}
}
override fun serializeNBT(): ListTag {
return ListTag().also {
for ((key, value) in backingMap) {
it.add(CompoundTag().also {
it.putUUID("key", key)
it.putInt("value", value)
})
}
}
}
override fun deserializeNBT(nbt: ListTag) {
backingMap.clear()
val old = this.value
this.value = 0
for (value in nbt) {
value as CompoundTag
if (value.contains("key", "value")) {
val int = value.getInt("value")
backingMap.put(value.getUUID("key"), int)
this.value += int
}
}
if (old != this.value) {
observer.invoke(this.value)
}
}
}

View File

@ -0,0 +1,96 @@
package ru.dbotthepony.mc.otm.item
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.runIfClient
import java.util.UUID
class ExoSuitSlotUpgradeItem(
val id: UUID?,
val slotCount: Int,
properties: Properties = Properties().stacksTo(64).rarity(Rarity.UNCOMMON).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)
) : Item(properties) {
val isCreative: Boolean get() = id == null
override fun getUseDuration(p_41454_: ItemStack): Int {
return 30
}
override fun appendHoverText(p_41421_: ItemStack, p_41422_: Level?, tooltip: MutableList<Component>, p_41424_: TooltipFlag) {
super.appendHoverText(p_41421_, p_41422_, tooltip, p_41424_)
val alreadyHasExosuit = runIfClient(true) {
minecraft.player?.matteryPlayer?.hasExoSuit == true
}
if (!alreadyHasExosuit) {
tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.no_exosuit").withStyle(ChatFormatting.GRAY))
if (runIfClient(false) { minecraft.player?.isCreative != true }) {
return
}
}
val alreadyHas = id != null && runIfClient(false) {
minecraft.player?.matteryPlayer?.exoSuitSlotCountModifiers?.contains(id) == true
}
if (alreadyHas) {
tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.already_activated").withStyle(ChatFormatting.DARK_RED))
}
tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.slots_upgrade", slotCount).withStyle(ChatFormatting.DARK_GREEN))
}
override fun use(p_41432_: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
val matteryPlayer = player.matteryPlayer ?: return super.use(p_41432_, player, hand)
if (matteryPlayer.hasExoSuit && (id == null || id !in matteryPlayer.exoSuitSlotCountModifiers)) {
player.startUsingItem(hand)
return InteractionResultHolder.consume(player.getItemInHand(hand))
}
return super.use(p_41432_, player, hand)
}
override fun finishUsingItem(itemStack: ItemStack, level: Level, player: LivingEntity): ItemStack {
if (player !is Player) return super.finishUsingItem(itemStack, level, player)
val matteryPlayer = player.matteryPlayer ?: return super.finishUsingItem(itemStack, level, player)
if (!matteryPlayer.hasExoSuit || (id != null && id in matteryPlayer.exoSuitSlotCountModifiers)) {
return super.finishUsingItem(itemStack, level, player)
}
if (!player.abilities.instabuild)
itemStack.shrink(1)
if (player is ServerPlayer) {
if (id != null) {
matteryPlayer.exoSuitSlotCountModifiers[id] = slotCount
} else {
matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount
}
player.displayClientMessage(TranslatableComponent("otm.exosuit_upgrades.slots_upgraded", slotCount).withStyle(ChatFormatting.WHITE), false)
}
return itemStack
}
override fun getUseAnimation(p_41452_: ItemStack): UseAnim = UseAnim.BOW
}

View File

@ -8,7 +8,10 @@ import java.io.DataOutputStream
import java.io.InputStream import java.io.InputStream
import java.math.BigDecimal import java.math.BigDecimal
import java.util.* import java.util.*
import kotlin.ConcurrentModificationException
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@ -95,20 +98,39 @@ class EnumValueCodec<V : Enum<V>>(private val clazz: Class<out V>) : INetworkVal
} }
} }
sealed interface IField<V> : ReadWriteProperty<Any, V> { sealed interface IField<V> : ReadOnlyProperty<Any, V> {
fun observe() fun observe()
fun markDirty() fun markDirty()
var value: V val value: V
fun write(stream: DataOutputStream) fun write(stream: DataOutputStream)
fun read(stream: DataInputStream) fun read(stream: DataInputStream)
override fun getValue(thisRef: Any, property: KProperty<*>): V { override fun getValue(thisRef: Any, property: KProperty<*>): V {
return value return value
} }
}
sealed interface IMutableField<V> : IField<V>, ReadWriteProperty<Any, V> {
override var value: V
override fun setValue(thisRef: Any, property: KProperty<*>, value: V) { override fun setValue(thisRef: Any, property: KProperty<*>, value: V) {
this.value = value this.value = value
} }
override fun getValue(thisRef: Any, property: KProperty<*>): V {
return super.getValue(thisRef, property)
}
}
data class MapChangeset<out K, out V>(
val action: MapAction,
val key: K?,
val value: V?
)
enum class MapAction {
CLEAR, ADD, REMOVE
} }
class FieldSynchronizer { class FieldSynchronizer {
@ -235,13 +257,29 @@ class FieldSynchronizer {
return ObservedField(delegate, ItemStackValueCodec) return ObservedField(delegate, ItemStackValueCodec)
} }
fun <K, V> map(
keyCodec: INetworkValueCodec<K>,
valueCodec: INetworkValueCodec<V>,
callback: ((changes: Collection<MapChangeset<K, V>>) -> Unit)? = null,
backingMap: MutableMap<K, V> = HashMap(),
observingBackingMap: MutableMap<K, V>? = null,
): Map<K, V> {
return Map(
keyCodec = keyCodec,
valueCodec = valueCodec,
callback = callback,
backingMap = backingMap,
observingBackingMap = observingBackingMap
)
}
inner class Field<V>( inner class Field<V>(
private var field: V, private var field: V,
private val codec: INetworkValueCodec<V>, private val codec: INetworkValueCodec<V>,
private val getter: FieldGetter<V>? = null, private val getter: FieldGetter<V>? = null,
private val setter: FieldSetter<V>? = null, private val setter: FieldSetter<V>? = null,
isObserver: Boolean = false, isObserver: Boolean = false,
) : IField<V> { ) : IMutableField<V> {
private var remote: V = codec.copy(field) private var remote: V = codec.copy(field)
val id = fields.size + 1 val id = fields.size + 1
@ -335,7 +373,7 @@ class FieldSynchronizer {
} }
} }
inner class ObservedField<V> : IField<V> { inner class ObservedField<V> : IMutableField<V> {
private val codec: NetworkValueCodec<V> private val codec: NetworkValueCodec<V>
private val getter: () -> V private val getter: () -> V
private val setter: (V) -> Unit private val setter: (V) -> Unit
@ -397,6 +435,211 @@ class FieldSynchronizer {
} }
} }
companion object {
private val ClearBacklogEntry = { stream: DataOutputStream -> stream.write(MapAction.CLEAR.ordinal + 1) }
private val MapActionList = MapAction.values()
private val ClearMapChangeset = MapChangeset(MapAction.CLEAR, null, null)
}
inner class Map<K, V>(
private val keyCodec: INetworkValueCodec<K>,
private val valueCodec: INetworkValueCodec<V>,
private val backingMap: MutableMap<K, V>,
private val observingBackingMap: MutableMap<K, V>? = null,
private val callback: ((changes: Collection<MapChangeset<K, V>>) -> Unit)? = null
) : IField<MutableMap<K, V>> {
private var isDirty = false
private var sentAllValues = false
private var isRemote = false
val id = fields.size + 1
init {
fields.add(this)
if (observingBackingMap != null)
observers.add(this)
}
private val backlog = LinkedList<(DataOutputStream) -> Unit>()
override fun observe() {
if (isRemote) {
return
}
val observingBackingMap = observingBackingMap
if (observingBackingMap != null) {
for ((key, value) in backingMap) {
val remoteValue = observingBackingMap[key] ?: throw ConcurrentModificationException("Backing map of $this was modified externally, or $value missed a modification")
if (!valueCodec.compare(value, remoteValue)) {
val valueCopy = valueCodec.copy(value)
backlog.add {
it.write(MapAction.ADD.ordinal + 1)
keyCodec.write(it, key)
valueCodec.write(it, valueCopy)
}
observingBackingMap[key] = valueCopy
if (!isDirty) {
dirtyFields.add(this)
isDirty = true
}
}
}
}
}
override fun markDirty() {
if (isRemote) {
return
}
if (!isDirty) {
dirtyFields.add(this)
isDirty = true
}
if (!sentAllValues) {
for ((key, value) in backingMap) {
val valueCopy = valueCodec.copy(value)
backlog.add {
it.write(MapAction.ADD.ordinal + 1)
keyCodec.write(it, key)
valueCodec.write(it, valueCopy)
}
observingBackingMap?.put(key, valueCopy)
}
sentAllValues = true
}
}
override val value: MutableMap<K, V> = object : ObservedMap<K, V>(backingMap) {
override fun onClear() {
if (isRemote) {
return
}
backlog.clear()
observingBackingMap?.clear()
backlog.add(ClearBacklogEntry)
if (!isDirty) {
dirtyFields.add(this@Map)
isDirty = true
}
}
override fun onValueAdded(key: K, value: V) {
if (isRemote) {
return
}
val valueCopy = valueCodec.copy(value)
backlog.add {
it.write(MapAction.ADD.ordinal + 1)
keyCodec.write(it, key)
valueCodec.write(it, valueCopy)
}
observingBackingMap?.put(key, valueCopy)
if (!isDirty) {
dirtyFields.add(this@Map)
isDirty = true
}
}
override fun onValueRemoved(key: K, value: V) {
if (isRemote) {
return
}
val keyCopy = keyCodec.copy(key)
backlog.add {
it.write(MapAction.REMOVE.ordinal + 1)
keyCodec.write(it, keyCopy)
}
observingBackingMap?.remove(key)
if (!isDirty) {
dirtyFields.add(this@Map)
isDirty = true
}
}
}
override fun write(stream: DataOutputStream) {
stream.write(id)
sentAllValues = false
isDirty = false
for (entry in backlog) {
entry.invoke(stream)
}
backlog.clear()
stream.write(0)
}
override fun read(stream: DataInputStream) {
if (!isRemote) {
isRemote = true
backlog.clear()
observingBackingMap?.clear()
}
isDirty = false
val changeset = LinkedList<MapChangeset<K, V>>()
var readAction = stream.read() - 1
while (readAction != -1) {
if (readAction >= MapActionList.size) {
throw IndexOutOfBoundsException("Unknown map action with ID $readAction")
}
when (MapActionList[readAction]) {
MapAction.CLEAR -> {
backingMap.clear()
changeset.add(ClearMapChangeset)
}
MapAction.ADD -> {
val key = keyCodec.read(stream)
val value = valueCodec.read(stream)
backingMap[key] = value
changeset.add(MapChangeset(MapAction.ADD, key, value))
}
MapAction.REMOVE -> {
val key = keyCodec.read(stream)
backingMap.remove(key)
changeset.add(MapChangeset(MapAction.REMOVE, key, null))
}
}
readAction = stream.read() - 1
}
if (changeset.size != 0) {
callback?.invoke(changeset)
}
}
}
fun invalidate() { fun invalidate() {
for (field in fields) { for (field in fields) {
field.markDirty() field.markDirty()
@ -438,6 +681,10 @@ class FieldSynchronizer {
i++ i++
} }
if (stream.read() != -1) {
throw IllegalStateException("Stream wasn't fully drain!")
}
return i return i
} }

View File

@ -7,6 +7,7 @@ import net.minecraftforge.registries.RegistryObject
class LazyList<T>(private val getters: ImmutableList<() -> T>) : AbstractList<T>() { class LazyList<T>(private val getters: ImmutableList<() -> T>) : AbstractList<T>() {
constructor(vararg getters: () -> T) : this(ImmutableList.copyOf(getters)) constructor(vararg getters: () -> T) : this(ImmutableList.copyOf(getters))
constructor(getters: List<() -> T>) : this(ImmutableList.copyOf(getters))
override val size: Int override val size: Int
get() = getters.size get() = getters.size

View File

@ -14,11 +14,14 @@ import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.item.* import ru.dbotthepony.mc.otm.item.*
import ru.dbotthepony.mc.otm.item.weapon.PlasmaRifleItem import ru.dbotthepony.mc.otm.item.weapon.PlasmaRifleItem
import java.util.*
import kotlin.collections.ArrayList
object MItems { object MItems {
private val DEFAULT_PROPERTIES = Item.Properties().stacksTo(64).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB) private val DEFAULT_PROPERTIES = Item.Properties().stacksTo(64).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)
@ -76,6 +79,39 @@ object MItems {
} }
val EXOSUIT_PROBE: Item by registry.register(MNames.EXOSUIT_PROBE, ::ExoSuitProbeItem) val EXOSUIT_PROBE: Item by registry.register(MNames.EXOSUIT_PROBE, ::ExoSuitProbeItem)
val EXOSUIT_INVENTORY_UPGRADE_CREATIVE: Item by registry.register("exosuit_inventory_upgrade_creative") { ExoSuitSlotUpgradeItem(null, 9, Item.Properties().stacksTo(64).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) }
val EXOSUIT_INVENTORY_UPGRADES: List<Item>
val EXOSUIT_INVENTORY_UPGRADES_CRAFTABLE: List<Item>
val EXOSUIT_INVENTORY_UPGRADES_UNCRAFTABLE: List<Item>
init {
val upgrades = ArrayList<() -> Item>()
val upgradesCraftable = ArrayList<() -> Item>()
val upgradesUncraftable = ArrayList<() -> Item>()
val baseSignificant = 7344348239534784L
var baseInsignificant = 848473865769484L
for (i in 1 .. 4) {
val obj = registry.register("exosuit_inventory_upgrade_$i") { ExoSuitSlotUpgradeItem(UUID(baseSignificant, baseInsignificant++), 9) }
upgrades.add(obj::get)
upgradesCraftable.add(obj::get)
}
for (i in 1 .. 16) {
val obj = registry.register("exosuit_inventory_upgrade_uncraftable_$i") { ExoSuitSlotUpgradeItem(UUID(baseSignificant, baseInsignificant++), 9 + (i / 5) * 9) }
upgrades.add(obj::get)
upgradesUncraftable.add(obj::get)
}
EXOSUIT_INVENTORY_UPGRADES = LazyList(upgrades)
EXOSUIT_INVENTORY_UPGRADES_CRAFTABLE = LazyList(upgradesCraftable)
EXOSUIT_INVENTORY_UPGRADES_UNCRAFTABLE = LazyList(upgradesUncraftable)
}
val EXOSUIT_INVENTORY_UPGRADE_BIG: Item by registry.register("exosuit_inventory_upgrade_big") { ExoSuitSlotUpgradeItem(UUID.fromString("121a17a5-533c-9ac0-ff02-03aea75ed20c"), 45, Item.Properties().stacksTo(64).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) }
val EXOSUIT_INVENTORY_UPGRADE_HUGE: Item by registry.register("exosuit_inventory_upgrade_huge") { ExoSuitSlotUpgradeItem(UUID.fromString("121a17a5-533c-9ac0-ff02-03aea75ed20d"), 90, Item.Properties().stacksTo(64).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) }
val DEBUG_EXPLOSION_SMALL: Item by registry.register(MNames.DEBUG_EXPLOSION_SMALL) { BlockItem(MBlocks.DEBUG_EXPLOSION_SMALL, DEFAULT_PROPERTIES) } val DEBUG_EXPLOSION_SMALL: Item by registry.register(MNames.DEBUG_EXPLOSION_SMALL) { BlockItem(MBlocks.DEBUG_EXPLOSION_SMALL, DEFAULT_PROPERTIES) }
val DEBUG_SPHERE_POINTS: Item by registry.register(MNames.DEBUG_SPHERE_POINTS) { BlockItem(MBlocks.DEBUG_SPHERE_POINTS, DEFAULT_PROPERTIES) } val DEBUG_SPHERE_POINTS: Item by registry.register(MNames.DEBUG_SPHERE_POINTS) { BlockItem(MBlocks.DEBUG_SPHERE_POINTS, DEFAULT_PROPERTIES) }