Extract energy interface from mattery player into own class

This commit is contained in:
DBotThePony 2022-09-05 18:47:13 +07:00
parent 11484eeec3
commit f94e3f11e4
Signed by: DBot
GPG Key ID: DCC23B5715498507
11 changed files with 273 additions and 272 deletions

View File

@ -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())

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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>

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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)