Quantum batteries now track statistics
This commit is contained in:
parent
e3643d7f61
commit
094f476fea
@ -130,6 +130,7 @@ private fun misc(provider: MatteryLanguageProvider) {
|
|||||||
misc("item.power.infinite.storage", "Stored energy: Infinity / Infinity")
|
misc("item.power.infinite.storage", "Stored energy: Infinity / Infinity")
|
||||||
misc("item.power.infinite.throughput", "Max I/O Infinite / Infinite")
|
misc("item.power.infinite.throughput", "Max I/O Infinite / Infinite")
|
||||||
misc("item.power.passed", "Passed energy: %s")
|
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.average", "Average throughput: %s/t")
|
||||||
misc("item.power.last_20_ticks", "Last second: %s")
|
misc("item.power.last_20_ticks", "Last second: %s")
|
||||||
misc("item.power.last_tick", "Last tick: %s")
|
misc("item.power.last_tick", "Last tick: %s")
|
||||||
|
@ -4,7 +4,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
|
|||||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
|
import net.minecraft.nbt.ByteArrayTag
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.Tag
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.world.item.*
|
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.MatteryPacket
|
||||||
import ru.dbotthepony.mc.otm.network.packetHandled
|
import ru.dbotthepony.mc.otm.network.packetHandled
|
||||||
import ru.dbotthepony.mc.otm.saveddata.SavedCountingMap
|
import ru.dbotthepony.mc.otm.saveddata.SavedCountingMap
|
||||||
import ru.dbotthepony.mc.otm.saveddata.SavedMapDelegate
|
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
class QuantumBatteryItem : Item {
|
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 inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
|
||||||
private val resolver = LazyOptional.of { this }
|
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> {
|
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
if (cap == ForgeCapabilities.ENERGY || cap == MatteryCapability.ENERGY) {
|
if (cap == ForgeCapabilities.ENERGY || cap == MatteryCapability.ENERGY) {
|
||||||
@ -53,30 +92,32 @@ class QuantumBatteryItem : Item {
|
|||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delegate.parent == null && isServerThread()) {
|
if (data.parent == null && isServerThread()) {
|
||||||
determineQuantumLink()
|
determineQuantumLink()
|
||||||
|
|
||||||
if (delegate.parent == null) {
|
if (data.parent == null) {
|
||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCreative) {
|
if (isCreative) {
|
||||||
val newEnergy = (delegate.value - howMuch).moreThanZero()
|
val newEnergy = (data.energy - howMuch).moreThanZero()
|
||||||
val diff = delegate.value - newEnergy
|
val diff = data.energy - newEnergy
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
delegate.value = newEnergy
|
data.energy = newEnergy
|
||||||
|
data.passed += diff
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
val newEnergy = (delegate.value - howMuch.coerceAtMost(throughput!!)).moreThanZero()
|
val newEnergy = (data.energy - howMuch.coerceAtMost(throughput!!)).moreThanZero()
|
||||||
val diff = delegate.value - newEnergy
|
val diff = data.energy - newEnergy
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
delegate.value = newEnergy
|
data.energy = newEnergy
|
||||||
|
data.passed += diff
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
@ -91,31 +132,33 @@ class QuantumBatteryItem : Item {
|
|||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delegate.parent == null && isServerThread()) {
|
if (data.parent == null && isServerThread()) {
|
||||||
determineQuantumLink()
|
determineQuantumLink()
|
||||||
|
|
||||||
if (delegate.parent == null) {
|
if (data.parent == null) {
|
||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCreative) {
|
if (isCreative) {
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
delegate.value += howMuch
|
data.energy += howMuch
|
||||||
|
data.received += howMuch
|
||||||
}
|
}
|
||||||
|
|
||||||
return howMuch
|
return howMuch
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delegate.value >= capacity!!) {
|
if (data.energy >= capacity!!) {
|
||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
val newEnergy = (delegate.value + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity)
|
val newEnergy = (data.energy + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity)
|
||||||
val diff = newEnergy - delegate.value
|
val diff = newEnergy - data.energy
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
delegate.value = newEnergy
|
data.energy = newEnergy
|
||||||
|
data.received += diff
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
@ -123,17 +166,41 @@ class QuantumBatteryItem : Item {
|
|||||||
|
|
||||||
override val batteryLevel: ImpreciseFraction
|
override val batteryLevel: ImpreciseFraction
|
||||||
get() {
|
get() {
|
||||||
if (delegate.parent == null) {
|
if (data.parent == null) {
|
||||||
determineQuantumLink()
|
determineQuantumLink()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isClientThread()) {
|
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
|
override val maxBatteryLevel: ImpreciseFraction
|
||||||
get() = capacity ?: (batteryLevel + ImpreciseFraction.LONG_MAX_VALUE)
|
get() = capacity ?: (batteryLevel + ImpreciseFraction.LONG_MAX_VALUE)
|
||||||
|
|
||||||
@ -149,39 +216,39 @@ class QuantumBatteryItem : Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun determineQuantumLink() {
|
private fun determineQuantumLink() {
|
||||||
if (delegate.parent == null && isServerThread()) {
|
if (data.parent == null && isServerThread()) {
|
||||||
val existing = stack.tag?.getInt("link_id")
|
val existing = stack.tag?.getInt("link_id")
|
||||||
|
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
val old = delegate
|
val old = data
|
||||||
delegate = saveData!!.factorize()
|
data = saveData!!.factorize()
|
||||||
delegate.value = old.value
|
data.energy = old.energy
|
||||||
stack.tagNotNull["link_id"] = delegate.index
|
stack.tagNotNull["link_id"] = data.index
|
||||||
} else {
|
} 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()) {
|
} else if (!isServerThread()) {
|
||||||
// client ?
|
// client ?
|
||||||
val existing = stack.tag?.getInt("link_id") ?: return
|
val existing = stack.tag?.getInt("link_id") ?: return
|
||||||
|
|
||||||
if (existing != delegate.index) {
|
if (existing != data.index) {
|
||||||
delegate = SavedMapDelegate(delegate.parent, existing, delegate.value)
|
data = Data(data.parent, existing, data.energy, data.passed, data.received)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun determineQuantumLinkWeak() {
|
fun determineQuantumLinkWeak() {
|
||||||
if (delegate.parent == null && isServerThread()) {
|
if (data.parent == null && isServerThread()) {
|
||||||
val existing = stack.tag?.getInt("link_id")
|
val existing = stack.tag?.getInt("link_id")
|
||||||
|
|
||||||
if (existing != null) {
|
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()) {
|
} else if (!isServerThread()) {
|
||||||
val existing = stack.tag?.getInt("link_id") ?: return
|
val existing = stack.tag?.getInt("link_id") ?: return
|
||||||
|
|
||||||
if (existing != delegate.index) {
|
if (existing != data.index) {
|
||||||
delegate = SavedMapDelegate(delegate.parent, existing, delegate.value)
|
data = Data(data.parent, existing, data.energy, data.passed, data.received)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,19 +260,25 @@ class QuantumBatteryItem : Item {
|
|||||||
|
|
||||||
val saveDataID: String
|
val saveDataID: String
|
||||||
|
|
||||||
val saveData: SavedCountingMap<SavedMapDelegate<ImpreciseFraction>>? get() {
|
val saveData: SavedCountingMap<Data>? get() {
|
||||||
if (isServerThread()) {
|
if (isServerThread()) {
|
||||||
return MINECRAFT_SERVER.overworld().dataStorage.computeIfAbsent({
|
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()}")
|
}, saveDataID) ?: throw NullPointerException("Unable to get save data for $this in ${MINECRAFT_SERVER.overworld()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
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" }
|
check(isClient) { "Invalid side" }
|
||||||
Int2ObjectAVLTreeMap()
|
Int2ObjectAVLTreeMap()
|
||||||
}
|
}
|
||||||
@ -242,8 +315,6 @@ class QuantumBatteryItem : Item {
|
|||||||
|
|
||||||
if (isCreative) {
|
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_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 {
|
} else {
|
||||||
components.add(TranslatableComponent("otm.item.power.normal.storage", power.batteryLevel.formatPower(), capacity!!.formatPower()).withStyle(ChatFormatting.GRAY))
|
components.add(TranslatableComponent("otm.item.power.normal.storage", power.batteryLevel.formatPower(), capacity!!.formatPower()).withStyle(ChatFormatting.GRAY))
|
||||||
components.add(
|
components.add(
|
||||||
@ -254,7 +325,15 @@ class QuantumBatteryItem : Item {
|
|||||||
).withStyle(ChatFormatting.GRAY))
|
).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 {
|
companion object {
|
||||||
@ -262,7 +341,9 @@ class QuantumBatteryItem : Item {
|
|||||||
return ChargePacket(
|
return ChargePacket(
|
||||||
(ForgeRegistries.ITEMS as ForgeRegistry<Item>).getValue(buff.readInt()) as QuantumBatteryItem,
|
(ForgeRegistries.ITEMS as ForgeRegistry<Item>).getValue(buff.readInt()) as QuantumBatteryItem,
|
||||||
buff.readInt(),
|
buff.readInt(),
|
||||||
buff.readImpreciseFraction()
|
buff.readImpreciseFraction(),
|
||||||
|
buff.readImpreciseFraction(),
|
||||||
|
buff.readImpreciseFraction(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,30 +358,56 @@ class QuantumBatteryItem : Item {
|
|||||||
|
|
||||||
power.determineQuantumLinkWeak()
|
power.determineQuantumLinkWeak()
|
||||||
|
|
||||||
if (power.delegate.index < 0) {
|
if (power.data.index < 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkedChannels.add(power.delegate.index)) {
|
if (networkedChannels.add(power.data.index)) {
|
||||||
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.delegate.index, power.batteryLevel))
|
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.data.index, power.batteryLevel, power.data.passed, power.data.received))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 value: ImpreciseFraction) : MatteryPacket {
|
class ChargePacket(
|
||||||
|
val type: QuantumBatteryItem,
|
||||||
|
val channel: Int,
|
||||||
|
val energy: ImpreciseFraction,
|
||||||
|
val passed: ImpreciseFraction,
|
||||||
|
val received: ImpreciseFraction,
|
||||||
|
) : MatteryPacket {
|
||||||
override fun write(buff: FriendlyByteBuf) {
|
override fun write(buff: FriendlyByteBuf) {
|
||||||
buff.writeInt((ForgeRegistries.ITEMS as ForgeRegistry<Item>).getID(type))
|
buff.writeInt((ForgeRegistries.ITEMS as ForgeRegistry<Item>).getID(type))
|
||||||
buff.writeInt(channel)
|
buff.writeInt(channel)
|
||||||
buff.writeImpreciseFraction(value)
|
buff.writeImpreciseFraction(energy)
|
||||||
|
buff.writeImpreciseFraction(passed)
|
||||||
|
buff.writeImpreciseFraction(received)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||||
context.packetHandled = true
|
context.packetHandled = true
|
||||||
type.clientPowerMap[channel] = value
|
type.clientPowerMap[channel] = ClientData(energy, passed, received)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user