fixes, wip hotbar hover text, fix crash in TextElement with empty lines

This commit is contained in:
Bixilon 2021-10-23 23:11:50 +02:00
parent 565b5b1950
commit 14d7eb0d89
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
10 changed files with 74 additions and 26 deletions

View File

@ -25,8 +25,8 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and
## System requirements ## System requirements
- CPU: Minosoft works mostly asynchronous, so multiple cores are good. For FPS more clock speed is better. - CPU: Minosoft works mostly asynchronous, so multiple cores are good. For FPS more clock speed is better.
- RAM: ~500Mib. With overhead, etc 2Gib recommended - 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 MB per minecraft version). - 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. - 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). - 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).

View File

@ -119,7 +119,7 @@ abstract class Element(val hudRenderer: HUDRenderer) {
if (RenderConstants.DISABLE_GUI_CACHE || !cacheEnabled) { if (RenderConstants.DISABLE_GUI_CACHE || !cacheEnabled) {
return forceRender(offset, z, consumer, options) 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) val cache = GUIMeshCache(hudRenderer.matrix)
cache.offset = offset cache.offset = offset
cache.z = z cache.z = z

View File

@ -39,11 +39,11 @@ class FadingTextElement(
) : TextElement(hudRenderer = hudRenderer, text = text, fontAlignment = fontAlignment, background = background, backgroundColor = backgroundColor, noBorder = noBorder, parent), Pollable { ) : TextElement(hudRenderer = hudRenderer, text = text, fontAlignment = fontAlignment, background = background, backgroundColor = backgroundColor, noBorder = noBorder, parent), Pollable {
override var cacheEnabled: Boolean override var cacheEnabled: Boolean
get() { get() {
if (!super.cacheEnabled || hidden) { if (hidden || !super.cacheEnabled) {
return true return false
} }
val time = System.currentTimeMillis() val time = System.currentTimeMillis()
return !((time < fadeInEndTime) || (time in (fadeInEndTime + 1) until fadeOutEndTime)) return (time >= fadeInEndTime) && (time < fadeOutStartTime)
} }
set(value) { set(value) {
super.cacheEnabled = value super.cacheEnabled = value
@ -76,6 +76,7 @@ class FadingTextElement(
} }
fun show() { fun show() {
// ToDo: Check if already showing
val time = System.currentTimeMillis() val time = System.currentTimeMillis()
fadeInStartTime = time fadeInStartTime = time
fadeInEndTime = fadeInStartTime + fadeInTime fadeInEndTime = fadeInStartTime + fadeInTime
@ -84,6 +85,18 @@ class FadingTextElement(
hidden = false 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() { fun forceHide() {
hidden = true hidden = true
} }
@ -104,8 +117,11 @@ class FadingTextElement(
if (hidden) { if (hidden) {
return 0 return 0
} }
val time = System.currentTimeMillis() val time = System.currentTimeMillis()
if (time > fadeOutEndTime) {
return 0
}
alpha = 1.0f alpha = 1.0f
if (time < fadeInEndTime) { if (time < fadeInEndTime) {
@ -116,7 +132,6 @@ class FadingTextElement(
} else if (time < fadeOutEndTime) { } else if (time < fadeOutEndTime) {
alpha = (fadeOutEndTime - time) / fadeOutTime.toFloat() alpha = (fadeOutEndTime - time) / fadeOutTime.toFloat()
} else { } else {
alpha = 0.0f
return 0 return 0
} }

View File

@ -100,20 +100,16 @@ open class TextElement(
override fun forceSilentApply() { override fun forceSilentApply() {
val size = Vec2i.EMPTY val size = Vec2i.EMPTY
if (chatComponent.message.contains("pitch=")) {
val a = maxSize
var b = 1
}
if (!emptyMessage) {
val renderInfo = TextRenderInfo( val renderInfo = TextRenderInfo(
fontAlignment = fontAlignment, fontAlignment = fontAlignment,
charHeight = charHeight, charHeight = charHeight,
charMargin = charMargin, charMargin = charMargin,
) )
if (!emptyMessage) {
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, 0, this, renderWindow, null, null, renderInfo, chatComponent) ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, 0, this, renderWindow, null, null, renderInfo, chatComponent)
renderInfo.currentLineNumber = 0 renderInfo.currentLineNumber = 0
this.renderInfo = renderInfo
} }
this.renderInfo = renderInfo
this.cacheUpToDate = false this.cacheUpToDate = false
_size = size _size = size

View File

@ -49,9 +49,7 @@ class HotbarBaseElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollab
frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 1, consumer, options) 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
} }

View File

@ -41,6 +41,9 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
private val topRight = RowLayout(hudRenderer, HorizontalAlignments.RIGHT, 1) // contains hunger, air 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 val itemText = FadingTextElement(hudRenderer, text = "", fadeInTime = 300, stayTime = 1500, fadeOutTime = 500, background = false, noBorder = true)
private var lastItemStackNameShown: ItemStack? = null private var lastItemStackNameShown: ItemStack? = null
private var lastItemSlot = -1 private var lastItemSlot = -1
@ -51,8 +54,11 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
private var renderElements = setOf( private var renderElements = setOf(
base, base,
experience,
topLeft, topLeft,
topRight, topRight,
itemText,
hoverText,
) )
override var cacheEnabled: Boolean = false // ToDo: Cache correctly override var cacheEnabled: Boolean = false // ToDo: Cache correctly
@ -79,12 +85,17 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
base.parent = this base.parent = this
experience.parent = this experience.parent = this
itemText.parent = this itemText.parent = this
hoverText.parent = this
forceSilentApply() forceSilentApply()
} }
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int { override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
var maxZ = 0 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) { if (itemTextShown) {
itemText.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, itemText.size.x), 0), z, consumer, options) itemText.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, itemText.size.x), 0), z, consumer, options)
offset.y += itemText.size.y + ITEM_NAME_OFFSET 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) 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 _size = size
cacheUpToDate = false cacheUpToDate = false
} }
@ -135,9 +152,13 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
if (currentItem != lastItemStackNameShown || itemSlot != lastItemSlot) { if (currentItem != lastItemStackNameShown || itemSlot != lastItemSlot) {
lastItemStackNameShown = currentItem lastItemStackNameShown = currentItem
lastItemSlot = itemSlot lastItemSlot = itemSlot
itemText.text = hudRenderer.connection.player.inventory.getHotbarSlot()?.displayName ?: "" // ToDo: This calls silentApply again... currentItem?.displayName?.let { itemText.text = it } // ToDo: This calls silentApply again...
if (currentItem == null) {
itemText.hide()
} else {
itemText.show() itemText.show()
} }
}
forceSilentApply() // ToDo: Check stuff forceSilentApply() // ToDo: Check stuff
return true return true
@ -150,16 +171,19 @@ class HotbarElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
override fun tick() { override fun tick() {
silentApply() silentApply()
hoverText.tick()
itemText.tick() itemText.tick()
base.tick()
if (gamemode.survival) { if (gamemode.survival) {
topLeft.tick() topLeft.tick()
topRight.tick() topRight.tick()
} }
experience.tick()
base.tick()
} }
companion object { companion object {
private const val HOVER_TEXT_OFFSET = 15
private const val ITEM_NAME_OFFSET = 5 private const val ITEM_NAME_OFFSET = 5
private const val VERTICAL_SPACING = 1 private const val VERTICAL_SPACING = 1
} }

