From d2257749e08d9ea8993c5f4089da438322a769ee Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 20 Oct 2022 20:59:04 +0700 Subject: [PATCH] Inventory scrollbar in all inventories Fixes #120 --- .../mc/otm/OverdriveThatMatters.java | 5 +- .../otm/capability/MatteryPlayerCapability.kt | 3 +- .../mc/otm/client/ClientEventHandler.kt | 165 +++++++++++---- .../mc/otm/client/screen/panels/FramePanel.kt | 32 ++- .../mc/otm/compat/ExtendedInventoryHandler.kt | 200 ++++++++++++++++++ .../mc/otm/network/MenuNetworkChannel.kt | 25 +-- .../resources/META-INF/accesstransformer.cfg | 2 + 7 files changed, 372 insertions(+), 60 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/compat/ExtendedInventoryHandler.kt diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 47389689f..ebdc8115c 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -14,8 +14,6 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import ru.dbotthepony.mc.otm.android.AndroidResearchManager; import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature; import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity; @@ -56,7 +54,6 @@ import javax.annotation.ParametersAreNonnullByDefault; public final class OverdriveThatMatters { // Directly reference a log4j logger. public static final String MOD_ID = "overdrive_that_matters"; - private static final Logger LOGGER = LogManager.getLogger(); public static OverdriveThatMatters INSTANCE; private StorageStackType ITEM_STORAGE; @@ -184,6 +181,8 @@ public final class OverdriveThatMatters { EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onMovementInputUpdate); EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onScreenOpen); EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onPostScreenInit); + EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onMouseDragged); + EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onMouseScrolled); EVENT_BUS.addListener(EventPriority.LOWEST, ClientTickHandlerKt::onClientTick); EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientConnected); EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientDisconnected); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index a0f31a2d1..1bbeb51dc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -113,7 +113,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial private set(value) { _exoSuitMenu = null - if (ply.containerMenu.slots.any { it.container == field }) { + @Suppress("SENSELESS_COMPARISON") + if (ply.containerMenu != null && (ply !is ServerPlayer || ply.connection != null)) { ply.closeContainer() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt index 3ec1bd18e..f613b95cd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt @@ -1,38 +1,32 @@ package ru.dbotthepony.mc.otm.client -import com.mojang.blaze3d.pipeline.MainTarget -import com.mojang.blaze3d.platform.GlConst.GL_COLOR_BUFFER_BIT -import com.mojang.blaze3d.platform.GlStateManager import com.mojang.blaze3d.platform.InputConstants -import com.mojang.blaze3d.systems.RenderSystem -import com.mojang.blaze3d.vertex.BufferUploader -import com.mojang.blaze3d.vertex.DefaultVertexFormat -import com.mojang.blaze3d.vertex.PoseStack -import com.mojang.blaze3d.vertex.VertexFormat -import com.mojang.math.Matrix4f -import net.minecraft.client.Minecraft +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen import net.minecraft.client.gui.screens.inventory.InventoryScreen -import net.minecraft.client.renderer.GameRenderer import net.minecraft.world.inventory.InventoryMenu +import net.minecraft.world.inventory.Slot import net.minecraftforge.client.event.MovementInputUpdateEvent import net.minecraftforge.client.event.ScreenEvent -import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature +import net.minecraftforge.client.event.ScreenEvent.MouseDragged +import net.minecraftforge.client.event.ScreenEvent.MouseScrolled import ru.dbotthepony.mc.otm.android.feature.JumpBoostFeature import ru.dbotthepony.mc.otm.capability.matteryPlayer -import ru.dbotthepony.mc.otm.client.render.GlitchRenderer import ru.dbotthepony.mc.otm.client.render.UVWindingOrder import ru.dbotthepony.mc.otm.client.render.Widgets18 -import ru.dbotthepony.mc.otm.client.render.tesselator -import ru.dbotthepony.mc.otm.client.render.zLevel import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen +import ru.dbotthepony.mc.otm.client.screen.MatteryScreen +import ru.dbotthepony.mc.otm.client.screen.panels.AbstractSlotPanel +import ru.dbotthepony.mc.otm.client.screen.panels.DiscreteScrollBarPanel import ru.dbotthepony.mc.otm.client.screen.panels.LargeRectangleButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.Panel2Widget +import ru.dbotthepony.mc.otm.compat.InventoryScrollPacket import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorScreen import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.identityFast +import ru.dbotthepony.mc.otm.core.maxScrollDivision +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.network.MenuNetworkChannel import ru.dbotthepony.mc.otm.registry.AndroidFeatures -import kotlin.math.min fun onMovementInputUpdate(event: MovementInputUpdateEvent) { val ply = event.entity @@ -73,37 +67,136 @@ fun onMovementInputUpdate(event: MovementInputUpdateEvent) { } var shouldOpenVanillaInventory = false +var inventoryScroll = 0 -fun onPostScreenInit(event: ScreenEvent.Init.Post) { +private fun inventoryLogic(event: ScreenEvent.Init.Post) { val player = minecraft.player?.matteryPlayer ?: return + if (!player.hasExoSuit) { + return + } + val eventScreen = event.screen val screen = if (eventScreen is AbstractContainerScreen<*> && (eventScreen.menu is InventoryMenu || eventScreen.isCosmeticArmorScreen)) eventScreen else return - if (player.hasExoSuit) { - val widget = Panel2Widget(LargeRectangleButtonPanel(screen, null, - x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE, - y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2, - skinElement = Widgets18.RETURN_ARROW_LEFT, - skinElementWinding = UVWindingOrder.FLOP, - onPress = { - shouldOpenVanillaInventory = false - val mouseX = minecraft.mouseHandler.xpos() - val mouseY = minecraft.mouseHandler.ypos() + val widget = Panel2Widget(LargeRectangleButtonPanel(screen, null, + x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE, + y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2, + skinElement = Widgets18.RETURN_ARROW_LEFT, + skinElementWinding = UVWindingOrder.FLOP, + onPress = { + shouldOpenVanillaInventory = false + val mouseX = minecraft.mouseHandler.xpos() + val mouseY = minecraft.mouseHandler.ypos() - event.screen.onClose() - minecraft.setScreen(ExoSuitInventoryScreen(player.exoSuitMenu)) + event.screen.onClose() + minecraft.setScreen(ExoSuitInventoryScreen(player.exoSuitMenu)) - InputConstants.grabOrReleaseMouse(minecraft.window.window, 212993, mouseX, mouseY) - }).also { it.tooltip = TranslatableComponent("otm.gui.exosuit.go_in") }) + InputConstants.grabOrReleaseMouse(minecraft.window.window, 212993, mouseX, mouseY) + }).also { it.tooltip = TranslatableComponent("otm.gui.exosuit.go_in") }) - event.addListener(widget) + event.addListener(widget) - tickWhileClient({ minecraft.screen == screen }) { - widget.panel.x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE - widget.panel.y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2f + tickWhileClient({ minecraft.screen == screen }) { + widget.panel.x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE + widget.panel.y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2f + } +} + +private fun exosuitInventoryLogic(event: ScreenEvent.Init.Post) { + val player = minecraft.player ?: return + val matteryPlayer = player.matteryPlayer ?: return + + if (!matteryPlayer.hasExoSuit || matteryPlayer.exoSuitContainer.containerSize == 0) { + return + } + + val screen = event.screen + + if (screen !is AbstractContainerScreen<*> || screen.menu is MatteryMenu || screen.menu is InventoryMenu) { + return + } + + val foundInventorySlots = Int2ObjectArrayMap() + + for (slot in screen.menu.slots) { + if (slot.container === player.inventory && slot.slotIndex in 9 .. 35) { + foundInventorySlots[slot.slotIndex] = slot } } + + for (i in 9 .. 35) { + if (i !in foundInventorySlots) { + return + } + } + + val mostTop = foundInventorySlots.values + .stream() + .min { o1, o2 -> o1.y.compareTo(o2.y) } + .get().y.toFloat() + + val mostBottom = foundInventorySlots.values + .stream() + .max { o1, o2 -> o1.y.compareTo(o2.y) } + .get().y.toFloat() + + val mostLeft = foundInventorySlots.values + .stream() + .max { o1, o2 -> o1.x.compareTo(o2.x) } + .get().x.toFloat() + 26f + + val scrollbar = DiscreteScrollBarPanel(screen, null, { maxScrollDivision(matteryPlayer.exoSuitContainer.containerSize, 9) }, { _, _, newScroll -> + inventoryScroll = newScroll + MenuNetworkChannel.sendToServer(InventoryScrollPacket(newScroll).also { it.play(player) }) + }, isSlim = true) + + // HOW + scrollbar.x = mostLeft + screen.guiLeft - 9f + scrollbar.y = mostTop + screen.guiTop - 1f + scrollbar.height = mostBottom - mostTop + AbstractSlotPanel.SIZE + + val widget = Panel2Widget(scrollbar) + event.addListener(widget) + + scrollbar.scroll = inventoryScroll +} + +fun onMouseDragged(event: MouseDragged.Pre) { + val screen = minecraft.screen as? AbstractContainerScreen<*> ?: return + + if (screen is MatteryScreen<*>) + return + + for (widget in screen.renderables) { + if (widget is Panel2Widget<*, *>) { + if (widget.panel.mouseDraggedChecked(event.mouseX, event.mouseY, event.mouseButton, event.dragX, event.dragY)) { + event.isCanceled = true + return + } + } + } +} + +fun onMouseScrolled(event: MouseScrolled.Pre) { + val screen = minecraft.screen as? AbstractContainerScreen<*> ?: return + + if (screen is MatteryScreen<*>) + return + + for (widget in screen.renderables) { + if (widget is Panel2Widget<*, *>) { + if (widget.panel.mouseScrolledChecked(event.mouseX, event.mouseY, event.scrollDelta)) { + event.isCanceled = true + return + } + } + } +} + +fun onPostScreenInit(event: ScreenEvent.Init.Post) { + inventoryLogic(event) + exosuitInventoryLogic(event) } fun onScreenOpen(event: ScreenEvent.Opening) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt index 48ffe2e3e..25f731094 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt @@ -18,9 +18,9 @@ open class FramePanel( y: Float, width: Float, height: Float, - protected var title: Component + protected var title: Component? ) : EditablePanel(screen, parent, x, y, width, height), NarratableEntry { - constructor(screen: S, width: Float, height: Float, title: Component) : this(screen, null, 0f, 0f, width, height, title) + constructor(screen: S, width: Float, height: Float, title: Component?) : this(screen, null, 0f, 0f, width, height, title) open inner class Tab( var onOpen: Runnable? = null, @@ -134,7 +134,7 @@ open class FramePanel( protected var dragging = false init { - setDockPadding(PADDING, PADDING_TOP, PADDING, PADDING) + setDockPadding(PADDING, if (title != null) PADDING_TOP else PADDING, PADDING, PADDING) } override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { @@ -160,17 +160,33 @@ open class FramePanel( override fun mouseDraggedInner(x: Double, y: Double, button: Int, xDelta: Double, yDelta: Double): Boolean { if (dragging) { - this.x += xDelta.toFloat() - this.y += yDelta.toFloat() + val oldX = this.x + val oldY = this.y + + if (canDrag(oldX, oldY, this.x + xDelta.toFloat(), this.y + yDelta.toFloat(), xDelta.toFloat(), yDelta.toFloat())) { + this.x += xDelta.toFloat() + this.y += yDelta.toFloat() + + onDragged(oldX, oldY, this.x, this.y, xDelta.toFloat(), yDelta.toFloat()) + } } return super.mouseDraggedInner(x, y, button, xDelta, yDelta) } + protected open fun canDrag(oldX: Float, oldY: Float, newX: Float, newY: Float, dragX: Float, dragY: Float): Boolean { + return true + } + + protected open fun onDragged(oldX: Float, oldY: Float, newX: Float, newY: Float, dragX: Float, dragY: Float) { + + } + override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) { RECTANGLE.render(stack, width = width, height = height) // title + val title = title ?: return RenderSystem.depthFunc(GL30.GL_ALWAYS) font.draw(stack, title, 8f, 5f, 4210752) RenderSystem.depthFunc(GL30.GL_ALWAYS) @@ -194,7 +210,7 @@ open class FramePanel( y: Float, width: Float, height: Float, - title: Component + title: Component? ) = FramePanel(screen, parent, x, y, width + PADDING * 2, height + PADDING_TOP + PADDING, title) fun padded( @@ -202,14 +218,14 @@ open class FramePanel( parent: EditablePanel<*>?, width: Float, height: Float, - title: Component + title: Component? ) = FramePanel(screen, parent, 0f, 0f, width + PADDING * 2, height + PADDING_TOP + PADDING, title) fun padded( screen: S, width: Float, height: Float, - title: Component + title: Component? ) = FramePanel(screen, null, 0f, 0f, width + PADDING * 2, height + PADDING_TOP + PADDING, title) const val PADDING = 8f diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ExtendedInventoryHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ExtendedInventoryHandler.kt new file mode 100644 index 000000000..72d05fb96 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ExtendedInventoryHandler.kt @@ -0,0 +1,200 @@ +package ru.dbotthepony.mc.otm.compat + +import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap +import it.unimi.dsi.fastutil.ints.Int2ObjectFunction +import it.unimi.dsi.fastutil.objects.ReferenceArraySet +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.inventory.Slot +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Items +import net.minecraftforge.network.NetworkEvent +import org.apache.logging.log4j.LogManager +import ru.dbotthepony.mc.otm.capability.matteryPlayer +import ru.dbotthepony.mc.otm.menu.MatterySlot +import ru.dbotthepony.mc.otm.network.MatteryPacket +import ru.dbotthepony.mc.otm.network.packetHandled +import ru.dbotthepony.mc.otm.network.sender +import java.util.* +import java.util.function.Supplier + +private val menuConfigurations = WeakHashMap() + +private class MenuConfiguration( + private val player: Player, + private val menu: AbstractContainerMenu, + originalInventorySlots: Collection, + private val indices: Collection +) { + private data class SlotPos(val x: Int, val y: Int) { + constructor(slot: Slot) : this(slot.x, slot.y) + } + + private val slotPositions = Int2ObjectArrayMap>() + private val rows = Int2ObjectAVLTreeMap>() + val isIncomplete: Boolean + var scroll = 0 + set(value) { + if (field == value || isIncomplete || value < 0) { + return + } + + val matteryPlayer = player.matteryPlayer ?: return + + if (!matteryPlayer.hasExoSuit || matteryPlayer.exoSuitContainer.containerSize <= value * 9) { + return + } + + field = value + + val indices = indices.iterator() + + for (rowIndex in 0 .. 2) { + val row = rows.computeIfAbsent(rowIndex + value, Int2ObjectFunction { + val row = ArrayList(9) + val offset = (it - 3) * 9 + + for (i in 0 .. 8) { + if (matteryPlayer.exoSuitContainer.containerSize > i + offset) { + row.add(MatterySlot(matteryPlayer.exoSuitContainer, i + offset)) + } else { + row.add(FakeSlot()) + } + } + + row + }) + + val positions = slotPositions[rowIndex] ?: throw IndexOutOfBoundsException("$rowIndex") + + for (column in 0 .. 8) { + val slot = row[column] + val (x, y) = positions[column] + + val index = indices.next() + menu.slots[index] = slot + slot.x = x + slot.y = y + + if (slot.item.isEmpty) { + menu.setRemoteSlotNoCopy(index, ItemStack(Items.BARRIER)) + } else { + menu.setRemoteSlotNoCopy(index, ItemStack.EMPTY) + } + + slot.index = index + } + } + } + + init { + kotlin.run { + for (i in 0 .. 2) { + val offset = 9 + i * 9 + val row = ArrayList(9) + val slotPositions = ArrayList(9) + + for (i2 in 0 .. 8) { + val slot = originalInventorySlots.firstOrNull { it.slotIndex == i2 + offset } + + if (slot == null) { + this.isIncomplete = true + + if (loggedClasses.add(menu::class.java)) { + LOGGER.error("Menu $menu <${menu::class.qualifiedName}> is incomplete, missing inventory slot at ${i2 + offset}") + } + + return@run + } + + row.add(slot) + slotPositions.add(SlotPos(slot)) + } + + rows[i] = row + this.slotPositions[i] = slotPositions + } + + this.isIncomplete = false + } + } + + companion object { + private val LOGGER = LogManager.getLogger() + private val loggedClasses = ReferenceArraySet>() + } +} + +private class FakeSlot : MatterySlot(SimpleContainer(1), 0, 0, 0) { + override fun mayPickup(player: Player): Boolean { + return false + } + + override fun mayPlace(itemStack: ItemStack): Boolean { + return false + } + + override fun getItem(): ItemStack { + return ItemStack.EMPTY + } + + override fun hasItem(): Boolean { + return false + } + + override fun set(p_40240_: ItemStack) { + // no op + } + + override fun remove(p_40227_: Int): ItemStack { + return ItemStack.EMPTY + } + + override fun setChanged() { + // no op + } + + override fun isSameInventory(other: Slot): Boolean { + return false + } + + override fun allowModification(p_150652_: Player): Boolean { + return false + } +} + +class InventoryScrollPacket(val scroll: Int) : MatteryPacket { + override fun write(buff: FriendlyByteBuf) { + buff.writeVarInt(scroll) + } + + fun play(player: Player) { + val containerMenu = player.containerMenu ?: return + + menuConfigurations.computeIfAbsent(containerMenu) { + val originalSlots = Int2ObjectAVLTreeMap() + + for (slot in it.slots) { + if (slot.container === player.inventory && slot.slotIndex in 9 .. 35) { + originalSlots[slot.index] = slot + } + } + + MenuConfiguration(player, containerMenu, originalSlots.values, originalSlots.keys) + }.scroll = scroll + } + + override fun play(context: Supplier) { + context.packetHandled = true + play(context.sender ?: throw IllegalStateException("Illegal side")) + } + + companion object { + fun read(buff: FriendlyByteBuf): InventoryScrollPacket { + return InventoryScrollPacket(buff.readVarInt()) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt index bcb803679..d09bb9034 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt @@ -1,25 +1,24 @@ package ru.dbotthepony.mc.otm.network -import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap -import it.unimi.dsi.fastutil.ints.IntAVLTreeSet -import it.unimi.dsi.fastutil.ints.IntArrayList import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import net.minecraft.network.FriendlyByteBuf -import net.minecraft.world.entity.player.Player -import net.minecraft.world.inventory.AbstractContainerMenu -import net.minecraft.world.inventory.Slot import net.minecraft.world.item.ItemStack import net.minecraftforge.network.NetworkDirection import net.minecraftforge.network.NetworkEvent -import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.compat.InventoryScrollPacket import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket -import ru.dbotthepony.mc.otm.core.TextComponent -import ru.dbotthepony.mc.otm.menu.* -import ru.dbotthepony.mc.otm.menu.data.* +import ru.dbotthepony.mc.otm.menu.CancelTaskPacket +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.menu.PatternsChangePacket +import ru.dbotthepony.mc.otm.menu.ReplicationRequestPacket +import ru.dbotthepony.mc.otm.menu.TasksChangePacket +import ru.dbotthepony.mc.otm.menu.data.ClearItemViewPacket +import ru.dbotthepony.mc.otm.menu.data.ItemViewInteractPacket +import ru.dbotthepony.mc.otm.menu.data.StackAddPacket +import ru.dbotthepony.mc.otm.menu.data.StackChangePacket +import ru.dbotthepony.mc.otm.menu.data.StackRemovePacket import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputPacket import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputPacket import ru.dbotthepony.mc.otm.menu.widget.OneWayPlayerInputPacket @@ -98,5 +97,7 @@ object MenuNetworkChannel : MatteryNetworkChannel( add(PatternsChangePacket::class.java, PatternsChangePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) add(TasksChangePacket::class.java, TasksChangePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) add(ReplicationRequestPacket::class.java, ReplicationRequestPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER) + + add(InventoryScrollPacket::class.java, InventoryScrollPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER) } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index dcd9ed97f..ab1b8dbcd 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -172,3 +172,5 @@ public net.minecraft.client.renderer.RenderStateShard f_173089_ # VIEW_SCALE_Z_E public net.minecraft.client.renderer.RenderStateShard f_110127_ # WEATHER_TARGET public net.minecraft.client.renderer.RenderStateShard$LineStateShard + +public net.minecraft.world.inventory.AbstractContainerMenu m_38897_(Lnet/minecraft/world/inventory/Slot;)Lnet/minecraft/world/inventory/Slot; # addSlot