Synchronized maps, update save keys, exosuit inventory upgrades as items
This commit is contained in:
parent
2915ef675b
commit
e7653d559f
@ -56,10 +56,17 @@ private fun misc(provider: MatteryLanguageProvider) {
|
||||
|
||||
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")
|
||||
|
||||
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.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.")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.Direction
|
||||
@ -64,6 +65,26 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
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, _ ->
|
||||
require(value >= 0) { "Invalid slot count $value" }
|
||||
|
||||
@ -334,37 +355,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
val tag = CompoundTag()
|
||||
|
||||
tag["androidEnergy"] = androidEnergy.serializeNBT()
|
||||
|
||||
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
|
||||
|
||||
// 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) {
|
||||
it.add(CompoundTag().also {
|
||||
it["ticks"] = ticks
|
||||
@ -373,21 +368,47 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
}
|
||||
|
||||
tag["exo_suit_slot_count"] = exoSuitSlotCount
|
||||
tag["has_exo_suit"] = hasExoSuit
|
||||
tag["exo_suit_inventory"] = exoSuitContainer.serializeNBT()
|
||||
tag["exo_suit_crafting_upgraded"] = isExoSuitCraftingUpgraded
|
||||
// exosuit
|
||||
tag["hasExoSuit"] = hasExoSuit
|
||||
tag["exoSuitContainer"] = exoSuitContainer.serializeNBT()
|
||||
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
|
||||
}
|
||||
|
||||
override fun deserializeNBT(tag: CompoundTag) {
|
||||
// iterations
|
||||
iteration = tag.getInt("iteration")
|
||||
shouldSendIteration = tag.getBoolean("should_send_iteration")
|
||||
shouldSendIteration = tag.getBoolean("shouldSendIteration")
|
||||
|
||||
deathLog.clear()
|
||||
|
||||
for (value in tag.getCompoundList("death_log")) {
|
||||
for (value in tag.getCompoundList("deathLog")) {
|
||||
val component = Component.Serializer.fromJson(value.getString("component"))
|
||||
|
||||
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)
|
||||
|
||||
features.clear()
|
||||
research.clear()
|
||||
|
||||
for (featureTag in tag.getCompoundList("features")) {
|
||||
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")) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -8,7 +8,10 @@ import java.io.DataOutputStream
|
||||
import java.io.InputStream
|
||||
import java.math.BigDecimal
|
||||
import java.util.*
|
||||
import kotlin.ConcurrentModificationException
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
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 markDirty()
|
||||
var value: V
|
||||
val value: V
|
||||
|
||||
fun write(stream: DataOutputStream)
|
||||
fun read(stream: DataInputStream)
|
||||
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): V {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface IMutableField<V> : IField<V>, ReadWriteProperty<Any, V> {
|
||||
override var value: V
|
||||
|
||||
override fun setValue(thisRef: Any, property: KProperty<*>, value: V) {
|
||||
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 {
|
||||
@ -235,13 +257,29 @@ class FieldSynchronizer {
|
||||
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>(
|
||||
private var field: V,
|
||||
private val codec: INetworkValueCodec<V>,
|
||||
private val getter: FieldGetter<V>? = null,
|
||||
private val setter: FieldSetter<V>? = null,
|
||||
isObserver: Boolean = false,
|
||||
) : IField<V> {
|
||||
) : IMutableField<V> {
|
||||
private var remote: V = codec.copy(field)
|
||||
|
||||
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 getter: () -> V
|
||||
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() {
|
||||
for (field in fields) {
|
||||
field.markDirty()
|
||||
@ -438,6 +681,10 @@ class FieldSynchronizer {
|
||||
i++
|
||||
}
|
||||
|
||||
if (stream.read() != -1) {
|
||||
throw IllegalStateException("Stream wasn't fully drain!")
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import net.minecraftforge.registries.RegistryObject
|
||||
|
||||
class LazyList<T>(private val getters: ImmutableList<() -> T>) : AbstractList<T>() {
|
||||
constructor(vararg getters: () -> T) : this(ImmutableList.copyOf(getters))
|
||||
constructor(getters: List<() -> T>) : this(ImmutableList.copyOf(getters))
|
||||
|
||||
override val size: Int
|
||||
get() = getters.size
|
||||
|
@ -14,11 +14,14 @@ import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
|
||||
import net.minecraftforge.registries.DeferredRegister
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.RegistryObject
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.item.*
|
||||
import ru.dbotthepony.mc.otm.item.weapon.PlasmaRifleItem
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
object MItems {
|
||||
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_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_SPHERE_POINTS: Item by registry.register(MNames.DEBUG_SPHERE_POINTS) { BlockItem(MBlocks.DEBUG_SPHERE_POINTS, DEFAULT_PROPERTIES) }
|
||||
|
Loading…
Reference in New Issue
Block a user