View File

@ -13,11 +13,13 @@
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.hotbar 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.ResourceLocation
import de.bixilon.minosoft.data.registries.other.game.event.handlers.gamemode.GamemodeChangeEvent 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.HUDRenderer
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDElement 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.ExperienceChangeEvent
import de.bixilon.minosoft.modding.event.events.SelectHotbarSlotEvent import de.bixilon.minosoft.modding.event.events.SelectHotbarSlotEvent
import de.bixilon.minosoft.modding.event.events.container.ContainerRevisionChangeEvent import de.bixilon.minosoft.modding.event.events.container.ContainerRevisionChangeEvent
@ -59,6 +61,14 @@ class HotbarHUDElement(hudRenderer: HUDRenderer) : HUDElement<HotbarElement>(hud
} }
layout.base.apply() layout.base.apply()
}) })
connection.registerEvent(CallbackEventInvoker.of<ChatMessageReceiveEvent> {
if (it.position != ChatTextPositions.ABOVE_HOTBAR) {
return@of
}
layout.hoverText.text = it.message
layout.hoverText.show()
})
} }

View File

@ -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.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection 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.ChatMessageS2CP
import de.bixilon.minosoft.protocol.packets.s2c.play.title.HotbarTextSetS2CP
import java.util.* import java.util.*
class ChatMessageReceiveEvent( 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: 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)
} }

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.protocol.packets.s2c.play.title 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.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
@ -29,5 +30,6 @@ class HotbarTextSetS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
Log.log(LogMessageType.CHAT_IN) { "[HOTBAR] $text" } Log.log(LogMessageType.CHAT_IN) { "[HOTBAR] $text" }
connection.fireEvent(ChatMessageReceiveEvent(connection, this))
} }
} }

View File

@ -123,7 +123,7 @@ object MicrosoftOAuthUtils {
response.body!! response.body!!
if (response.statusCode != 200) { 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() return response.body["access_token"].unsafeCast()
} }