Quantum battery now display power level on client

This commit is contained in:
DBotThePony 2022-09-02 13:49:37 +07:00
parent cbea8873e9
commit a9d78fc31a
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 166 additions and 31 deletions

View File

@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
import ru.dbotthepony.mc.otm.matter.MatterDataKt;
@ -88,6 +89,7 @@ public final class OverdriveThatMatters {
MinecraftForge.EVENT_BUS.register(MatterDataKt.class);
MinecraftForge.EVENT_BUS.register(ExplosionQueue.Companion);
MinecraftForge.EVENT_BUS.register(AbstractWeaponItem.Companion);
MinecraftForge.EVENT_BUS.addListener(QuantumBatteryItem.Companion::tick);
FMLJavaModLoadingContext.get().getModEventBus().register(MatteryCapability.class);
@ -105,6 +107,7 @@ public final class OverdriveThatMatters {
WeaponNetworkChannel.INSTANCE.register();
RegistryNetworkChannel.INSTANCE.register();
WorldNetworkChannel.INSTANCE.register();
GenericNetworkChannel.INSTANCE.register();
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125"));

View File

@ -118,6 +118,8 @@ private var _server: MinecraftServer? = null
private var _serverThread: Thread? = null
private var _clientThread: Thread? = null
val isClient: Boolean get() = _clientThread !== null
fun recordClientThread() {
if (_clientThread != null) {
throw IllegalStateException("Already have client channel")
@ -127,13 +129,13 @@ fun recordClientThread() {
}
fun runIfClient(lambda: () -> Unit) {
if (_clientThread !== null) {
if (isClient) {
lambda.invoke()
}
}
fun <V> runIfClient(value: V, lambda: () -> V): V {
if (_clientThread !== null) {
if (isClient) {
return lambda.invoke()
}

View File

@ -0,0 +1,28 @@
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack
class ContainerIterator(private val container: Container) : MutableIterator<ItemStack> {
private var index = 0
override fun hasNext(): Boolean {
return index < container.containerSize
}
override fun next(): ItemStack {
if (index >= container.containerSize) {
throw IllegalStateException("Already finished iterating")
}
return container[index++]
}
override fun remove() {
if (index == 0) {
throw IllegalStateException("Never called next()")
}
container[index - 1] = ItemStack.EMPTY
}
}

View File

@ -6,30 +6,6 @@ import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.core.ifPresentK
class ContainerIterator(private val container: Container) : MutableIterator<ItemStack> {
private var index = 0
override fun hasNext(): Boolean {
return index < container.containerSize
}
override fun next(): ItemStack {
if (index >= container.containerSize) {
throw IllegalStateException("Already finished iterating")
}
return container[index++]
}
override fun remove() {
if (index == 0) {
throw IllegalStateException("Never called next()")
}
container[index - 1] = ItemStack.EMPTY
}
}
open class NonEmptyItemStackIterator(protected open val parent: Iterator<ItemStack>) : Iterator<ItemStack> {
private var itemStack: ItemStack? = null
private var searched = false

View File

@ -0,0 +1,30 @@
package ru.dbotthepony.mc.otm.core
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
class MenuIterator(private val menu: AbstractContainerMenu) : MutableIterator<ItemStack> {
private var index = 0
override fun hasNext(): Boolean {
return index < menu.slots.size
}
override fun next(): ItemStack {
if (index >= menu.slots.size) {
throw IllegalStateException("Already finished iterating")
}
return menu.slots[index++].item
}
override fun remove() {
if (index == 0) {
throw IllegalStateException("Never called next()")
}
menu.slots[index - 1].set(ItemStack.EMPTY)
}
}
fun AbstractContainerMenu.itemStackIterator() : MutableIterator<ItemStack> = MenuIterator(this)

View File

@ -1,24 +1,35 @@
package ru.dbotthepony.mc.otm.item
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.CompoundTag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.item.*
import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.event.TickEvent
import net.minecraftforge.event.TickEvent.ServerTickEvent
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.ForgeRegistry
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.core.itemStackIterator
import ru.dbotthepony.mc.otm.container.nonEmpty
import ru.dbotthepony.mc.otm.core.*
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 {
private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
@ -112,6 +123,10 @@ class QuantumBatteryItem : Item {
determineQuantumLink()
}
if (isClientThread()) {
return clientPowerMap[delegate.index] ?: delegate.value
}
return delegate.value
}
@ -142,7 +157,23 @@ class QuantumBatteryItem : Item {
delegate = saveData?.computeIfAbsent(existing) ?: SavedMapDelegate(null, existing, delegate.value)
}
} else if (!isServerThread()) {
// client
// client ?
val existing = stack.tag?.getInt("link_id") ?: return
if (existing != delegate.index) {
delegate = SavedMapDelegate(delegate.parent, existing, delegate.value)
}
}
}
fun determineQuantumLinkWeak() {
if (delegate.parent == null && isServerThread()) {
val existing = stack.tag?.getInt("link_id")
if (existing != null) {
delegate = saveData?.computeIfAbsent(existing) ?: SavedMapDelegate(null, existing, delegate.value)
}
} else if (!isServerThread()) {
val existing = stack.tag?.getInt("link_id") ?: return
if (existing != delegate.index) {
@ -170,6 +201,11 @@ class QuantumBatteryItem : Item {
return null
}
val clientPowerMap: Int2ObjectAVLTreeMap<ImpreciseFraction> by lazy {
check(isClient) { "Invalid side" }
Int2ObjectAVLTreeMap()
}
constructor(saveDataID: String) : super(Properties().stacksTo(1).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = true
capacity = null
@ -216,4 +252,51 @@ class QuantumBatteryItem : Item {
components.add(TranslatableComponent("otm.item.quantum_link_id", power.delegate.index).withStyle(ChatFormatting.DARK_GRAY))
}
companion object {
fun readPacket(buff: FriendlyByteBuf): ChargePacket {
return ChargePacket(
(ForgeRegistries.ITEMS as ForgeRegistry<Item>).getValue(buff.readInt()) as QuantumBatteryItem,
buff.readInt(),
buff.readImpreciseFraction()
)
}
fun tick(event: ServerTickEvent) {
if (event.phase == TickEvent.Phase.END) {
for (ply in event.server.playerList.players) {
val networkedChannels = IntAVLTreeSet()
for (item in ply.containerMenu.itemStackIterator().nonEmpty()) {
if (item.item is QuantumBatteryItem) {
val power = item.getCapability(MatteryCapability.ENERGY).orThrow() as Power
power.determineQuantumLinkWeak()
if (power.delegate.index < 0) {
continue
}
if (networkedChannels.add(power.delegate.index)) {
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.delegate.index, power.batteryLevel))
}
}
}
}
}
}
}
class ChargePacket(val type: QuantumBatteryItem, val channel: Int, val value: ImpreciseFraction) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt((ForgeRegistries.ITEMS as ForgeRegistry<Item>).getID(type))
buff.writeInt(channel)
buff.writeImpreciseFraction(value)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
type.clientPowerMap[channel] = value
}
}
}

View File

@ -0,0 +1,13 @@
package ru.dbotthepony.mc.otm.network
import net.minecraftforge.network.NetworkDirection
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem
object GenericNetworkChannel : MatteryNetworkChannel(
version = "1",
name = "generic"
) {
fun register() {
add(QuantumBatteryItem.ChargePacket::class.java, QuantumBatteryItem.Companion::readPacket, NetworkDirection.PLAY_TO_CLIENT)
}
}