From a9d78fc31a23e8aba360f591ccc0942333940629 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 2 Sep 2022 13:49:37 +0700 Subject: [PATCH] Quantum battery now display power level on client --- .../mc/otm/OverdriveThatMatters.java | 3 + .../dbotthepony/mc/otm/GlobalEventHandler.kt | 6 +- .../mc/otm/container/ContainerIterator.kt | 28 ++++++ .../dbotthepony/mc/otm/container/Iterators.kt | 24 ----- .../dbotthepony/mc/otm/core/MenuIterator.kt | 30 ++++++ .../mc/otm/item/QuantumBatteryItem.kt | 93 ++++++++++++++++++- .../mc/otm/network/GenericNetworkChannel.kt | 13 +++ 7 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerIterator.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/MenuIterator.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index ab93ceed1..3a1c6cdcc 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -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")); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index 076683ed5..b61ca6dee 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -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 runIfClient(value: V, lambda: () -> V): V { - if (_clientThread !== null) { + if (isClient) { return lambda.invoke() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerIterator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerIterator.kt new file mode 100644 index 000000000..73036c966 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ContainerIterator.kt @@ -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 { + 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 + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/Iterators.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/Iterators.kt index 465be0375..e1ce0b281 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/Iterators.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/Iterators.kt @@ -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 { - 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) : Iterator { private var itemStack: ItemStack? = null private var searched = false diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/MenuIterator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/MenuIterator.kt new file mode 100644 index 000000000..836534a6a --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/MenuIterator.kt @@ -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 { + 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 = MenuIterator(this) \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt index 9915197ba..a323f0d7a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt @@ -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 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).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).getID(type)) + buff.writeInt(channel) + buff.writeImpreciseFraction(value) + } + + override fun play(context: Supplier) { + context.packetHandled = true + type.clientPowerMap[channel] = value + } + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt new file mode 100644 index 000000000..be695f2e8 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt @@ -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) + } +}