Quantum batteries now track statistics

This commit is contained in:
DBotThePony 2022-09-04 18:36:42 +07:00
parent e3643d7f61
commit 094f476fea
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 154 additions and 46 deletions

View File

@ -130,6 +130,7 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("item.power.infinite.storage", "Stored energy: Infinity / Infinity")
misc("item.power.infinite.throughput", "Max I/O Infinite / Infinite")
misc("item.power.passed", "Passed energy: %s")
misc("item.power.received", "Received energy: %s")
misc("item.power.average", "Average throughput: %s/t")
misc("item.power.last_20_ticks", "Last second: %s")
misc("item.power.last_tick", "Last tick: %s")

View File

@ -4,7 +4,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import net.minecraft.ChatFormatting
import net.minecraft.core.Direction
import net.minecraft.nbt.ByteArrayTag
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.world.item.*
@ -28,13 +30,50 @@ import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.saveddata.SavedCountingMap
import ru.dbotthepony.mc.otm.saveddata.SavedMapDelegate
import java.util.function.Supplier
class QuantumBatteryItem : Item {
class Data(
val parent: SavedCountingMap<Data>?,
val index: Int = -1,
energy: ImpreciseFraction = ImpreciseFraction.ZERO,
passed: ImpreciseFraction = ImpreciseFraction.ZERO,
received: ImpreciseFraction = ImpreciseFraction.ZERO,
) {
constructor(
energy: ImpreciseFraction = ImpreciseFraction.ZERO,
passed: ImpreciseFraction = ImpreciseFraction.ZERO,
received: ImpreciseFraction = ImpreciseFraction.ZERO,
) : this(null, -1, energy, passed, received)
var energy: ImpreciseFraction = energy
set(value) {
if (field != value) {
field = value
parent?.isDirty = true
}
}
var passed: ImpreciseFraction = passed
set(value) {
if (field != value) {
field = value
parent?.isDirty = true
}
}
var received: ImpreciseFraction = received
set(value) {
if (field != value) {
field = value
parent?.isDirty = true
}
}
}
private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
private val resolver = LazyOptional.of { this }
var delegate = SavedMapDelegate(ImpreciseFraction.ZERO)
var data = Data()
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap == ForgeCapabilities.ENERGY || cap == MatteryCapability.ENERGY) {
@ -53,30 +92,32 @@ class QuantumBatteryItem : Item {
return ImpreciseFraction.ZERO
}
if (delegate.parent == null && isServerThread()) {
if (data.parent == null && isServerThread()) {
determineQuantumLink()
if (delegate.parent == null) {
if (data.parent == null) {
return ImpreciseFraction.ZERO
}
}
if (isCreative) {
val newEnergy = (delegate.value - howMuch).moreThanZero()
val diff = delegate.value - newEnergy
val newEnergy = (data.energy - howMuch).moreThanZero()
val diff = data.energy - newEnergy
if (!simulate) {
delegate.value = newEnergy
data.energy = newEnergy
data.passed += diff
}
return diff
}
val newEnergy = (delegate.value - howMuch.coerceAtMost(throughput!!)).moreThanZero()
val diff = delegate.value - newEnergy
val newEnergy = (data.energy - howMuch.coerceAtMost(throughput!!)).moreThanZero()
val diff = data.energy - newEnergy
if (!simulate) {
delegate.value = newEnergy
data.energy = newEnergy
data.passed += diff
}
return diff
@ -91,31 +132,33 @@ class QuantumBatteryItem : Item {
return ImpreciseFraction.ZERO
}
if (delegate.parent == null && isServerThread()) {
if (data.parent == null && isServerThread()) {
determineQuantumLink()
if (delegate.parent == null) {
if (data.parent == null) {
return ImpreciseFraction.ZERO
}
}
if (isCreative) {
if (!simulate) {
delegate.value += howMuch
data.energy += howMuch
data.received += howMuch
}
return howMuch
}
if (delegate.value >= capacity!!) {
if (data.energy >= capacity!!) {
return ImpreciseFraction.ZERO
}
val newEnergy = (delegate.value + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity)
val diff = newEnergy - delegate.value
val newEnergy = (data.energy + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity)
val diff = newEnergy - data.energy
if (!simulate) {
delegate.value = newEnergy
data.energy = newEnergy
data.received += diff
}
return diff
@ -123,15 +166,39 @@ class QuantumBatteryItem : Item {
override val batteryLevel: ImpreciseFraction
get() {
if (delegate.parent == null) {
if (data.parent == null) {
determineQuantumLink()
}
if (isClientThread()) {
return clientPowerMap[delegate.index] ?: delegate.value
return clientPowerMap[data.index]?.energy ?: data.energy
}
return delegate.value
return data.energy
}
val passed: ImpreciseFraction get() {
if (data.parent == null) {
determineQuantumLink()
}
if (isClientThread()) {
return clientPowerMap[data.index]?.passed ?: data.passed
}
return data.passed
}
val received: ImpreciseFraction get() {
if (data.parent == null) {
determineQuantumLink()
}
if (isClientThread()) {
return clientPowerMap[data.index]?.received ?: data.received
}
return data.received
}
override val maxBatteryLevel: ImpreciseFraction
@ -149,39 +216,39 @@ class QuantumBatteryItem : Item {
}
private fun determineQuantumLink() {
if (delegate.parent == null && isServerThread()) {
if (data.parent == null && isServerThread()) {
val existing = stack.tag?.getInt("link_id")
if (existing == null) {
val old = delegate
delegate = saveData!!.factorize()
delegate.value = old.value
stack.tagNotNull["link_id"] = delegate.index
val old = data
data = saveData!!.factorize()
data.energy = old.energy
stack.tagNotNull["link_id"] = data.index
} else {
delegate = saveData?.computeIfAbsent(existing) ?: SavedMapDelegate(null, existing, delegate.value)
data = saveData?.computeIfAbsent(existing) ?: Data(null, existing, data.energy, data.passed, data.received)
}
} else if (!isServerThread()) {
// client ?
val existing = stack.tag?.getInt("link_id") ?: return
if (existing != delegate.index) {
delegate = SavedMapDelegate(delegate.parent, existing, delegate.value)
if (existing != data.index) {
data = Data(data.parent, existing, data.energy, data.passed, data.received)
}
}
}
fun determineQuantumLinkWeak() {
if (delegate.parent == null && isServerThread()) {
if (data.parent == null && isServerThread()) {
val existing = stack.tag?.getInt("link_id")
if (existing != null) {
delegate = saveData?.computeIfAbsent(existing) ?: SavedMapDelegate(null, existing, delegate.value)
data = saveData?.computeIfAbsent(existing) ?: Data(null, existing, data.energy, data.passed, data.received)
}
} else if (!isServerThread()) {
val existing = stack.tag?.getInt("link_id") ?: return
if (existing != delegate.index) {
delegate = SavedMapDelegate(delegate.parent, existing, delegate.value)
if (existing != data.index) {
data = Data(data.parent, existing, data.energy, data.passed, data.received)
}
}
}
@ -193,19 +260,25 @@ class QuantumBatteryItem : Item {
val saveDataID: String
val saveData: SavedCountingMap<SavedMapDelegate<ImpreciseFraction>>? get() {
val saveData: SavedCountingMap<Data>? get() {
if (isServerThread()) {
return MINECRAFT_SERVER.overworld().dataStorage.computeIfAbsent({
SavedMapDelegate.makeMap(ImpreciseFraction::serializeNBT, ImpreciseFraction.Companion::deserializeNBT, ImpreciseFraction.ZERO).load(it)
SavedCountingMap(Companion::storeValue, Companion::loadValue, ::Data).load(it)
}, {
SavedMapDelegate.makeMap(ImpreciseFraction::serializeNBT, ImpreciseFraction.Companion::deserializeNBT, ImpreciseFraction.ZERO)
SavedCountingMap(Companion::storeValue, Companion::loadValue, ::Data)
}, saveDataID) ?: throw NullPointerException("Unable to get save data for $this in ${MINECRAFT_SERVER.overworld()}")
}
return null
}
val clientPowerMap: Int2ObjectAVLTreeMap<ImpreciseFraction> by lazy {
data class ClientData(
val energy: ImpreciseFraction = ImpreciseFraction.ZERO,
val passed: ImpreciseFraction = ImpreciseFraction.ZERO,
val received: ImpreciseFraction = ImpreciseFraction.ZERO,
)
val clientPowerMap: Int2ObjectAVLTreeMap<ClientData> by lazy {
check(isClient) { "Invalid side" }
Int2ObjectAVLTreeMap()
}
@ -242,8 +315,6 @@ class QuantumBatteryItem : Item {
if (isCreative) {
components.add(TranslatableComponent("otm.item.quantum_battery.creative_power", power.batteryLevel.formatPower()).withStyle(ChatFormatting.GRAY))
components.add(TranslatableComponent("otm.item.quantum_battery.creative").withStyle(ChatFormatting.DARK_GRAY))
components.add(TranslatableComponent("otm.item.quantum_battery.creative2").withStyle(ChatFormatting.DARK_GRAY))
} else {
components.add(TranslatableComponent("otm.item.power.normal.storage", power.batteryLevel.formatPower(), capacity!!.formatPower()).withStyle(ChatFormatting.GRAY))
components.add(
@ -254,7 +325,15 @@ class QuantumBatteryItem : Item {
).withStyle(ChatFormatting.GRAY))
}
components.add(TranslatableComponent("otm.item.quantum_link_id", power.delegate.index).withStyle(ChatFormatting.DARK_GRAY))
components.add(TranslatableComponent("otm.item.power.passed", power.passed.formatPower()).withStyle(ChatFormatting.GRAY))
components.add(TranslatableComponent("otm.item.power.received", power.received.formatPower()).withStyle(ChatFormatting.GRAY))
if (isCreative) {
components.add(TranslatableComponent("otm.item.quantum_battery.creative").withStyle(ChatFormatting.DARK_GRAY))
components.add(TranslatableComponent("otm.item.quantum_battery.creative2").withStyle(ChatFormatting.DARK_GRAY))
}
components.add(TranslatableComponent("otm.item.quantum_link_id", power.data.index).withStyle(ChatFormatting.DARK_GRAY))
}
companion object {
@ -262,7 +341,9 @@ class QuantumBatteryItem : Item {
return ChargePacket(
(ForgeRegistries.ITEMS as ForgeRegistry<Item>).getValue(buff.readInt()) as QuantumBatteryItem,
buff.readInt(),
buff.readImpreciseFraction()
buff.readImpreciseFraction(),
buff.readImpreciseFraction(),
buff.readImpreciseFraction(),
)
}
@ -277,13 +358,12 @@ class QuantumBatteryItem : Item {
power.determineQuantumLinkWeak()
if (power.delegate.index < 0) {
if (power.data.index < 0) {
continue
}
if (networkedChannels.add(power.delegate.index)) {
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.delegate.index, power.batteryLevel))
}
if (networkedChannels.add(power.data.index)) {
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.data.index, power.batteryLevel, power.data.passed, power.data.received))
}
}
}
@ -291,16 +371,43 @@ class QuantumBatteryItem : Item {
}
}
class ChargePacket(val type: QuantumBatteryItem, val channel: Int, val value: ImpreciseFraction) : MatteryPacket {
private fun loadValue(parent: SavedCountingMap<Data>, tag: Tag, index: Int): Data {
if (tag is ByteArrayTag) {
return Data(parent, index, ImpreciseFraction.deserializeNBT(tag))
} else if (tag is CompoundTag) {
return Data(parent, index, ImpreciseFraction.deserializeNBT(tag["energy"]), ImpreciseFraction.deserializeNBT(tag["passed"]), ImpreciseFraction.deserializeNBT(tag["received"]))
} else {
return Data(parent, index)
}
}
private fun storeValue(parent: SavedCountingMap<Data>, value: Data, index: Int): CompoundTag {
return CompoundTag().also {
it["energy"] = value.energy.serializeNBT()
it["passed"] = value.passed.serializeNBT()
it["received"] = value.received.serializeNBT()
}
}
}
class ChargePacket(
val type: QuantumBatteryItem,
val channel: Int,
val energy: ImpreciseFraction,
val passed: ImpreciseFraction,
val received: ImpreciseFraction,
) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt((ForgeRegistries.ITEMS as ForgeRegistry<Item>).getID(type))
buff.writeInt(channel)
buff.writeImpreciseFraction(value)
buff.writeImpreciseFraction(energy)
buff.writeImpreciseFraction(passed)
buff.writeImpreciseFraction(received)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
type.clientPowerMap[channel] = value
type.clientPowerMap[channel] = ClientData(energy, passed, received)
}
}
}