From f94e3f11e489f34c97911d243ca65b5318874971 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Mon, 5 Sep 2022 18:47:13 +0700 Subject: [PATCH] Extract energy interface from mattery player into own class --- .../mc/otm/android/feature/NanobotsArmor.kt | 6 +- .../android/feature/NanobotsRegeneration.kt | 2 +- .../block/entity/AndroidStationBlockEntity.kt | 4 +- .../otm/capability/MatteryPlayerCapability.kt | 244 ++++-------------- .../SynchronizedPowerWithBattery.kt | 171 ++++++++++++ .../dbotthepony/mc/otm/client/MatteryGUI.kt | 4 +- .../dbotthepony/mc/otm/core/CompoundTagExt.kt | 31 +++ .../mc/otm/item/EnergySwordItem.kt | 2 +- .../mc/otm/menu/AndroidStationMenu.kt | 2 +- .../mc/otm/network/FieldSynchronizer.kt | 30 +-- .../network/MatteryPlayerNetworkChannel.kt | 49 ---- 11 files changed, 273 insertions(+), 272 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/capability/SynchronizedPowerWithBattery.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt index bc61f5055..d47cad690 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt @@ -24,12 +24,12 @@ class NanobotsArmor(android: MatteryPlayerCapability) : AndroidFeature(AndroidFe private var layers = 0 override fun tickServer() { - if (layers < strength + 1 && android.extractEnergyInnerExact(ENERGY_PER_LAYER, true).isPositive) { + if (layers < strength + 1 && android.androidEnergy.extractEnergyInnerExact(ENERGY_PER_LAYER, true).isPositive) { ticksPassed++ if (ticksPassed >= TICKS[speed]) { layers++ - android.extractEnergyInner(ENERGY_PER_LAYER, false) + android.androidEnergy.extractEnergyInner(ENERGY_PER_LAYER, false) } } else { ticksPassed = 0 @@ -44,7 +44,7 @@ class NanobotsArmor(android: MatteryPlayerCapability) : AndroidFeature(AndroidFe if (absorbed > 0.1f) { val powerRequired = ENERGY_PER_HITPOINT * absorbed - val powerExtracted = android.extractEnergyInner(powerRequired, false) + val powerExtracted = android.androidEnergy.extractEnergyInner(powerRequired, false) val realAbsorbed = (powerExtracted / ENERGY_PER_HITPOINT).toFloat() event.amount = event.amount - realAbsorbed (entity as ServerPlayer?)?.awardStat(StatNames.DAMAGE_ABSORBED, (realAbsorbed * 10f).roundToInt()) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt index 611d9e688..dfebaefb8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt @@ -25,7 +25,7 @@ class NanobotsRegeneration(android: MatteryPlayerCapability) : AndroidFeature(An if (ticksPassed > waitTime) { val missingHealth = entity.maxHealth - entity.health val power = ENERGY_PER_HITPOINT * missingHealth - val extracted = android.extractEnergyInner(power, false) + val extracted = android.androidEnergy.extractEnergyInner(power, false) if (extracted.isPositive) { healTicks = (healTicks + 1).coerceAtMost(level) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt index 39874d3ac..21a7ff339 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt @@ -77,13 +77,13 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : if (!it.isAndroid) return@ifPresentK - val missing = it.missingPower + val missing = it.androidEnergy.missingPower if (missing > ImpreciseFraction.ZERO) { val extract = energy.extractEnergyInner(missing, true) if (extract > ImpreciseFraction.ZERO) { - val received = it.receiveEnergyOuter(extract, false) + val received = it.androidEnergy.receiveEnergyOuter(extract, false) energy.extractEnergyInner(received, false) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index a083eaf6e..bbd43abfd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -6,7 +6,6 @@ import net.minecraft.core.Direction import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag import net.minecraft.nbt.StringTag -import net.minecraft.nbt.Tag import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer @@ -20,7 +19,6 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse import net.minecraft.world.level.GameRules import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.LazyOptional @@ -31,8 +29,6 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.player.EntityItemPickupEvent import net.minecraftforge.event.entity.player.PlayerEvent -import net.minecraftforge.eventbus.api.EventPriority -import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent import org.apache.commons.lang3.mutable.MutableInt import org.apache.logging.log4j.LogManager @@ -47,13 +43,12 @@ import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu import ru.dbotthepony.mc.otm.network.* import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.MRegistry -import ru.dbotthepony.mc.otm.registry.StatNames import java.util.* import kotlin.collections.ArrayDeque import kotlin.collections.ArrayList @Suppress("unused") -class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEnergyStorage, INBTSerializable { +class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerializable { private inner class PlayerMatteryContainer(size: Int) : MatteryContainer(size) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { super.setChanged(slot, new, old) @@ -150,9 +145,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn private val deathLog = ArrayDeque>() - private var battery by synchronizer.fraction() - private var maxBattery by synchronizer.fraction(ImpreciseFraction(60000)) - private val features = IdentityHashMap, AndroidFeature>() private val networkQueue = ArrayList() private val queuedTicks = ArrayList() @@ -169,7 +161,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn var willBecomeAndroid by synchronizer.bool() var isAndroid by synchronizer.bool() - var batteryItemStack by synchronizer.item() + + val androidEnergy = SynchronizedPowerWithBattery(ply, synchronizer, DEFAULT_MAX_ANDROID_POWER, DEFAULT_MAX_ANDROID_POWER) fun invalidateNetworkState() { invalidateNetworkIn = 10 @@ -189,8 +182,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn shouldPlaySound = false iteration = 0 deathLog.clear() - battery = ImpreciseFraction(60000) - maxBattery = ImpreciseFraction(60000) + androidEnergy.batteryLevel = DEFAULT_MAX_ANDROID_POWER + androidEnergy.maxBatteryLevel = DEFAULT_MAX_ANDROID_POWER } fun becomeAndroidAndKill() { @@ -208,8 +201,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn shouldPlaySound = false iteration = 0 deathLog.clear() - battery = ImpreciseFraction(0) - maxBattery = ImpreciseFraction(60000) + androidEnergy.batteryLevel = ImpreciseFraction.ZERO + androidEnergy.maxBatteryLevel = DEFAULT_MAX_ANDROID_POWER dropBattery() } @@ -341,9 +334,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn override fun serializeNBT(): CompoundTag { val tag = CompoundTag() - tag["energy_stored"] = battery.serializeNBT() - tag["energy_stored_max"] = maxBattery.serializeNBT() - tag["battery"] = batteryItemStack.serializeNBT() + tag["androidEnergy"] = androidEnergy.serializeNBT() val featureList = ListTag() @@ -390,14 +381,13 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn return tag } - override fun deserializeNBT(compound: CompoundTag) { - iteration = compound.getInt("iteration") - shouldSendIteration = compound.getBoolean("should_send_iteration") + override fun deserializeNBT(tag: CompoundTag) { + iteration = tag.getInt("iteration") + shouldSendIteration = tag.getBoolean("should_send_iteration") deathLog.clear() - for (value in compound.getList("death_log", Tag.TAG_COMPOUND.toInt())) { - value as CompoundTag + for (value in tag.getCompoundList("death_log")) { val component = Component.Serializer.fromJson(value.getString("component")) if (component != null) { @@ -405,67 +395,49 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn } } - compound.ifHas("energy_stored") { - battery = ImpreciseFraction.deserializeNBT(it) - } - - compound.ifHas("energy_stored_max") { - maxBattery = ImpreciseFraction.deserializeNBT(it) - } - - compound.ifHas("battery", CompoundTag::class.java) { - batteryItemStack = ItemStack.of(it) - } + tag.map("androidEnergy", androidEnergy::deserializeNBT) features.clear() - val featuresNbt = compound.getList("features", Tag.TAG_COMPOUND.toInt()) + for (featureTag in tag.getCompoundList("features")) { + val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(featureTag.getString("id"))) - for (tag in featuresNbt) { - if (tag is CompoundTag) { - val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(tag.getString("id"))) + if (feature?.isApplicable(this) == true) { + val instance = feature.create(this) - if (feature?.isApplicable(this) == true) { - val instance = feature.create(this) + instance.deserializeNBT(featureTag) + addFeature(instance) - instance.deserializeNBT(tag) - addFeature(instance) - - if (!ply.level.isClientSide) { - queuedTicks.add(instance::applyModifiers) - } + if (!ply.level.isClientSide) { + queuedTicks.add(instance::applyModifiers) } } } - isAndroid = compound.getBoolean("is_android") - willBecomeAndroid = compound.getBoolean("will_become_android") + isAndroid = tag.getBoolean("is_android") + willBecomeAndroid = tag.getBoolean("will_become_android") research.clear() - val list = compound.getList("research", Tag.TAG_COMPOUND.toInt()) + for (researchTag in tag.getCompoundList("research")) { + val research = MRegistry.ANDROID_RESEARCH.getValue(ResourceLocation(researchTag.getString("id"))) - for (tag in list) { - if (tag is CompoundTag) { - val research = MRegistry.ANDROID_RESEARCH.getValue(ResourceLocation(tag.getString("id"))) - - if (research != null) { - val instance = research.factory(this) - instance.deserializeNBT(tag) - this.research[research] = instance - } + if (research != null) { + val instance = research.factory(this) + instance.deserializeNBT(researchTag) + this.research[research] = instance } } - hasExoSuit = compound.getBoolean("has_exo_suit") - exoSuitSlotCount = compound.getInt("exo_suit_slot_count") - exoSuitContainer.deserializeNBT(compound["exo_suit_inventory"]) - isExoSuitCraftingUpgraded = compound.getBoolean("exo_suit_crafting_upgraded") + 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() { - if (batteryItemStack.isEmpty) return - ply.spawnAtLocation(batteryItemStack) - batteryItemStack = ItemStack.EMPTY + if (androidEnergy.item.isEmpty) return + ply.spawnAtLocation(androidEnergy.item) + androidEnergy.item = ItemStack.EMPTY } private fun sendNetwork(packet: Any) { @@ -539,45 +511,37 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn if (ply.hasEffect(effect)) ply.removeEffect(effect) - if (!batteryItemStack.isEmpty && battery < maxBattery) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresent { - if (it is IMatteryEnergyStorage) { - battery += it.extractEnergyInner(maxBattery - battery, false) - } else { - battery += it.extractEnergy(maxBattery - battery, false) - } - } - } - // TODO: Maybe passive drain? // extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false); if (ply.isSwimming && !hasFeature(AndroidFeatures.AIR_BAGS)) { ply.isSwimming = false } + androidEnergy.tick() + val stats = ply.foodData - while (stats.foodLevel < 18 && extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { - extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false) + while (stats.foodLevel < 18 && androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { + androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false) stats.foodLevel = stats.foodLevel + 1 } // "block" quick regeneration // also cause power to generate while in peaceful - while (stats.foodLevel > 18 && receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { - receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false) + while (stats.foodLevel > 18 && androidEnergy.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { + androidEnergy.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false) stats.foodLevel = stats.foodLevel - 1 } val foodLevel = stats.foodLevel.toFloat() if (stats.saturationLevel < foodLevel) { - val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (foodLevel - stats.saturationLevel), false) + val extracted = androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (foodLevel - stats.saturationLevel), false) stats.setSaturation(stats.saturationLevel + (extracted / ENERGY_FOR_HUNGER_POINT).toFloat()) } if (stats.exhaustionLevel > 0f) { - val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (stats.exhaustionLevel / 4f), false) + val extracted = androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (stats.exhaustionLevel / 4f), false) stats.setExhaustion(stats.exhaustionLevel - (extracted / ENERGY_FOR_HUNGER_POINT).toFloat() * 4f) } @@ -648,124 +612,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn tickInventory() } - override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - return ImpreciseFraction.ZERO - } - - override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - @Suppress("name_shadowing") - var howMuch = howMuch - var drained = ImpreciseFraction.ZERO - - if (!batteryItemStack.isEmpty) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - val extracted = it.extractEnergyOuter(howMuch, simulate) - drained += extracted - howMuch -= extracted - } else { - val extracted = it.extractEnergy(howMuch, simulate) - drained += extracted - howMuch -= extracted - } - } - - if (howMuch.isZero) { - if (!simulate && ply is ServerPlayer) { - ply.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) - } - - return drained - } - } - - val new = (battery - howMuch).moreThanZero() - drained += battery - new - - if (!simulate) { - battery = new - - if (ply is ServerPlayer) { - ply.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) - } - } - - return drained - } - - override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - @Suppress("name_shadowing") - var howMuch = howMuch - var received = ImpreciseFraction.ZERO - - if (!batteryItemStack.isEmpty) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - val extracted = it.receiveEnergyOuter(howMuch, simulate) - received += extracted - howMuch -= extracted - } else { - val extracted = it.receiveEnergy(howMuch, simulate) - received += extracted - howMuch -= extracted - } - } - - if (howMuch.isZero) { - return received - } - } - - val new = (battery + howMuch).coerceAtMost(maxBattery) - received += new - battery - - if (!simulate) { - battery = new - } - - return received - } - - override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - return receiveEnergyOuter(howMuch, simulate) - } - - override var batteryLevel: ImpreciseFraction - get() { - if (!batteryItemStack.isEmpty) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - return battery + it.batteryLevel - } else { - return battery + it.energyStored - } - } - } - - return battery - } - set(value) { - battery = value - } - - override var maxBatteryLevel: ImpreciseFraction - get() { - if (batteryItemStack != ItemStack.EMPTY) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - return maxBattery + it.maxBatteryLevel - } else { - return maxBattery + it.maxEnergyStored - } - } - } - - return maxBattery - } - set(value) { - maxBattery = value - } - private val resolver = LazyOptional.of { this } override fun getCapability(cap: Capability, side: Direction?): LazyOptional { @@ -942,5 +788,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn val leftover = it.exoSuitContainer.addItem(event.item.item, false) event.item.item.count = leftover.count } + + val DEFAULT_MAX_ANDROID_POWER = ImpreciseFraction(60000) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/SynchronizedPowerWithBattery.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/SynchronizedPowerWithBattery.kt new file mode 100644 index 000000000..be1c0f49d --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/SynchronizedPowerWithBattery.kt @@ -0,0 +1,171 @@ +package ru.dbotthepony.mc.otm.capability + +import net.minecraft.nbt.CompoundTag +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack +import net.minecraftforge.common.capabilities.ForgeCapabilities +import net.minecraftforge.common.util.INBTSerializable +import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.getImpreciseFraction +import ru.dbotthepony.mc.otm.core.getItemStack +import ru.dbotthepony.mc.otm.core.ifPresentK +import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.network.FieldSynchronizer +import ru.dbotthepony.mc.otm.registry.StatNames + +class SynchronizedPowerWithBattery( + private val ply: Player, + synchronizer: FieldSynchronizer, + initialCharge: ImpreciseFraction, + maxCharge: ImpreciseFraction +) : IMatteryEnergyStorage, INBTSerializable { + private var battery by synchronizer.fraction(initialCharge) + private var maxBattery by synchronizer.fraction(maxCharge) + + var item by synchronizer.item() + + override fun serializeNBT(): CompoundTag { + return CompoundTag().also { + it["battery"] = battery.serializeNBT() + it["maxBattery"] = maxBattery.serializeNBT() + it["item"] = item.serializeNBT() + } + } + + override fun deserializeNBT(tag: CompoundTag) { + battery = tag.getImpreciseFraction("battery") + maxBattery = tag.getImpreciseFraction("maxBattery") + item = tag.getItemStack("item") + } + + fun tick() { + if (!item.isEmpty && battery < maxBattery) { + item.getCapability(ForgeCapabilities.ENERGY).ifPresent { + if (it is IMatteryEnergyStorage) { + battery += it.extractEnergyInner(maxBattery - battery, false) + } else { + battery += it.extractEnergy(maxBattery - battery, false) + } + } + } + } + + override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + return receiveEnergyOuter(howMuch, simulate) + } + + override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + return ImpreciseFraction.ZERO + } + + override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + @Suppress("name_shadowing") + var howMuch = howMuch + var drained = ImpreciseFraction.ZERO + + if (!item.isEmpty) { + item.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + val extracted = it.extractEnergyOuter(howMuch, simulate) + drained += extracted + howMuch -= extracted + } else { + val extracted = it.extractEnergy(howMuch, simulate) + drained += extracted + howMuch -= extracted + } + } + + if (howMuch.isZero) { + if (!simulate && ply is ServerPlayer) { + ply.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) + } + + return drained + } + } + + val new = (battery - howMuch).moreThanZero() + drained += battery - new + + if (!simulate) { + battery = new + + if (ply is ServerPlayer) { + ply.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) + } + } + + return drained + } + + override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + @Suppress("name_shadowing") + var howMuch = howMuch + var received = ImpreciseFraction.ZERO + + if (!item.isEmpty) { + item.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + val extracted = it.receiveEnergyOuter(howMuch, simulate) + received += extracted + howMuch -= extracted + } else { + val extracted = it.receiveEnergy(howMuch, simulate) + received += extracted + howMuch -= extracted + } + } + + if (howMuch.isZero) { + return received + } + } + + val new = (battery + howMuch).coerceAtMost(maxBattery) + received += new - battery + + if (!simulate) { + battery = new + } + + return received + } + + override var batteryLevel: ImpreciseFraction + get() { + if (!item.isEmpty) { + item.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + return battery + it.batteryLevel + } else { + return battery + it.energyStored + } + } + } + + return battery + } + set(value) { + battery = value + } + + override var maxBatteryLevel: ImpreciseFraction + get() { + if (item != ItemStack.EMPTY) { + item.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + return maxBattery + it.maxBatteryLevel + } else { + return maxBattery + it.maxEnergyStored + } + } + } + + return maxBattery + } + set(value) { + maxBattery = value + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt index 00c3dad64..a0a5240bf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt @@ -232,10 +232,10 @@ object MatteryGUI { val yOffset = if (ply.hasEffect(MobEffects.HUNGER)) 18 else 0 var level: Float - if (android.maxBatteryLevel.isZero) { + if (android.androidEnergy.maxBatteryLevel.isZero) { level = 0f } else { - level = android.batteryLevel.div(android.maxBatteryLevel).toFloat() + level = android.androidEnergy.batteryLevel.div(android.androidEnergy.maxBatteryLevel).toFloat() if (level >= 0.98f) level = 1f diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt index 1aad61935..7a9575472 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt @@ -1,7 +1,19 @@ package ru.dbotthepony.mc.otm.core +import net.minecraft.nbt.ByteArrayTag +import net.minecraft.nbt.ByteTag import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.DoubleTag +import net.minecraft.nbt.FloatTag +import net.minecraft.nbt.IntArrayTag +import net.minecraft.nbt.IntTag +import net.minecraft.nbt.ListTag +import net.minecraft.nbt.LongArrayTag +import net.minecraft.nbt.LongTag +import net.minecraft.nbt.ShortTag +import net.minecraft.nbt.StringTag import net.minecraft.nbt.Tag +import net.minecraft.world.item.ItemStack import java.util.UUID operator fun CompoundTag.set(index: String, value: Tag) = put(index, value) @@ -39,6 +51,8 @@ inline fun CompoundTag.map(s: String, consumer: (T) -> R): return null } +fun CompoundTag.getItemStack(key: String): ItemStack = map(key, ItemStack::of) ?: ItemStack.EMPTY + inline fun CompoundTag.ifHas(s: String, consumer: (Tag) -> Unit) { val tag = get(s) @@ -62,3 +76,20 @@ inline fun CompoundTag.ifHas(s: String, type: Class, consum consumer(tag as T) } } + +fun CompoundTag.getList(key: String): ListTag { + return this[key] as? ListTag ?: ListTag() +} + +fun CompoundTag.getByteList(key: String): MutableList = getList(key, Tag.TAG_BYTE.toInt()) as MutableList +fun CompoundTag.getShortList(key: String): MutableList = getList(key, Tag.TAG_SHORT.toInt()) as MutableList +fun CompoundTag.getIntList(key: String): MutableList = getList(key, Tag.TAG_INT.toInt()) as MutableList +fun CompoundTag.getLongList(key: String): MutableList = getList(key, Tag.TAG_LONG.toInt()) as MutableList +fun CompoundTag.getFloatList(key: String): MutableList = getList(key, Tag.TAG_FLOAT.toInt()) as MutableList +fun CompoundTag.getDoubleList(key: String): MutableList = getList(key, Tag.TAG_DOUBLE.toInt()) as MutableList +fun CompoundTag.getByteArrayList(key: String): MutableList = getList(key, Tag.TAG_BYTE_ARRAY.toInt()) as MutableList +fun CompoundTag.getStringList(key: String): MutableList = getList(key, Tag.TAG_STRING.toInt()) as MutableList +fun CompoundTag.getListList(key: String): MutableList = getList(key, Tag.TAG_LIST.toInt()) as MutableList +fun CompoundTag.getCompoundList(key: String): MutableList = getList(key, Tag.TAG_COMPOUND.toInt()) as MutableList +fun CompoundTag.getIntArrayList(key: String): MutableList = getList(key, Tag.TAG_INT_ARRAY.toInt()) as MutableList +fun CompoundTag.getLongArrayList(key: String): MutableList = getList(key, Tag.TAG_LONG_ARRAY.toInt()) as MutableList diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt index 95cf9a292..da1d4fc37 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt @@ -72,7 +72,7 @@ class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(Ov itemStack.getCapability(MatteryCapability.ENERGY).orNull()?.let { if (!it.extractEnergyInnerExact(ENERGY_PER_SWING, false).isZero) { victim.matteryPlayer?.let { - it.extractEnergyInner(ENERGY_ZAP, false) + it.androidEnergy.extractEnergyInner(ENERGY_ZAP, false) victim.hurt(EMPDamageSource(attacker), 8f) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt index 225b3f41e..9dfd646ef 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt @@ -108,7 +108,7 @@ class AndroidStationMenu @JvmOverloads constructor( } } - val androidBattery: MatterySlot = AndroidSlot(container { it::batteryItemStack }) { + val androidBattery: MatterySlot = AndroidSlot(container { it.androidEnergy::item }) { it.getCapability(ForgeCapabilities.ENERGY).isPresent } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt index 6ad6e783b..065ea6203 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt @@ -237,12 +237,12 @@ class FieldSynchronizer { inner class Field( private var field: V, - private val dispatcher: INetworkValueCodec, + private val codec: INetworkValueCodec, private val getter: FieldGetter? = null, private val setter: FieldSetter? = null, isObserver: Boolean = false, ) : IField { - private var remote: V = dispatcher.copy(field) + private var remote: V = codec.copy(field) val id = fields.size + 1 @@ -262,7 +262,7 @@ class FieldSynchronizer { } override fun write(value: V) { - if (!isDirty && !dispatcher.compare(remote, value)) { + if (!isDirty && !codec.compare(remote, value)) { dirtyFields.add(this@Field) isDirty = true } @@ -272,7 +272,7 @@ class FieldSynchronizer { } override fun observe() { - if (!isDirty && !dispatcher.compare(remote, field)) { + if (!isDirty && !codec.compare(remote, field)) { dirtyFields.add(this) isDirty = true } @@ -300,7 +300,7 @@ class FieldSynchronizer { return } - if (!isDirty && !dispatcher.compare(remote, value)) { + if (!isDirty && !codec.compare(remote, value)) { dirtyFields.add(this) isDirty = true } @@ -317,13 +317,13 @@ class FieldSynchronizer { override fun write(stream: DataOutputStream) { stream.write(id) - dispatcher.write(stream, field) + codec.write(stream, field) isDirty = false - remote = dispatcher.copy(field) + remote = codec.copy(field) } override fun read(stream: DataInputStream) { - val value = dispatcher.read(stream) + val value = codec.read(stream) val setter = this.setter if (setter != null) { @@ -336,7 +336,7 @@ class FieldSynchronizer { } inner class ObservedField : IField { - private val dispatcher: NetworkValueCodec + private val codec: NetworkValueCodec private val getter: () -> V private val setter: (V) -> Unit @@ -347,14 +347,14 @@ class FieldSynchronizer { set(value) { setter.invoke(value) } constructor(field: KMutableProperty0, dispatcher: NetworkValueCodec) { - this.dispatcher = dispatcher + this.codec = dispatcher getter = field::get setter = field::set remote = dispatcher.copy(value) } constructor(getter: () -> V, setter: (V) -> Unit, dispatcher: NetworkValueCodec) { - this.dispatcher = dispatcher + this.codec = dispatcher this.getter = getter this.setter = setter remote = dispatcher.copy(value) @@ -370,7 +370,7 @@ class FieldSynchronizer { } override fun observe() { - if (!isDirty && !dispatcher.compare(remote, value)) { + if (!isDirty && !codec.compare(remote, value)) { dirtyFields.add(this) isDirty = true } @@ -387,13 +387,13 @@ class FieldSynchronizer { override fun write(stream: DataOutputStream) { stream.write(id) val value = value - dispatcher.write(stream, value) + codec.write(stream, value) isDirty = false - remote = dispatcher.copy(value) + remote = codec.copy(value) } override fun read(stream: DataInputStream) { - this.value = dispatcher.read(stream) + this.value = codec.read(stream) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt index 19546909a..d8aa1e709 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt @@ -161,53 +161,6 @@ class AndroidFeatureRemovePacket(val type: AndroidFeatureType<*>) : MatteryPacke } } -class AndroidBatteryItemPacket(val item: ItemStack) : MatteryPacket { - override fun write(buff: FriendlyByteBuf) { - buff.writeItem(item) - } - - override fun play(context: Supplier) { - context.get().packetHandled = true - context.get().enqueueWork { - val android = minecraft.player?.matteryPlayer ?: return@enqueueWork - - android.batteryItemStack = item - } - } - - companion object { - fun read(buff: FriendlyByteBuf): AndroidBatteryItemPacket { - return AndroidBatteryItemPacket(buff.readItem()) - } - } -} - -class AndroidEnergyLevelPacket(val level: ImpreciseFraction, val isMaxEnergy: Boolean) : MatteryPacket { - override fun write(buff: FriendlyByteBuf) { - buff.writeImpreciseFraction(level) - buff.writeBoolean(isMaxEnergy) - } - - override fun play(context: Supplier) { - context.get().packetHandled = true - context.get().enqueueWork { - val android = minecraft.player?.matteryPlayer ?: return@enqueueWork - - if (isMaxEnergy) { - android.maxBatteryLevel = level - } else { - android.batteryLevel = level - } - } - } - - companion object { - fun read(buff: FriendlyByteBuf): AndroidEnergyLevelPacket { - return AndroidEnergyLevelPacket(buff.readImpreciseFraction(), buff.readBoolean()) - } - } -} - class PlayerIterationPacket(val iteration: Int, val deathLog: List>) : MatteryPacket { override fun write(buff: FriendlyByteBuf) { buff.writeInt(iteration) @@ -392,8 +345,6 @@ object MatteryPlayerNetworkChannel : MatteryNetworkChannel( add(AndroidResearchSyncPacket::class, AndroidResearchSyncPacket.Companion::read, PLAY_TO_CLIENT) add(AndroidFeatureSyncPacket::class, AndroidFeatureSyncPacket.Companion::read, PLAY_TO_CLIENT) add(AndroidFeatureRemovePacket::class, AndroidFeatureRemovePacket.Companion::read, PLAY_TO_CLIENT) - add(AndroidBatteryItemPacket::class, AndroidBatteryItemPacket.Companion::read, PLAY_TO_CLIENT) - add(AndroidEnergyLevelPacket::class, AndroidEnergyLevelPacket.Companion::read, PLAY_TO_CLIENT) add(PlayerIterationPacket::class, PlayerIterationPacket.Companion::read, PLAY_TO_CLIENT)