parent
c6fae3348b
commit
d2257749e0
@ -14,8 +14,6 @@ import net.minecraftforge.fml.common.Mod;
|
|||||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
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.AndroidResearchManager;
|
||||||
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature;
|
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature;
|
||||||
import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity;
|
import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity;
|
||||||
@ -56,7 +54,6 @@ import javax.annotation.ParametersAreNonnullByDefault;
|
|||||||
public final class OverdriveThatMatters {
|
public final class OverdriveThatMatters {
|
||||||
// Directly reference a log4j logger.
|
// Directly reference a log4j logger.
|
||||||
public static final String MOD_ID = "overdrive_that_matters";
|
public static final String MOD_ID = "overdrive_that_matters";
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
|
||||||
|
|
||||||
public static OverdriveThatMatters INSTANCE;
|
public static OverdriveThatMatters INSTANCE;
|
||||||
private StorageStackType<ItemStackWrapper> ITEM_STORAGE;
|
private StorageStackType<ItemStackWrapper> ITEM_STORAGE;
|
||||||
@ -184,6 +181,8 @@ public final class OverdriveThatMatters {
|
|||||||
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onMovementInputUpdate);
|
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onMovementInputUpdate);
|
||||||
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onScreenOpen);
|
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onScreenOpen);
|
||||||
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onPostScreenInit);
|
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.LOWEST, ClientTickHandlerKt::onClientTick);
|
||||||
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientConnected);
|
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientConnected);
|
||||||
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientDisconnected);
|
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientDisconnected);
|
||||||
|
@ -113,7 +113,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
|||||||
private set(value) {
|
private set(value) {
|
||||||
_exoSuitMenu = null
|
_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()
|
ply.closeContainer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,32 @@
|
|||||||
package ru.dbotthepony.mc.otm.client
|
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.platform.InputConstants
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
|
||||||
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 net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||||
import net.minecraft.client.gui.screens.inventory.InventoryScreen
|
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.InventoryMenu
|
||||||
|
import net.minecraft.world.inventory.Slot
|
||||||
import net.minecraftforge.client.event.MovementInputUpdateEvent
|
import net.minecraftforge.client.event.MovementInputUpdateEvent
|
||||||
import net.minecraftforge.client.event.ScreenEvent
|
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.android.feature.JumpBoostFeature
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
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.UVWindingOrder
|
||||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
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.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.LargeRectangleButtonPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.Panel2Widget
|
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.compat.cos.isCosmeticArmorScreen
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
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 ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
fun onMovementInputUpdate(event: MovementInputUpdateEvent) {
|
fun onMovementInputUpdate(event: MovementInputUpdateEvent) {
|
||||||
val ply = event.entity
|
val ply = event.entity
|
||||||
@ -73,37 +67,136 @@ fun onMovementInputUpdate(event: MovementInputUpdateEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var shouldOpenVanillaInventory = false
|
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
|
val player = minecraft.player?.matteryPlayer ?: return
|
||||||
|
|
||||||
|
if (!player.hasExoSuit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val eventScreen = event.screen
|
val eventScreen = event.screen
|
||||||
val screen = if (eventScreen is AbstractContainerScreen<*> && (eventScreen.menu is InventoryMenu || eventScreen.isCosmeticArmorScreen)) eventScreen else return
|
val screen = if (eventScreen is AbstractContainerScreen<*> && (eventScreen.menu is InventoryMenu || eventScreen.isCosmeticArmorScreen)) eventScreen else return
|
||||||
|
|
||||||
if (player.hasExoSuit) {
|
val widget = Panel2Widget(LargeRectangleButtonPanel(screen, null,
|
||||||
val widget = Panel2Widget(LargeRectangleButtonPanel(screen, null,
|
x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE,
|
||||||
x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE,
|
y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2,
|
||||||
y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2,
|
skinElement = Widgets18.RETURN_ARROW_LEFT,
|
||||||
skinElement = Widgets18.RETURN_ARROW_LEFT,
|
skinElementWinding = UVWindingOrder.FLOP,
|
||||||
skinElementWinding = UVWindingOrder.FLOP,
|
onPress = {
|
||||||
onPress = {
|
shouldOpenVanillaInventory = false
|
||||||
shouldOpenVanillaInventory = false
|
val mouseX = minecraft.mouseHandler.xpos()
|
||||||
val mouseX = minecraft.mouseHandler.xpos()
|
val mouseY = minecraft.mouseHandler.ypos()
|
||||||
val mouseY = minecraft.mouseHandler.ypos()
|
|
||||||
|
|
||||||
event.screen.onClose()
|
event.screen.onClose()
|
||||||
minecraft.setScreen(ExoSuitInventoryScreen(player.exoSuitMenu))
|
minecraft.setScreen(ExoSuitInventoryScreen(player.exoSuitMenu))
|
||||||
|
|
||||||
InputConstants.grabOrReleaseMouse(minecraft.window.window, 212993, mouseX, mouseY)
|
InputConstants.grabOrReleaseMouse(minecraft.window.window, 212993, mouseX, mouseY)
|
||||||
}).also { it.tooltip = TranslatableComponent("otm.gui.exosuit.go_in") })
|
}).also { it.tooltip = TranslatableComponent("otm.gui.exosuit.go_in") })
|
||||||
|
|
||||||
event.addListener(widget)
|
event.addListener(widget)
|
||||||
|
|
||||||
tickWhileClient({ minecraft.screen == screen }) {
|
tickWhileClient({ minecraft.screen == screen }) {
|
||||||
widget.panel.x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE
|
widget.panel.x = screen.guiLeft + screen.xSize - 2f - LargeRectangleButtonPanel.SIZE
|
||||||
widget.panel.y = screen.guiTop.toFloat() - LargeRectangleButtonPanel.SIZE - 2f
|
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<Slot>()
|
||||||
|
|
||||||
|
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) {
|
fun onScreenOpen(event: ScreenEvent.Opening) {
|
||||||
|
@ -18,9 +18,9 @@ open class FramePanel<out S : Screen>(
|
|||||||
y: Float,
|
y: Float,
|
||||||
width: Float,
|
width: Float,
|
||||||
height: Float,
|
height: Float,
|
||||||
protected var title: Component
|
protected var title: Component?
|
||||||
) : EditablePanel<S>(screen, parent, x, y, width, height), NarratableEntry {
|
) : EditablePanel<S>(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(
|
open inner class Tab(
|
||||||
var onOpen: Runnable? = null,
|
var onOpen: Runnable? = null,
|
||||||
@ -134,7 +134,7 @@ open class FramePanel<out S : Screen>(
|
|||||||
protected var dragging = false
|
protected var dragging = false
|
||||||
|
|
||||||
init {
|
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 {
|
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||||
@ -160,17 +160,33 @@ open class FramePanel<out S : Screen>(
|
|||||||
|
|
||||||
override fun mouseDraggedInner(x: Double, y: Double, button: Int, xDelta: Double, yDelta: Double): Boolean {
|
override fun mouseDraggedInner(x: Double, y: Double, button: Int, xDelta: Double, yDelta: Double): Boolean {
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
this.x += xDelta.toFloat()
|
val oldX = this.x
|
||||||
this.y += yDelta.toFloat()
|
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)
|
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) {
|
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||||
RECTANGLE.render(stack, width = width, height = height)
|
RECTANGLE.render(stack, width = width, height = height)
|
||||||
|
|
||||||
// title
|
// title
|
||||||
|
val title = title ?: return
|
||||||
RenderSystem.depthFunc(GL30.GL_ALWAYS)
|
RenderSystem.depthFunc(GL30.GL_ALWAYS)
|
||||||
font.draw(stack, title, 8f, 5f, 4210752)
|
font.draw(stack, title, 8f, 5f, 4210752)
|
||||||
RenderSystem.depthFunc(GL30.GL_ALWAYS)
|
RenderSystem.depthFunc(GL30.GL_ALWAYS)
|
||||||
@ -194,7 +210,7 @@ open class FramePanel<out S : Screen>(
|
|||||||
y: Float,
|
y: Float,
|
||||||
width: Float,
|
width: Float,
|
||||||
height: Float,
|
height: Float,
|
||||||
title: Component
|
title: Component?
|
||||||
) = FramePanel(screen, parent, x, y, width + PADDING * 2, height + PADDING_TOP + PADDING, title)
|
) = FramePanel(screen, parent, x, y, width + PADDING * 2, height + PADDING_TOP + PADDING, title)
|
||||||
|
|
||||||
fun <S : Screen> padded(
|
fun <S : Screen> padded(
|
||||||
@ -202,14 +218,14 @@ open class FramePanel<out S : Screen>(
|
|||||||
parent: EditablePanel<*>?,
|
parent: EditablePanel<*>?,
|
||||||
width: Float,
|
width: Float,
|
||||||
height: Float,
|
height: Float,
|
||||||
title: Component
|
title: Component?
|
||||||
) = FramePanel(screen, parent, 0f, 0f, width + PADDING * 2, height + PADDING_TOP + PADDING, title)
|
) = FramePanel(screen, parent, 0f, 0f, width + PADDING * 2, height + PADDING_TOP + PADDING, title)
|
||||||
|
|
||||||
fun <S : Screen> padded(
|
fun <S : Screen> padded(
|
||||||
screen: S,
|
screen: S,
|
||||||
width: Float,
|
width: Float,
|
||||||
height: Float,
|
height: Float,
|
||||||
title: Component
|
title: Component?
|
||||||
) = FramePanel(screen, null, 0f, 0f, width + PADDING * 2, height + PADDING_TOP + PADDING, title)
|
) = FramePanel(screen, null, 0f, 0f, width + PADDING * 2, height + PADDING_TOP + PADDING, title)
|
||||||
|
|
||||||
const val PADDING = 8f
|
const val PADDING = 8f
|
||||||
|
@ -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<AbstractContainerMenu, MenuConfiguration>()
|
||||||
|
|
||||||
|
private class MenuConfiguration(
|
||||||
|
private val player: Player,
|
||||||
|
private val menu: AbstractContainerMenu,
|
||||||
|
originalInventorySlots: Collection<Slot>,
|
||||||
|
private val indices: Collection<Int>
|
||||||
|
) {
|
||||||
|
private data class SlotPos(val x: Int, val y: Int) {
|
||||||
|
constructor(slot: Slot) : this(slot.x, slot.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val slotPositions = Int2ObjectArrayMap<List<SlotPos>>()
|
||||||
|
private val rows = Int2ObjectAVLTreeMap<List<Slot>>()
|
||||||
|
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<Slot>(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<Slot>(9)
|
||||||
|
val slotPositions = ArrayList<SlotPos>(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<Class<*>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Slot>()
|
||||||
|
|
||||||
|
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<NetworkEvent.Context>) {
|
||||||
|
context.packetHandled = true
|
||||||
|
play(context.sender ?: throw IllegalStateException("Illegal side"))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun read(buff: FriendlyByteBuf): InventoryScrollPacket {
|
||||||
|
return InventoryScrollPacket(buff.readVarInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,24 @@
|
|||||||
package ru.dbotthepony.mc.otm.network
|
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.io.FastByteArrayOutputStream
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
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.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.network.NetworkDirection
|
import net.minecraftforge.network.NetworkDirection
|
||||||
import net.minecraftforge.network.NetworkEvent
|
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.block.entity.storage.ItemMonitorPlayerSettings
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
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.container.ItemFilterSlotPacket
|
||||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
import ru.dbotthepony.mc.otm.menu.CancelTaskPacket
|
||||||
import ru.dbotthepony.mc.otm.menu.*
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.data.*
|
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.BooleanPlayerInputPacket
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputPacket
|
import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputPacket
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.OneWayPlayerInputPacket
|
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(PatternsChangePacket::class.java, PatternsChangePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
|
||||||
add(TasksChangePacket::class.java, TasksChangePacket.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(ReplicationRequestPacket::class.java, ReplicationRequestPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
|
||||||
|
|
||||||
|
add(InventoryScrollPacket::class.java, InventoryScrollPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 f_110127_ # WEATHER_TARGET
|
||||||
|
|
||||||
public net.minecraft.client.renderer.RenderStateShard$LineStateShard
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user