Extract energy interface from mattery player into own class
This commit is contained in:
parent
11484eeec3
commit
f94e3f11e4
@ -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())
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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<CompoundTag> {
|
||||
class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerializable<CompoundTag> {
|
||||
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<Pair<Int, Component>>()
|
||||
|
||||
private var battery by synchronizer.fraction()
|
||||
private var maxBattery by synchronizer.fraction(ImpreciseFraction(60000))
|
||||
|
||||
private val features = IdentityHashMap<AndroidFeatureType<*>, AndroidFeature>()
|
||||
private val networkQueue = ArrayList<Any>()
|
||||
private val queuedTicks = ArrayList<Runnable>()
|
||||
@ -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 <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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<CompoundTag> {
|
||||
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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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 <R, reified T : Tag> 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 <reified T : Tag> CompoundTag.ifHas(s: String, type: Class<T>, consum
|
||||
consumer(tag as T)
|
||||
}
|
||||
}
|
||||
|
||||
fun CompoundTag.getList(key: String): ListTag {
|
||||
return this[key] as? ListTag ?: ListTag()
|
||||
}
|
||||
|
||||
fun CompoundTag.getByteList(key: String): MutableList<ByteTag> = getList(key, Tag.TAG_BYTE.toInt()) as MutableList<ByteTag>
|
||||
fun CompoundTag.getShortList(key: String): MutableList<ShortTag> = getList(key, Tag.TAG_SHORT.toInt()) as MutableList<ShortTag>
|
||||
fun CompoundTag.getIntList(key: String): MutableList<IntTag> = getList(key, Tag.TAG_INT.toInt()) as MutableList<IntTag>
|
||||
fun CompoundTag.getLongList(key: String): MutableList<LongTag> = getList(key, Tag.TAG_LONG.toInt()) as MutableList<LongTag>
|
||||
fun CompoundTag.getFloatList(key: String): MutableList<FloatTag> = getList(key, Tag.TAG_FLOAT.toInt()) as MutableList<FloatTag>
|
||||
fun CompoundTag.getDoubleList(key: String): MutableList<DoubleTag> = getList(key, Tag.TAG_DOUBLE.toInt()) as MutableList<DoubleTag>
|
||||
fun CompoundTag.getByteArrayList(key: String): MutableList<ByteArrayTag> = getList(key, Tag.TAG_BYTE_ARRAY.toInt()) as MutableList<ByteArrayTag>
|
||||
fun CompoundTag.getStringList(key: String): MutableList<StringTag> = getList(key, Tag.TAG_STRING.toInt()) as MutableList<StringTag>
|
||||
fun CompoundTag.getListList(key: String): MutableList<ListTag> = getList(key, Tag.TAG_LIST.toInt()) as MutableList<ListTag>
|
||||
fun CompoundTag.getCompoundList(key: String): MutableList<CompoundTag> = getList(key, Tag.TAG_COMPOUND.toInt()) as MutableList<CompoundTag>
|
||||
fun CompoundTag.getIntArrayList(key: String): MutableList<IntArrayTag> = getList(key, Tag.TAG_INT_ARRAY.toInt()) as MutableList<IntArrayTag>
|
||||
fun CompoundTag.getLongArrayList(key: String): MutableList<LongArrayTag> = getList(key, Tag.TAG_LONG_ARRAY.toInt()) as MutableList<LongArrayTag>
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -237,12 +237,12 @@ class FieldSynchronizer {
|
||||
|
||||
inner class Field<V>(
|
||||
private var field: V,
|
||||
private val dispatcher: INetworkValueCodec<V>,
|
||||
private val codec: INetworkValueCodec<V>,
|
||||
private val getter: FieldGetter<V>? = null,
|
||||
private val setter: FieldSetter<V>? = null,
|
||||
isObserver: Boolean = false,
|
||||
) : IField<V> {
|
||||
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<V> : IField<V> {
|
||||
private val dispatcher: NetworkValueCodec<V>
|
||||
private val codec: NetworkValueCodec<V>
|
||||
private val getter: () -> V
|
||||
private val setter: (V) -> Unit
|
||||
|
||||
@ -347,14 +347,14 @@ class FieldSynchronizer {
|
||||
set(value) { setter.invoke(value) }
|
||||
|
||||
constructor(field: KMutableProperty0<V>, dispatcher: NetworkValueCodec<V>) {
|
||||
this.dispatcher = dispatcher
|
||||
this.codec = dispatcher
|
||||
getter = field::get
|
||||
setter = field::set
|
||||
remote = dispatcher.copy(value)
|
||||
}
|
||||
|
||||
constructor(getter: () -> V, setter: (V) -> Unit, dispatcher: NetworkValueCodec<V>) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<NetworkEvent.Context>) {
|
||||
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<NetworkEvent.Context>) {
|
||||
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<Pair<Int, Component>>) : 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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user