From 14d7eb0d896d1198ce4e54da3d88d480fd539483 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Sat, 23 Oct 2021 23:11:50 +0200 Subject: [PATCH] fixes, wip hotbar hover text, fix crash in TextElement with empty lines --- ReadMe.md | 4 +-- .../gui/rendering/gui/elements/Element.kt | 2 +- .../gui/elements/text/FadingTextElement.kt | 25 ++++++++++++---- .../gui/elements/text/TextElement.kt | 16 ++++------ .../hud/elements/hotbar/HotbarBaseElement.kt | 6 ++-- .../gui/hud/elements/hotbar/HotbarElement.kt | 30 +++++++++++++++++-- .../hud/elements/hotbar/HotbarHUDElement.kt | 10 +++++++ .../event/events/ChatMessageReceiveEvent.kt | 3 ++ .../s2c/play/title/HotbarTextSetS2CP.kt | 2 ++ .../account/microsoft/MicrosoftOAuthUtils.kt | 2 +- 10 files changed, 74 insertions(+), 26 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index a5854a2c5..8bb596369 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -25,8 +25,8 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and ## System requirements - CPU: Minosoft works mostly asynchronous, so multiple cores are good. For FPS more clock speed is better. -- RAM: ~500Mib. With overhead, etc 2Gib recommended -- Disk space: Minosoft itself is pretty small (2-3 Mib), the libraries are a bit bigger (~80 Mib). You also need to have the "normal" minecraft assets (~ 300 MB per minecraft version). +- RAM: Minimum 300 MiB, 1 GiB recommended +- Disk space: Minosoft itself is pretty small (2-3 MiB), the libraries are a bit bigger (~80 MiB). You also need to have the "normal" minecraft assets (~ 300 MiB per minecraft version). - GPU: OpenGL 3.3+. Every modern GPU works and is recommended. - Java 11+, newest version recommended (This is really important, we use features that are only available in this version. Java 8 is currently **not** supported). diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt index ca109ced3..5a2092899 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt @@ -119,7 +119,7 @@ abstract class Element(val hudRenderer: HUDRenderer) { if (RenderConstants.DISABLE_GUI_CACHE || !cacheEnabled) { return forceRender(offset, z, consumer, options) } - if (!cacheUpToDate || cache.offset != offset || hudRenderer.matrixChange || cache.matrix != hudRenderer.matrix || z != cache.z) { + if (!cacheUpToDate || cache.offset != offset || hudRenderer.matrixChange || cache.matrix !== hudRenderer.matrix || z != cache.z) { val cache = GUIMeshCache(hudRenderer.matrix) cache.offset = offset cache.z = z diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/FadingTextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/FadingTextElement.kt index 54b79e55e..0e058406c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/FadingTextElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/FadingTextElement.kt @@ -39,11 +39,11 @@ class FadingTextElement( ) : TextElement(hudRenderer = hudRenderer, text = text, fontAlignment = fontAlignment, background = background, backgroundColor = backgroundColor, noBorder = noBorder, parent), Pollable { override var cacheEnabled: Boolean get() { - if (!super.cacheEnabled || hidden) { - return true + if (hidden || !super.cacheEnabled) { + return false } val time = System.currentTimeMillis() - return !((time < fadeInEndTime) || (time in (fadeInEndTime + 1) until fadeOutEndTime)) + return (time >= fadeInEndTime) && (time < fadeOutStartTime) } set(value) { super.cacheEnabled = value @@ -76,6 +76,7 @@ class FadingTextElement( } fun show() { + // ToDo: Check if already showing val time = System.currentTimeMillis() fadeInStartTime = time fadeInEndTime = fadeInStartTime + fadeInTime @@ -84,6 +85,18 @@ class FadingTextElement( hidden = false } + fun hide() { + if (hidden) { + return + } + // ToDo: Eventually fade out when fading in + val time = System.currentTimeMillis() + fadeInStartTime = -1L + fadeInEndTime = -1L + fadeOutStartTime = time + fadeOutEndTime = fadeOutStartTime + fadeOutTime + } + fun forceHide() { hidden = true } @@ -104,8 +117,11 @@ class FadingTextElement( if (hidden) { return 0 } - val time = System.currentTimeMillis() + if (time > fadeOutEndTime) { + return 0 + } + alpha = 1.0f if (time < fadeInEndTime) { @@ -116,7 +132,6 @@ class FadingTextElement( } else if (time < fadeOutEndTime) { alpha = (fadeOutEndTime - time) / fadeOutTime.toFloat() } else { - alpha = 0.0f return 0 } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt index a4b501f32..ef4f7c837 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt @@ -100,20 +100,16 @@ open class TextElement( override fun forceSilentApply() { val size = Vec2i.EMPTY - if (chatComponent.message.contains("pitch=")) { - val a = maxSize - var b = 1 - } + val renderInfo = TextRenderInfo( + fontAlignment = fontAlignment, + charHeight = charHeight, + charMargin = charMargin, + ) if (!emptyMessage) { - val renderInfo = TextRenderInfo( - fontAlignment = fontAlignment, - charHeight = charHeight, - charMargin = charMargin, - ) ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, 0, this, renderWindow, null, null, renderInfo, chatComponent) renderInfo.currentLineNumber = 0 - this.renderInfo = renderInfo } + this.renderInfo = renderInfo this.cacheUpToDate = false _size = size diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarBaseElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarBaseElement.kt index 47c699861..2df61a302 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarBaseElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarBaseElement.kt @@ -49,11 +49,9 @@ class HotbarBaseElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollab frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 1, consumer, options) } - val inventoryZ = inventoryElement.render(offset, z + 2, consumer, options) + val inventoryZ = inventoryElement.render(offset + HORIZONTAL_MARGIN, z + 2, consumer, options) - // ToDo: Item rendering - - return 2 + inventoryZ// bar + frame + return 2 + inventoryZ // bar + frame } override fun poll(): Boolean { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarElement.kt index 1cbfa2b50..f2f0375cb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarElement.kt @@ -41,6 +41,9 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) { private val topRight = RowLayout(hudRenderer, HorizontalAlignments.RIGHT, 1) // contains hunger, air + val hoverText = FadingTextElement(hudRenderer, text = "", fadeInTime = 300, stayTime = 3000, fadeOutTime = 500, background = false, noBorder = true) + private var hoverTextShown = false + private val itemText = FadingTextElement(hudRenderer, text = "", fadeInTime = 300, stayTime = 1500, fadeOutTime = 500, background = false, noBorder = true) private var lastItemStackNameShown: ItemStack? = null private var lastItemSlot = -1 @@ -51,8 +54,11 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) { private var renderElements = setOf( base, + experience, topLeft, topRight, + itemText, + hoverText, ) override var cacheEnabled: Boolean = false // ToDo: Cache correctly @@ -79,12 +85,17 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) { base.parent = this experience.parent = this itemText.parent = this + hoverText.parent = this forceSilentApply() } override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int { var maxZ = 0 + if (hoverTextShown) { + hoverText.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, hoverText.size.x), 0), z, consumer, options) + offset.y += hoverText.size.y + HOVER_TEXT_OFFSET + } if (itemTextShown) { itemText.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, itemText.size.x), 0), z, consumer, options) offset.y += itemText.size.y + ITEM_NAME_OFFSET @@ -125,6 +136,12 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) { size.x = max(size.x, itemText.size.x) } + hoverTextShown = !hoverText.hidden + if (hoverTextShown) { + size.y += hoverText.size.y + HOVER_TEXT_OFFSET + size.x = max(size.x, hoverText.size.x) + } + _size = size cacheUpToDate = false } @@ -135,8 +152,12 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) { if (currentItem != lastItemStackNameShown || itemSlot != lastItemSlot) { lastItemStackNameShown = currentItem lastItemSlot = itemSlot - itemText.text = hudRenderer.connection.player.inventory.getHotbarSlot()?.displayName ?: "" // ToDo: This calls silentApply again... - itemText.show() + currentItem?.displayName?.let { itemText.text = it } // ToDo: This calls silentApply again... + if (currentItem == null) { + itemText.hide() + } else { + itemText.show() + } } forceSilentApply() // ToDo: Check stuff @@ -150,16 +171,19 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) { override fun tick() { silentApply() + hoverText.tick() itemText.tick() - base.tick() if (gamemode.survival) { topLeft.tick() topRight.tick() } + experience.tick() + base.tick() } companion object { + private const val HOVER_TEXT_OFFSET = 15 private const val ITEM_NAME_OFFSET = 5 private const val VERTICAL_SPACING = 1 } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHUDElement.kt index 67083987f..c8517ae2c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHUDElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHUDElement.kt @@ -13,11 +13,13 @@ package de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar +import de.bixilon.minosoft.data.ChatTextPositions import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.other.game.event.handlers.gamemode.GamemodeChangeEvent import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDElement +import de.bixilon.minosoft.modding.event.events.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.ExperienceChangeEvent import de.bixilon.minosoft.modding.event.events.SelectHotbarSlotEvent import de.bixilon.minosoft.modding.event.events.container.ContainerRevisionChangeEvent @@ -59,6 +61,14 @@ class HotbarHUDElement(hudRenderer: HUDRenderer) : HUDElement(hud } layout.base.apply() }) + + connection.registerEvent(CallbackEventInvoker.of { + if (it.position != ChatTextPositions.ABOVE_HOTBAR) { + return@of + } + layout.hoverText.text = it.message + layout.hoverText.show() + }) } diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/ChatMessageReceiveEvent.kt b/src/main/java/de/bixilon/minosoft/modding/event/events/ChatMessageReceiveEvent.kt index 45af4235f..3b407481b 100644 --- a/src/main/java/de/bixilon/minosoft/modding/event/events/ChatMessageReceiveEvent.kt +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/ChatMessageReceiveEvent.kt @@ -18,6 +18,7 @@ import de.bixilon.minosoft.modding.event.EventInitiators import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.s2c.play.ChatMessageS2CP +import de.bixilon.minosoft.protocol.packets.s2c.play.title.HotbarTextSetS2CP import java.util.* class ChatMessageReceiveEvent( @@ -30,4 +31,6 @@ class ChatMessageReceiveEvent( constructor(connection: PlayConnection, packet: ChatMessageS2CP) : this(connection, EventInitiators.SERVER, packet.message, packet.position, packet.sender) + + constructor(connection: PlayConnection, packet: HotbarTextSetS2CP) : this(connection, EventInitiators.SERVER, packet.text, ChatTextPositions.ABOVE_HOTBAR, null) } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/title/HotbarTextSetS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/title/HotbarTextSetS2CP.kt index 940c67b80..cab2f9282 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/title/HotbarTextSetS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/title/HotbarTextSetS2CP.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.title +import de.bixilon.minosoft.modding.event.events.ChatMessageReceiveEvent import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer @@ -29,5 +30,6 @@ class HotbarTextSetS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { override fun handle(connection: PlayConnection) { Log.log(LogMessageType.CHAT_IN) { "[HOTBAR] $text" } + connection.fireEvent(ChatMessageReceiveEvent(connection, this)) } } diff --git a/src/main/java/de/bixilon/minosoft/util/account/microsoft/MicrosoftOAuthUtils.kt b/src/main/java/de/bixilon/minosoft/util/account/microsoft/MicrosoftOAuthUtils.kt index 0834c8b77..fecd9cf3a 100644 --- a/src/main/java/de/bixilon/minosoft/util/account/microsoft/MicrosoftOAuthUtils.kt +++ b/src/main/java/de/bixilon/minosoft/util/account/microsoft/MicrosoftOAuthUtils.kt @@ -123,7 +123,7 @@ object MicrosoftOAuthUtils { response.body!! if (response.statusCode != 200) { - throw LoginException(response.statusCode, "Could not get minecraft access token ", response.body["errorMessage"].unsafeCast()) + throw LoginException(response.statusCode, "Could not get minecraft access token ", (response.body["errorMessage"] ?: response.body["error"] ?: "unknown").unsafeCast()) } return response.body["access_token"].unsafeCast() }